/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999
+ Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "charset.h"
#include "ccl.h"
#include "frame.h"
-#include "fontset.h"
#include "dispextern.h"
+#include "fontset.h"
#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
int *, int *, int *));
static void note_mode_line_highlight P_ ((struct window *, int, int));
-static void x_check_font P_ ((struct frame *, XFontStruct *));
static void note_mouse_highlight P_ ((struct frame *, int, int));
static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
static void XTframe_rehighlight P_ ((struct frame *));
static void x_frame_rehighlight P_ ((struct x_display_info *));
static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
XRectangle *));
static void expose_frame P_ ((struct frame *, int, int, int, int));
static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
struct glyph *,
- XChar2b *));
+ XChar2b *,
+ int *));
static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
int, XChar2b *, int));
static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
int, int, double));
static void x_produce_glyphs P_ ((struct it *));
static void x_produce_image_glyph P_ ((struct it *it));
-
+
/* Return a pointer to per-char metric information in FONT of a
character pointed by B which is a pointer to an XChar2b. */
: &((font)->max_bounds))
-/* 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. */
+/* 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)
pcm = &font->max_bounds;
}
-
- if (pcm == NULL || pcm->width == 0)
- {
- /* Character not contained in the font. FONT->default_char
- gives the character that will be printed. FONT->default_char
- is a 16-bit character code with byte1 in the most significant
- byte and byte2 in the least significant byte. */
- XChar2b default_char;
- default_char.byte1 = (font->default_char >> BITS_PER_CHAR) & 0xff;
- default_char.byte2 = font->default_char & 0xff;
-
- /* Avoid an endless recursion if FONT->default_char itself
- hasn't per char metrics. handa@etl.go.jp reports that some
- fonts have this problem. */
- if (default_char.byte1 != char2b->byte1
- || default_char.byte2 != char2b->byte2)
- pcm = x_per_char_metric (font, &default_char);
- else
- pcm = &font->max_bounds;
- }
-
- return pcm;
+ return ((pcm == NULL
+ || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
+ ? NULL : pcm);
}
/* We assume that MSBs are appropriately set/reset by CCL
program. */
if (font->max_byte1 == 0) /* 1-byte font */
- char2b->byte2 = ccl->reg[1];
+ char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
else
char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
}
sure to use a face suitable for unibyte. */
char2b->byte1 = 0;
char2b->byte2 = c;
-
- if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
- {
- face_id = FACE_FOR_CHARSET (f, face_id, -1);
- face = FACE_FROM_ID (f, face_id);
- }
+ 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)
{
else
char2b->byte1 = 0, char2b->byte2 = c1;
- /* Get the face for displaying C. If `face' is not suitable for
- charset, get the one that fits. (This can happen for the
- translations of a composition where the glyph
- specifies a face for the first component, but the other
- components have a different charset.) */
- if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
- {
- face_id = FACE_FOR_CHARSET (f, face_id, charset);
- face = FACE_FROM_ID (f, face_id);
- }
-
/* Maybe encode the character in *CHAR2B. */
- if (charset != CHARSET_ASCII)
+ 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);
- if (charset == charset_latin_iso8859_1)
- {
- xassert (((XFontStruct *) font_info->font)->max_char_or_byte2
- >= 0x80);
- char2b->byte2 |= 0x80;
- }
- }
+ x_encode_char (c, char2b, font_info);
}
}
a pointer to a realized face that is ready for display. */
static INLINE struct face *
-x_get_glyph_face_and_encoding (f, glyph, char2b)
+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
if (font_info)
{
x_encode_char (glyph->u.ch, char2b, font_info);
- if (charset == charset_latin_iso8859_1)
- char2b->byte2 |= 0x80;
+ if (two_byte_p)
+ *two_byte_p
+ = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
}
}
}
glyph->multibyte_p = it->multibyte_p;
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
+ glyph->glyph_not_available_p = it->glyph_not_available_p;
++it->glyph_row->used[area];
}
}
PREPARE_FACE_FOR_DISPLAY (it->f, face);
prepare_image_for_display (it->f, img);
- it->ascent = it->phys_ascent = IMAGE_ASCENT (img);
+ it->ascent = it->phys_ascent = image_ascent (img, face);
it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
it->pixel_width = img->width + 2 * img->margin;
struct it *it;
{
/* (space :width WIDTH :height HEIGHT. */
- extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
+#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;
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;
+ 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 */
- /* Maybe translate single-byte characters to multibyte. */
+ /* Maybe translate single-byte characters to multibyte, or the
+ other way. */
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))))
+ if (!ASCII_BYTE_P (it->c))
{
- it->char_to_display = unibyte_char_to_multibyte (it->c);
- it->charset = CHAR_CHARSET (it->char_to_display);
+ 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->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->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+ face = FACE_FROM_ID (it->f, it->face_id);
+ }
}
- /* Get face and font to use. Encode IT->char_to_display. */
- face = x_get_char_face_and_encoding (it->f, it->char_to_display,
- it->face_id, &char2b,
- it->multibyte_p);
+ /* 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. */
pcm = x_per_char_metric (font, &char2b);
it->ascent = font->ascent + boff;
it->descent = font->descent - boff;
- it->phys_ascent = pcm->ascent + boff;
- it->phys_descent = pcm->descent - boff;
- it->pixel_width = pcm->width;
+
+ 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->ascent + boff;
+ it->phys_descent = font->descent - boff;
+ it->pixel_width = FONT_WIDTH (font);
+ }
/* If this is a space inside a region of text with
`space-width' property, change its width. */
/* 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->lbearing < 0
- || pcm->rbearing > pcm->width)
+ if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
it->glyph_row->contains_overlapping_glyphs_p = 1;
}
}
else if (it->char_to_display == '\t')
{
int tab_width = it->tab_width * CANON_X_UNIT (it->f);
- int x = (it->current_x
- - it->prompt_width
- + it->continuation_lines_width);
+ int x = it->current_x + it->continuation_lines_width;
int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
it->pixel_width = next_tab_x - x;
from the charset width; this is what old redisplay code
did. */
pcm = x_per_char_metric (font, &char2b);
- it->pixel_width = pcm->width;
- if (font_not_found_p)
- it->pixel_width *= CHARSET_WIDTH (it->charset);
+ 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->ascent + boff;
+ it->phys_descent = font->descent - 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->ascent + boff;
it->descent = font->descent - boff;
- 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;
-
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
glyph matrix. There are no padding glyphs. */
XChar2b char2b;
XFontStruct *font;
- struct face *face;
+ struct face *face = FACE_FROM_ID (it->f, it->face_id);
XCharStruct *pcm;
int font_not_found_p;
struct font_info *font_info;
&& !NILP (Vnonascii_translation_table))))
{
it->char_to_display = unibyte_char_to_multibyte (it->c);
- it->charset = CHAR_CHARSET (it->char_to_display);
}
/* Get face and font to use. Encode IT->char_to_display. */
- face = x_get_char_face_and_encoding (it->f, it->char_to_display,
- it->face_id, &char2b,
- it->multibyte_p);
+ 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. */
int font_descent = font->descent - boff;
/* Bounding box of the overall glyphs. */
int leftmost, rightmost, lowest, highest;
- int i;
+ int i, width, ascent, descent;
cmp->font = (void *) font;
/* Initialize the bounding box. */
pcm = x_per_char_metric (font, &char2b);
+ if (pcm)
+ {
+ width = pcm->width;
+ ascent = pcm->ascent;
+ descent = pcm->descent;
+ }
+ else
+ {
+ width = FONT_WIDTH (font);
+ ascent = font->ascent;
+ descent = font->descent;
+ }
+
+ rightmost = width;
+ lowest = - descent + boff;
+ highest = ascent + boff;
leftmost = 0;
- rightmost = pcm->width;
- lowest = - pcm->descent + boff;
- highest = pcm->ascent + boff;
+
if (font_info
&& font_info->default_ascent
&& CHAR_TABLE_P (Vuse_default_ascent)
{
int left, right, btm, top;
int ch = COMPOSITION_GLYPH (cmp, i);
-
- face = x_get_char_face_and_encoding (it->f, ch,
- it->face_id, &char2b,
- it->multibyte_p);
+ 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)
{
}
pcm = x_per_char_metric (font, &char2b);
+ if (pcm)
+ {
+ width = pcm->width;
+ ascent = pcm->ascent;
+ descent = pcm->descent;
+ }
+ else
+ {
+ width = FONT_WIDTH (font);
+ ascent = font->ascent;
+ descent = font->descent;
+ }
if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
{
/* Relative composition with or without
alternate chars. */
- left = (leftmost + rightmost - pcm->width) / 2;
- btm = - pcm->descent + boff;
+ 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 (- pcm->descent
- >= font_info->relative_compose)
+ if (- descent >= font_info->relative_compose)
/* One extra pixel between two glyphs. */
btm = highest + 1;
- else if (pcm->ascent <= 0)
+ else if (ascent <= 0)
/* One extra pixel between two glyphs. */
- btm = lowest - 1 - pcm->ascent - pcm->descent;
+ btm = lowest - 1 - ascent - descent;
}
}
else
left = (leftmost
+ grefx * (rightmost - leftmost) / 2
- - nrefx * pcm->width / 2);
+ - nrefx * width / 2);
btm = ((grefy == 0 ? highest
: grefy == 1 ? 0
: grefy == 2 ? lowest
: (highest + lowest) / 2)
- - (nrefy == 0 ? pcm->ascent + pcm->descent
- : nrefy == 1 ? pcm->descent - boff
+ - (nrefy == 0 ? ascent + descent
+ : nrefy == 1 ? descent - boff
: nrefy == 2 ? 0
- : (pcm->ascent + pcm->descent) / 2));
+ : (ascent + descent) / 2));
}
cmp->offsets[i * 2] = left;
- cmp->offsets[i * 2 + 1] = btm + pcm->descent;
+ cmp->offsets[i * 2 + 1] = btm + descent;
/* Update the bounding box of the overall glyphs. */
- right = left + pcm->width;
- top = btm + pcm->descent + pcm->ascent;
+ right = left + width;
+ top = btm + descent + ascent;
if (left < leftmost)
leftmost = left;
if (right > rightmost)
else if (it->what == IT_STRETCH)
x_produce_stretch_glyph (it);
- /* Accumulate dimensions. */
- xassert (it->ascent >= 0 && it->descent > 0);
+ /* 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);
XChar2b *char2b;
int nchars;
- /* Character set of this glyph string. */
- int charset;
-
/* A face-override for drawing cursors, mouse face and similar. */
enum draw_glyphs_face hl;
static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
enum glyph_row_area));
+#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. */
struct glyph_string *s;
{
int face_id;
+ struct face *face;
/* What face has to be used for the mouse face? */
face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
- face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
+ face = FACE_FROM_ID (s->f, 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);
struct frame *f;
int *left, *right;
{
- int c;
-
*left = *right = 0;
if (glyph->type == CHAR_GLYPH)
struct face *face;
struct font_info *font_info;
XChar2b char2b;
-
- face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
+ XCharStruct *pcm;
+
+ face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
font = face->font;
font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
- if (font)
+ if (font
+ && (pcm = x_per_char_metric (font, &char2b)))
{
- XCharStruct *pcm = x_per_char_metric (font, &char2b);
-
if (pcm->rbearing > pcm->width)
*right = pcm->rbearing - pcm->width;
if (pcm->lbearing < 0)
#ifdef USE_X_TOOLKIT
-/* Allocate the color COLOR->pixel on the screen and display of
- widget WIDGET in colormap CMAP. If an exact match cannot be
- allocated, try the nearest color available. Value is non-zero
- if successful. This is called from lwlib. */
+static struct frame *x_frame_of_widget P_ ((Widget));
-int
-x_alloc_nearest_color_for_widget (widget, cmap, color)
+
+/* Return the frame on which widget WIDGET is used.. Abort if frame
+ cannot be determined. */
+
+struct frame *
+x_frame_of_widget (widget)
Widget widget;
- Colormap cmap;
- XColor *color;
{
- struct frame *f;
struct x_display_info *dpyinfo;
Lisp_Object tail;
-
+ struct frame *f;
+
dpyinfo = x_display_info_for_display (XtDisplay (widget));
/* Find the top-level shell of the widget. Note that this function
(f->output_data.nothing != 1
&& FRAME_X_DISPLAY_INFO (f) == dpyinfo))
&& f->output_data.x->widget == widget)
- return x_alloc_nearest_color (f, cmap, color);
+ return f;
abort ();
}
+
+/* Allocate the color COLOR->pixel on the screen and display of
+ widget WIDGET in colormap CMAP. If an exact match cannot be
+ allocated, try the nearest color available. Value is non-zero
+ if successful. This is called from lwlib. */
+
+int
+x_alloc_nearest_color_for_widget (widget, cmap, color)
+ Widget widget;
+ Colormap cmap;
+ XColor *color;
+{
+ struct frame *f = x_frame_of_widget (widget);
+ return x_alloc_nearest_color (f, cmap, color);
+}
+
+
#endif /* USE_X_TOOLKIT */
rc = XAllocColor (display, cmap, color);
}
+#ifdef DEBUG_X_COLORS
+ if (rc)
+ register_color (color->pixel);
+#endif /* DEBUG_X_COLORS */
+
return rc;
}
+/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
+ It's necessary to do this instead of just using PIXEL directly to
+ get color reference counts right. */
+
+unsigned long
+x_copy_color (f, pixel)
+ struct frame *f;
+ unsigned long pixel;
+{
+ XColor color;
+
+ color.pixel = pixel;
+ BLOCK_INPUT;
+ XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
+ XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
+ UNBLOCK_INPUT;
+#ifdef DEBUG_X_COLORS
+ register_color (pixel);
+#endif
+ return color.pixel;
+}
+
+
+/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
+ It's necessary to do this instead of just using PIXEL directly to
+ get color reference counts right. */
+
+unsigned long
+x_copy_dpy_color (dpy, cmap, pixel)
+ Display *dpy;
+ Colormap cmap;
+ unsigned long pixel;
+{
+ XColor color;
+
+ color.pixel = pixel;
+ BLOCK_INPUT;
+ XQueryColor (dpy, cmap, &color);
+ XAllocColor (dpy, cmap, &color);
+ UNBLOCK_INPUT;
+#ifdef DEBUG_X_COLORS
+ register_color (pixel);
+#endif
+ return color.pixel;
+}
+
+
/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
or DELTA. Try a color with RGB values multiplied by FACTOR first.
If this produces the same color as PIXEL, try a color where all RGB
{
/* If we end up with the same color as before, try adding
delta to the RGB values. */
- int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
-
- /* If display has an immutable color map, freeing colors is
- not necessary and some servers don't allow it. So don't
- do it. */
- if (class != StaticColor
- && class != StaticGray
- && class != TrueColor)
- XFreeColors (display, cmap, &new.pixel, 1, 0);
+ x_free_colors (f, &new.pixel, 1);
new.red = min (0xffff, delta + color.red);
new.green = min (0xffff, delta + color.green);
unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
unsigned long pixel;
unsigned long background = di->relief_background;
- Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ Colormap cmap = FRAME_X_COLORMAP (f);
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Display *dpy = FRAME_X_DISPLAY (f);
if (relief->gc
&& relief->allocated_p)
{
- /* If display has an immutable color map, freeing colors is not
- necessary and some servers don't allow it. So don't do it. */
- int class = dpyinfo->visual->class;
- if (class != StaticColor
- && class != StaticGray
- && class != TrueColor)
- XFreeColors (dpy, cmap, &relief->pixel, 1, 0);
+ x_free_colors (f, &relief->pixel, 1);
relief->allocated_p = 0;
}
struct glyph_string *s;
{
int x;
- int y = s->ybase - IMAGE_ASCENT (s->img);
+ 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. */
int x0, y0, x1, y1, thick, raised_p;
XRectangle r;
int x;
- int y = s->ybase - IMAGE_ASCENT (s->img);
+ 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. */
Pixmap pixmap;
{
int x;
- int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
+ 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. */
{
struct glyph *glyph, *last;
int voffset;
+ int glyph_not_available_p;
xassert (s->f == XFRAME (s->w->frame));
xassert (s->nchars == 0);
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 charset, nowadays. */
- && glyph->face_id == face_id)
+ /* 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);
- if (s->char2b[s->nchars].byte2 != 0)
- s->two_byte_p = 1;
-
+ 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;
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)
+ if (s->font == NULL || glyph_not_available_p)
{
s->font_not_found_p = 1;
s->font = FRAME_FONT (s->f);
#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
do \
{ \
- int c, charset, face_id; \
+ int c, face_id; \
XChar2b *char2b; \
\
c = (ROW)->glyphs[AREA][START].u.ch; \
- charset = CHAR_CHARSET (c); \
face_id = (ROW)->glyphs[AREA][START].face_id; \
\
s = (struct glyph_string *) alloca (sizeof *s); \
char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
x_append_glyph_string (&HEAD, &TAIL, s); \
- s->charset = charset; \
s->x = (X); \
START = x_fill_glyph_string (s, face_id, START, END, \
OVERLAPS_P); \
do { \
int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
int face_id = (ROW)->glyphs[AREA][START].face_id; \
+ struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
struct composition *cmp = composition_table[cmp_id]; \
int glyph_len = cmp->glyph_len; \
XChar2b *char2b; \
struct glyph_string *first_s = NULL; \
int n; \
\
+ base_face = base_face->ascii_face; \
char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
/* At first, fill in `char2b' and `faces'. */ \
for (n = 0; n < glyph_len; n++) \
{ \
int c = COMPOSITION_GLYPH (cmp, n); \
- faces[n] = x_get_char_face_and_encoding (XFRAME (w->frame), c, \
- face_id, char2b + n, 1); \
+ int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
+ faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
+ x_get_char_face_and_encoding (XFRAME (w->frame), c, \
+ this_face_id, char2b + n, 1); \
} \
\
/* Make glyph_strings for each glyph sequence that is drawable by \
x_append_glyph_string (&(HEAD), &(TAIL), s); \
s->cmp = cmp; \
s->gidx = n; \
- s->charset = 0; \
s->x = (X); \
\
if (n == 0) \
int *hpos, *vpos, *area;
{
struct glyph *glyph, *end;
- struct glyph_row *row;
+ struct glyph_row *row = NULL;
int x0, i, left_area_width;
/* Find row containing Y. Give up if some row is not enabled. */
return;
#endif
- if (disable_mouse_highlight)
+ if (disable_mouse_highlight
+ || !f->glyphs_initialized_p)
return;
dpyinfo->mouse_face_mouse_x = x;
best_row = row;
best_row_vpos = row_vpos;
}
+
+ if (row->y + row->height >= yb)
+ break;
++row;
++row_vpos;
ev->display = FRAME_X_DISPLAY (f);
ev->window = FRAME_X_WINDOW (f);
ev->format = 32;
- ev->data.l[0] = (long) window;
+ ev->data.l[0] = (long) XFASTINT (window);
ev->data.l[1] = (long) part;
ev->data.l[2] = (long) 0;
ev->data.l[3] = (long) portion;
struct input_event *ievent;
{
XClientMessageEvent *ev = (XClientMessageEvent *) event;
- Lisp_Object window = (Lisp_Object) ev->data.l[0];
- struct frame *f = XFRAME (XWINDOW (window)->frame);
+ Lisp_Object window;
+ struct frame *f;
+
+ XSETFASTINT (window, ev->data.l[0]);
+ f = XFRAME (XWINDOW (window)->frame);
ievent->kind = scroll_bar_click;
ievent->frame_or_window = window;
{
#ifdef HAVE_XAW3D
ScrollbarWidget sb = (ScrollbarWidget) widget;
- int scroll_mode;
+ int scroll_mode = 0;
/* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
if (xaw3d_arrow_scroll)
{
XNextEvent (dpyinfo->display, &event);
- if (display_busy_cursor_p)
- {
- /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
- display until the next X event is read and we come
- here again. Setting it to 1 inhibits busy-cursor
- display for direct commands. */
- if (event.type == MotionNotify
- || event.type == EnterNotify
- || (dpyinfo->grabbed
- && event.type != ButtonRelease))
- inhibit_busy_cursor = 2;
- else
- inhibit_busy_cursor = 1;
- }
-
#ifdef HAVE_X_I18N
{
/* Filter events for the current X input method.
else if (event.xclient.message_type
== dpyinfo->Xatom_Scrollbar)
{
- if (display_busy_cursor_p)
- inhibit_busy_cursor = 2;
x_scroll_bar_to_input_event (&event, bufp);
++bufp, ++count, --numchars;
goto out;
if (status_return == XLookupNone)
break;
else if (status_return == XLookupChars)
- keysym = NoSymbol;
+ {
+ keysym = NoSymbol;
+ modifiers = 0;
+ }
else if (status_return != XLookupKeySym
&& status_return != XLookupBoth)
abort ();
bufp++;
count++;
numchars--;
-
- if (display_busy_cursor_p)
- if (keysym != XK_Return || minibuf_level == 0)
- inhibit_busy_cursor = 2;
}
else if (numchars > nbytes)
{
else
abort ();
}
+#ifdef HAVE_X_I18N
+ /* Don't dispatch this event since XtDispatchEvent calls
+ XFilterEvent, and two calls in a row may freeze the
+ client. */
+ break;
+#else
goto OTHER;
+#endif
case KeyRelease:
+#ifdef HAVE_X_I18N
+ /* Don't dispatch this event since XtDispatchEvent calls
+ XFilterEvent, and two calls in a row may freeze the
+ client. */
+ break;
+#else
goto OTHER;
+#endif
/* Here's a possible interpretation of the whole
FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
if (event.xfocus.detail != NotifyPointer)
dpyinfo->x_focus_event_frame = f;
if (f)
- x_new_focus_frame (dpyinfo, f);
+ {
+ x_new_focus_frame (dpyinfo, f);
+
+ /* Don't stop displaying the initial startup message
+ for a switch-frame event we don't need. */
+ if (GC_NILP (Vterminal_frame)
+ && GC_CONSP (Vframe_list)
+ && !GC_NILP (XCDR (Vframe_list)))
+ {
+ bufp->kind = FOCUS_IN_EVENT;
+ XSETFRAME (bufp->frame_or_window, f);
+ ++bufp, ++count, --numchars;
+ }
+ }
#ifdef HAVE_X_I18N
if (f && FRAME_XIC (f))
if (!tool_bar_p)
last_tool_bar_item = -1;
- if (display_busy_cursor_p)
- inhibit_busy_cursor = 2;
}
else
{
--gerd. */
static void
-x_draw_bar_cursor (w, row)
+x_draw_bar_cursor (w, row, width)
struct window *w;
struct glyph_row *row;
+ int width;
{
/* If cursor hpos is out of bounds, don't draw garbage. This can
happen in mini-buffer windows when switching between echo area
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
}
+ if (width < 0)
+ width = f->output_data.x->cursor_width;
+
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
x_clip_to_row (w, row, gc, 0);
XFillRectangle (dpy, window, gc,
x,
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
- min (cursor_glyph->pixel_width,
- f->output_data.x->cursor_width),
+ min (cursor_glyph->pixel_width, width),
row->height);
XSetClipMask (dpy, gc, None);
}
/* If the cursor is in the mouse face area, redisplay that when
we clear the cursor. */
- if (w == XWINDOW (dpyinfo->mouse_face_window)
+ if (! NILP (dpyinfo->mouse_face_window)
+ && w == XWINDOW (dpyinfo->mouse_face_window)
&& (vpos > dpyinfo->mouse_face_beg_row
|| (vpos == dpyinfo->mouse_face_beg_row
&& hpos >= dpyinfo->mouse_face_beg_col))
{
struct frame *f = XFRAME (w->frame);
int new_cursor_type;
+ int new_cursor_width;
struct glyph_matrix *current_glyphs;
struct glyph_row *glyph_row;
struct glyph *glyph;
the cursor type given by the frame parameter. If explicitly
marked off, draw no cursor. In all other cases, we want a hollow
box cursor. */
+ new_cursor_width = -1;
if (cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f)
&& EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
if (w != XWINDOW (selected_window)
|| f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
{
- if (MINI_WINDOW_P (w))
+ extern int cursor_in_non_selected_windows;
+
+ if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
new_cursor_type = NO_CURSOR;
else
new_cursor_type = HOLLOW_BOX_CURSOR;
else if (w->cursor_off_p)
new_cursor_type = NO_CURSOR;
else
- new_cursor_type = FRAME_DESIRED_CURSOR (f);
+ {
+ struct buffer *b = XBUFFER (w->buffer);
+
+ if (EQ (b->cursor_type, Qt))
+ new_cursor_type = FRAME_DESIRED_CURSOR (f);
+ else
+ new_cursor_type = x_specified_cursor_type (b->cursor_type,
+ &new_cursor_width);
+ }
}
/* If cursor is currently being shown and we don't want it to be or
break;
case BAR_CURSOR:
- x_draw_bar_cursor (w, glyph_row);
+ x_draw_bar_cursor (w, glyph_row, new_cursor_width);
break;
case NO_CURSOR:
default:
abort ();
}
+
+#ifdef HAVE_X_I18N
+ if (w == XWINDOW (f->selected_window))
+ if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
+ xic_set_preeditarea (w, x, y);
+#endif
}
#ifndef XFlush
{
BLOCK_INPUT;
x_display_and_set_cursor (w, on, hpos, vpos, x, y);
-
-#ifdef HAVE_X_I18N
- {
- struct frame *f = XFRAME (w->frame);
-
- if (w == XWINDOW (f->selected_window))
- if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
- xic_set_preeditarea (w, x, y);
- }
-#endif
-
UNBLOCK_INPUT;
}
struct window *w;
int on;
{
- BLOCK_INPUT;
- x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
- w->phys_cursor.x, w->phys_cursor.y);
- UNBLOCK_INPUT;
+ /* Don't update cursor in windows whose frame is in the process
+ of being deleted. */
+ if (w->current_matrix)
+ {
+ BLOCK_INPUT;
+ x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
+ w->phys_cursor.x, w->phys_cursor.y);
+ UNBLOCK_INPUT;
+ }
}
/* Indicate that this display is dead. */
+#if 0 /* Closing the display caused a bus error on OpenWindows. */
#ifdef USE_X_TOOLKIT
XtCloseDisplay (display);
+#endif
#endif
- dpyinfo->display = 0;
+ if (dpyinfo)
+ dpyinfo->display = 0;
/* First delete frames whose mini-buffers are on frames
that are on the dead display. */
register char *fontname;
{
struct font_info *fontp
- = fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1);
+ = FS_LOAD_FONT (f, 0, fontname, -1);
if (!fontp)
return Qnil;
struct frame *f;
char *fontsetname;
{
- int fontset = fs_query_fontset (f, fontsetname);
- struct fontset_info *fontsetp;
+ int fontset = fs_query_fontset (build_string (fontsetname), 0);
Lisp_Object result;
if (fontset < 0)
if (f->output_data.x->fontset == fontset)
/* This fontset is already set in frame F. There's nothing more
to do. */
- return build_string (fontsetname);
+ return fontset_name (fontset);
- fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-
- if (!fontsetp->fontname[CHARSET_ASCII])
- /* This fontset doesn't contain ASCII font. */
- return Qnil;
-
- result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
+ result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
if (!STRINGP (result))
/* Can't load ASCII font. */
/* Since x_new_font doesn't update any fontset information, do it now. */
f->output_data.x->fontset = fontset;
- FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
- CHARSET_ASCII, fontsetp->fontname[CHARSET_ASCII], fontset);
#ifdef HAVE_X_I18N
if (FRAME_XIC (f)
&& (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
- xic_set_xfontset (f, fontsetp->fontname[CHARSET_ASCII]);
+ xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
#endif
return build_string (fontsetname);
if (xim)
{
- XIMValuesList *xim_values_list;
#ifdef HAVE_X11R6
XIMCallback destroy;
#endif
}
-#ifdef HAVE_X11R6
+#ifdef HAVE_X11R6_XIM
struct xim_inst_t
{
}
}
-#endif /* HAVE_X11R6 */
+#endif /* HAVE_X11R6_XIM */
/* Open a connection to the XIM server on display DPYINFO.
struct x_display_info *dpyinfo;
char *resource_name;
{
-#ifdef HAVE_X11R6
+#ifdef HAVE_X11R6_XIM
struct xim_inst_t *xim_inst;
int len;
XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
resource_name, EMACS_CLASS,
xim_instantiate_callback,
- (XPointer)xim_inst);
-#else /* not HAVE_X11R6 */
+ /* Fixme: This is XPointer in
+ XFree86 but (XPointer *) on
+ Tru64, at least. */
+ (XPointer) xim_inst);
+#else /* not HAVE_X11R6_XIM */
dpyinfo->xim = NULL;
xim_open_dpy (dpyinfo, resource_name);
-#endif /* not HAVE_X11R6 */
+#endif /* not HAVE_X11R6_XIM */
}
xim_close_dpy (dpyinfo)
struct x_display_info *dpyinfo;
{
-#ifdef HAVE_X11R6
+#ifdef HAVE_X11R6_XIM
XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
NULL, EMACS_CLASS,
xim_instantiate_callback, NULL);
-#endif /* HAVE_X11R6 */
+#endif /* not HAVE_X11R6_XIM */
XCloseIM (dpyinfo->xim);
dpyinfo->xim = NULL;
XFree (dpyinfo->xim_styles);
}
-#endif /* HAVE_X_I18N */
+#endif /* not HAVE_X11R6_XIM */
\f
{
Window newroot, newparent = 0xdeadbeef;
Window *newchildren;
- int nchildren;
+ unsigned int nchildren;
if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
&newparent, &newchildren, &nchildren))
/* It could be confusing if a real alarm arrives while
processing the fake one. Turn it off and let the
handler reset it. */
+ extern void poll_for_input_1 P_ ((void));
int old_poll_suppress_count = poll_suppress_count;
poll_suppress_count = 1;
poll_for_input_1 ();
free_frame_menubar (f);
#endif /* USE_X_TOOLKIT */
+ unload_color (f, f->output_data.x->foreground_pixel);
+ unload_color (f, f->output_data.x->background_pixel);
+ unload_color (f, f->output_data.x->cursor_pixel);
+ unload_color (f, f->output_data.x->cursor_foreground_pixel);
+ unload_color (f, f->output_data.x->border_pixel);
+ unload_color (f, f->output_data.x->mouse_pixel);
+ if (f->output_data.x->scroll_bar_background_pixel != -1)
+ unload_color (f, f->output_data.x->scroll_bar_background_pixel);
+ if (f->output_data.x->scroll_bar_foreground_pixel != -1)
+ unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
+ if (f->output_data.x->white_relief.allocated_p)
+ unload_color (f, f->output_data.x->white_relief.pixel);
+ if (f->output_data.x->black_relief.allocated_p)
+ unload_color (f, f->output_data.x->black_relief.pixel);
+
free_frame_faces (f);
XFlush (FRAME_X_DISPLAY (f));
}
for (; CONSP (patterns); patterns = XCDR (patterns))
{
int num_fonts;
- char **names;
+ char **names = NULL;
pattern = XCAR (patterns);
/* See if we cached the result for this particular query.
/* The slot `encoding' specifies how to map a character
code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
- the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
- the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
- 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
+ the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
+ (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
2:0xA020..0xFF7F). For the moment, we don't know which charset
uses this font. So, we set information in fontp->encoding[1]
which is never used by any charset. If mapping can't be
if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
{
char *vendor = ServerVendor (dpy);
+ UNBLOCK_INPUT;
dpyinfo->kboard->Vsystem_key_alist
= call1 (Qvendor_specific_keysyms,
build_string (vendor ? vendor : ""));
+ BLOCK_INPUT;
}
dpyinfo->kboard->next_kboard = all_kboards;
dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
DefaultScreen (dpyinfo->display));
- dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
- &dpyinfo->n_planes);
+ select_visual (dpyinfo);
+ dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
dpyinfo->height = HeightOfScreen (dpyinfo->screen);
dpyinfo->width = WidthOfScreen (dpyinfo->screen);
dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
dpyinfo->x_highlight_frame = 0;
dpyinfo->image_cache = make_image_cache ();
+ /* See if a private colormap is requested. */
+ if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
+ {
+ if (dpyinfo->visual->class == PseudoColor)
+ {
+ Lisp_Object value;
+ value = display_x_get_resource (dpyinfo,
+ build_string ("privateColormap"),
+ build_string ("PrivateColormap"),
+ Qnil, Qnil);
+ if (STRINGP (value)
+ && (!strcmp (XSTRING (value)->data, "true")
+ || !strcmp (XSTRING (value)->data, "on")))
+ dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
+ }
+ }
+ else
+ dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->visual, AllocNone);
+
{
int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
double pixels = DisplayHeight (dpyinfo->display, screen_number);
#endif
#endif
+ /* See if we should run in synchronous mode. This is useful
+ for debugging X code. */
+ {
+ Lisp_Object value;
+ value = display_x_get_resource (dpyinfo,
+ build_string ("synchronous"),
+ build_string ("Synchronous"),
+ Qnil, Qnil);
+ if (STRINGP (value)
+ && (!strcmp (XSTRING (value)->data, "true")
+ || !strcmp (XSTRING (value)->data, "on")))
+ XSynchronize (dpyinfo->display, True);
+ }
+
UNBLOCK_INPUT;
return dpyinfo;
}
}
+ if (next_noop_dpyinfo == dpyinfo)
+ next_noop_dpyinfo = dpyinfo->next;
+
if (x_display_list == dpyinfo)
x_display_list = dpyinfo->next;
else