leftmost character with special glyphs, which will display as,
well, empty. On text terminals, these special glyphs are simply
blank characters. On graphics terminals, there's a single stretch
- glyph with suitably computed width. Both the blanks and the
+ glyph of a suitably computed width. Both the blanks and the
stretch glyph are given the face of the background of the line.
This way, the terminal-specific back-end can still draw the glyphs
left to right, even for R2L lines.
+ Bidirectional display and character compositions
+
+ Some scripts cannot be displayed by drawing each character
+ individually, because adjacent characters change each other's shape
+ on display. For example, Arabic and Indic scripts belong to this
+ category.
+
+ Emacs display supports this by providing "character compositions",
+ most of which is implemented in composite.c. During the buffer
+ scan that delivers characters to PRODUCE_GLYPHS, if the next
+ character to be delivered is a composed character, the iteration
+ calls composition_reseat_it and next_element_from_composition. If
+ they succeed to compose the character with one or more of the
+ following characters, the whole sequence of characters that where
+ composed is recorded in the `struct composition_it' object that is
+ part of the buffer iterator. The composed sequence could produce
+ one or more font glyphs (called "grapheme clusters") on the screen.
+ Each of these grapheme clusters is then delivered to PRODUCE_GLYPHS
+ in the direction corresponding to the current bidi scan direction
+ (recorded in the scan_dir member of the `struct bidi_it' object
+ that is part of the buffer iterator). In particular, if the bidi
+ iterator currently scans the buffer backwards, the grapheme
+ clusters are delivered back to front. This reorders the grapheme
+ clusters as appropriate for the current bidi context. Note that
+ this means that the grapheme clusters are always stored in the
+ LGSTRING object (see composite.c) in the logical order.
+
+ Moving an iterator in bidirectional text
+ without producing glyphs
+
Note one important detail mentioned above: that the bidi reordering
engine, driven by the iterator, produces characters in R2L rows
starting at the character that will be the rightmost on display.
#ifdef HAVE_WINDOW_SYSTEM
#define CLEAR_IMAGE_CACHE_COUNT 101
static int clear_image_cache_count;
+
+/* Null glyph slice */
+static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
#endif
/* Non-zero while redisplay_internal is in progress. */
Lisp_Object previous_help_echo_string;
-/* Null glyph slice */
-
-static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
-
/* Platform-independent portion of hourglass implementation. */
/* Non-zero means we're allowed to display a hourglass pointer. */
/* Number of seconds to wait before displaying an hourglass cursor. */
Lisp_Object Vhourglass_delay;
+/* Name of the face used to display glyphless characters. */
+Lisp_Object Qglyphless_char;
+
+/* Char-table to control the display of glyphless characters. */
+Lisp_Object Vglyphless_char_display;
+
+/* Symbol for the purpose of Vglyphless_char_display. */
+Lisp_Object Qglyphless_char_display;
+
+/* Method symbols for Vglyphless_char_display. */
+static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width;
+
+/* Default pixel width of `thin-space' display method. */
+#define THIN_SPACE_WIDTH 1
+
/* Default number of seconds to wait before displaying an hourglass
cursor. */
#define DEFAULT_HOURGLASS_DELAY 1
EMACS_INT, EMACS_INT);
static void store_mode_line_noprop_char (char);
static int store_mode_line_noprop (const unsigned char *, int, int);
-static void x_consider_frame_title (Lisp_Object);
static void handle_stop (struct it *);
static void handle_stop_backwards (struct it *, EMACS_INT);
-static int tool_bar_lines_needed (struct frame *, int *);
static int single_display_spec_intangible_p (Lisp_Object);
static void ensure_echo_area_buffers (void);
static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object);
#ifdef HAVE_WINDOW_SYSTEM
+static void x_consider_frame_title (Lisp_Object);
+static int tool_bar_lines_needed (struct frame *, int *);
static void update_tool_bar (struct frame *, int);
static void build_desired_tool_bar_string (struct frame *f);
static int redisplay_tool_bar (struct frame *);
int, int, int, int);
static void append_stretch_glyph (struct it *, Lisp_Object,
int, int, int);
-static int coords_in_mouse_face_p (struct window *, int, int);
-
#endif /* HAVE_WINDOW_SYSTEM */
+static int coords_in_mouse_face_p (struct window *, int, int);
+
+
\f
/***********************************************************************
Window display dimensions
}
-/* Return the next character from STR which is MAXLEN bytes long.
- Return in *LEN the length of the character. This is like
- STRING_CHAR_AND_LENGTH but never returns an invalid character. If
- we find one, we return a `?', but with the length of the invalid
- character. */
+/* Return the next character from STR. Return in *LEN the length of
+ the character. This is like STRING_CHAR_AND_LENGTH but never
+ returns an invalid character. If we find one, we return a `?', but
+ with the length of the invalid character. */
static INLINE int
string_char_and_length (const unsigned char *str, int *len)
if (STRING_MULTIBYTE (string))
{
- EMACS_INT rest = SBYTES (string) - BYTEPOS (pos);
const unsigned char *p = SDATA (string) + BYTEPOS (pos);
int len;
while (nchars--)
{
string_char_and_length (p, &len);
- p += len, rest -= len;
- xassert (rest >= 0);
+ p += len;
CHARPOS (pos) += 1;
BYTEPOS (pos) += len;
}
if (multibyte_p)
{
- EMACS_INT rest = strlen (s);
int len;
SET_TEXT_POS (pos, 0, 0);
while (charpos--)
{
string_char_and_length (s, &len);
- s += len, rest -= len;
- xassert (rest >= 0);
+ s += len;
CHARPOS (pos) += 1;
BYTEPOS (pos) += len;
}
}
-#ifdef HAVE_WINDOW_SYSTEM
-
/* Find the glyph under window-relative coordinates X/Y in window W.
Consider only glyphs from buffer text, i.e. no glyphs from overlay
strings. Return in *HPOS and *VPOS the row and column number of
return glyph;
}
-
/* EXPORT:
Convert frame-relative x/y to coordinates relative to window W.
Takes pseudo-windows into account. */
}
}
+#ifdef HAVE_WINDOW_SYSTEM
+
/* EXPORT:
Return in RECTS[] at most N clipping rectangles for glyph string S.
Return the number of stored rectangles. */
frame pixel coordinates X/Y on frame F. */
if (!f->glyphs_initialized_p
- || (window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0),
+ || (window = window_from_coordinates (f, gx, gy, &part, 0),
NILP (window)))
{
width = FRAME_SMALLEST_CHAR_WIDTH (f);
width = WINDOW_FRAME_COLUMN_WIDTH (w);
height = WINDOW_FRAME_LINE_HEIGHT (w);
+ x = window_relative_x_coord (w, part, gx);
+ y = gy - WINDOW_TOP_EDGE_Y (w);
+
r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
&& it->stop_charpos <= it->end_charpos));
it->current.overlay_string_index = -1;
it->n_overlay_strings = 0;
+ it->overlay_strings_charpos = -1;
/* If we're at the end of the buffer, record that we have
processed the overlay strings there already, so that
/* There are more overlay strings to process. If
IT->current.overlay_string_index has advanced to a position
where we must load IT->overlay_strings with more strings, do
- it. */
+ it. We must load at the IT->overlay_strings_charpos where
+ IT->n_overlay_strings was originally computed; when invisible
+ text is present, this might not be IT_CHARPOS (Bug#7016). */
int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
if (it->current.overlay_string_index && i == 0)
- load_overlay_strings (it, 0);
+ load_overlay_strings (it, it->overlay_strings_charpos);
/* Initialize IT to deliver display elements from the overlay
string. */
if (n > 1)
qsort (entries, n, sizeof *entries, compare_overlay_entries);
- /* Record the total number of strings to process. */
+ /* Record number of overlay strings, and where we computed it. */
it->n_overlay_strings = n;
+ it->overlay_strings_charpos = charpos;
/* IT->current.overlay_string_index is the number of overlay strings
that have already been consumed by IT. Copy some of the
(IT)->string)))
+/* Lookup the char-table Vglyphless_char_display for character C (-1
+ if we want information for no-font case), and return the display
+ method symbol. By side-effect, update it->what and
+ it->glyphless_method. This function is called from
+ get_next_display_element for each character element, and from
+ x_produce_glyphs when no suitable font was found. */
+
+Lisp_Object
+lookup_glyphless_char_display (int c, struct it *it)
+{
+ Lisp_Object glyphless_method = Qnil;
+
+ if (CHAR_TABLE_P (Vglyphless_char_display)
+ && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
+ glyphless_method = (c >= 0
+ ? CHAR_TABLE_REF (Vglyphless_char_display, c)
+ : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
+ retry:
+ if (NILP (glyphless_method))
+ {
+ if (c >= 0)
+ /* The default is to display the character by a proper font. */
+ return Qnil;
+ /* The default for the no-font case is to display an empty box. */
+ glyphless_method = Qempty_box;
+ }
+ if (EQ (glyphless_method, Qzero_width))
+ {
+ if (c >= 0)
+ return glyphless_method;
+ /* This method can't be used for the no-font case. */
+ glyphless_method = Qempty_box;
+ }
+ if (EQ (glyphless_method, Qthin_space))
+ it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
+ else if (EQ (glyphless_method, Qempty_box))
+ it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
+ else if (EQ (glyphless_method, Qhex_code))
+ it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
+ else if (STRINGP (glyphless_method))
+ it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
+ else
+ {
+ /* Invalid value. We use the default method. */
+ glyphless_method = Qnil;
+ goto retry;
+ }
+ it->what = IT_GLYPHLESS;
+ return glyphless_method;
+}
+
/* Load IT's display element fields with information about the next
display element from the current position of IT. Value is zero if
end of buffer (or C string) is reached. */
static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS);
static int last_escape_glyph_merged_face_id = 0;
+struct frame *last_glyphless_glyph_frame = NULL;
+unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
+int last_glyphless_glyph_merged_face_id = 0;
+
int
get_next_display_element (struct it *it)
{
goto get_next;
}
+ if (! NILP (lookup_glyphless_char_display (c, it)))
+ {
+ if (it->what == IT_GLYPHLESS)
+ goto done;
+ /* Don't display this character. */
+ set_iterator_to_next (it, 0);
+ goto get_next;
+ }
+
if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
nbsp_or_shy = (c == 0xA0 ? char_is_nbsp
: c == 0xAD ? char_is_soft_hyphen
}
#endif
+ done:
/* Is this character the last one of a run of characters with
box? If yes, set IT->end_of_box_run_p to 1. */
if (it->face_box_p
Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
+ if (!NILP (current_buffer->bidi_display_reordering))
+ current_buffer->bidi_paragraph_direction = Qleft_to_right;
/* Insert new message at BEG. */
TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
int *hpos, int *vpos, int *prop_idx)
{
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
struct window *w = XWINDOW (f->tool_bar_window);
int area;
return -1;
/* Is mouse on the highlighted item? */
- if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
- && *vpos >= dpyinfo->mouse_face_beg_row
- && *vpos <= dpyinfo->mouse_face_end_row
- && (*vpos > dpyinfo->mouse_face_beg_row
- || *hpos >= dpyinfo->mouse_face_beg_col)
- && (*vpos < dpyinfo->mouse_face_end_row
- || *hpos < dpyinfo->mouse_face_end_col
- || dpyinfo->mouse_face_past_end))
+ if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
+ && *vpos >= hlinfo->mouse_face_beg_row
+ && *vpos <= hlinfo->mouse_face_end_row
+ && (*vpos > hlinfo->mouse_face_beg_row
+ || *hpos >= hlinfo->mouse_face_beg_col)
+ && (*vpos < hlinfo->mouse_face_end_row
+ || *hpos < hlinfo->mouse_face_end_col
+ || hlinfo->mouse_face_past_end))
return 0;
return 1;
handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
unsigned int modifiers)
{
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
struct window *w = XWINDOW (f->tool_bar_window);
int hpos, vpos, prop_idx;
struct glyph *glyph;
if (down_p)
{
/* Show item in pressed state. */
- show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
- dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
+ show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
+ hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
last_tool_bar_item = prop_idx;
}
else
EVENT_INIT (event);
/* Show item in released state. */
- show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
- dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
+ show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
+ hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
Lisp_Object window = f->tool_bar_window;
struct window *w = XWINDOW (window);
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
int hpos, vpos;
struct glyph *glyph;
struct glyph_row *row;
values when mouse moves outside of the frame. */
if (x <= 0 || y <= 0)
{
- clear_mouse_face (dpyinfo);
+ clear_mouse_face (hlinfo);
return;
}
if (rc < 0)
{
/* Not on tool-bar item. */
- clear_mouse_face (dpyinfo);
+ clear_mouse_face (hlinfo);
return;
}
else if (rc == 0)
/* On same tool-bar item as before. */
goto set_help_echo;
- clear_mouse_face (dpyinfo);
+ clear_mouse_face (hlinfo);
/* Mouse is down, but on different tool-bar item? */
mouse_down_p = (dpyinfo->grabbed
&& last_tool_bar_item != prop_idx)
return;
- dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
+ hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
/* If tool-bar item is not enabled, don't highlight it. */
x += row->glyphs[TEXT_AREA][i].pixel_width;
/* Record this as the current active region. */
- dpyinfo->mouse_face_beg_col = hpos;
- dpyinfo->mouse_face_beg_row = vpos;
- dpyinfo->mouse_face_beg_x = x;
- dpyinfo->mouse_face_beg_y = row->y;
- dpyinfo->mouse_face_past_end = 0;
-
- dpyinfo->mouse_face_end_col = hpos + 1;
- dpyinfo->mouse_face_end_row = vpos;
- dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
- dpyinfo->mouse_face_end_y = row->y;
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
+ hlinfo->mouse_face_beg_col = hpos;
+ hlinfo->mouse_face_beg_row = vpos;
+ hlinfo->mouse_face_beg_x = x;
+ hlinfo->mouse_face_beg_y = row->y;
+ hlinfo->mouse_face_past_end = 0;
+
+ hlinfo->mouse_face_end_col = hpos + 1;
+ hlinfo->mouse_face_end_row = vpos;
+ hlinfo->mouse_face_end_x = x + glyph->pixel_width;
+ hlinfo->mouse_face_end_y = row->y;
+ hlinfo->mouse_face_window = window;
+ hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
/* Display it as active. */
- show_mouse_face (dpyinfo, draw);
- dpyinfo->mouse_face_image_state = draw;
+ show_mouse_face (hlinfo, draw);
+ hlinfo->mouse_face_image_state = draw;
}
set_help_echo:
reconsider_clip_changes (w, current_buffer);
last_escape_glyph_frame = NULL;
last_escape_glyph_face_id = (1 << FACE_ID_BITS);
+ last_glyphless_glyph_frame = NULL;
+ last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
/* If new fonts have been loaded that make a glyph matrix adjustment
necessary, do it. */
&& BUFFERP (glyph->object) && glyph->charpos == pt_old)
&& bpos_covered < pt_old)
{
+ /* An empty line has a single glyph whose OBJECT is zero and
+ whose CHARPOS is the position of a newline on that line.
+ Note that on a TTY, there are more glyphs after that, which
+ were produced by extend_face_to_end_of_line, but their
+ CHARPOS is zero or negative. */
+ int empty_line_p =
+ (row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
+ && INTEGERP (glyph->object) && glyph->charpos > 0;
+
if (row->ends_in_ellipsis_p && pos_after == last_pos)
{
EMACS_INT ellipsis_pos;
|| (row->truncated_on_left_p && pt_old < bpos_min)
|| (row->truncated_on_right_p && pt_old > bpos_max)
/* Zero-width characters produce no glyphs. */
- || ((row->reversed_p
- ? glyph_after > glyphs_end
- : glyph_after < glyphs_end)
- && eabs (glyph_after - glyph_before) == 1))
+ || (!string_seen
+ && !empty_line_p
+ && (row->reversed_p
+ ? glyph_after > glyphs_end
+ : glyph_after < glyphs_end)))
{
cursor = glyph_after;
x = -1;
cursor on that character's glyph. */
EMACS_INT strpos = glyph->charpos;
- cursor = glyph;
- for (glyph += incr;
+ if (tem)
+ cursor = glyph;
+ for ( ;
(row->reversed_p ? glyph > stop : glyph < stop)
&& EQ (glyph->object, str);
glyph += incr)
cursor = glyph;
break;
}
- if (glyph->charpos < strpos)
+ if (tem && glyph->charpos < strpos)
{
strpos = glyph->charpos;
cursor = glyph;
}
/* This string is not what we want; skip all of the
glyphs that came from it. */
- do
- glyph += incr;
while ((row->reversed_p ? glyph > stop : glyph < stop)
- && EQ (glyph->object, str));
+ && EQ (glyph->object, str))
+ glyph += incr;
}
else
glyph += incr;
/* If cursor ends up on a partially visible line,
treat that as being off the bottom of the screen. */
- if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0))
+ if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0)
+ /* It's possible that the cursor is on the first line of the
+ buffer, which is partially obscured due to a vscroll
+ (Bug#7537). In that case, avoid looping forever . */
+ && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
{
clear_glyph_matrix (w->desired_matrix);
++extra_scroll_margin_lines;
+ (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
+ window_internal_height (w));
+#if defined (HAVE_GPM) || defined (MSDOS)
+ x_clear_window_mouse_face (w);
+#endif
/* Perform the operation on the screen. */
if (dvpos > 0)
{
}
+/* Fill glyph string S from a sequence glyphs for glyphless characters.
+ See the comment of fill_glyph_string for arguments.
+ Value is the index of the first glyph not in S. */
+
+
+static int
+fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
+ int start, int end, int overlaps)
+{
+ struct glyph *glyph, *last;
+ int voffset;
+
+ xassert (s->first_glyph->type == GLYPHLESS_GLYPH);
+ s->for_overlaps = overlaps;
+ glyph = s->row->glyphs[s->area] + start;
+ last = s->row->glyphs[s->area] + end;
+ voffset = glyph->voffset;
+ s->face = FACE_FROM_ID (s->f, face_id);
+ s->font = s->face->font;
+ s->nchars = 1;
+ s->width = glyph->pixel_width;
+ glyph++;
+ while (glyph < last
+ && glyph->type == GLYPHLESS_GLYPH
+ && glyph->voffset == voffset
+ && glyph->face_id == face_id)
+ {
+ s->nchars++;
+ s->width += glyph->pixel_width;
+ glyph++;
+ }
+ s->ybase += voffset;
+ return glyph - s->row->glyphs[s->area];
+}
+
+
/* 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
} while (0)
+/* Add a glyph string for a sequence of glyphless character's glyphs
+ to the list of strings between HEAD and TAIL. The meanings of
+ arguments are the same as those of BUILD_CHAR_GLYPH_STRINGS. */
+
+#define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+ do \
+ { \
+ int face_id; \
+ XChar2b *char2b; \
+ \
+ face_id = (row)->glyphs[area][START].face_id; \
+ \
+ s = (struct glyph_string *) alloca (sizeof *s); \
+ INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
+ append_glyph_string (&HEAD, &TAIL, s); \
+ s->x = (X); \
+ START = fill_glyphless_glyph_string (s, face_id, START, END, \
+ overlaps); \
+ } \
+ while (0)
+
+
/* Build a list of glyph strings between HEAD and TAIL for the glyphs
of AREA of glyph row ROW on window W between indices START and END.
HL overrides the face for drawing glyph strings, e.g. it is
BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
HL, X, LAST_X); \
break; \
- \
+ \
case COMPOSITE_GLYPH: \
if (first_glyph->u.cmp.automatic) \
BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
HL, X, LAST_X); \
break; \
- \
+ \
case STRETCH_GLYPH: \
BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
HL, X, LAST_X); \
break; \
- \
+ \
case IMAGE_GLYPH: \
BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
HL, X, LAST_X); \
break; \
- \
+ \
+ case GLYPHLESS_GLYPH: \
+ BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
+ HL, X, LAST_X); \
+ break; \
+ \
default: \
abort (); \
} \
- \
+ \
if (s) \
{ \
set_glyph_string_background_width (s, START, LAST_X); \
if (head && !overlaps && row->contains_overlapping_glyphs_p)
{
struct glyph_string *h, *t;
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
int mouse_beg_col, mouse_end_col, check_mouse_face = 0;
int dummy_x = 0;
{
struct glyph_row *mouse_beg_row, *mouse_end_row;
- mouse_beg_row = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
- mouse_end_row = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+ mouse_beg_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
+ mouse_end_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
if (row >= mouse_beg_row && row <= mouse_end_row)
{
check_mouse_face = 1;
mouse_beg_col = (row == mouse_beg_row)
- ? dpyinfo->mouse_face_beg_col : 0;
+ ? hlinfo->mouse_face_beg_col : 0;
mouse_end_col = (row == mouse_end_row)
- ? dpyinfo->mouse_face_end_col
+ ? hlinfo->mouse_face_end_col
: row->used[TEXT_AREA];
}
}
}
+/* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
+ is a face ID to be used for the glyph. FOR_NO_FONT is nonzero if
+ and only if this is for a character for which no font was found.
+
+ If the display method (it->glyphless_method) is
+ GLYPHLESS_DISPLAY_ACRONYM or GLYPHLESS_DISPLAY_HEX_CODE, LEN is a
+ length of the acronym or the hexadecimal string, UPPER_XOFF and
+ UPPER_YOFF are pixel offsets for the upper part of the string,
+ LOWER_XOFF and LOWER_YOFF are for the lower part.
+
+ For the other display methods, LEN through LOWER_YOFF are zero. */
+
+static void
+append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
+ short upper_xoff, short upper_yoff,
+ short lower_xoff, short lower_yoff)
+{
+ 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])
+ {
+ /* If the glyph row is reversed, we need to prepend the glyph
+ rather than append it. */
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ struct glyph *g;
+
+ /* Make room for the additional glyph. */
+ for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
+ g[1] = *g;
+ glyph = it->glyph_row->glyphs[area];
+ }
+ glyph->charpos = CHARPOS (it->position);
+ glyph->object = it->object;
+ glyph->pixel_width = it->pixel_width;
+ glyph->ascent = it->ascent;
+ glyph->descent = it->descent;
+ glyph->voffset = it->voffset;
+ glyph->type = GLYPHLESS_GLYPH;
+ glyph->u.glyphless.method = it->glyphless_method;
+ glyph->u.glyphless.for_no_font = for_no_font;
+ glyph->u.glyphless.len = len;
+ glyph->u.glyphless.ch = it->c;
+ glyph->slice.glyphless.upper_xoff = upper_xoff;
+ glyph->slice.glyphless.upper_yoff = upper_yoff;
+ glyph->slice.glyphless.lower_xoff = lower_xoff;
+ glyph->slice.glyphless.lower_yoff = lower_yoff;
+ glyph->avoid_cursor_p = it->avoid_cursor_p;
+ 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 = face_id;
+ glyph->font_type = FONT_TYPE_UNKNOWN;
+ if (it->bidi_p)
+ {
+ glyph->resolved_level = it->bidi_it.resolved_level;
+ if ((it->bidi_it.type & 7) != it->bidi_it.type)
+ abort ();
+ glyph->bidi_type = it->bidi_it.type;
+ }
+ ++it->glyph_row->used[area];
+ }
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
+}
+
+
+/* Produce a glyph for a glyphless character for iterator IT.
+ IT->glyphless_method specifies which method to use for displaying
+ the character. See the description of enum
+ glyphless_display_method in dispextern.h for the detail.
+
+ FOR_NO_FONT is nonzero if and only if this is for a character for
+ which no font was found. ACRONYM, if non-nil, is an acronym string
+ for the character. */
+
+static void
+produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
+{
+ int face_id;
+ struct face *face;
+ struct font *font;
+ int base_width, base_height, width, height;
+ short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
+ int len;
+
+ /* Get the metrics of the base font. We always refer to the current
+ ASCII face. */
+ face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
+ font = face->font ? face->font : FRAME_FONT (it->f);
+ it->ascent = FONT_BASE (font) + font->baseline_offset;
+ it->descent = FONT_DESCENT (font) - font->baseline_offset;
+ base_height = it->ascent + it->descent;
+ base_width = font->average_width;
+
+ /* Get a face ID for the glyph by utilizing a cache (the same way as
+ doen for `escape-glyph' in get_next_display_element). */
+ if (it->f == last_glyphless_glyph_frame
+ && it->face_id == last_glyphless_glyph_face_id)
+ {
+ face_id = last_glyphless_glyph_merged_face_id;
+ }
+ else
+ {
+ /* Merge the `glyphless-char' face into the current face. */
+ face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
+ last_glyphless_glyph_frame = it->f;
+ last_glyphless_glyph_face_id = it->face_id;
+ last_glyphless_glyph_merged_face_id = face_id;
+ }
+
+ if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
+ {
+ it->pixel_width = THIN_SPACE_WIDTH;
+ len = 0;
+ upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
+ }
+ else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
+ {
+ width = CHAR_WIDTH (it->c);
+ if (width == 0)
+ width = 1;
+ else if (width > 4)
+ width = 4;
+ it->pixel_width = base_width * width;
+ len = 0;
+ upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
+ }
+ else
+ {
+ char buf[7], *str;
+ unsigned int code[6];
+ int upper_len;
+ int ascent, descent;
+ struct font_metrics metrics_upper, metrics_lower;
+
+ face = FACE_FROM_ID (it->f, face_id);
+ font = face->font ? face->font : FRAME_FONT (it->f);
+ PREPARE_FACE_FOR_DISPLAY (it->f, face);
+
+ if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
+ {
+ if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
+ acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
+ str = STRINGP (acronym) ? (char *) SDATA (acronym) : "";
+ }
+ else
+ {
+ xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
+ sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
+ str = buf;
+ }
+ for (len = 0; str[len] && ASCII_BYTE_P (str[len]); len++)
+ code[len] = font->driver->encode_char (font, str[len]);
+ upper_len = (len + 1) / 2;
+ font->driver->text_extents (font, code, upper_len,
+ &metrics_upper);
+ font->driver->text_extents (font, code + upper_len, len - upper_len,
+ &metrics_lower);
+
+
+
+ /* +4 is for vertical bars of a box plus 1-pixel spaces at both side. */
+ width = max (metrics_upper.width, metrics_lower.width) + 4;
+ upper_xoff = upper_yoff = 2; /* the typical case */
+ if (base_width >= width)
+ {
+ /* Align the upper to the left, the lower to the right. */
+ it->pixel_width = base_width;
+ lower_xoff = base_width - 2 - metrics_lower.width;
+ }
+ else
+ {
+ /* Center the shorter one. */
+ it->pixel_width = width;
+ if (metrics_upper.width >= metrics_lower.width)
+ lower_xoff = (width - metrics_lower.width) / 2;
+ else
+ upper_xoff = (width - metrics_upper.width) / 2;
+ }
+
+ /* +5 is for horizontal bars of a box plus 1-pixel spaces at
+ top, bottom, and between upper and lower strings. */
+ height = (metrics_upper.ascent + metrics_upper.descent
+ + metrics_lower.ascent + metrics_lower.descent) + 5;
+ /* Center vertically.
+ H:base_height, D:base_descent
+ h:height, ld:lower_descent, la:lower_ascent, ud:upper_descent
+
+ ascent = - (D - H/2 - h/2 + 1); "+ 1" for rounding up
+ descent = D - H/2 + h/2;
+ lower_yoff = descent - 2 - ld;
+ upper_yoff = lower_yoff - la - 1 - ud; */
+ ascent = - (it->descent - (base_height + height + 1) / 2);
+ descent = it->descent - (base_height - height) / 2;
+ lower_yoff = descent - 2 - metrics_lower.descent;
+ upper_yoff = (lower_yoff - metrics_lower.ascent - 1
+ - metrics_upper.descent);
+ /* Don't make the height shorter than the base height. */
+ if (height > base_height)
+ {
+ it->ascent = ascent;
+ it->descent = descent;
+ }
+ }
+
+ it->phys_ascent = it->ascent;
+ it->phys_descent = it->descent;
+ if (it->glyph_row)
+ append_glyphless_glyph (it, face_id, for_no_font, len,
+ upper_xoff, upper_yoff,
+ lower_xoff, lower_yoff);
+ it->nglyphs = 1;
+ take_vertical_position_into_account (it);
+}
+
+
/* RIF:
Produce glyphs/get display metrics for the display element IT is
loaded with. See the description of struct it in dispextern.h
XChar2b char2b;
struct face *face = FACE_FROM_ID (it->f, it->face_id);
struct font *font = face->font;
- int font_not_found_p = font == NULL;
struct font_metrics *pcm = NULL;
int boff; /* baseline offset */
- if (font_not_found_p)
- {
- /* When no suitable font found, display an empty box based
- on the metrics of the font of the default face (or what
- remapped). */
- struct face *no_font_face
- = FACE_FROM_ID (it->f,
- NILP (Vface_remapping_alist) ? DEFAULT_FACE_ID
- : lookup_basic_face (it->f, DEFAULT_FACE_ID));
- font = no_font_face->font;
- boff = font->baseline_offset;
- }
- else
+ if (font == NULL)
{
- boff = font->baseline_offset;
- if (font->vertical_centering)
- boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+ /* When no suitable font is found, display this character by
+ the method specified in the first extra slot of
+ Vglyphless_char_display. */
+ Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
+
+ xassert (it->what == IT_GLYPHLESS);
+ produce_glyphless_glyph (it, 1, STRINGP (acronym) ? acronym : Qnil);
+ goto done;
}
+ boff = font->baseline_offset;
+ if (font->vertical_centering)
+ boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+
if (it->char_to_display != '\n' && it->char_to_display != '\t')
{
int stretched_p;
it->descent = FONT_DESCENT (font) - boff;
}
- if (! font_not_found_p
- && get_char_glyph_code (it->char_to_display, font, &char2b))
+ if (get_char_glyph_code (it->char_to_display, font, &char2b))
{
pcm = get_per_char_metric (it->f, font, &char2b);
if (pcm->width == 0
if (it->glyph_row)
append_composite_glyph (it);
}
+ else if (it->what == IT_GLYPHLESS)
+ produce_glyphless_glyph (it, 0, Qnil);
else if (it->what == IT_IMAGE)
produce_image_glyph (it);
else if (it->what == IT_STRETCH)
produce_stretch_glyph (it);
+ done:
/* 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);
}
+#ifdef HAVE_WINDOW_SYSTEM
+
/* Return the cursor we want to be displayed in window W. Return
width of bar/hbar cursor through WIDTH arg. Return with
ACTIVE_CURSOR arg set to 1 if cursor in window W is `active'
/* Detect a nonselected window or nonselected frame. */
else if (w != XWINDOW (f->selected_window)
-#ifdef HAVE_WINDOW_SYSTEM
- || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
-#endif
- )
+ || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
{
*active_cursor = 0;
/* Use normal cursor if not blinked off. */
if (!w->cursor_off_p)
{
-#ifdef HAVE_WINDOW_SYSTEM
if (glyph != NULL && glyph->type == IMAGE_GLYPH)
{
if (cursor_type == FILLED_BOX_CURSOR)
cursor_type = HOLLOW_BOX_CURSOR;
}
}
-#endif
return cursor_type;
}
}
-#ifdef HAVE_WINDOW_SYSTEM
-
/* Notice when the text cursor of window W has been completely
overwritten by a drawing operation that outputs glyphs in AREA
starting at X0 and ending at X1 in the line starting at Y0 and
erase_phys_cursor (struct window *w)
{
struct frame *f = XFRAME (w->frame);
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
int hpos = w->phys_cursor.hpos;
int vpos = w->phys_cursor.vpos;
int mouse_face_here_p = 0;
/* If the cursor is in the mouse face area, redisplay that when
we clear the cursor. */
- if (! NILP (dpyinfo->mouse_face_window)
+ if (! NILP (hlinfo->mouse_face_window)
&& coords_in_mouse_face_p (w, hpos, vpos)
/* Don't redraw the cursor's spot in mouse face if it is at the
end of a line (on a newline). The cursor appears there, but
update_window_cursor (w, 0);
}
+#endif /* HAVE_WINDOW_SYSTEM */
+
+/* Implementation of draw_row_with_mouse_face for GUI sessions, GPM,
+ and MSDOS. */
+void
+draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
+ int start_hpos, int end_hpos,
+ enum draw_glyphs_face draw)
+{
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (XFRAME (w->frame)))
+ {
+ draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
+ return;
+ }
+#endif
+#if defined (HAVE_GPM) || defined (MSDOS)
+ tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
+#endif
+}
/* EXPORT:
Display the active region described by mouse_face_* according to DRAW. */
void
-show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw)
+show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
{
- struct window *w = XWINDOW (dpyinfo->mouse_face_window);
+ struct window *w = XWINDOW (hlinfo->mouse_face_window);
struct frame *f = XFRAME (WINDOW_FRAME (w));
if (/* If window is in the process of being destroyed, don't bother
to do anything. */
w->current_matrix != NULL
/* Don't update mouse highlight if hidden */
- && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
+ && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
/* Recognize when we are called to operate on rows that don't exist
anymore. This can happen when a window is split. */
- && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
+ && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
{
int phys_cursor_on_p = w->phys_cursor_on_p;
struct glyph_row *row, *first, *last;
- first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
- last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+ first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
+ last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
for (row = first; row <= last && row->enabled_p; ++row)
{
highlighted area in R2L rows. */
if (!row->reversed_p)
{
- start_hpos = dpyinfo->mouse_face_beg_col;
- start_x = dpyinfo->mouse_face_beg_x;
+ start_hpos = hlinfo->mouse_face_beg_col;
+ start_x = hlinfo->mouse_face_beg_x;
}
else if (row == last)
{
- start_hpos = dpyinfo->mouse_face_end_col;
- start_x = dpyinfo->mouse_face_end_x;
+ start_hpos = hlinfo->mouse_face_end_col;
+ start_x = hlinfo->mouse_face_end_x;
}
else
{
}
else if (row->reversed_p && row == last)
{
- start_hpos = dpyinfo->mouse_face_end_col;
- start_x = dpyinfo->mouse_face_end_x;
+ start_hpos = hlinfo->mouse_face_end_col;
+ start_x = hlinfo->mouse_face_end_x;
}
else
{
if (row == last)
{
if (!row->reversed_p)
- end_hpos = dpyinfo->mouse_face_end_col;
+ end_hpos = hlinfo->mouse_face_end_col;
else if (row == first)
- end_hpos = dpyinfo->mouse_face_beg_col;
+ end_hpos = hlinfo->mouse_face_beg_col;
else
{
end_hpos = row->used[TEXT_AREA];
}
}
else if (row->reversed_p && row == first)
- end_hpos = dpyinfo->mouse_face_beg_col;
+ end_hpos = hlinfo->mouse_face_beg_col;
else
{
end_hpos = row->used[TEXT_AREA];
if (end_hpos > start_hpos)
{
- draw_glyphs (w, start_x, row, TEXT_AREA,
- start_hpos, end_hpos,
- draw, 0);
+ draw_row_with_mouse_face (w, start_x, row,
+ start_hpos, end_hpos, draw);
row->mouse_face_p
= draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
}
}
+#ifdef HAVE_WINDOW_SYSTEM
/* When we've written over the cursor, arrange for it to
be displayed again. */
- if (phys_cursor_on_p && !w->phys_cursor_on_p)
+ if (FRAME_WINDOW_P (f)
+ && phys_cursor_on_p && !w->phys_cursor_on_p)
{
BLOCK_INPUT;
display_and_set_cursor (w, 1,
w->phys_cursor.x, w->phys_cursor.y);
UNBLOCK_INPUT;
}
+#endif /* HAVE_WINDOW_SYSTEM */
}
+#ifdef HAVE_WINDOW_SYSTEM
/* Change the mouse cursor. */
- if (draw == DRAW_NORMAL_TEXT && !EQ (dpyinfo->mouse_face_window, f->tool_bar_window))
- FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
- else if (draw == DRAW_MOUSE_FACE)
- FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
- else
- FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
+ if (FRAME_WINDOW_P (f))
+ {
+ if (draw == DRAW_NORMAL_TEXT
+ && !EQ (hlinfo->mouse_face_window, f->tool_bar_window))
+ FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
+ else if (draw == DRAW_MOUSE_FACE)
+ FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
+ else
+ FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
+ }
+#endif /* HAVE_WINDOW_SYSTEM */
}
/* EXPORT:
face was actually drawn unhighlighted. */
int
-clear_mouse_face (Display_Info *dpyinfo)
+clear_mouse_face (Mouse_HLInfo *hlinfo)
{
int cleared = 0;
- if (!dpyinfo->mouse_face_hidden && !NILP (dpyinfo->mouse_face_window))
+ if (!hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window))
{
- show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
+ show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
cleared = 1;
}
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- dpyinfo->mouse_face_overlay = Qnil;
+ hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+ hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+ hlinfo->mouse_face_window = Qnil;
+ hlinfo->mouse_face_overlay = Qnil;
return cleared;
}
static int
coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
{
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
/* Quickly resolve the easy cases. */
- if (!(WINDOWP (dpyinfo->mouse_face_window)
- && XWINDOW (dpyinfo->mouse_face_window) == w))
+ if (!(WINDOWP (hlinfo->mouse_face_window)
+ && XWINDOW (hlinfo->mouse_face_window) == w))
return 0;
- if (vpos < dpyinfo->mouse_face_beg_row
- || vpos > dpyinfo->mouse_face_end_row)
+ if (vpos < hlinfo->mouse_face_beg_row
+ || vpos > hlinfo->mouse_face_end_row)
return 0;
- if (vpos > dpyinfo->mouse_face_beg_row
- && vpos < dpyinfo->mouse_face_end_row)
+ if (vpos > hlinfo->mouse_face_beg_row
+ && vpos < hlinfo->mouse_face_end_row)
return 1;
if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
{
- if (dpyinfo->mouse_face_beg_row == dpyinfo->mouse_face_end_row)
+ if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
{
- if (dpyinfo->mouse_face_beg_col <= hpos && hpos < dpyinfo->mouse_face_end_col)
+ if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
return 1;
}
- else if ((vpos == dpyinfo->mouse_face_beg_row
- && hpos >= dpyinfo->mouse_face_beg_col)
- || (vpos == dpyinfo->mouse_face_end_row
- && hpos < dpyinfo->mouse_face_end_col))
+ else if ((vpos == hlinfo->mouse_face_beg_row
+ && hpos >= hlinfo->mouse_face_beg_col)
+ || (vpos == hlinfo->mouse_face_end_row
+ && hpos < hlinfo->mouse_face_end_col))
return 1;
}
else
{
- if (dpyinfo->mouse_face_beg_row == dpyinfo->mouse_face_end_row)
+ if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
{
- if (dpyinfo->mouse_face_end_col < hpos && hpos <= dpyinfo->mouse_face_beg_col)
+ if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
return 1;
}
- else if ((vpos == dpyinfo->mouse_face_beg_row
- && hpos <= dpyinfo->mouse_face_beg_col)
- || (vpos == dpyinfo->mouse_face_end_row
- && hpos > dpyinfo->mouse_face_end_col))
+ else if ((vpos == hlinfo->mouse_face_beg_row
+ && hpos <= hlinfo->mouse_face_beg_col)
+ || (vpos == hlinfo->mouse_face_end_row
+ && hpos > hlinfo->mouse_face_end_col))
return 1;
}
return 0;
}
}
-/* This function sets the mouse_face_* elements of DPYINFO, assuming
+/* This function sets the mouse_face_* elements of HLINFO, assuming
the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in
window WINDOW. START_CHARPOS and END_CHARPOS are buffer positions
for the overlay or run of text properties specifying the mouse
static void
mouse_face_from_buffer_pos (Lisp_Object window,
- Display_Info *dpyinfo,
+ Mouse_HLInfo *hlinfo,
EMACS_INT mouse_charpos,
EMACS_INT start_charpos,
EMACS_INT end_charpos,
if (r2 == NULL)
{
r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
- dpyinfo->mouse_face_past_end = 1;
+ hlinfo->mouse_face_past_end = 1;
}
else if (!NILP (after_string))
{
r1 = tem;
}
- dpyinfo->mouse_face_beg_y = r1->y;
- dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
- dpyinfo->mouse_face_end_y = r2->y;
- dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
+ hlinfo->mouse_face_beg_y = r1->y;
+ hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
+ hlinfo->mouse_face_end_y = r2->y;
+ hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
/* For a bidi-reordered row, the positions of BEFORE_STRING,
AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS
start_charpos);
/* If pos == 0, it means before_string came from an
overlay, not from a buffer position. */
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ if (!pos || (pos >= start_charpos && pos < end_charpos))
break;
}
else if (EQ (glyph->object, after_string))
{
pos = string_buffer_position (w, after_string, end_charpos);
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ if (!pos || (pos >= start_charpos && pos < end_charpos))
break;
}
x += glyph->pixel_width;
}
- dpyinfo->mouse_face_beg_x = x;
- dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
+ hlinfo->mouse_face_beg_x = x;
+ hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
}
else
{
pos = string_buffer_position (w, before_string, start_charpos);
/* If pos == 0, it means before_string came from an
overlay, not from a buffer position. */
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ if (!pos || (pos >= start_charpos && pos < end_charpos))
break;
}
else if (EQ (glyph->object, after_string))
{
pos = string_buffer_position (w, after_string, end_charpos);
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ if (!pos || (pos >= start_charpos && pos < end_charpos))
break;
}
}
glyph++; /* first glyph to the right of the highlighted area */
for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
x += g->pixel_width;
- dpyinfo->mouse_face_beg_x = x;
- dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
+ hlinfo->mouse_face_beg_x = x;
+ hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
}
/* If the highlight ends in a different row, compute GLYPH and END
if (EQ (end->object, before_string))
{
pos = string_buffer_position (w, before_string, start_charpos);
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ if (!pos || (pos >= start_charpos && pos < end_charpos))
break;
}
else if (EQ (end->object, after_string))
{
pos = string_buffer_position (w, after_string, end_charpos);
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ if (!pos || (pos >= start_charpos && pos < end_charpos))
break;
}
}
for (; glyph <= end; ++glyph)
x += glyph->pixel_width;
- dpyinfo->mouse_face_end_x = x;
- dpyinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
+ hlinfo->mouse_face_end_x = x;
+ hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
}
else
{
if (EQ (end->object, before_string))
{
pos = string_buffer_position (w, before_string, start_charpos);
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ if (!pos || (pos >= start_charpos && pos < end_charpos))
break;
}
else if (EQ (end->object, after_string))
{
pos = string_buffer_position (w, after_string, end_charpos);
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ if (!pos || (pos >= start_charpos && pos < end_charpos))
break;
}
x += end->pixel_width;
}
- dpyinfo->mouse_face_end_x = x;
- dpyinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
+ hlinfo->mouse_face_end_x = x;
+ hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
}
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id
+ hlinfo->mouse_face_window = window;
+ hlinfo->mouse_face_face_id
= face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore,
mouse_charpos + 1,
- !dpyinfo->mouse_face_hidden, -1);
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ !hlinfo->mouse_face_hidden, -1);
+ show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
}
/* The following function is not used anymore (replaced with
/* Find the positions of the first and the last glyphs in window W's
current matrix that occlude positions [STARTPOS..ENDPOS] in OBJECT
- (assumed to be a string), and return in DPYINFO's mouse_face
+ (assumed to be a string), and return in HLINFO's mouse_face_*
members the pixel and column/row coordinates of those glyphs. */
static void
-mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo,
+mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
Lisp_Object object,
EMACS_INT startpos, EMACS_INT endpos)
{
if (EQ (g->object, object)
&& startpos <= g->charpos && g->charpos <= endpos)
{
- dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows;
- dpyinfo->mouse_face_beg_y = r->y;
- dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
- dpyinfo->mouse_face_beg_x = gx;
+ hlinfo->mouse_face_beg_row = r - w->current_matrix->rows;
+ hlinfo->mouse_face_beg_y = r->y;
+ hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
+ hlinfo->mouse_face_beg_x = gx;
found = 1;
break;
}
if (EQ ((g-1)->object, object)
&& startpos <= (g-1)->charpos && (g-1)->charpos <= endpos)
{
- dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows;
- dpyinfo->mouse_face_beg_y = r->y;
- dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
+ hlinfo->mouse_face_beg_row = r - w->current_matrix->rows;
+ hlinfo->mouse_face_beg_y = r->y;
+ hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
gx += g1->pixel_width;
- dpyinfo->mouse_face_beg_x = gx;
+ hlinfo->mouse_face_beg_x = gx;
found = 1;
break;
}
r--;
/* Set the end row and its vertical pixel coordinate. */
- dpyinfo->mouse_face_end_row = r - w->current_matrix->rows;
- dpyinfo->mouse_face_end_y = r->y;
+ hlinfo->mouse_face_end_row = r - w->current_matrix->rows;
+ hlinfo->mouse_face_end_y = r->y;
/* Compute and set the end column and the end column's horizontal
pixel coordinate. */
if (EQ ((e-1)->object, object)
&& startpos <= (e-1)->charpos && (e-1)->charpos <= endpos)
break;
- dpyinfo->mouse_face_end_col = e - g;
+ hlinfo->mouse_face_end_col = e - g;
for (gx = r->x; g < e; ++g)
gx += g->pixel_width;
- dpyinfo->mouse_face_end_x = gx;
+ hlinfo->mouse_face_end_x = gx;
}
else
{
break;
gx += e->pixel_width;
}
- dpyinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
- dpyinfo->mouse_face_end_x = gx;
+ hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
+ hlinfo->mouse_face_end_x = gx;
}
}
+#ifdef HAVE_WINDOW_SYSTEM
+
/* See if position X, Y is within a hot-spot of an image. */
static int
FRAME_RIF (f)->define_frame_cursor (f, cursor);
}
+#endif /* HAVE_WINDOW_SYSTEM */
+
/* Take proper action when mouse has moved to the mode or header line
or marginal area AREA of window W, x-position X and y-position Y.
X is relative to the start of the text display area of W, so the
{
struct window *w = XWINDOW (window);
struct frame *f = XFRAME (w->frame);
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+#ifdef HAVE_WINDOW_SYSTEM
+ Display_Info *dpyinfo;
+#endif
+ Cursor cursor = No_Cursor;
Lisp_Object pointer = Qnil;
int dx, dy, width, height;
EMACS_INT charpos;
help = Qnil;
+#ifdef HAVE_WINDOW_SYSTEM
if (IMAGEP (object))
{
Lisp_Object image_map, hotspot;
if (NILP (pointer))
pointer = Fplist_get (XCDR (object), QCpointer);
}
+#endif /* HAVE_WINDOW_SYSTEM */
if (STRINGP (string))
{
}
}
- if (NILP (pointer))
- pointer = Fget_text_property (pos, Qpointer, string);
-
- /* Change the mouse pointer according to what is under X/Y. */
- if (NILP (pointer) && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f))
{
- Lisp_Object map;
- map = Fget_text_property (pos, Qlocal_map, string);
- if (!KEYMAPP (map))
- map = Fget_text_property (pos, Qkeymap, string);
- if (!KEYMAPP (map))
- cursor = dpyinfo->vertical_scroll_bar_cursor;
+ dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+ if (NILP (pointer))
+ pointer = Fget_text_property (pos, Qpointer, string);
+
+ /* Change the mouse pointer according to what is under X/Y. */
+ if (NILP (pointer)
+ && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)))
+ {
+ Lisp_Object map;
+ map = Fget_text_property (pos, Qlocal_map, string);
+ if (!KEYMAPP (map))
+ map = Fget_text_property (pos, Qkeymap, string);
+ if (!KEYMAPP (map))
+ cursor = dpyinfo->vertical_scroll_bar_cursor;
+ }
}
+#endif
/* Change the mouse face according to what is under X/Y. */
mouse_face = Fget_text_property (pos, Qmouse_face, string);
/* If GLYPH's position is included in the region that is
already drawn in mouse face, we have nothing to do. */
- if ( EQ (window, dpyinfo->mouse_face_window)
+ if ( EQ (window, hlinfo->mouse_face_window)
&& (!row->reversed_p
- ? (dpyinfo->mouse_face_beg_col <= hpos
- && hpos < dpyinfo->mouse_face_end_col)
+ ? (hlinfo->mouse_face_beg_col <= hpos
+ && hpos < hlinfo->mouse_face_end_col)
/* In R2L rows we swap BEG and END, see below. */
- : (dpyinfo->mouse_face_end_col <= hpos
- && hpos < dpyinfo->mouse_face_beg_col))
- && dpyinfo->mouse_face_beg_row == vpos )
+ : (hlinfo->mouse_face_end_col <= hpos
+ && hpos < hlinfo->mouse_face_beg_col))
+ && hlinfo->mouse_face_beg_row == vpos )
return;
- if (clear_mouse_face (dpyinfo))
+ if (clear_mouse_face (hlinfo))
cursor = No_Cursor;
if (!row->reversed_p)
{
- dpyinfo->mouse_face_beg_col = hpos;
- dpyinfo->mouse_face_beg_x = original_x_pixel
+ hlinfo->mouse_face_beg_col = hpos;
+ hlinfo->mouse_face_beg_x = original_x_pixel
- (total_pixel_width + dx);
- dpyinfo->mouse_face_end_col = hpos + gseq_length;
- dpyinfo->mouse_face_end_x = 0;
+ hlinfo->mouse_face_end_col = hpos + gseq_length;
+ hlinfo->mouse_face_end_x = 0;
}
else
{
/* In R2L rows, show_mouse_face expects BEG and END
coordinates to be swapped. */
- dpyinfo->mouse_face_end_col = hpos;
- dpyinfo->mouse_face_end_x = original_x_pixel
+ hlinfo->mouse_face_end_col = hpos;
+ hlinfo->mouse_face_end_x = original_x_pixel
- (total_pixel_width + dx);
- dpyinfo->mouse_face_beg_col = hpos + gseq_length;
- dpyinfo->mouse_face_beg_x = 0;
+ hlinfo->mouse_face_beg_col = hpos + gseq_length;
+ hlinfo->mouse_face_beg_x = 0;
}
- dpyinfo->mouse_face_beg_row = vpos;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row;
- dpyinfo->mouse_face_beg_y = 0;
- dpyinfo->mouse_face_end_y = 0;
- dpyinfo->mouse_face_past_end = 0;
- dpyinfo->mouse_face_window = window;
-
- dpyinfo->mouse_face_face_id = face_at_string_position (w, string,
- charpos,
- 0, 0, 0,
- &ignore,
- glyph->face_id,
- 1);
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ hlinfo->mouse_face_beg_row = vpos;
+ hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
+ hlinfo->mouse_face_beg_y = 0;
+ hlinfo->mouse_face_end_y = 0;
+ hlinfo->mouse_face_past_end = 0;
+ hlinfo->mouse_face_window = window;
+
+ hlinfo->mouse_face_face_id = face_at_string_position (w, string,
+ charpos,
+ 0, 0, 0,
+ &ignore,
+ glyph->face_id,
+ 1);
+ show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
if (NILP (pointer))
pointer = Qhand;
}
else if ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))
- clear_mouse_face (dpyinfo);
+ clear_mouse_face (hlinfo);
}
- define_frame_cursor1 (f, cursor, pointer);
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f))
+ define_frame_cursor1 (f, cursor, pointer);
+#endif
}
void
note_mouse_highlight (struct frame *f, int x, int y)
{
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
enum window_part part;
Lisp_Object window;
struct window *w;
struct buffer *b;
/* When a menu is active, don't highlight because this looks odd. */
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (MSDOS)
if (popup_activated ())
return;
#endif
|| f->pointer_invisible)
return;
- dpyinfo->mouse_face_mouse_x = x;
- dpyinfo->mouse_face_mouse_y = y;
- dpyinfo->mouse_face_mouse_frame = f;
+ hlinfo->mouse_face_mouse_x = x;
+ hlinfo->mouse_face_mouse_y = y;
+ hlinfo->mouse_face_mouse_frame = f;
- if (dpyinfo->mouse_face_defer)
+ if (hlinfo->mouse_face_defer)
return;
if (gc_in_progress)
{
- dpyinfo->mouse_face_deferred_gc = 1;
+ hlinfo->mouse_face_deferred_gc = 1;
return;
}
/* Which window is that in? */
- window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
+ window = window_from_coordinates (f, x, y, &part, 1);
/* If we were displaying active text in another window, clear that.
Also clear if we move out of text area in same window. */
- if (! EQ (window, dpyinfo->mouse_face_window)
+ if (! EQ (window, hlinfo->mouse_face_window)
|| (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE
- && !NILP (dpyinfo->mouse_face_window)))
- clear_mouse_face (dpyinfo);
+ && !NILP (hlinfo->mouse_face_window)))
+ clear_mouse_face (hlinfo);
/* Not on a window -> return. */
if (!WINDOWP (window))
w = XWINDOW (window);
frame_to_window_pixel_xy (w, &x, &y);
+#ifdef HAVE_WINDOW_SYSTEM
/* Handle tool-bar window differently since it doesn't display a
buffer. */
if (EQ (window, f->tool_bar_window))
note_tool_bar_highlight (f, x, y);
return;
}
+#endif
/* Mouse is on the mode, header line or margin? */
if (part == ON_MODE_LINE || part == ON_HEADER_LINE
return;
}
+#ifdef HAVE_WINDOW_SYSTEM
if (part == ON_VERTICAL_BORDER)
{
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else
cursor = FRAME_X_OUTPUT (f)->text_cursor;
+#endif
/* Are we in a window whose display is up to date?
And verify the buffer's text has not changed. */
/* Find the glyph under X/Y. */
glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
+#ifdef HAVE_WINDOW_SYSTEM
/* Look for :pointer property on image. */
if (glyph != NULL && glyph->type == IMAGE_GLYPH)
{
pointer = Fplist_get (XCDR (img->spec), QCpointer);
}
}
+#endif /* HAVE_WINDOW_SYSTEM */
/* Clear mouse face if X/Y not over text. */
if (glyph == NULL
|| area != TEXT_AREA
|| !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p
+ /* Glyph's OBJECT is an integer for glyphs inserted by the
+ display engine for its internal purposes, like truncation
+ and continuation glyphs and blanks beyond the end of
+ line's text on text terminals. If we are over such a
+ glyph, we are not over any text. */
+ || INTEGERP (glyph->object)
/* R2L rows have a stretch glyph at their front, which
stands for no text, whereas L2R rows have no glyphs at
all beyond the end of text. Treat such stretch glyphs
&& glyph->type == STRETCH_GLYPH
&& glyph->avoid_cursor_p))
{
- if (clear_mouse_face (dpyinfo))
+ if (clear_mouse_face (hlinfo))
cursor = No_Cursor;
- if (NILP (pointer))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f) && NILP (pointer))
{
if (area != TEXT_AREA)
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else
pointer = Vvoid_text_area_pointer;
}
+#endif
goto set_cursor;
}
the one we are currently highlighting, we have to
check if we enter the overlapping overlay, and then
highlight only that. */
- || (OVERLAYP (dpyinfo->mouse_face_overlay)
- && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
+ || (OVERLAYP (hlinfo->mouse_face_overlay)
+ && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
{
/* Find the highest priority overlay with a mouse-face. */
overlay = Qnil;
/* If we're highlighting the same overlay as before, there's
no need to do that again. */
- if (!NILP (overlay) && EQ (overlay, dpyinfo->mouse_face_overlay))
+ if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
goto check_help_echo;
- dpyinfo->mouse_face_overlay = overlay;
+ hlinfo->mouse_face_overlay = overlay;
/* Clear the display of the old active region, if any. */
- if (clear_mouse_face (dpyinfo))
+ if (clear_mouse_face (hlinfo))
cursor = No_Cursor;
/* If no overlay applies, get a text property. */
b = make_number (0);
if (NILP (e))
e = make_number (SCHARS (object) - 1);
- mouse_face_from_string_pos (w, dpyinfo, object,
+ mouse_face_from_string_pos (w, hlinfo, object,
XINT (b), XINT (e));
- dpyinfo->mouse_face_past_end = 0;
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id
+ hlinfo->mouse_face_past_end = 0;
+ hlinfo->mouse_face_window = window;
+ hlinfo->mouse_face_face_id
= face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
glyph->face_id, 1);
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
cursor = No_Cursor;
}
else
if (!STRINGP (after_string)) after_string = Qnil;
}
- mouse_face_from_buffer_pos (window, dpyinfo, pos,
+ mouse_face_from_buffer_pos (window, hlinfo, pos,
XFASTINT (before),
XFASTINT (after),
before_string, after_string,
}
}
+#ifdef HAVE_WINDOW_SYSTEM
/* Look for a `pointer' property. */
- if (NILP (pointer))
+ if (FRAME_WINDOW_P (f) && NILP (pointer))
{
/* Check overlays first. */
for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
Qpointer, object);
}
}
+#endif /* HAVE_WINDOW_SYSTEM */
BEGV = obegv;
ZV = ozv;
set_cursor:
- define_frame_cursor1 (f, cursor, pointer);
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f))
+ define_frame_cursor1 (f, cursor, pointer);
+#else
+ /* This is here to prevent a compiler error, about "label at end of
+ compound statement". */
+ return;
+#endif
}
void
x_clear_window_mouse_face (struct window *w)
{
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
Lisp_Object window;
BLOCK_INPUT;
XSETWINDOW (window, w);
- if (EQ (window, dpyinfo->mouse_face_window))
- clear_mouse_face (dpyinfo);
+ if (EQ (window, hlinfo->mouse_face_window))
+ clear_mouse_face (hlinfo);
UNBLOCK_INPUT;
}
cancel_mouse_face (struct frame *f)
{
Lisp_Object window;
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
- window = dpyinfo->mouse_face_window;
+ window = hlinfo->mouse_face_window;
if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
{
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
+ hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+ hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+ hlinfo->mouse_face_window = Qnil;
}
}
-#endif /* HAVE_WINDOW_SYSTEM */
-
\f
/***********************************************************************
Exposure Events
focus-follows-mouse with delayed raise. --jason 2001-10-12 */
if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
{
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- if (f == dpyinfo->mouse_face_mouse_frame)
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+ if (f == hlinfo->mouse_face_mouse_frame)
{
- int x = dpyinfo->mouse_face_mouse_x;
- int y = dpyinfo->mouse_face_mouse_y;
- clear_mouse_face (dpyinfo);
+ int x = hlinfo->mouse_face_mouse_x;
+ int y = hlinfo->mouse_face_mouse_y;
+ clear_mouse_face (hlinfo);
note_mouse_highlight (f, x, y);
}
}
hourglass_atimer = NULL;
hourglass_shown_p = 0;
+
+ DEFSYM (Qglyphless_char, "glyphless-char");
+ DEFSYM (Qhex_code, "hex-code");
+ DEFSYM (Qempty_box, "empty-box");
+ DEFSYM (Qthin_space, "thin-space");
+ DEFSYM (Qzero_width, "zero-width");
+
+ DEFSYM (Qglyphless_char_display, "glyphless-char-display");
+ /* Intern this now in case it isn't already done.
+ Setting this variable twice is harmless.
+ But don't staticpro it here--that is done in alloc.c. */
+ Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots");
+ Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1));
+
+ DEFVAR_LISP ("glyphless-char-display", &Vglyphless_char_display,
+ doc: /* Char-table to control displaying of glyphless characters.
+Each element, if non-nil, is an ASCII acronym string (displayed in a box)
+or one of these symbols:
+ hex-code: display the hexadecimal code of a character in a box
+ empty-box: display as an empty box
+ thin-space: display as 1-pixel width space
+ zero-width: don't display
+
+It has one extra slot to control the display of a character for which
+no font is found. The value of the slot is `hex-code' or `empty-box'.
+The default is `empty-box'. */);
+ Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
+ Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),
+ Qempty_box);
}