Commit 5da0698e authored by Kim F. Storm's avatar Kim F. Storm
Browse files

Remove consolidated defines and code.

(x_per_char_metric, x_encode_char)
(x_compute_glyph_string_overhangs): Adapt to RIF requirements.
(x_redisplay_interface): Add new members.
parent 133c764e
......@@ -333,19 +333,6 @@ extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
extern Lisp_Object x_icon_type P_ ((struct frame *));
/* Enumeration for overriding/changing the face to use for drawing
glyphs in x_draw_glyphs. */
enum draw_glyphs_face
{
DRAW_NORMAL_TEXT,
DRAW_INVERSE_VIDEO,
DRAW_CURSOR,
DRAW_MOUSE_FACE,
DRAW_IMAGE_RAISED,
DRAW_IMAGE_SUNKEN
};
static int cursor_in_mouse_face_p P_ ((struct window *));
static int clear_mouse_face P_ ((struct x_display_info *));
static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
......@@ -433,15 +420,12 @@ void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
GC, int));
static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,
int, int, int, int));
static void x_flush P_ ((struct frame *f));
static void x_update_begin P_ ((struct frame *));
static void x_update_window_begin P_ ((struct window *));
static void x_draw_vertical_border P_ ((struct window *));
static void x_after_update_window_line P_ ((struct glyph_row *));
static INLINE void take_vertical_position_into_account P_ ((struct it *));
static void x_produce_stretch_glyph P_ ((struct it *));
static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
enum scroll_bar_part *,
......@@ -923,30 +907,17 @@ XTcursor_to (vpos, hpos, y, x)
/* Function prototypes of this page. */
static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
struct glyph *,
XChar2b *,
int *));
static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
int, XChar2b *, int,
int));
static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
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));
static int x_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
is not contained in the font. */
static INLINE XCharStruct *
x_per_char_metric (font, char2b)
static XCharStruct *
x_per_char_metric (font, char2b, font_type)
XFontStruct *font;
XChar2b *char2b;
int font_type; /* unused on X */
{
/* The result metric information. */
XCharStruct *pcm = NULL;
......@@ -1014,11 +985,12 @@ x_per_char_metric (font, char2b)
/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
the two-byte form of C. Encoding is returned in *CHAR2B. */
static INLINE void
x_encode_char (c, char2b, font_info)
static int
x_encode_char (c, char2b, font_info, two_byte_p)
int c;
XChar2b *char2b;
struct font_info *font_info;
int *two_byte_p;
{
int charset = CHAR_CHARSET (c);
XFontStruct *font = font_info->font;
......@@ -1066,1070 +1038,11 @@ x_encode_char (c, char2b, font_info)
if (enc == 1 || enc == 3)
char2b->byte2 |= 0x80;
}
}
/* Get face and two-byte form of character C in face FACE_ID on frame
F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
means we want to display multibyte text. DISPLAY_P non-zero means
make sure that X resources for the face returned are allocated.
Value is a pointer to a realized face that is ready for display if
DISPLAY_P is non-zero. */
static INLINE struct face *
x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
struct frame *f;
int c, face_id;
XChar2b *char2b;
int multibyte_p, display_p;
{
struct face *face = FACE_FROM_ID (f, face_id);
if (!multibyte_p)
{
/* Unibyte case. We don't have to encode, but we have to make
sure to use a face suitable for unibyte. */
char2b->byte1 = 0;
char2b->byte2 = 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->byte1 = 0;
char2b->byte2 = 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->byte1 = c1, char2b->byte2 = c2;
else
char2b->byte1 = 0, char2b->byte2 = 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)
x_encode_char (c, char2b, font_info);
}
}
/* Make sure X resources of the face are allocated. */
if (display_p)
{
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;
XChar2b *char2b;
int *two_byte_p;
{
struct face *face;
xassert (glyph->type == CHAR_GLYPH);
face = FACE_FROM_ID (f, glyph->face_id);
if (two_byte_p)
*two_byte_p = 0;
if (!glyph->multibyte_p)
{
/* Unibyte case. We don't have to encode, but we have to make
sure to use a face suitable for unibyte. */
char2b->byte1 = 0;
char2b->byte2 = 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->byte1 = 0;
char2b->byte2 = 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->byte1 = c1, char2b->byte2 = c2;
else
char2b->byte1 = 0, char2b->byte2 = 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)
{
x_encode_char (glyph->u.ch, char2b, font_info);
if (two_byte_p)
*two_byte_p
= ((XFontStruct *) (font_info->font))->max_byte1 > 0;
}
}
}
/* 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;
++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;
++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)
{
if (face->box_line_width > 0)
{
it->ascent += face->box_line_width;
it->descent += face->box_line_width;
}
if (it->start_of_box_run_p)
it->pixel_width += abs (face->box_line_width);
if (it->end_of_box_run_p)
it->pixel_width += abs (face->box_line_width);
}
take_vertical_position_into_account (it);
if (it->glyph_row)
{
struct glyph *glyph;
enum glyph_row_area area = it->area;
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
{
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
glyph->pixel_width = it->pixel_width;
glyph->voffset = it->voffset;
glyph->type = IMAGE_GLYPH;
glyph->multibyte_p = it->multibyte_p;
glyph->left_box_line_p = it->start_of_box_run_p;
glyph->right_box_line_p = it->end_of_box_run_p;
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
glyph->face_id = it->face_id;
glyph->u.img_id = img->id;
++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;
++it->glyph_row->used[area];
}
}
/* Produce a stretch glyph for iterator IT. IT->object is the value
of the glyph property displayed. The value must be a list
`(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
being recognized:
1. `:width WIDTH' specifies that the space should be WIDTH *
canonical char width wide. WIDTH may be an integer or floating
point number.
2. `:relative-width FACTOR' specifies that the width of the stretch
should be computed from the width of the first character having the
`glyph' property, and should be FACTOR times that width.
3. `:align-to HPOS' specifies that the space should be wide enough
to reach HPOS, a value in canonical character units.
Exactly one of the above pairs must be present.
4. `:height HEIGHT' specifies that the height of the stretch produced
should be HEIGHT, measured in canonical character units.
5. `:relative-height FACTOR' specifies that the height of the
stretch should be FACTOR times the height of the characters having
the glyph property.
Either none or exactly one of 4 or 5 must be present.
6. `:ascent ASCENT' specifies that ASCENT percent of the height
of the stretch should be used for the ascent of the stretch.
ASCENT must be in the range 0 <= ASCENT <= 100. */
#define NUMVAL(X) \
((INTEGERP (X) || FLOATP (X)) \
? XFLOATINT (X) \
: - 1)
static void
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->ascent / 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)
{
if (face->box_line_width > 0)
{
it->ascent += face->box_line_width;
it->descent += face->box_line_width;
}
if (it->start_of_box_run_p)
it->pixel_width += abs (face->box_line_width);
if (it->end_of_box_run_p)
it->pixel_width += abs (face->box_line_width);
}
take_vertical_position_into_account (it);
}
/* 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 \
+ (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
+ (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
- ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
/* 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)
{
XChar2b char2b;
XFontStruct *font;
struct face *face = FACE_FROM_ID (it->f, it->face_id);
XCharStruct *pcm;
int font_not_found_p;
struct font_info *font_info;
int boff; /* baseline offset */
/* We may change it->multibyte_p upon unibyte<->multibyte
conversion. So, save the current value now and restore it
later.
Note: It seems that we don't have to record multibyte_p in
struct glyph because the character code itself tells if or
not the character is multibyte. Thus, in the future, we must
consider eliminating the field `multibyte_p' in the struct
glyph. */
int saved_multibyte_p = it->multibyte_p;
/* Maybe translate single-byte characters to multibyte, or the
other way. */
it->char_to_display = it->c;
if (!ASCII_BYTE_P (it->c))
{
if (unibyte_display_via_language_environment
&& SINGLE_BYTE_CHAR_P (it->c)
&& (it->c >= 0240
|| !NILP (Vnonascii_translation_table)))
{
it->char_to_display = unibyte_char_to_multibyte (it->c);
it->multibyte_p = 1;
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
}
else if (!SINGLE_BYTE_CHAR_P (it->c)
&& !it->multibyte_p)
{
it->multibyte_p = 1;
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
}
}
/* Get font to use. Encode IT->char_to_display. */
x_get_char_face_and_encoding (it->f, it->char_to_display,
it->face_id, &char2b,
it->multibyte_p, 0);
font = face->font;
/* When no suitable font found, use the default font. */
font_not_found_p = font == NULL;
if (font_not_found_p)
{
font = FRAME_FONT (it->f);