+/* This is called when starting Emacs and when restarting after
+ suspend. When starting Emacs, no window is mapped. And nothing
+ must be done to Emacs's own window if it is suspended (though that
+ rarely happens). */
+
+static void
+w32_set_terminal_modes (void)
+{
+}
+
+/* This is called when exiting or suspending Emacs. Exiting will make
+ the W32 windows go away, and suspending requires no action. */
+
+static void
+w32_reset_terminal_modes (void)
+{
+}
+
+
+\f
+/***********************************************************************
+ Output Cursor
+ ***********************************************************************/
+
+/* Set the global variable output_cursor to CURSOR. All cursor
+ positions are relative to updated_window. */
+
+static void
+set_output_cursor (cursor)
+ struct cursor_pos *cursor;
+{
+ output_cursor.hpos = cursor->hpos;
+ output_cursor.vpos = cursor->vpos;
+ output_cursor.x = cursor->x;
+ output_cursor.y = cursor->y;
+}
+
+
+/* Set a nominal cursor position.
+
+ HPOS and VPOS are column/row positions in a window glyph matrix. X
+ and Y are window text area relative pixel positions.
+
+ If this is done during an update, updated_window will contain the
+ window that is being updated and the position is the future output
+ cursor position for that window. If updated_window is null, use
+ selected_window and display the cursor at the given position. */
+
+static void
+w32_cursor_to (vpos, hpos, y, x)
+ int vpos, hpos, y, x;
+{
+ struct window *w;
+
+ /* If updated_window is not set, work on selected_window. */
+ if (updated_window)
+ w = updated_window;
+ else
+ w = XWINDOW (selected_window);
+
+ /* Set the output cursor. */
+ output_cursor.hpos = hpos;
+ output_cursor.vpos = vpos;
+ output_cursor.x = x;
+ output_cursor.y = y;
+
+ /* If not called as part of an update, really display the cursor.
+ This will also set the cursor position of W. */
+ if (updated_window == NULL)
+ {
+ BLOCK_INPUT;
+ x_display_cursor (w, 1, hpos, vpos, x, y);
+ UNBLOCK_INPUT;
+ }
+}
+
+
+\f
+/***********************************************************************
+ Display Iterator
+ ***********************************************************************/
+
+/* Function prototypes of this page. */
+
+static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
+ struct glyph *,
+ wchar_t *,
+ int *));
+static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
+ int, wchar_t *, int));
+static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
+ wchar_t *,
+ enum w32_char_font_type));
+static enum w32_char_font_type
+ w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
+static void x_append_glyph P_ ((struct it *));
+static void x_append_composite_glyph P_ ((struct it *));
+static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
+ int, int, double));
+static void x_produce_glyphs P_ ((struct it *));
+static void x_produce_image_glyph P_ ((struct it *it));
+
+
+/* Dealing with bits of wchar_t as if they were an XChar2B. */
+#define BUILD_WCHAR_T(byte1, byte2) \
+ ((wchar_t)((((byte1) & 0x00ff) << 8) | ((byte2) & 0x00ff)))
+
+
+#define BYTE1(ch) \
+ (((ch) & 0xff00) >> 8)
+
+#define BYTE2(ch) \
+ ((ch) & 0x00ff)
+
+
+/* Get metrics of character CHAR2B in FONT. Value is always non-null.
+ If CHAR2B is not contained in FONT, the font's default character
+ metric is returned. */
+
+static int
+w32_bdf_per_char_metric (font, char2b, dim, pcm)
+ XFontStruct *font;
+ wchar_t *char2b;
+ int dim;
+ XCharStruct * pcm;
+{
+ glyph_metric * bdf_metric;
+ char buf[2];
+
+ if (dim == 1)
+ buf[0] = (char)(*char2b);
+ else
+ {
+ buf[0] = BYTE1 (*char2b);
+ buf[1] = BYTE2 (*char2b);
+ }
+
+ bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
+
+ if (bdf_metric)
+ {
+ pcm->width = bdf_metric->dwidth;
+ pcm->lbearing = bdf_metric->bbox;
+ pcm->rbearing = bdf_metric->dwidth
+ - (bdf_metric->bbox + bdf_metric->bbw);
+ pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
+ pcm->descent = -bdf_metric->bboy;
+
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+w32_native_per_char_metric (font, char2b, font_type, pcm)
+ XFontStruct *font;
+ wchar_t *char2b;
+ enum w32_char_font_type font_type;
+ XCharStruct * pcm;
+{
+ HDC hdc = GetDC (NULL);
+ HFONT old_font;
+ BOOL retval = FALSE;
+
+ xassert (font && char2b);
+ xassert (font->hfont);
+ xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
+
+ old_font = SelectObject (hdc, font->hfont);
+
+ if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
+ {
+ ABC char_widths;
+
+ if (font_type == UNICODE_FONT)
+ retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
+ else
+ retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
+
+ if (retval)
+ {
+ pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
+ pcm->lbearing = char_widths.abcA;
+ pcm->rbearing = pcm->width - char_widths.abcC;
+ pcm->ascent = FONT_BASE (font);
+ pcm->descent = FONT_DESCENT (font);
+ }
+ }
+
+ if (!retval)
+ {
+ /* Either font is not a True-type font, or GetCharABCWidthsW
+ failed (it is not supported on Windows 9x for instance), so we
+ can't determine the full info we would like. All is not lost
+ though - we can call GetTextExtentPoint32 to get rbearing and
+ deduce width based on the font's per-string overhang. lbearing
+ is assumed to be zero. */
+
+ /* TODO: Some Thai characters (and other composites if Windows
+ supports them) do have lbearing, and report their total width
+ as zero. Need some way of handling them when
+ GetCharABCWidthsW fails. */
+ SIZE sz;
+
+ if (font_type == UNICODE_FONT)
+ retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
+ else
+ retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
+
+ if (retval)
+ {
+ pcm->width = sz.cx - font->tm.tmOverhang;
+ pcm->rbearing = sz.cx;
+ pcm->lbearing = 0;
+ pcm->ascent = FONT_BASE (font);
+ pcm->descent = FONT_DESCENT (font);
+ }
+ }
+
+
+ if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
+ {
+ retval = FALSE;
+ }
+
+ SelectObject (hdc, old_font);
+ ReleaseDC (NULL, hdc);
+
+ return retval;
+}
+
+
+static XCharStruct *
+w32_per_char_metric (font, char2b, font_type)
+ XFontStruct *font;
+ wchar_t *char2b;
+ enum w32_char_font_type font_type;
+{
+ /* The result metric information. */
+ XCharStruct *pcm;
+ BOOL retval;
+
+ xassert (font && char2b);
+ xassert (font_type != UNKNOWN_FONT);
+
+ /* Handle the common cases quickly. */
+ if (!font->bdf && font->per_char == NULL)
+ /* TODO: determine whether char2b exists in font? */
+ return &font->max_bounds;
+ else if (!font->bdf && *char2b < 128)
+ return &font->per_char[*char2b];
+
+ pcm = &font->scratch;
+
+ if (font_type == BDF_1D_FONT)
+ retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
+ else if (font_type == BDF_2D_FONT)
+ retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
+ else
+ retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
+
+ if (retval)
+ return pcm;
+
+ return NULL;
+}
+
+void
+w32_cache_char_metrics (font)
+ XFontStruct *font;
+{
+ wchar_t char2b = L'x';
+
+ /* Cache char metrics for the common cases. */
+ if (font->bdf)
+ {
+ /* TODO: determine whether font is fixed-pitch. */
+ if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
+ {
+ /* Use the font width and height as max bounds, as not all BDF
+ fonts contain the letter 'x'. */
+ font->max_bounds.width = FONT_MAX_WIDTH (font);
+ font->max_bounds.lbearing = -font->bdf->llx;
+ font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
+ font->max_bounds.ascent = FONT_BASE (font);
+ font->max_bounds.descent = FONT_DESCENT (font);
+ }
+ }
+ else
+ {
+ if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
+ /* Some fonts (eg DBCS fonts) are marked as fixed width even
+ though they contain characters of different widths. */
+ || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
+ {
+ /* Font is not fixed pitch, so cache per_char info for the
+ ASCII characters. It would be much more work, and probably
+ not worth it, to cache other chars, since we may change
+ between using Unicode and ANSI text drawing functions at
+ run-time. */
+ int i;
+
+ font->per_char = xmalloc (128 * sizeof(XCharStruct));
+ for (i = 0; i < 128; i++)
+ {
+ char2b = i;
+ w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+ &font->per_char[i]);
+ }
+ }
+ else
+ w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+ &font->max_bounds);
+ }
+}
+
+
+/* Determine if a font is double byte. */
+int w32_font_is_double_byte (XFontStruct *font)
+{
+ return font->double_byte_p;
+}
+
+
+static BOOL
+w32_use_unicode_for_codepage (codepage)
+ int codepage;
+{
+ /* If the current codepage is supported, use Unicode for output. */
+ return (w32_enable_unicode_output
+ && codepage != CP_8BIT
+ && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
+}
+
+/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
+ the two-byte form of C. Encoding is returned in *CHAR2B. */
+
+static INLINE enum w32_char_font_type
+w32_encode_char (c, char2b, font_info, two_byte_p)
+ int c;
+ wchar_t *char2b;
+ struct font_info *font_info;
+ int * two_byte_p;
+{
+ int charset = CHAR_CHARSET (c);
+ int codepage;
+ int unicode_p = 0;
+
+ XFontStruct *font = font_info->font;
+
+ xassert (two_byte_p);
+
+ *two_byte_p = w32_font_is_double_byte (font);
+
+ /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
+ This may be either a program in a special encoder language or a
+ fixed encoding. */
+ if (font_info->font_encoder)
+ {
+ /* It's a program. */
+ struct ccl_program *ccl = font_info->font_encoder;
+
+ if (CHARSET_DIMENSION (charset) == 1)
+ {
+ ccl->reg[0] = charset;
+ ccl->reg[1] = BYTE2 (*char2b);
+ }
+ else
+ {
+ ccl->reg[0] = charset;
+ ccl->reg[1] = BYTE1 (*char2b);
+ ccl->reg[2] = BYTE2 (*char2b);
+ }
+
+ ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+
+ /* We assume that MSBs are appropriately set/reset by CCL
+ program. */
+ if (!*two_byte_p) /* 1-byte font */
+ *char2b = BUILD_WCHAR_T (0, ccl->reg[1]);
+ else
+ *char2b = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
+ }
+ else if (font_info->encoding[charset])
+ {
+ /* Fixed encoding scheme. See fontset.h for the meaning of the
+ encoding numbers. */
+ int enc = font_info->encoding[charset];
+
+ if ((enc == 1 || enc == 2)
+ && CHARSET_DIMENSION (charset) == 2)
+ *char2b = BUILD_WCHAR_T (BYTE1 (*char2b) | 0x80, BYTE2 (*char2b));
+
+ if (enc == 1 || enc == 3
+ || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
+ *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), BYTE2 (*char2b) | 0x80);
+ else if (enc == 4)
+ {
+ int sjis1, sjis2;
+
+ ENCODE_SJIS (BYTE1 (*char2b), BYTE2 (*char2b),
+ sjis1, sjis2);
+ *char2b = BUILD_WCHAR_T (sjis1, sjis2);
+ }
+ }
+ codepage = w32_codepage_for_font (font_info->name);
+
+ /* If charset is not ASCII or Latin-1, may need to move it into
+ Unicode space. */
+ if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
+ && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)
+ {
+ char temp[3];
+ temp[0] = BYTE1 (*char2b);
+ temp[1] = BYTE2 (*char2b);
+ temp[2] = '\0';
+ if (codepage != CP_UNICODE)
+ {
+ if (temp[0])
+ MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
+ else
+ MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
+ }
+ unicode_p = 1;
+ *two_byte_p = 1;
+ }
+ if (!font)
+ return UNKNOWN_FONT;
+ else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
+ return BDF_1D_FONT;
+ else if (font->bdf)
+ return BDF_2D_FONT;
+ else if (unicode_p)
+ return UNICODE_FONT;
+ else
+ return ANSI_FONT;
+}
+
+
+/* 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. Value is a pointer to a
+ realized face that is ready for display. */
+
+static INLINE struct face *
+x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
+ struct frame *f;
+ int c, face_id;
+ wchar_t *char2b;
+ int multibyte_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. */
+ *char2b = BUILD_WCHAR_T (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. */
+ *char2b = BUILD_WCHAR_T (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)
+ *char2b = BUILD_WCHAR_T (c1, c2);
+ else
+ *char2b = BUILD_WCHAR_T (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)
+ w32_encode_char (c, char2b, font_info, &multibyte_p);
+ }
+ }
+
+ /* Make sure X resources of the face are allocated. */
+ xassert (face != NULL);
+ PREPARE_FACE_FOR_DISPLAY (f, face);
+
+ return face;
+}
+
+
+/* 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 *
+x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
+ struct frame *f;
+ struct glyph *glyph;
+ wchar_t *char2b;
+ int *two_byte_p;
+{
+ struct face *face;
+ int dummy = 0;
+
+ xassert (glyph->type == CHAR_GLYPH);
+ face = FACE_FROM_ID (f, glyph->face_id);
+
+ if (two_byte_p)
+ *two_byte_p = 0;
+ else
+ two_byte_p = &dummy;
+
+ 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. */
+ *char2b = BUILD_WCHAR_T (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. */
+ *char2b = BUILD_WCHAR_T (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)
+ *char2b = BUILD_WCHAR_T (c1, c2);
+ else
+ *char2b = BUILD_WCHAR_T (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->w32_font_type
+ = w32_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;
+}
+
+
+/* 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
+x_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->w32_font_type = UNKNOWN_FONT;
+ ++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
+x_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->w32_font_type = UNKNOWN_FONT;
+ ++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
+x_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)
+ {
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
+
+ if (it->start_of_box_run_p)
+ it->pixel_width += face->box_line_width;
+ if (it->end_of_box_run_p)
+ it->pixel_width += 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->w32_font_type = UNKNOWN_FONT;
+ ++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
+x_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->w32_font_type = UNKNOWN_FONT;
+ ++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 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
+x_produce_stretch_glyph (it)
+ struct it *it;
+{
+ /* (space :width WIDTH :height HEIGHT. */
+#if GLYPH_DEBUG
+ extern Lisp_Object Qspace;
+#endif
+ extern Lisp_Object QCwidth, QCheight, QCascent;
+ extern Lisp_Object QCrelative_width, QCrelative_height;
+ extern Lisp_Object QCalign_to;
+ Lisp_Object prop, plist;
+ double width = 0, height = 0, 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;
+ x_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)
+ {
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
+
+ if (it->start_of_box_run_p)
+ it->pixel_width += face->box_line_width;
+ if (it->end_of_box_run_p)
+ it->pixel_width += face->box_line_width;
+ }
+
+ take_vertical_position_into_account (it);
+}
+
+/* Return proper value to be used as baseline offset of font that has
+ ASCENT and DESCENT to draw characters by the font at the vertical
+ center of the line of frame F.
+
+ Here, out task is to find the value of BOFF in the following figure;
+
+ -------------------------+-----------+-
+ -+-+---------+-+ | |
+ | | | | | |
+ | | | | F_ASCENT F_HEIGHT
+ | | | ASCENT | |
+ HEIGHT | | | | |
+ | | |-|-+------+-----------|------- baseline
+ | | | | BOFF | |
+ | |---------|-+-+ | |
+ | | | DESCENT | |
+ -+-+---------+-+ F_DESCENT |
+ -------------------------+-----------+-
+
+ -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
+ BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
+ DESCENT = FONT->descent
+ HEIGHT = FONT_HEIGHT (FONT)
+ F_DESCENT = (F->output_data.x->font->descent
+ - F->output_data.x->baseline_offset)
+ F_HEIGHT = FRAME_LINE_HEIGHT (F)
+*/
+
+#define VCENTER_BASELINE_OFFSET(FONT, F) \
+ (FONT_DESCENT (FONT) \
+ + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
+ + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
+ - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
+
+/* 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. */
+
+static void
+x_produce_glyphs (it)
+ struct it *it;
+{
+ it->glyph_not_available_p = 0;
+
+ if (it->what == IT_CHARACTER)
+ {
+ wchar_t 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->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
+ it->multibyte_p = 0;
+ 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. */
+ x_get_char_face_and_encoding (it->f, it->char_to_display,
+ it->face_id, &char2b,
+ it->multibyte_p);
+ 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 = it->f->output_data.w32->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 (it->char_to_display >= ' '
+ && (!it->multibyte_p || it->char_to_display < 128))
+ {
+ /* Either unibyte or ASCII. */
+ int stretched_p;
+
+ it->nglyphs = 1;
+
+ pcm = w32_per_char_metric (font, &char2b,
+ font->bdf ? BDF_1D_FONT : ANSI_FONT);
+ 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;
+
+ it->ascent += thick;
+ it->descent += 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);
+ x_append_stretch_glyph (it, it->object, it->pixel_width,
+ it->ascent + it->descent, ascent);
+ }
+ else
+ x_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)
+ {
+ int thick = face->box_line_width;
+ it->ascent += thick;
+ it->descent += thick;
+ }
+ }
+ 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);
+ x_append_stretch_glyph (it, it->object, it->pixel_width,
+ it->ascent + it->descent, ascent);
+ }
+ }
+ else
+ {
+ /* A multi-byte character.
+ 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. */
+ enum w32_char_font_type type;
+
+ if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
+ type = BDF_1D_FONT;
+ else if (font->bdf)
+ type = BDF_2D_FONT;
+ else
+ type = UNICODE_FONT;
+
+ pcm = w32_per_char_metric (font, &char2b, type);
+
+ 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;
+ it->ascent += thick;
+ it->descent += 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)
+ x_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. */
+ wchar_t 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);
+ x_get_char_face_and_encoding (it->f, it->char_to_display,
+ it->face_id, &char2b, it->multibyte_p);
+ 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 = it->f->output_data.w32->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;
+ }
+
+ /* 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;
+ enum w32_char_font_type font_type;
+
+ cmp->font = (void *) font;
+
+ if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
+ font_type = BDF_1D_FONT;
+ else if (font->bdf)
+ font_type = BDF_2D_FONT;
+ else
+ font_type = UNICODE_FONT;
+
+ /* Initialize the bounding box. */
+ if (font_info
+ && (pcm = w32_per_char_metric (font, &char2b, font_type)))
+ {
+ 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);
+ x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
+ it->multibyte_p);
+ font = face->font;
+ if (font == NULL)
+ {
+ font = FRAME_FONT (it->f);
+ boff = it->f->output_data.w32->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->bdf && CHARSET_DIMENSION (CHAR_CHARSET (ch)) == 1)
+ font_type = BDF_1D_FONT;
+ else if (font->bdf)
+ font_type = BDF_2D_FONT;
+ else
+ font_type = UNICODE_FONT;
+
+ if (font_info
+ && (pcm = w32_per_char_metric (font, &char2b, font_type)))
+ {
+ 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;
+ it->ascent += thick;
+ it->descent += 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)
+ x_append_composite_glyph (it);
+ }
+ else if (it->what == IT_IMAGE)
+ x_produce_image_glyph (it);
+ else if (it->what == IT_STRETCH)
+ x_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);
+}
+
+
+/* Estimate the pixel height of the mode or top line on frame F.
+ FACE_ID specifies what line's height to estimate. */
+
+int
+x_estimate_mode_line_height (f, face_id)
+ struct frame *f;
+ enum face_id face_id;
+{
+ int height = FONT_HEIGHT (FRAME_FONT (f));
+
+ /* This function is called so early when Emacs starts that the face
+ cache and mode line face are not yet initialized. */
+ if (FRAME_FACE_CACHE (f))
+ {
+ struct face *face = FACE_FROM_ID (f, face_id);
+ if (face)
+ {
+ if (face->font)
+ height = FONT_HEIGHT (face->font);
+ height += 2 * face->box_line_width;
+ }
+ }
+
+ return height;
+}
+
+\f
+/***********************************************************************
+ Glyph display
+ ***********************************************************************/
+
+/* A sequence of glyphs to be drawn in the same face.
+
+ This data structure is not really completely X specific, so it
+ could possibly, at least partially, be useful for other systems. It
+ is currently not part of the external redisplay interface because
+ it's not clear what other systems will need. */
+
+struct glyph_string
+{
+ /* X-origin of the string. */
+ int x;
+
+ /* Y-origin and y-position of the base line of this string. */
+ int y, ybase;
+
+ /* The width of the string, not including a face extension. */
+ int width;
+
+ /* The width of the string, including a face extension. */
+ int background_width;
+
+ /* The height of this string. This is the height of the line this
+ string is drawn in, and can be different from the height of the
+ font the string is drawn in. */
+ int height;
+
+ /* Number of pixels this string overwrites in front of its x-origin.
+ This number is zero if the string has an lbearing >= 0; it is
+ -lbearing, if the string has an lbearing < 0. */
+ int left_overhang;
+
+ /* Number of pixels this string overwrites past its right-most
+ nominal x-position, i.e. x + width. Zero if the string's
+ rbearing is <= its nominal width, rbearing - width otherwise. */
+ int right_overhang;
+
+ /* The frame on which the glyph string is drawn. */
+ struct frame *f;
+
+ /* The window on which the glyph string is drawn. */
+ struct window *w;
+
+ /* X display and window for convenience. */
+ Window window;
+
+ /* The glyph row for which this string was built. It determines the
+ y-origin and height of the string. */
+ struct glyph_row *row;
+
+ /* The area within row. */
+ enum glyph_row_area area;
+
+ /* Characters to be drawn, and number of characters. */
+ wchar_t *char2b;
+ int nchars;
+
+ /* A face-override for drawing cursors, mouse face and similar. */
+ enum draw_glyphs_face hl;
+
+ /* Face in which this string is to be drawn. */
+ struct face *face;
+
+ /* Font in which this string is to be drawn. */
+ XFontStruct *font;
+
+ /* Font info for this string. */
+ struct font_info *font_info;
+
+ /* Non-null means this string describes (part of) a composition.
+ All characters from char2b are drawn composed. */
+ struct composition *cmp;
+
+ /* Index of this glyph string's first character in the glyph
+ definition of CMP. If this is zero, this glyph string describes
+ the first character of a composition. */
+ int gidx;
+
+ /* 1 means this glyph strings face has to be drawn to the right end
+ of the window's drawing area. */
+ unsigned extends_to_end_of_line_p : 1;
+
+ /* 1 means the background of this string has been drawn. */
+ unsigned background_filled_p : 1;
+
+ /* 1 means glyph string must be drawn with 16-bit functions. */
+ unsigned two_byte_p : 1;
+
+ /* 1 means that the original font determined for drawing this glyph
+ string could not be loaded. The member `font' has been set to
+ the frame's default font in this case. */
+ unsigned font_not_found_p : 1;
+
+ /* 1 means that the face in which this glyph string is drawn has a
+ stipple pattern. */
+ unsigned stippled_p : 1;
+
+ /* 1 means only the foreground of this glyph string must be drawn,
+ and we should use the physical height of the line this glyph
+ string appears in as clip rect. */
+ unsigned for_overlaps_p : 1;
+
+ /* The GC to use for drawing this glyph string. */
+ XGCValues *gc;
+
+ HDC hdc;
+
+ /* A pointer to the first glyph in the string. This glyph
+ corresponds to char2b[0]. Needed to draw rectangles if
+ font_not_found_p is 1. */
+ struct glyph *first_glyph;
+
+ /* Image, if any. */
+ struct image *img;
+
+ struct glyph_string *next, *prev;
+};
+
+
+/* Encapsulate the different ways of displaying text under W32. */
+
+void W32_TEXTOUT (s, x, y,chars,nchars)
+ struct glyph_string * s;
+ int x, y;
+ wchar_t * chars;
+ int nchars;
+{
+ int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
+ if (s->gc->font->bdf)
+ w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
+ x, y, (char *) chars, charset_dim,
+ nchars * charset_dim, 0);
+ else if (s->first_glyph->w32_font_type == UNICODE_FONT)
+ ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
+ else
+ ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
+ nchars * charset_dim, NULL);
+}
+
+#if 0
+
+static void
+x_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 */
+
+
+
+static void x_append_glyph_string_lists P_ ((struct glyph_string **,
+ struct glyph_string **,
+ struct glyph_string *,
+ struct glyph_string *));
+static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
+ struct glyph_string **,
+ struct glyph_string *,
+ struct glyph_string *));
+static void x_append_glyph_string P_ ((struct glyph_string **,
+ struct glyph_string **,
+ struct glyph_string *));
+static int x_left_overwritten P_ ((struct glyph_string *));
+static int x_left_overwriting P_ ((struct glyph_string *));
+static int x_right_overwritten P_ ((struct glyph_string *));
+static int x_right_overwriting P_ ((struct glyph_string *));
+static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
+ int));
+static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
+ wchar_t *, struct window *,
+ struct glyph_row *,
+ enum glyph_row_area, int,
+ enum draw_glyphs_face));
+static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
+ enum glyph_row_area, int, int,
+ enum draw_glyphs_face, int *, int *, int));
+static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
+static void x_set_glyph_string_gc P_ ((struct glyph_string *));
+static void x_draw_glyph_string_background P_ ((struct glyph_string *,
+ int));
+static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
+static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
+static void x_draw_glyph_string_box P_ ((struct glyph_string *));
+static void x_draw_glyph_string P_ ((struct glyph_string *));
+static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
+static void x_set_cursor_gc P_ ((struct glyph_string *));
+static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
+static void x_set_mouse_face_gc P_ ((struct glyph_string *));
+static void w32_get_glyph_overhangs P_ ((HDC hdc, struct glyph *,
+ struct frame *,
+ int *, int *));
+static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
+static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
+static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
+ double, int, COLORREF));
+static void x_setup_relief_colors P_ ((struct glyph_string *));
+static void x_draw_image_glyph_string P_ ((struct glyph_string *));
+static void x_draw_image_relief P_ ((struct glyph_string *));
+static void x_draw_image_foreground P_ ((struct glyph_string *));
+static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
+static void x_fill_image_glyph_string P_ ((struct glyph_string *));
+static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
+ int, int, int));
+static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
+ int, int, int, int, RECT *));
+static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
+ int, int, int, RECT *));
+static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
+ enum glyph_row_area));
+static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
+ struct glyph_row *,
+ enum glyph_row_area, int, int));
+
+#if GLYPH_DEBUG
+static void x_check_font P_ ((struct frame *, XFontStruct *));
+#endif
+
+
+/* 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
+x_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
+x_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
+x_append_glyph_string (head, tail, s)
+ struct glyph_string **head, **tail;
+ struct glyph_string *s;
+{
+ s->next = s->prev = NULL;
+ x_append_glyph_string_lists (head, tail, s, s);
+}
+
+
+/* Set S->gc to a suitable GC for drawing glyph string S in cursor
+ face. */
+
+static void
+x_set_cursor_gc (s)
+ struct glyph_string *s;
+{
+ if (s->font == FRAME_FONT (s->f)
+ && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
+ && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
+ && !s->cmp)
+ s->gc = s->f->output_data.w32->cursor_gc;
+ else
+ {
+ /* Cursor on non-default face: must merge. */
+ XGCValues xgcv;
+ unsigned long mask;
+
+ xgcv.background = s->f->output_data.w32->cursor_pixel;
+ xgcv.foreground = s->face->background;
+
+ /* If the glyph would be invisible, try a different foreground. */
+ if (xgcv.foreground == xgcv.background)
+ xgcv.foreground = s->face->foreground;
+ if (xgcv.foreground == xgcv.background)
+ xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
+ if (xgcv.foreground == xgcv.background)
+ xgcv.foreground = s->face->foreground;
+
+ /* Make sure the cursor is distinct from text in this face. */
+ if (xgcv.background == s->face->background
+ && xgcv.foreground == s->face->foreground)
+ {
+ xgcv.background = s->face->foreground;
+ xgcv.foreground = s->face->background;
+ }
+
+ IF_DEBUG (x_check_font (s->f, s->font));
+ xgcv.font = s->font;
+ mask = GCForeground | GCBackground | GCFont;
+
+ if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
+ XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
+ mask, &xgcv);
+ else
+ FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
+ = XCreateGC (NULL, s->window, mask, &xgcv);
+
+ s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
+ }
+}
+
+
+/* Set up S->gc of glyph string S for drawing text in mouse face. */
+
+static void
+x_set_mouse_face_gc (s)
+ struct glyph_string *s;
+{
+ int face_id;
+ struct face *face;
+
+ /* What face has to be used last for the mouse face? */
+ face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
+ face = FACE_FROM_ID (s->f, face_id);
+ if (face == NULL)
+ face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+
+ if (s->first_glyph->type == CHAR_GLYPH)
+ face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+ else
+ face_id = FACE_FOR_CHAR (s->f, face, 0);
+ s->face = FACE_FROM_ID (s->f, face_id);
+ PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+
+ /* If font in this face is same as S->font, use it. */
+ if (s->font == s->face->font)
+ s->gc = s->face->gc;
+ else
+ {
+ /* Otherwise construct scratch_cursor_gc with values from FACE
+ but font FONT. */
+ XGCValues xgcv;
+ unsigned long mask;
+
+ xgcv.background = s->face->background;
+ xgcv.foreground = s->face->foreground;
+ IF_DEBUG (x_check_font (s->f, s->font));
+ xgcv.font = s->font;
+ mask = GCForeground | GCBackground | GCFont;
+
+ if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
+ XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
+ mask, &xgcv);
+ else
+ FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
+ = XCreateGC (NULL, s->window, mask, &xgcv);
+
+ s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
+ }
+
+ xassert (s->gc != 0);
+}
+
+
+/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
+ Faces to use in the mode line have already been computed when the
+ matrix was built, so there isn't much to do, here. */
+
+static INLINE void
+x_set_mode_line_face_gc (s)
+ struct glyph_string *s;
+{
+ s->gc = s->face->gc;
+}
+
+
+/* Set S->gc of glyph string S for drawing that glyph string. Set
+ S->stippled_p to a non-zero value if the face of S has a stipple
+ pattern. */
+
+static INLINE void
+x_set_glyph_string_gc (s)
+ struct glyph_string *s;
+{
+ PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+
+ if (s->hl == DRAW_NORMAL_TEXT)
+ {
+ s->gc = s->face->gc;
+ s->stippled_p = s->face->stipple != 0;
+ }
+ else if (s->hl == DRAW_INVERSE_VIDEO)
+ {
+ x_set_mode_line_face_gc (s);
+ s->stippled_p = s->face->stipple != 0;
+ }
+ else if (s->hl == DRAW_CURSOR)
+ {
+ x_set_cursor_gc (s);
+ s->stippled_p = 0;
+ }
+ else if (s->hl == DRAW_MOUSE_FACE)
+ {
+ x_set_mouse_face_gc (s);
+ s->stippled_p = s->face->stipple != 0;
+ }
+ else if (s->hl == DRAW_IMAGE_RAISED
+ || s->hl == DRAW_IMAGE_SUNKEN)
+ {
+ s->gc = s->face->gc;
+ s->stippled_p = s->face->stipple != 0;
+ }
+ else
+ {
+ s->gc = s->face->gc;
+ s->stippled_p = s->face->stipple != 0;
+ }
+
+ /* GC must have been set. */
+ xassert (s->gc != 0);
+}
+
+
+/* Return in *R the clipping rectangle for glyph string S. */
+
+static void
+w32_get_glyph_string_clip_rect (s, r)
+ struct glyph_string *s;
+ RECT *r;
+{
+ int r_height, r_width;
+
+ if (s->row->full_width_p)
+ {
+ /* Draw full-width. X coordinates are relative to S->w->left. */
+ int canon_x = CANON_X_UNIT (s->f);
+
+ r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
+ r_width = XFASTINT (s->w->width) * canon_x;
+
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
+ {
+ int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
+ r->left -= width;
+ }
+
+ r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
+
+ /* Unless displaying a mode or menu bar line, which are always
+ fully visible, clip to the visible part of the row. */
+ if (s->w->pseudo_window_p)
+ r_height = s->row->visible_height;
+ else
+ r_height = s->height;
+ }
+ else
+ {
+ /* This is a text line that may be partially visible. */
+ r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
+ r_width = window_box_width (s->w, s->area);
+ r_height = s->row->visible_height;
+ }
+
+ /* Don't use S->y for clipping because it doesn't take partially
+ visible lines into account. For example, it can be negative for
+ partially visible lines at the top of a window. */
+ if (!s->row->full_width_p
+ && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
+ r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+ else
+ r->top = max (0, s->row->y);
+
+ /* If drawing a tool-bar window, draw it over the internal border
+ at the top of the window. */
+ if (s->w == XWINDOW (s->f->tool_bar_window))
+ r->top -= s->f->output_data.w32->internal_border_width;
+
+ /* If S draws overlapping rows, it's sufficient to use the top and
+ bottom of the window for clipping because this glyph string
+ intentionally draws over other lines. */
+ if (s->for_overlaps_p)
+ {
+ r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+ r_height = window_text_bottom_y (s->w) - r->top;
+ }
+
+ r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
+
+ r->bottom = r->top + r_height;
+ r->right = r->left + r_width;
+}
+
+
+/* Set clipping for output of glyph string S. S may be part of a mode
+ line or menu if we don't have X toolkit support. */
+
+static INLINE void
+x_set_glyph_string_clipping (s)
+ struct glyph_string *s;
+{
+ RECT r;
+ w32_get_glyph_string_clip_rect (s, &r);
+ w32_set_clip_rectangle (s->hdc, &r);
+}
+
+
+/* Compute left and right overhang of glyph string S. If S is a glyph
+ string for a composition, assume overhangs don't exist. */
+
+static INLINE void
+x_compute_glyph_string_overhangs (s)
+ struct glyph_string *s;
+{
+ /* TODO: Windows does not appear to have a method for
+ getting this info without getting the ABC widths for each
+ individual character and working it out manually. */
+}
+
+
+/* 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
+x_compute_overhangs_and_x (s, x, backward_p)
+ struct glyph_string *s;
+ int x;
+ int backward_p;
+{
+ if (backward_p)
+ {
+ while (s)
+ {
+ x_compute_glyph_string_overhangs (s);
+ x -= s->width;
+ s->x = x;
+ s = s->prev;
+ }
+ }
+ else
+ {
+ while (s)
+ {
+ x_compute_glyph_string_overhangs (s);
+ s->x = x;
+ x += s->width;
+ s = s->next;
+ }
+ }
+}
+
+
+/* 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. */
+
+static void
+w32_get_glyph_overhangs (hdc, glyph, f, left, right)
+ HDC hdc;
+ struct glyph *glyph;
+ struct frame *f;
+ int *left, *right;
+{
+ *left = *right = 0;
+
+ if (glyph->type == CHAR_GLYPH)
+ {
+ XFontStruct *font;
+ struct face *face;
+ wchar_t char2b;
+ XCharStruct *pcm;
+
+ face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
+ font = face->font;
+
+ if (font
+ && (pcm = w32_per_char_metric (font, &char2b,
+ glyph->w32_font_type)))
+ {
+ if (pcm->rbearing > pcm->width)
+ *right = pcm->rbearing - pcm->width;
+ if (pcm->lbearing < 0)
+ *left = -pcm->lbearing;
+ }
+ }
+}
+
+
+static void
+x_get_glyph_overhangs (glyph, f, left, right)
+ struct glyph *glyph;
+ struct frame *f;
+ int *left, *right;
+{
+ HDC hdc = get_frame_dc (f);
+ /* Convert to unicode! */
+ w32_get_glyph_overhangs (hdc, glyph, f, left, right);
+ release_frame_dc (f, hdc);
+}
+
+
+/* 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
+x_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
+x_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;
+ w32_get_glyph_overhangs (s->hdc, 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
+x_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
+x_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;
+ w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
+ if (x - left < 0)
+ k = i;
+ x += glyphs[i].pixel_width;
+ }
+
+ return k;
+}
+
+
+/* Fill rectangle X, Y, W, H with background color of glyph string S. */
+
+static INLINE void
+x_clear_glyph_string_rect (s, x, y, w, h)
+ struct glyph_string *s;
+ int x, y, w, h;
+{
+ int real_x = x;
+ int real_y = y;
+ int real_w = w;
+ int real_h = h;
+#if 0
+ /* Take clipping into account. */
+ if (s->gc->clip_mask == Rect)
+ {
+ real_x = max (real_x, s->gc->clip_rectangle.left);
+ real_y = max (real_y, s->gc->clip_rectangle.top);
+ real_w = min (real_w, s->gc->clip_rectangle.right
+ - s->gc->clip_rectangle.left);
+ real_h = min (real_h, s->gc->clip_rectangle.bottom
+ - s->gc->clip_rectangle.top);
+ }
+#endif
+ w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
+ real_w, real_h);
+}
+
+
+/* Draw the background of glyph_string S. If S->background_filled_p
+ is non-zero don't draw it. FORCE_P non-zero means draw the
+ background even if it wouldn't be drawn normally. This is used
+ when a string preceding S draws into the background of S, or S
+ contains the first component of a composition. */
+
+static void
+x_draw_glyph_string_background (s, force_p)
+ struct glyph_string *s;
+ int force_p;
+{
+ /* Nothing to do if background has already been drawn or if it
+ shouldn't be drawn in the first place. */
+ if (!s->background_filled_p)
+ {
+#if 0 /* TODO: stipple */
+ if (s->stippled_p)
+ {
+ /* Fill background with a stipple pattern. */
+ XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+ XFillRectangle (s->display, s->window, s->gc, s->x,
+ s->y + s->face->box_line_width,
+ s->background_width,
+ s->height - 2 * s->face->box_line_width);
+ XSetFillStyle (s->display, s->gc, FillSolid);
+ s->background_filled_p = 1;
+ }
+ else
+#endif
+ if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
+ || s->font_not_found_p
+ || s->extends_to_end_of_line_p
+ || s->font->bdf
+ || force_p)
+ {
+ x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
+ s->background_width,
+ s->height - 2 * s->face->box_line_width);
+ s->background_filled_p = 1;
+ }
+ }
+}
+
+
+/* Draw the foreground of glyph string S. */
+
+static void
+x_draw_glyph_string_foreground (s)
+ struct glyph_string *s;
+{
+ int i, x;
+ HFONT old_font;
+
+ /* If first glyph of S has a left box line, start drawing the text
+ of S to the right of that box line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + s->face->box_line_width;
+ else
+ x = s->x;
+
+ if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
+ SetBkMode (s->hdc, TRANSPARENT);
+ else
+ SetBkMode (s->hdc, OPAQUE);
+
+ SetTextColor (s->hdc, s->gc->foreground);
+ SetBkColor (s->hdc, s->gc->background);
+ SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
+
+ if (s->font && s->font->hfont)
+ old_font = SelectObject (s->hdc, s->font->hfont);
+
+ /* Draw characters of S as rectangles if S's font could not be
+ loaded. */
+ if (s->font_not_found_p)
+ {
+ for (i = 0; i < s->nchars; ++i)
+ {
+ struct glyph *g = s->first_glyph + i;
+
+ w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
+ s->height - 1);
+ x += g->pixel_width;
+ }
+ }
+ else
+ {
+ char *char1b = (char *) s->char2b;
+ int boff = s->font_info->baseline_offset;
+
+ if (s->font_info->vertical_centering)
+ boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
+
+ /* If we can use 8-bit functions, condense S->char2b. */
+ if (!s->two_byte_p)
+ for (i = 0; i < s->nchars; ++i)
+ char1b[i] = BYTE2 (s->char2b[i]);
+
+ /* Draw text with TextOut and friends. */
+ W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
+ }
+ if (s->font && s->font->hfont)
+ SelectObject (s->hdc, old_font);
+}
+
+/* Draw the foreground of composite glyph string S. */
+
+static void
+x_draw_composite_glyph_string_foreground (s)
+ struct glyph_string *s;
+{
+ int i, x;
+ HFONT old_font;
+
+ /* If first glyph of S has a left box line, start drawing the text
+ of S to the right of that box line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + s->face->box_line_width;
+ else
+ x = s->x;
+
+ /* S is a glyph string for a composition. S->gidx is the index of
+ the first character drawn for glyphs of this composition.
+ S->gidx == 0 means we are drawing the very first character of
+ this composition. */
+
+ SetTextColor (s->hdc, s->gc->foreground);
+ SetBkColor (s->hdc, s->gc->background);
+ SetBkMode (s->hdc, TRANSPARENT);
+ SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
+
+ if (s->font && s->font->hfont)
+ old_font = SelectObject (s->hdc, s->font->hfont);
+
+ /* Draw a rectangle for the composition if the font for the very
+ first character of the composition could not be loaded. */
+ if (s->font_not_found_p)
+ {
+ if (s->gidx == 0)
+ w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
+ s->height - 1);
+ }
+ else
+ {
+ for (i = 0; i < s->nchars; i++, ++s->gidx)
+ W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
+ s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
+ s->char2b + i, 1);
+ }
+ if (s->font && s->font->hfont)
+ SelectObject (s->hdc, old_font);
+}
+
+
+/* Brightness beyond which a color won't have its highlight brightness
+ boosted.
+
+ Nominally, highlight colors for `3d' faces are calculated by
+ brightening an object's color by a constant scale factor, but this
+ doesn't yield good results for dark colors, so for colors who's
+ brightness is less than this value (on a scale of 0-255) have to
+ use an additional additive factor.
+
+ The value here is set so that the default menu-bar/mode-line color
+ (grey75) will not have its highlights changed at all. */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
+
+
+/* Allocate a color which is lighter or darker than *COLOR by FACTOR
+ or DELTA. Try a color with RGB values multiplied by FACTOR first.
+ If this produces the same color as COLOR, try a color where all RGB
+ values have DELTA added. Return the allocated color in *COLOR.
+ DISPLAY is the X display, CMAP is the colormap to operate on.
+ Value is non-zero if successful. */
+
+static int
+w32_alloc_lighter_color (f, color, factor, delta)
+ struct frame *f;
+ COLORREF *color;
+ double factor;
+ int delta;
+{
+ COLORREF new;
+ long bright;
+
+ /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
+ delta /= 256;
+
+ /* Change RGB values by specified FACTOR. Avoid overflow! */
+ xassert (factor >= 0);
+ new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
+ min (0xff, factor * GetGValue (*color)),
+ min (0xff, factor * GetBValue (*color)));
+
+ /* Calculate brightness of COLOR. */
+ bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
+ + GetBValue (*color)) / 6;
+
+ /* We only boost colors that are darker than
+ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
+ if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+ /* Make an additive adjustment to NEW, because it's dark enough so
+ that scaling by FACTOR alone isn't enough. */
+ {
+ /* How far below the limit this color is (0 - 1, 1 being darker). */
+ double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+ /* The additive adjustment. */
+ int min_delta = delta * dimness * factor / 2;
+
+ if (factor < 1)
+ new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
+ max (0, min (0xff, min_delta - GetGValue (*color))),
+ max (0, min (0xff, min_delta - GetBValue (*color))));
+ else
+ new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
+ max (0, min (0xff, min_delta + GetGValue (*color))),
+ max (0, min (0xff, min_delta + GetBValue (*color))));
+ }
+
+ if (new == *color)
+ new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
+ max (0, min (0xff, delta + GetGValue (*color))),
+ max (0, min (0xff, delta + GetBValue (*color))));
+
+ /* TODO: Map to palette and retry with delta if same? */
+ /* TODO: Free colors (if using palette)? */
+
+ if (new == *color)
+ return 0;
+
+ *color = new;
+
+ return 1;
+}
+
+
+/* Set up the foreground color for drawing relief lines of glyph
+ string S. RELIEF is a pointer to a struct relief containing the GC
+ with which lines will be drawn. Use a color that is FACTOR or
+ DELTA lighter or darker than the relief's background which is found
+ in S->f->output_data.x->relief_background. If such a color cannot
+ be allocated, use DEFAULT_PIXEL, instead. */
+
+static void
+w32_setup_relief_color (f, relief, factor, delta, default_pixel)
+ struct frame *f;
+ struct relief *relief;
+ double factor;
+ int delta;
+ COLORREF default_pixel;
+{
+ XGCValues xgcv;
+ struct w32_output *di = f->output_data.w32;
+ unsigned long mask = GCForeground;
+ COLORREF pixel;
+ COLORREF background = di->relief_background;
+ struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+
+ /* TODO: Free colors (if using palette)? */
+
+ /* Allocate new color. */
+ xgcv.foreground = default_pixel;
+ pixel = background;
+ if (w32_alloc_lighter_color (f, &pixel, factor, delta))
+ {
+ relief->allocated_p = 1;
+ xgcv.foreground = relief->pixel = pixel;
+ }
+
+ if (relief->gc == 0)
+ {
+#if 0 /* TODO: stipple */
+ xgcv.stipple = dpyinfo->gray;
+ mask |= GCStipple;
+#endif
+ relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
+ }
+ else
+ XChangeGC (NULL, relief->gc, mask, &xgcv);
+}
+
+
+/* Set up colors for the relief lines around glyph string S. */
+
+static void
+x_setup_relief_colors (s)
+ struct glyph_string *s;
+{
+ struct w32_output *di = s->f->output_data.w32;
+ COLORREF color;
+
+ if (s->face->use_box_color_for_shadows_p)
+ color = s->face->box_color;
+ else
+ color = s->gc->background;
+
+ if (di->white_relief.gc == 0
+ || color != di->relief_background)
+ {
+ di->relief_background = color;
+ w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
+ WHITE_PIX_DEFAULT (s->f));
+ w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
+ BLACK_PIX_DEFAULT (s->f));
+ }
+}
+
+
+/* Draw a relief on frame F inside the rectangle given by LEFT_X,
+ TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
+ to draw, it must be >= 0. RAISED_P non-zero means draw a raised
+ relief. LEFT_P non-zero means draw a relief on the left side of
+ the rectangle. RIGHT_P non-zero means draw a relief on the right
+ side of the rectangle. CLIP_RECT is the clipping rectangle to use
+ when drawing. */
+
+static void
+w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
+ raised_p, left_p, right_p, clip_rect)
+ struct frame *f;
+ int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
+ RECT *clip_rect;
+{
+ int i;
+ XGCValues gc;
+ HDC hdc = get_frame_dc (f);
+
+ if (raised_p)
+ gc.foreground = f->output_data.w32->white_relief.gc->foreground;
+ else
+ gc.foreground = f->output_data.w32->black_relief.gc->foreground;
+
+ w32_set_clip_rectangle (hdc, clip_rect);
+
+ /* Top. */
+ for (i = 0; i < width; ++i)
+ {
+ w32_fill_area (f, hdc, gc.foreground,
+ left_x + i * left_p, top_y + i,
+ (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
+ }
+
+ /* Left. */
+ if (left_p)
+ for (i = 0; i < width; ++i)
+ {
+ w32_fill_area (f, hdc, gc.foreground,
+ left_x + i, top_y + i, 1,
+ (bottom_y - i) - (top_y + i));
+ }
+
+ w32_set_clip_rectangle (hdc, NULL);
+
+ if (raised_p)
+ gc.foreground = f->output_data.w32->black_relief.gc->foreground;
+ else
+ gc.foreground = f->output_data.w32->white_relief.gc->foreground;
+
+
+ w32_set_clip_rectangle (hdc, clip_rect);
+
+ /* Bottom. */
+ for (i = 0; i < width; ++i)
+ {
+ w32_fill_area (f, hdc, gc.foreground,
+ left_x + i * left_p, bottom_y - i,
+ (right_x + 1 - i * right_p) - left_x + i * left_p, 1);
+ }
+
+ /* Right. */
+ if (right_p)
+ for (i = 0; i < width; ++i)
+ {
+ w32_fill_area (f, hdc, gc.foreground,
+ right_x - i, top_y + i + 1, 1,
+ (bottom_y - i) - (top_y + i + 1));
+ }
+
+ w32_set_clip_rectangle (hdc, NULL);
+
+ release_frame_dc (f, hdc);
+}
+
+
+/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
+ RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
+ draw, it must be >= 0. LEFT_P non-zero means draw a line on the
+ left side of the rectangle. RIGHT_P non-zero means draw a line
+ on the right side of the rectangle. CLIP_RECT is the clipping
+ rectangle to use when drawing. */
+
+static void
+w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
+ left_p, right_p, clip_rect)
+ struct glyph_string *s;
+ int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
+ RECT *clip_rect;
+{
+ w32_set_clip_rectangle (s->hdc, clip_rect);
+
+ /* Top. */
+ w32_fill_area (s->f, s->hdc, s->face->box_color,
+ left_x, top_y, right_x - left_x + 1, width);
+
+ /* Left. */
+ if (left_p)
+ {
+ w32_fill_area (s->f, s->hdc, s->face->box_color,
+ left_x, top_y, width, bottom_y - top_y + 1);
+ }
+
+ /* Bottom. */
+ w32_fill_area (s->f, s->hdc, s->face->box_color,
+ left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+
+ /* Right. */
+ if (right_p)
+ {
+ w32_fill_area (s->f, s->hdc, s->face->box_color,
+ right_x - width + 1, top_y, width, bottom_y - top_y + 1);
+ }
+
+ w32_set_clip_rectangle (s->hdc, NULL);
+}
+
+
+/* Draw a box around glyph string S. */
+
+static void
+x_draw_glyph_string_box (s)
+ struct glyph_string *s;
+{
+ int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
+ int left_p, right_p;
+ struct glyph *last_glyph;
+ RECT clip_rect;
+
+ last_x = window_box_right (s->w, s->area);
+ if (s->row->full_width_p
+ && !s->w->pseudo_window_p)
+ {
+ last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
+ last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
+ }
+
+ /* The glyph that may have a right box line. */
+ last_glyph = (s->cmp || s->img
+ ? s->first_glyph
+ : s->first_glyph + s->nchars - 1);
+
+ width = s->face->box_line_width;
+ raised_p = s->face->box == FACE_RAISED_BOX;
+ left_x = s->x;
+ right_x = ((s->row->full_width_p
+ ? last_x - 1
+ : min (last_x, s->x + s->background_width) - 1));
+ top_y = s->y;
+ bottom_y = top_y + s->height - 1;
+
+ left_p = (s->first_glyph->left_box_line_p
+ || (s->hl == DRAW_MOUSE_FACE
+ && (s->prev == NULL
+ || s->prev->hl != s->hl)));
+ right_p = (last_glyph->right_box_line_p
+ || (s->hl == DRAW_MOUSE_FACE
+ && (s->next == NULL
+ || s->next->hl != s->hl)));
+
+ w32_get_glyph_string_clip_rect (s, &clip_rect);
+
+ if (s->face->box == FACE_SIMPLE_BOX)
+ w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
+ left_p, right_p, &clip_rect);
+ else
+ {
+ x_setup_relief_colors (s);
+ w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
+ width, raised_p, left_p, right_p, &clip_rect);
+ }
+}
+
+
+/* Draw foreground of image glyph string S. */
+
+static void
+x_draw_image_foreground (s)
+ struct glyph_string *s;
+{
+ int x;
+ int y = s->ybase - image_ascent (s->img, s->face);
+
+ /* If first glyph of S has a left box line, start drawing it to the
+ right of that line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + s->face->box_line_width;
+ else
+ x = s->x;
+
+ /* If there is a margin around the image, adjust x- and y-position
+ by that margin. */
+ x += s->img->hmargin;
+ y += s->img->vmargin;
+
+ SaveDC (s->hdc);
+
+ if (s->img->pixmap)
+ {
+#if 0 /* TODO: image mask */
+ if (s->img->mask)
+ {
+ /* We can't set both a clip mask and use XSetClipRectangles
+ because the latter also sets a clip mask. We also can't
+ trust on the shape extension to be available
+ (XShapeCombineRegion). So, compute the rectangle to draw
+ manually. */
+ unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
+ | GCFunction);
+ XGCValues xgcv;
+ XRectangle clip_rect, image_rect, r;
+
+ xgcv.clip_mask = s->img->mask;
+ xgcv.clip_x_origin = x;
+ xgcv.clip_y_origin = y;
+ xgcv.function = GXcopy;
+ XChangeGC (s->display, s->gc, mask, &xgcv);
+
+ w32_get_glyph_string_clip_rect (s, &clip_rect);
+ image_rect.x = x;
+ image_rect.y = y;
+ image_rect.width = s->img->width;
+ image_rect.height = s->img->height;
+ if (IntersectRect (&r, &clip_rect, &image_rect))
+ XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
+ r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+ }
+ else
+#endif
+ {
+ HDC compat_hdc = CreateCompatibleDC (s->hdc);
+ HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
+ HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
+ HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
+ x_set_glyph_string_clipping (s);
+
+ SetTextColor (s->hdc, s->gc->foreground);
+ SetBkColor (s->hdc, s->gc->background);
+#if 0 /* From w32bdf.c (which is from Meadow). */
+ BitBlt (s->hdc, x, y, s->img->width, s->img->height,
+ compat_hdc, 0, 0, SRCCOPY);
+ BitBlt (s->hdc, x, y, s->img->width, s->img->height,
+ compat_hdc, 0, 0, 0xB8074A);
+#else
+ BitBlt (s->hdc, x, y, s->img->width, s->img->height,
+ compat_hdc, 0, 0, 0xE20746);
+#endif
+ SelectObject (s->hdc, orig_brush);
+ DeleteObject (fg_brush);
+ SelectObject (compat_hdc, orig_obj);
+ DeleteDC (compat_hdc);
+
+ /* When the image has a mask, we can expect that at
+ least part of a mouse highlight or a block cursor will
+ be visible. If the image doesn't have a mask, make
+ a block cursor visible by drawing a rectangle around
+ the image. I believe it's looking better if we do
+ nothing here for mouse-face. */
+ if (s->hl == DRAW_CURSOR)
+ w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
+ s->img->height - 1);
+ w32_set_clip_rectangle (s->hdc, NULL);
+ }
+ }
+ else
+ w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
+ s->img->height - 1);
+
+ RestoreDC (s->hdc ,-1);
+}
+
+
+
+/* Draw a relief around the image glyph string S. */
+
+static void
+x_draw_image_relief (s)
+ struct glyph_string *s;
+{
+ int x0, y0, x1, y1, thick, raised_p;
+ RECT r;
+ int x;
+ int y = s->ybase - image_ascent (s->img, s->face);
+
+ /* If first glyph of S has a left box line, start drawing it to the
+ right of that line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + s->face->box_line_width;
+ else
+ x = s->x;
+
+ /* If there is a margin around the image, adjust x- and y-position
+ by that margin. */
+ x += s->img->hmargin;
+ y += s->img->vmargin;
+
+ if (s->hl == DRAW_IMAGE_SUNKEN
+ || s->hl == DRAW_IMAGE_RAISED)
+ {
+ thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
+ raised_p = s->hl == DRAW_IMAGE_RAISED;
+ }
+ else
+ {
+ thick = abs (s->img->relief);
+ raised_p = s->img->relief > 0;
+ }
+
+ x0 = x - thick;
+ y0 = y - thick;
+ x1 = x + s->img->width + thick - 1;
+ y1 = y + s->img->height + thick - 1;
+
+ x_setup_relief_colors (s);
+ w32_get_glyph_string_clip_rect (s, &r);
+ w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+}
+
+
+/* Draw the foreground of image glyph string S to PIXMAP. */
+
+static void
+w32_draw_image_foreground_1 (s, pixmap)
+ struct glyph_string *s;
+ HBITMAP pixmap;
+{
+ HDC hdc = CreateCompatibleDC (s->hdc);
+ HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
+ int x;
+ int y = s->ybase - s->y - image_ascent (s->img, s->face);
+
+ /* If first glyph of S has a left box line, start drawing it to the
+ right of that line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->face->box_line_width;
+ else
+ x = 0;
+
+ /* If there is a margin around the image, adjust x- and y-position
+ by that margin. */
+ x += s->img->hmargin;
+ y += s->img->vmargin;
+
+ if (s->img->pixmap)
+ {
+#if 0 /* TODO: image mask */
+ if (s->img->mask)
+ {
+ /* We can't set both a clip mask and use XSetClipRectangles
+ because the latter also sets a clip mask. We also can't
+ trust on the shape extension to be available
+ (XShapeCombineRegion). So, compute the rectangle to draw
+ manually. */
+ unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
+ | GCFunction);
+ XGCValues xgcv;
+
+ xgcv.clip_mask = s->img->mask;
+ xgcv.clip_x_origin = x;
+ xgcv.clip_y_origin = y;
+ xgcv.function = GXcopy;
+ XChangeGC (s->display, s->gc, mask, &xgcv);
+
+ XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
+ 0, 0, s->img->width, s->img->height, x, y);
+ XSetClipMask (s->display, s->gc, None);
+ }
+ else
+#endif
+ {
+ HDC compat_hdc = CreateCompatibleDC (hdc);
+ HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
+ HBRUSH orig_brush = SelectObject (hdc, fg_brush);
+ HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
+
+ SetTextColor (hdc, s->gc->foreground);
+ SetBkColor (hdc, s->gc->background);
+#if 0 /* From w32bdf.c (which is from Meadow). */
+ BitBlt (hdc, x, y, s->img->width, s->img->height,
+ compat_hdc, 0, 0, SRCCOPY);
+ BitBlt (hdc, x, y, s->img->width, s->img->height,
+ compat_hdc, 0, 0, 0xB8074A);
+#else
+ BitBlt (hdc, x, y, s->img->width, s->img->height,
+ compat_hdc, 0, 0, 0xE20746);
+#endif
+ SelectObject (hdc, orig_brush);
+ DeleteObject (fg_brush);
+ SelectObject (compat_hdc, orig_obj);
+ DeleteDC (compat_hdc);
+
+ /* When the image has a mask, we can expect that at
+ least part of a mouse highlight or a block cursor will
+ be visible. If the image doesn't have a mask, make
+ a block cursor visible by drawing a rectangle around
+ the image. I believe it's looking better if we do
+ nothing here for mouse-face. */
+ if (s->hl == DRAW_CURSOR)
+ w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
+ s->img->height - 1);
+ }
+ }
+ else
+ w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
+ s->img->height - 1);
+
+ SelectObject (hdc, orig_hdc_obj);
+ DeleteDC (hdc);
+}
+
+
+/* Draw part of the background of glyph string S. X, Y, W, and H
+ give the rectangle to draw. */
+
+static void
+x_draw_glyph_string_bg_rect (s, x, y, w, h)
+ struct glyph_string *s;
+ int x, y, w, h;
+{
+#if 0 /* TODO: stipple */
+ if (s->stippled_p)
+ {
+ /* Fill background with a stipple pattern. */
+ XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+ XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
+ XSetFillStyle (s->display, s->gc, FillSolid);
+ }
+ else
+#endif
+ x_clear_glyph_string_rect (s, x, y, w, h);
+}
+
+
+/* Draw image glyph string S.
+
+ s->y
+ s->x +-------------------------
+ | s->face->box
+ |
+ | +-------------------------
+ | | s->img->vmargin
+ | |
+ | | +-------------------
+ | | | the image
+
+ */
+
+static void
+x_draw_image_glyph_string (s)
+ struct glyph_string *s;
+{
+ int x, y;
+ int box_line_width = s->face->box_line_width;
+ int height;
+ HBITMAP pixmap = 0;
+
+ height = s->height - 2 * box_line_width;
+
+ /* Fill background with face under the image. Do it only if row is
+ taller than image or if image has a clip mask to reduce
+ flickering. */
+ s->stippled_p = s->face->stipple != 0;
+ if (height > s->img->height
+ || s->img->hmargin
+ || s->img->vmargin
+#if 0 /* TODO: image mask */
+ || s->img->mask
+#endif
+ || s->img->pixmap == 0
+ || s->width != s->background_width)
+ {
+ if (box_line_width && s->first_glyph->left_box_line_p)
+ x = s->x + box_line_width;
+ else
+ x = s->x;
+
+ y = s->y + box_line_width;
+#if 0 /* TODO: image mask */
+ if (s->img->mask)
+ {
+ /* Create a pixmap as large as the glyph string. Fill it
+ with the background color. Copy the image to it, using
+ its mask. Copy the temporary pixmap to the display. */
+ Screen *screen = FRAME_X_SCREEN (s->f);
+ int depth = DefaultDepthOfScreen (screen);
+
+ /* Create a pixmap as large as the glyph string. */
+ pixmap = XCreatePixmap (s->display, s->window,
+ s->background_width,
+ s->height, depth);
+
+ /* Don't clip in the following because we're working on the
+ pixmap. */
+ XSetClipMask (s->display, s->gc, None);
+
+ /* Fill the pixmap with the background color/stipple. */
+ if (s->stippled_p)
+ {
+ /* Fill background with a stipple pattern. */
+ XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+ XFillRectangle (s->display, pixmap, s->gc,
+ 0, 0, s->background_width, s->height);
+ XSetFillStyle (s->display, s->gc, FillSolid);
+ }
+ else
+ {
+ XGCValues xgcv;
+ XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
+ &xgcv);
+ XSetForeground (s->display, s->gc, xgcv.background);
+ XFillRectangle (s->display, pixmap, s->gc,
+ 0, 0, s->background_width, s->height);
+ XSetForeground (s->display, s->gc, xgcv.foreground);
+ }
+ }
+ else
+#endif
+ x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+
+ s->background_filled_p = 1;
+ }
+
+ /* Draw the foreground. */
+ if (pixmap != 0)
+ {
+ w32_draw_image_foreground_1 (s, pixmap);
+ x_set_glyph_string_clipping (s);
+ {
+ HDC compat_hdc = CreateCompatibleDC (s->hdc);
+ HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
+ HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
+ HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
+
+ SetTextColor (s->hdc, s->gc->foreground);
+ SetBkColor (s->hdc, s->gc->background);
+#if 0 /* From w32bdf.c (which is from Meadow). */
+ BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
+ compat_hdc, 0, 0, SRCCOPY);
+ BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
+ compat_hdc, 0, 0, 0xB8074A);
+#else
+ BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
+ compat_hdc, 0, 0, 0xE20746);
+#endif
+ SelectObject (s->hdc, orig_brush);
+ DeleteObject (fg_brush);
+ SelectObject (compat_hdc, orig_obj);
+ DeleteDC (compat_hdc);
+ }
+ DeleteObject (pixmap);
+ pixmap = 0;
+ }
+ else
+ x_draw_image_foreground (s);
+
+ /* If we must draw a relief around the image, do it. */
+ if (s->img->relief
+ || s->hl == DRAW_IMAGE_RAISED
+ || s->hl == DRAW_IMAGE_SUNKEN)
+ x_draw_image_relief (s);
+}
+
+
+/* Draw stretch glyph string S. */
+
+static void
+x_draw_stretch_glyph_string (s)
+ struct glyph_string *s;
+{
+ xassert (s->first_glyph->type == STRETCH_GLYPH);
+ s->stippled_p = s->face->stipple != 0;
+
+ if (s->hl == DRAW_CURSOR
+ && !x_stretch_cursor_p)
+ {
+ /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
+ as wide as the stretch glyph. */
+ int width = min (CANON_X_UNIT (s->f), s->background_width);
+
+ /* Draw cursor. */
+ x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
+
+ /* Clear rest using the GC of the original non-cursor face. */
+ if (width < s->background_width)
+ {
+ XGCValues *gc = s->face->gc;
+ int x = s->x + width, y = s->y;
+ int w = s->background_width - width, h = s->height;
+ RECT r;
+ HDC hdc = s->hdc;
+ w32_get_glyph_string_clip_rect (s, &r);
+ w32_set_clip_rectangle (hdc, &r);
+
+#if 0 /* TODO: stipple */
+ if (s->face->stipple)
+ {
+ /* Fill background with a stipple pattern. */
+ XSetFillStyle (s->display, gc, FillOpaqueStippled);
+ XFillRectangle (s->display, s->window, gc, x, y, w, h);
+ XSetFillStyle (s->display, gc, FillSolid);
+ }
+ else
+#endif
+ {
+ w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
+ }
+ }
+ }
+ else
+ x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
+ s->height);
+
+ s->background_filled_p = 1;
+}
+
+
+/* Draw glyph string S. */
+
+static void
+x_draw_glyph_string (s)
+ struct glyph_string *s;
+{
+ /* If S draws into the background of its successor, draw the
+ background of the successor first so that S can draw into it.
+ This makes S->next use XDrawString instead of XDrawImageString. */
+ if (s->next && s->right_overhang && !s->for_overlaps_p)
+ {
+ xassert (s->next->img == NULL);
+ x_set_glyph_string_gc (s->next);
+ x_set_glyph_string_clipping (s->next);
+ x_draw_glyph_string_background (s->next, 1);
+ }
+
+ /* Set up S->gc, set clipping and draw S. */
+ x_set_glyph_string_gc (s);
+ x_set_glyph_string_clipping (s);
+
+ switch (s->first_glyph->type)
+ {
+ case IMAGE_GLYPH:
+ x_draw_image_glyph_string (s);
+ break;
+
+ case STRETCH_GLYPH:
+ x_draw_stretch_glyph_string (s);
+ break;
+
+ case CHAR_GLYPH:
+ if (s->for_overlaps_p)
+ s->background_filled_p = 1;
+ else
+ x_draw_glyph_string_background (s, 0);
+ x_draw_glyph_string_foreground (s);
+ break;
+
+ case COMPOSITE_GLYPH:
+ if (s->for_overlaps_p || s->gidx > 0)
+ s->background_filled_p = 1;
+ else
+ x_draw_glyph_string_background (s, 1);
+ x_draw_composite_glyph_string_foreground (s);
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (!s->for_overlaps_p)
+ {
+ /* Draw underline. */
+ if (s->face->underline_p
+ && (s->font->bdf || !s->font->tm.tmUnderlined))
+ {
+ unsigned long h = 1;
+ unsigned long dy = s->height - h;
+
+ if (s->face->underline_defaulted_p)
+ {
+ w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+ s->y + dy, s->width, 1);
+ }
+ else
+ {
+ w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+ s->y + dy, s->width, 1);
+ }
+ }
+
+ /* Draw overline. */
+ if (s->face->overline_p)
+ {
+ unsigned long dy = 0, h = 1;
+
+ if (s->face->overline_color_defaulted_p)
+ {
+ w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+ s->y + dy, s->width, h);
+ }
+ else
+ {
+ w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+ s->y + dy, s->width, h);
+ }
+ }
+
+ /* Draw strike-through. */
+ if (s->face->strike_through_p
+ && (s->font->bdf || !s->font->tm.tmStruckOut))
+ {
+ unsigned long h = 1;
+ unsigned long dy = (s->height - h) / 2;
+
+ if (s->face->strike_through_color_defaulted_p)
+ {
+ w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
+ s->width, h);
+ }
+ else
+ {
+ w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+ s->y + dy, s->width, h);
+ }
+ }
+
+ /* Draw relief. */
+ if (s->face->box != FACE_NO_BOX)
+ x_draw_glyph_string_box (s);
+ }
+
+ /* Reset clipping. */
+ w32_set_clip_rectangle (s->hdc, NULL);
+}
+
+
+static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
+ struct face **, int));
+
+
+/* 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
+x_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
+x_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 = x_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
+x_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
+x_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;
+
+ xassert (s->face && s->face->gc);
+ return glyph - s->row->glyphs[s->area];
+}
+
+
+/* Initialize glyph string S. CHAR2B is a suitably allocated vector
+ of XChar2b structures for S; it can't be allocated in
+ x_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. */
+
+static void
+w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
+ struct glyph_string *s;
+ HDC hdc;
+ wchar_t *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);
+ s->hdc = hdc;
+ s->window = FRAME_W32_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 -= s->f->output_data.w32->internal_border_width;
+
+ s->ybase = s->y + row->ascent;
+}