/* Display generation from window structure and buffer text.
-Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- 2010 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
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.
#define INFINITY 10000000
Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
-Lisp_Object Qwindow_text_change_functions, Vwindow_text_change_functions;
-Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
+Lisp_Object Qwindow_scroll_functions;
+Lisp_Object Qwindow_text_change_functions;
+Lisp_Object Qredisplay_end_trigger_functions;
Lisp_Object Qinhibit_point_motion_hooks;
Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
Lisp_Object Qfontified;
/* Pointer shapes */
Lisp_Object Qarrow, Qhand, Qtext;
-Lisp_Object Qrisky_local_variable;
-
/* Holds the list (error). */
Lisp_Object list_of_error;
-/* Functions called to fontify regions of text. */
-
-Lisp_Object Vfontification_functions;
Lisp_Object Qfontification_functions;
-/* Non-nil means automatically select any window when the mouse
- cursor moves into it. */
-Lisp_Object Vmouse_autoselect_window;
-
-Lisp_Object Vwrap_prefix, Qwrap_prefix;
-Lisp_Object Vline_prefix, Qline_prefix;
-
-/* Non-zero means draw tool bar buttons raised when the mouse moves
- over them. */
-
-int auto_raise_tool_bar_buttons_p;
-
-/* Non-zero means to reposition window if cursor line is only partially visible. */
-
-int make_cursor_line_fully_visible_p;
-
-/* Margin below tool bar in pixels. 0 or nil means no margin.
- If value is `internal-border-width' or `border-width',
- the corresponding frame parameter is used. */
-
-Lisp_Object Vtool_bar_border;
-
-/* Margin around tool bar buttons in pixels. */
-
-Lisp_Object Vtool_bar_button_margin;
-
-/* Thickness of shadow to draw around tool bar buttons. */
-
-EMACS_INT tool_bar_button_relief;
-
-/* Non-nil means automatically resize tool-bars so that all tool-bar
- items are visible, and no blank lines remain.
-
- If value is `grow-only', only make tool-bar bigger. */
-
-Lisp_Object Vauto_resize_tool_bars;
-
-/* Type of tool bar. Can be symbols image, text, both or both-hroiz. */
-
-Lisp_Object Vtool_bar_style;
-
-/* Maximum number of characters a label can have to be shown. */
-
-EMACS_INT tool_bar_max_label_size;
-
-/* Non-zero means draw block and hollow cursor as wide as the glyph
- under it. For example, if a block cursor is over a tab, it will be
- drawn as wide as that tab on the display. */
-
-int x_stretch_cursor_p;
+Lisp_Object Qwrap_prefix;
+Lisp_Object Qline_prefix;
/* Non-nil means don't actually do any redisplay. */
-Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
-
-/* Non-zero means Lisp evaluation during redisplay is inhibited. */
-
-int inhibit_eval_during_redisplay;
+Lisp_Object Qinhibit_redisplay;
/* Names of text properties relevant for redisplay. */
Lisp_Object Qdisplay;
-/* Symbols used in text property values. */
-
-Lisp_Object Vdisplay_pixels_per_inch;
Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
Lisp_Object Qslice;
Lisp_Object Qmargin, Qpointer;
Lisp_Object Qline_height;
-/* Non-nil means highlight trailing whitespace. */
-
-Lisp_Object Vshow_trailing_whitespace;
-
-/* Non-nil means escape non-break space and hyphens. */
-
-Lisp_Object Vnobreak_char_display;
-
#ifdef HAVE_WINDOW_SYSTEM
/* Test if overflow newline into fringe. Called with iterator IT
#define IT_DISPLAYING_WHITESPACE(it) \
(it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t'))
-/* Non-nil means show the text cursor in void text areas
- i.e. in blank areas after eol and eob. This used to be
- the default in 21.3. */
-
-Lisp_Object Vvoid_text_area_pointer;
-
/* Name of the face used to highlight trailing whitespace. */
Lisp_Object Qtrailing_whitespace;
static int this_line_start_x;
-/* Buffer that this_line_.* variables are referring to. */
-
-static struct buffer *this_line_buffer;
-
-/* Nonzero means truncate lines in all windows less wide than the
- frame. */
-
-Lisp_Object Vtruncate_partial_width_windows;
-
-/* A flag to control how to display unibyte 8-bit character. */
-
-int unibyte_display_via_language_environment;
-
-/* Nonzero means we have more than one non-mini-buffer-only frame.
- Not guaranteed to be accurate except while parsing
- frame-title-format. */
+/* The smallest character position seen by move_it_* functions as they
+ move across display lines. Used to set MATRIX_ROW_START_CHARPOS of
+ hscrolled lines, see display_line. */
-int multiple_frames;
+static struct text_pos this_line_min_pos;
-Lisp_Object Vglobal_mode_string;
-
-
-/* List of variables (symbols) which hold markers for overlay arrows.
- The symbols on this list are examined during redisplay to determine
- where to display overlay arrows. */
-
-Lisp_Object Voverlay_arrow_variable_list;
-
-/* Marker for where to display an arrow on top of the buffer text. */
-
-Lisp_Object Voverlay_arrow_position;
+/* Buffer that this_line_.* variables are referring to. */
-/* String to display for the arrow. Only used on terminal frames. */
+static struct buffer *this_line_buffer;
-Lisp_Object Voverlay_arrow_string;
/* Values of those variables at last redisplay are stored as
properties on `overlay-arrow-position' symbol. However, if
Lisp_Object Qoverlay_arrow_string, Qoverlay_arrow_bitmap;
-/* Like mode-line-format, but for the title bar on a visible frame. */
-
-Lisp_Object Vframe_title_format;
-
-/* Like mode-line-format, but for the title bar on an iconified frame. */
-
-Lisp_Object Vicon_title_format;
-
-/* List of functions to call when a window's size changes. These
- functions get one arg, a frame on which one or more windows' sizes
- have changed. */
-
-static Lisp_Object Vwindow_size_change_functions;
-
-Lisp_Object Qmenu_bar_update_hook, Vmenu_bar_update_hook;
+Lisp_Object Qmenu_bar_update_hook;
/* Nonzero if an overlay arrow has been displayed in this window. */
static int overlay_arrow_seen;
-/* Nonzero means highlight the region even in nonselected windows. */
-
-int highlight_nonselected_windows;
-
-/* If cursor motion alone moves point off frame, try scrolling this
- many lines up or down if that will bring it back. */
-
-static EMACS_INT scroll_step;
-
-/* Nonzero means scroll just far enough to bring point back on the
- screen, when appropriate. */
-
-static EMACS_INT scroll_conservatively;
-
-/* Recenter the window whenever point gets within this many lines of
- the top or bottom of the window. This value is translated into a
- pixel value by multiplying it with FRAME_LINE_HEIGHT, which means
- that there is really a fixed pixel height scroll margin. */
-
-EMACS_INT scroll_margin;
-
/* Number of windows showing the buffer of the selected window (or
another buffer with the same base buffer). keyboard.c refers to
this. */
static Lisp_Object default_invis_vector[3];
-/* Zero means display the mode-line/header-line/menu-bar in the default face
- (this slightly odd definition is for compatibility with previous versions
- of emacs), non-zero means display them using their respective faces.
-
- This variable is deprecated. */
-
-int mode_line_inverse_video;
-
-/* Prompt to display in front of the mini-buffer contents. */
-
-Lisp_Object minibuf_prompt;
-
-/* Width of current mini-buffer prompt. Only set after display_line
- of the line that contains the prompt. */
-
-int minibuf_prompt_width;
-
/* This is the window where the echo area message was displayed. It
is always a mini-buffer window, but it may not be the same window
currently active as a mini-buffer. */
int line_number_displayed;
-/* Maximum buffer size for which to display line numbers. */
-
-Lisp_Object Vline_number_display_limit;
-
-/* Line width to consider when repositioning for line number display. */
-
-static EMACS_INT line_number_display_limit_width;
-
-/* Number of lines to keep in the message log buffer. t means
- infinite. nil means don't log at all. */
-
-Lisp_Object Vmessage_log_max;
-
/* The name of the *Messages* buffer, a string. */
static Lisp_Object Vmessages_buffer_name;
/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
Lisp_Object Qinhibit_menubar_update;
-int inhibit_menubar_update;
-
-/* When evaluating expressions from menu bar items (enable conditions,
- for instance), this is the frame they are being processed for. */
-
-Lisp_Object Vmenu_updating_frame;
-
-/* Maximum height for resizing mini-windows. Either a float
- specifying a fraction of the available height, or an integer
- specifying a number of lines. */
-
-Lisp_Object Vmax_mini_window_height;
-
-/* Non-zero means messages should be displayed with truncated
- lines instead of being continued. */
-
-int message_truncate_lines;
Lisp_Object Qmessage_truncate_lines;
/* Set to 1 in clear_message to make redisplay_internal aware
static int message_cleared_p;
-/* How to blink the default frame cursor off. */
-Lisp_Object Vblink_cursor_alist;
-
/* A scratch glyph row with contents used for generating truncation
glyphs. Also used in direct_output_for_insert. */
#if GLYPH_DEBUG
-/* Variables to turn off display optimizations from Lisp. */
-
-int inhibit_try_window_id, inhibit_try_window_reusing;
-int inhibit_try_cursor_movement;
-
/* Non-zero means print traces of redisplay if compiled with
GLYPH_DEBUG != 0. */
#define TRACE_MOVE(x) (void) 0
#endif
-/* Non-zero means automatically scroll windows horizontally to make
- point visible. */
-
-int automatic_hscrolling_p;
Lisp_Object Qauto_hscroll_mode;
-/* How close to the margin can point get before the window is scrolled
- horizontally. */
-EMACS_INT hscroll_margin;
-
-/* How much to scroll horizontally when point is inside the above margin. */
-Lisp_Object Vhscroll_step;
-
-/* The variable `resize-mini-windows'. If nil, don't resize
- mini-windows. If t, always resize them to fit the text they
- display. If `grow-only', let mini-windows grow only until they
- become empty. */
-
-Lisp_Object Vresize_mini_windows;
-
/* Buffer being redisplayed -- for redisplay_window_error. */
struct buffer *displayed_buffer;
-/* Space between overline and text. */
-
-EMACS_INT overline_margin;
-
-/* Require underline to be at least this many screen pixels below baseline
- This to avoid underline "merging" with the base of letters at small
- font sizes, particularly when x_use_underline_position_properties is on. */
-
-EMACS_INT underline_minimum_offset;
-
/* Value returned from text property handlers (see below). */
enum prop_handled
#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. */
int redisplaying_p;
-/* Non-zero means don't free realized faces. Bound while freeing
- realized faces is dangerous because glyph matrices might still
- reference them. */
-
-int inhibit_free_realized_faces;
Lisp_Object Qinhibit_free_realized_faces;
/* If a string, XTread_socket generates an event to display that string.
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. */
-int display_hourglass_p;
-
/* Non-zero means an hourglass cursor is currently shown. */
int hourglass_shown_p;
an hourglass cursor on all frames. */
struct atimer *hourglass_atimer;
-/* 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;
+
+/* 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. */
static void mark_window_display_accurate_1 (struct window *, int);
static int single_display_spec_string_p (Lisp_Object, Lisp_Object);
static int display_prop_string_p (Lisp_Object, Lisp_Object);
-static int cursor_row_p (struct window *, struct glyph_row *);
+static int cursor_row_p (struct glyph_row *);
static int redisplay_mode_lines (Lisp_Object, int);
static char *decode_mode_spec_coding (Lisp_Object, char *, int);
static void handle_line_prefix (struct it *);
-static void pint2str (char *, int, int);
+static void pint2str (char *, int, EMACS_INT);
static void pint2hrstr (char *, int, int);
static struct text_pos run_window_scroll_functions (Lisp_Object,
struct text_pos);
static int text_outside_line_unchanged_p (struct window *,
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 int store_mode_line_noprop (const char *, int, int);
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);
static int try_scrolling (Lisp_Object, int, EMACS_INT, EMACS_INT, int, int);
static int try_cursor_movement (Lisp_Object, struct text_pos, int *);
static int trailing_whitespace_p (EMACS_INT);
-static int message_log_check_duplicate (EMACS_INT, EMACS_INT,
- EMACS_INT, EMACS_INT);
+static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT,
+ EMACS_INT, EMACS_INT);
static void push_it (struct it *);
static void pop_it (struct it *);
static void sync_frame_with_window_matrix_rows (struct window *);
static int display_mode_line (struct window *, enum face_id, Lisp_Object);
static int display_mode_element (struct it *, int, int, int, Lisp_Object, Lisp_Object, int);
static int store_mode_line_string (const char *, Lisp_Object, int, int, int, Lisp_Object);
-static const char *decode_mode_spec (struct window *, int, int, int,
- Lisp_Object *);
+static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
static void display_menu_bar (struct window *);
static int display_count_lines (EMACS_INT, EMACS_INT, EMACS_INT, int,
EMACS_INT *);
-static int display_string (const unsigned char *, Lisp_Object, Lisp_Object,
+static int display_string (const char *, Lisp_Object, Lisp_Object,
EMACS_INT, EMACS_INT, struct it *, int, int, int, int);
static void compute_line_metrics (struct it *);
static void run_redisplay_end_trigger_hook (struct it *);
static void load_overlay_strings (struct it *, EMACS_INT);
static int init_from_display_pos (struct it *, struct window *,
struct display_pos *);
-static void reseat_to_string (struct it *, const unsigned char *,
+static void reseat_to_string (struct it *, const char *,
Lisp_Object, EMACS_INT, EMACS_INT, int, int);
static enum move_it_result
move_it_in_display_line_to (struct it *, EMACS_INT, int,
static struct text_pos string_pos_nchars_ahead (struct text_pos,
Lisp_Object, EMACS_INT);
static struct text_pos string_pos (EMACS_INT, Lisp_Object);
-static struct text_pos c_string_pos (EMACS_INT, const unsigned char *, int);
-static EMACS_INT number_of_chars (const unsigned char *, int);
+static struct text_pos c_string_pos (EMACS_INT, const char *, int);
+static EMACS_INT number_of_chars (const char *, int);
static void compute_stop_pos (struct it *);
static void compute_string_pos (struct text_pos *, struct text_pos,
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
if (WINDOW_WANTS_MODELINE_P (w))
current_mode_line_height
= display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
- current_buffer->mode_line_format);
+ BVAR (current_buffer, mode_line_format));
if (WINDOW_WANTS_HEADER_LINE_P (w))
current_header_line_height
= display_mode_line (w, HEADER_LINE_FACE_ID,
- current_buffer->header_line_format);
+ BVAR (current_buffer, header_line_format));
start_display (&it, w, top);
move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
}
-/* 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;
}
means recognize multibyte characters. */
static struct text_pos
-c_string_pos (EMACS_INT charpos, const unsigned char *s, int multibyte_p)
+c_string_pos (EMACS_INT charpos, const char *s, int multibyte_p)
{
struct text_pos pos;
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);
+ string_char_and_length ((const unsigned char *) s, &len);
+ s += len;
CHARPOS (pos) += 1;
BYTEPOS (pos) += len;
}
non-zero means recognize multibyte characters. */
static EMACS_INT
-number_of_chars (const unsigned char *s, int multibyte_p)
+number_of_chars (const char *s, int multibyte_p)
{
EMACS_INT nchars;
{
EMACS_INT rest = strlen (s);
int len;
- unsigned char *p = (unsigned char *) s;
+ const unsigned char *p = (const unsigned char *) s;
for (nchars = 0; rest > 0; ++nchars)
{
}
-#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);
static Lisp_Object
safe_eval_handler (Lisp_Object arg)
{
- add_to_log ("Error during redisplay: %s", arg, Qnil);
+ add_to_log ("Error during redisplay: %S", arg, Qnil);
return Qnil;
}
redisplay during the evaluation. */
Lisp_Object
-safe_call (int nargs, Lisp_Object *args)
+safe_call (size_t nargs, Lisp_Object *args)
{
Lisp_Object val;
if (base_face_id == DEFAULT_FACE_ID
&& FRAME_WINDOW_P (it->f))
{
- if (NATNUMP (current_buffer->extra_line_spacing))
- it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
- else if (FLOATP (current_buffer->extra_line_spacing))
- it->extra_line_spacing = (XFLOAT_DATA (current_buffer->extra_line_spacing)
+ if (NATNUMP (BVAR (current_buffer, extra_line_spacing)))
+ it->extra_line_spacing = XFASTINT (BVAR (current_buffer, extra_line_spacing));
+ else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
+ it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
* FRAME_LINE_HEIGHT (it->f));
else if (it->f->extra_line_spacing > 0)
it->extra_line_spacing = it->f->extra_line_spacing;
it->override_ascent = -1;
/* Are control characters displayed as `^C'? */
- it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
+ it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
/* -1 means everything between a CR and the following line end
is invisible. >0 means lines indented more than this value are
invisible. */
- it->selective = (INTEGERP (current_buffer->selective_display)
- ? XFASTINT (current_buffer->selective_display)
- : (!NILP (current_buffer->selective_display)
+ it->selective = (INTEGERP (BVAR (current_buffer, selective_display))
+ ? XFASTINT (BVAR (current_buffer, selective_display))
+ : (!NILP (BVAR (current_buffer, selective_display))
? -1 : 0));
it->selective_display_ellipsis_p
- = !NILP (current_buffer->selective_display_ellipses);
+ = !NILP (BVAR (current_buffer, selective_display_ellipses));
/* Display table to use. */
it->dp = window_display_table (w);
/* Are multibyte characters enabled in current_buffer? */
- it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
+ it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
/* Do we need to reorder bidirectional text? Not if this is a
unibyte buffer: by definition, none of the single-byte characters
are strong R2L, so no reordering is needed. And bidi.c doesn't
support unibyte buffers anyway. */
it->bidi_p
- = !NILP (current_buffer->bidi_display_reordering) && it->multibyte_p;
+ = !NILP (BVAR (current_buffer, bidi_display_reordering)) && it->multibyte_p;
/* Non-zero if we should highlight the region. */
highlight_region_p
= (!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active)
- && XMARKER (current_buffer->mark)->buffer != 0);
+ && !NILP (BVAR (current_buffer, mark_active))
+ && XMARKER (BVAR (current_buffer, mark))->buffer != 0);
/* Set IT->region_beg_charpos and IT->region_end_charpos to the
start and end of a visible region in window IT->w. Set both to
&& WINDOWP (minibuf_selected_window)
&& w == XWINDOW (minibuf_selected_window))))
{
- EMACS_INT charpos = marker_position (current_buffer->mark);
- it->region_beg_charpos = min (PT, charpos);
- it->region_end_charpos = max (PT, charpos);
+ EMACS_INT markpos = marker_position (BVAR (current_buffer, mark));
+ it->region_beg_charpos = min (PT, markpos);
+ it->region_end_charpos = max (PT, markpos);
}
else
it->region_beg_charpos = it->region_end_charpos = -1;
it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
/* Correct bogus values of tab_width. */
- it->tab_width = XINT (current_buffer->tab_width);
+ it->tab_width = XINT (BVAR (current_buffer, tab_width));
if (it->tab_width <= 0 || it->tab_width > 1000)
it->tab_width = 8;
&& (WINDOW_TOTAL_COLS (it->w)
< XINT (Vtruncate_partial_width_windows))))))
it->line_wrap = TRUNCATE;
- else if (NILP (current_buffer->truncate_lines))
- it->line_wrap = NILP (current_buffer->word_wrap)
+ else if (NILP (BVAR (current_buffer, truncate_lines)))
+ it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
? WINDOW_WRAP : WORD_WRAP;
else
it->line_wrap = TRUNCATE;
{
/* Note the paragraph direction that this buffer wants to
use. */
- if (EQ (current_buffer->bidi_paragraph_direction, Qleft_to_right))
+ if (EQ (BVAR (current_buffer, bidi_paragraph_direction), Qleft_to_right))
it->paragraph_embedding = L2R;
- else if (EQ (current_buffer->bidi_paragraph_direction, Qright_to_left))
+ else if (EQ (BVAR (current_buffer, bidi_paragraph_direction), Qright_to_left))
it->paragraph_embedding = R2L;
else
it->paragraph_embedding = NEUTRAL_DIR;
to 16 in 22.1 to make this a lesser problem. */
for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
{
- const char *s = SDATA (it->overlay_strings[i]);
+ const char *s = SSDATA (it->overlay_strings[i]);
const char *e = s + SBYTES (it->overlay_strings[i]);
while (s < e && *s != '\n')
{
int count = SPECPDL_INDEX ();
Lisp_Object val;
+ struct buffer *obuf = current_buffer;
+ int begv = BEGV, zv = ZV;
+ int old_clip_changed = current_buffer->clip_changed;
val = Vfontification_functions;
specbind (Qfontification_functions, Qnil);
+ xassert (it->end_charpos == ZV);
+
if (!CONSP (val) || EQ (XCAR (val), Qlambda))
safe_call1 (val, pos);
else
{
- Lisp_Object globals, fn;
+ Lisp_Object fns, fn;
struct gcpro gcpro1, gcpro2;
- globals = Qnil;
- GCPRO2 (val, globals);
+ fns = Qnil;
+ GCPRO2 (val, fns);
for (; CONSP (val); val = XCDR (val))
{
In a global value, t should not occur. If it
does, we must ignore it to avoid an endless
loop. */
- for (globals = Fdefault_value (Qfontification_functions);
- CONSP (globals);
- globals = XCDR (globals))
+ for (fns = Fdefault_value (Qfontification_functions);
+ CONSP (fns);
+ fns = XCDR (fns))
{
- fn = XCAR (globals);
+ fn = XCAR (fns);
if (!EQ (fn, Qt))
safe_call1 (fn, pos);
}
unbind_to (count, Qnil);
+ /* Fontification functions routinely call `save-restriction'.
+ Normally, this tags clip_changed, which can confuse redisplay
+ (see discussion in Bug#6671). Since we don't perform any
+ special handling of fontification changes in the case where
+ `save-restriction' isn't called, there's no point doing so in
+ this case either. So, if the buffer's restrictions are
+ actually left unchanged, reset clip_changed. */
+ if (obuf == current_buffer)
+ {
+ if (begv == BEGV && zv == ZV)
+ current_buffer->clip_changed = old_clip_changed;
+ }
+ /* There isn't much we can reasonably do to protect against
+ misbehaving fontification, but here's a fig leaf. */
+ else if (!NILP (BVAR (obuf, name)))
+ set_buffer_internal_1 (obuf);
+
+ /* The fontification code may have added/removed text.
+ It could do even a lot worse, but let's at least protect against
+ the most obvious case where only the text past `pos' gets changed',
+ as is/was done in grep.el where some escapes sequences are turned
+ into face properties (bug#7876). */
+ it->end_charpos = ZV;
+
/* Return HANDLED_RECOMPUTE_PROPS only if function fontified
something. This avoids an endless loop if they failed to
fontify the text for which reason ever. */
else if (NUMBERP (it->font_height))
{
/* Value is a multiple of the canonical char height. */
- struct face *face;
+ struct face *f;
- face = FACE_FROM_ID (it->f,
- lookup_basic_face (it->f, DEFAULT_FACE_ID));
+ f = FACE_FROM_ID (it->f,
+ lookup_basic_face (it->f, DEFAULT_FACE_ID));
new_height = (XFLOATINT (it->font_height)
- * XINT (face->lface[LFACE_HEIGHT_INDEX]));
+ * XINT (f->lface[LFACE_HEIGHT_INDEX]));
}
else
{
return 0;
}
-/* Look for STRING in overlays and text properties in W's buffer,
- between character positions FROM and TO (excluding TO).
+/* Look for STRING in overlays and text properties in the current
+ buffer, between character positions FROM and TO (excluding TO).
BACK_P non-zero means look back (in this case, TO is supposed to be
less than FROM).
Value is the first character position where STRING was found, or
zero if it wasn't found before hitting TO.
- W's buffer must be current.
-
This function may only use code that doesn't eval because it is
called asynchronously from note_mouse_highlight. */
static EMACS_INT
-string_buffer_position_lim (struct window *w, Lisp_Object string,
+string_buffer_position_lim (Lisp_Object string,
EMACS_INT from, EMACS_INT to, int back_p)
{
Lisp_Object limit, prop, pos;
return found ? XINT (pos) : 0;
}
-/* Determine which buffer position in W's buffer STRING comes from.
+/* Determine which buffer position in current buffer STRING comes from.
AROUND_CHARPOS is an approximate position where it could come from.
Value is the buffer position or 0 if it couldn't be determined.
- W's buffer must be current.
-
This function is necessary because we don't record buffer positions
in glyphs generated from strings (to keep struct glyph small).
This function may only use code that doesn't eval because it is
called asynchronously from note_mouse_highlight. */
-EMACS_INT
-string_buffer_position (struct window *w, Lisp_Object string, EMACS_INT around_charpos)
+static EMACS_INT
+string_buffer_position (Lisp_Object string, EMACS_INT around_charpos)
{
const int MAX_DISTANCE = 1000;
- EMACS_INT found = string_buffer_position_lim (w, string, around_charpos,
+ EMACS_INT found = string_buffer_position_lim (string, around_charpos,
around_charpos + MAX_DISTANCE,
0);
if (!found)
- found = string_buffer_position_lim (w, string, around_charpos,
+ found = string_buffer_position_lim (string, around_charpos,
around_charpos - MAX_DISTANCE, 1);
return found;
}
&& 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->method = GET_FROM_BUFFER;
it->object = it->w->buffer;
it->area = TEXT_AREA;
- it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
+ it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
it->sp = 0;
it->string_from_display_prop_p = 0;
it->face_before_selective_p = 0;
calling this function. */
static void
-reseat_to_string (struct it *it, const unsigned char *s, Lisp_Object string,
+reseat_to_string (struct it *it, const char *s, Lisp_Object string,
EMACS_INT charpos, EMACS_INT precision, int field_width,
int multibyte)
{
}
else
{
- it->s = s;
+ it->s = (const unsigned char *) s;
it->string = Qnil;
/* Note that we use IT->current.pos, not it->current.string_pos,
(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
&& it->current_y < it->last_visible_y)
handle_line_prefix (it);
+ if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
+ SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
+
while (1)
{
int x, i, ascent = 0, descent = 0;
if (it->area != TEXT_AREA)
{
set_iterator_to_next (it, 1);
+ if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
+ SET_TEXT_POS (this_line_min_pos,
+ IT_CHARPOS (*it), IT_BYTEPOS (*it));
continue;
}
}
set_iterator_to_next (it, 1);
+ if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
+ SET_TEXT_POS (this_line_min_pos,
+ IT_CHARPOS (*it), IT_BYTEPOS (*it));
/* On graphical terminals, newlines may
"overflow" into the fringe if
overflow-newline-into-fringe is non-nil.
/* The current display element has been consumed. Advance
to the next. */
set_iterator_to_next (it, 1);
+ if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
+ SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
/* Stop if lines are truncated and IT's current x-position is
past the right edge of the window now. */
void
message_dolog (const char *m, EMACS_INT nbytes, int nlflag, int multibyte)
{
+ const unsigned char *msg = (const unsigned char *) m;
+
if (!NILP (Vmemory_full))
return;
old_deactivate_mark = Vdeactivate_mark;
oldbuf = current_buffer;
Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
- current_buffer->undo_list = Qt;
+ BVAR (current_buffer, undo_list) = Qt;
oldpoint = message_dolog_marker1;
set_marker_restricted (oldpoint, make_number (PT), Qnil);
/* Insert the string--maybe converting multibyte to single byte
or vice versa, so that all the text fits the buffer. */
if (multibyte
- && NILP (current_buffer->enable_multibyte_characters))
+ && NILP (BVAR (current_buffer, enable_multibyte_characters)))
{
EMACS_INT i;
int c, char_bytes;
- unsigned char work[1];
+ char work[1];
/* Convert a multibyte string to single-byte
for the *Message* buffer. */
for (i = 0; i < nbytes; i += char_bytes)
{
- c = string_char_and_length (m + i, &char_bytes);
+ c = string_char_and_length (msg + i, &char_bytes);
work[0] = (ASCII_CHAR_P (c)
? c
- : multibyte_char_to_unibyte (c, Qnil));
+ : multibyte_char_to_unibyte (c));
insert_1_both (work, 1, 1, 1, 0, 0);
}
}
else if (! multibyte
- && ! NILP (current_buffer->enable_multibyte_characters))
+ && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
{
EMACS_INT i;
int c, char_bytes;
- unsigned char *msg = (unsigned char *) m;
unsigned char str[MAX_MULTIBYTE_LENGTH];
/* Convert a single-byte string to multibyte
for the *Message* buffer. */
c = msg[i];
MAKE_CHAR_MULTIBYTE (c);
char_bytes = CHAR_STRING (c, str);
- insert_1_both (str, 1, char_bytes, 1, 0, 0);
+ insert_1_both ((char *) str, 1, char_bytes, 1, 0, 0);
}
}
else if (nbytes)
if (nlflag)
{
EMACS_INT this_bol, this_bol_byte, prev_bol, prev_bol_byte;
- int dup;
+ unsigned long int dups;
insert_1 ("\n", 1, 1, 0, 0);
scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
prev_bol = PT;
prev_bol_byte = PT_BYTE;
- dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
- this_bol, this_bol_byte);
- if (dup)
+ dups = message_log_check_duplicate (prev_bol, prev_bol_byte,
+ this_bol, this_bol_byte);
+ if (dups)
{
del_range_both (prev_bol, prev_bol_byte,
this_bol, this_bol_byte, 0);
- if (dup > 1)
+ if (dups > 1)
{
char dupstr[40];
int duplen;
/* If you change this format, don't forget to also
change message_log_check_duplicate. */
- sprintf (dupstr, " [%d times]", dup);
+ sprintf (dupstr, " [%lu times]", dups);
duplen = strlen (dupstr);
TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
insert_1 (dupstr, duplen, 1, 0, 1);
Return 0 if different, 1 if the new one should just replace it, or a
value N > 1 if we should also append " [N times]". */
-static int
+static unsigned long int
message_log_check_duplicate (EMACS_INT prev_bol, EMACS_INT prev_bol_byte,
EMACS_INT this_bol, EMACS_INT this_bol_byte)
{
return 2;
if (*p1++ == ' ' && *p1++ == '[')
{
- int n = 0;
- while (*p1 >= '0' && *p1 <= '9')
- n = n * 10 + *p1++ - '0';
- if (strncmp (p1, " times]\n", 8) == 0)
+ char *pend;
+ unsigned long int n = strtoul ((char *) p1, &pend, 10);
+ if (strncmp (pend, " times]\n", 8) == 0)
return n+1;
}
return 0;
cmd_error, so this must be just an informative message; toss it. */
if (FRAME_MESSAGE_BUF (f))
{
- Lisp_Object args[2], message;
+ Lisp_Object args[2], msg;
struct gcpro gcpro1, gcpro2;
args[0] = build_string (m);
- args[1] = message = string;
- GCPRO2 (args[0], message);
+ args[1] = msg = string;
+ GCPRO2 (args[0], msg);
gcpro1.nvars = 2;
- message = Fformat (2, args);
+ msg = Fformat (2, args);
if (log)
- message3 (message, SBYTES (message), STRING_MULTIBYTE (message));
+ message3 (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
else
- message3_nolog (message, SBYTES (message), STRING_MULTIBYTE (message));
+ message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
UNGCPRO;
Lisp_Object string;
string = Fcurrent_message ();
message3 (string, SBYTES (string),
- !NILP (current_buffer->enable_multibyte_characters));
+ !NILP (BVAR (current_buffer, enable_multibyte_characters)));
}
}
for (i = 0; i < 2; ++i)
if (!BUFFERP (echo_buffer[i])
- || NILP (XBUFFER (echo_buffer[i])->name))
+ || NILP (BVAR (XBUFFER (echo_buffer[i]), name)))
{
char name[30];
Lisp_Object old_buffer;
old_buffer = echo_buffer[i];
sprintf (name, " *Echo Area %d*", i);
echo_buffer[i] = Fget_buffer_create (build_string (name));
- XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
+ BVAR (XBUFFER (echo_buffer[i]), truncate_lines) = Qnil;
/* to force word wrap in echo area -
it was decided to postpone this*/
/* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
}
- current_buffer->undo_list = Qt;
- current_buffer->read_only = Qnil;
+ BVAR (current_buffer, undo_list) = Qt;
+ BVAR (current_buffer, read_only) = Qnil;
specbind (Qinhibit_read_only, Qt);
specbind (Qinhibit_modification_hooks, Qt);
/* Switch to that buffer and clear it. */
set_buffer_internal (XBUFFER (echo_area_buffer[0]));
- current_buffer->truncate_lines = Qnil;
+ BVAR (current_buffer, truncate_lines) = Qnil;
if (Z > BEG)
{
/* Set up the buffer for the multibyteness we need. */
if (multibyte_p
- != !NILP (current_buffer->enable_multibyte_characters))
+ != !NILP (BVAR (current_buffer, enable_multibyte_characters)))
Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
/* Raise the frame containing the echo area. */
{
/* Someone switched buffers between print requests. */
set_buffer_internal (XBUFFER (echo_area_buffer[0]));
- current_buffer->truncate_lines = Qnil;
+ BVAR (current_buffer, truncate_lines) = Qnil;
}
}
}
set_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT nbytes, EMACS_INT multibyte_p)
{
const char *s = (const char *) a1;
+ const unsigned char *msg = (const unsigned char *) s;
Lisp_Object string = a2;
/* Change multibyteness of the echo buffer appropriately. */
if (message_enable_multibyte
- != !NILP (current_buffer->enable_multibyte_characters))
+ != !NILP (BVAR (current_buffer, enable_multibyte_characters)))
Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
- current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
+ BVAR (current_buffer, truncate_lines) = message_truncate_lines ? Qt : Qnil;
+ if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
+ BVAR (current_buffer, bidi_paragraph_direction) = Qleft_to_right;
/* Insert new message at BEG. */
TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
if (nbytes == 0)
nbytes = strlen (s);
- if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
+ if (multibyte_p && NILP (BVAR (current_buffer, enable_multibyte_characters)))
{
/* Convert from multi-byte to single-byte. */
EMACS_INT i;
int c, n;
- unsigned char work[1];
+ char work[1];
/* Convert a multibyte string to single-byte. */
for (i = 0; i < nbytes; i += n)
{
- c = string_char_and_length (s + i, &n);
+ c = string_char_and_length (msg + i, &n);
work[0] = (ASCII_CHAR_P (c)
? c
- : multibyte_char_to_unibyte (c, Qnil));
+ : multibyte_char_to_unibyte (c));
insert_1_both (work, 1, 1, 1, 0, 0);
}
}
else if (!multibyte_p
- && !NILP (current_buffer->enable_multibyte_characters))
+ && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
{
/* Convert from single-byte to multi-byte. */
EMACS_INT i;
int c, n;
- const unsigned char *msg = (const unsigned char *) s;
unsigned char str[MAX_MULTIBYTE_LENGTH];
/* Convert a single-byte string to multibyte. */
c = msg[i];
MAKE_CHAR_MULTIBYTE (c);
n = CHAR_STRING (c, str);
- insert_1_both (str, 1, n, 1, 0, 0);
+ insert_1_both ((char *) str, 1, n, 1, 0, 0);
}
}
else
/* Store part of a frame title in mode_line_noprop_buf, beginning at
- mode_line_noprop_ptr. STR is the string to store. Do not copy
+ mode_line_noprop_ptr. STRING is the string to store. Do not copy
characters that yield more columns than PRECISION; PRECISION <= 0
means copy the whole string. Pad with spaces until FIELD_WIDTH
number of characters have been copied; FIELD_WIDTH <= 0 means don't
frame title. */
static int
-store_mode_line_noprop (const unsigned char *str, int field_width, int precision)
+store_mode_line_noprop (const char *string, int field_width, int precision)
{
+ const unsigned char *str = (const unsigned char *) string;
int n = 0;
EMACS_INT dummy, nbytes;
/* Copy at most PRECISION chars from STR. */
- nbytes = strlen (str);
+ nbytes = strlen (string);
n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
while (nbytes--)
store_mode_line_noprop_char (*str++);
< BUF_MODIFF (XBUFFER (w->buffer)))
!= !NILP (w->last_had_star))
|| ((!NILP (Vtransient_mark_mode)
- && !NILP (XBUFFER (w->buffer)->mark_active))
+ && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
!= !NILP (w->region_showing)))
{
struct buffer *prev = current_buffer;
< BUF_MODIFF (XBUFFER (w->buffer)))
!= !NILP (w->last_had_star))
|| ((!NILP (Vtransient_mark_mode)
- && !NILP (XBUFFER (w->buffer)->mark_active))
+ && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
!= !NILP (w->region_showing)))
{
struct buffer *prev = current_buffer;
row->used[TEXT_AREA] = n_glyphs_before;
*it = it_before;
/* If this is the only glyph on this line, it will never fit on the
- toolbar, so skip it. But ensure there is at least one glyph,
+ tool-bar, so skip it. But ensure there is at least one glyph,
so we don't accidentally disable the tool-bar. */
if (n_glyphs_before == 0
&& (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
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:
current_buffer = XBUFFER (w->buffer);
if (w == XWINDOW (selected_window))
- pt = BUF_PT (current_buffer);
+ pt = PT;
else
{
pt = marker_position (w->pointm);
/* Values of window_end_pos and window_end_vpos at the end of
try_window_id. */
-EMACS_INT debug_end_pos, debug_end_vpos;
+EMACS_INT debug_end_vpos;
/* Append a string to W->desired_matrix->method. FMT is a printf
format string. A1...A9 are a supplement for a variable-length
w,
((BUFFERP (w->buffer)
&& STRINGP (XBUFFER (w->buffer)->name))
- ? (char *) SDATA (XBUFFER (w->buffer)->name)
+ ? SSDATA (XBUFFER (w->buffer)->name)
: "no buffer"),
buffer);
}
/* If selective display, can't optimize if changes start at the
beginning of the line. */
if (unchanged_p
- && INTEGERP (current_buffer->selective_display)
- && XINT (current_buffer->selective_display) > 0
+ && INTEGERP (BVAR (current_buffer, selective_display))
+ && XINT (BVAR (current_buffer, selective_display)) > 0
&& (BEG_UNCHANGED < start || GPT <= start))
unchanged_p = 0;
require to redisplay the whole paragraph. It might be worthwhile
to find the paragraph limits and widen the range of redisplayed
lines to that, but for now just give up this optimization. */
- if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering)
- && NILP (XBUFFER (w->buffer)->bidi_paragraph_direction))
+ if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
+ && NILP (BVAR (XBUFFER (w->buffer), bidi_paragraph_direction)))
unchanged_p = 0;
}
EMACS_INT pt;
if (w == XWINDOW (selected_window))
- pt = BUF_PT (current_buffer);
+ pt = PT;
else
pt = marker_position (w->pointm);
redisplay_internal (int preserve_echo_area)
{
struct window *w = XWINDOW (selected_window);
- struct frame *f;
- int pause;
+ struct window *sw;
+ struct frame *fr;
+ int pending;
int must_finish = 0;
struct text_pos tlbufpos, tlendpos;
int number_of_visible_frames;
/* Don't examine these until after testing Vinhibit_redisplay.
When Emacs is shutting down, perhaps because its connection to
X has dropped, we should not look at them at all. */
- f = XFRAME (w->frame);
+ fr = XFRAME (w->frame);
sf = SELECTED_FRAME ();
- if (!f->glyphs_initialized_p)
+ if (!fr->glyphs_initialized_p)
return;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
}
retry:
+ /* Remember the currently selected window. */
+ sw = w;
+
if (!EQ (old_frame, selected_frame)
&& FRAME_LIVE_P (XFRAME (old_frame)))
/* When running redisplay, we play a bit fast-and-loose and allow e.g.
may need to run Elisp code (via prepare_menu_bars). */
select_frame_for_redisplay (old_frame);
- pause = 0;
+ pending = 0;
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. */
/* Notice any pending interrupt request to change frame size. */
do_pending_window_change (1);
+ /* do_pending_window_change could change the selected_window due to
+ frame resizing which makes the selected window too small. */
+ if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
+ {
+ sw = w;
+ reconsider_clip_changes (w, current_buffer);
+ }
+
/* Clear frames marked as garbaged. */
if (frame_garbaged)
clear_garbaged_frames ();
&& !(PT == XFASTINT (w->last_point)
&& XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
- && (XFASTINT (w->column_number_displayed)
- != (int) current_column ())) /* iftc */
+ && (XFASTINT (w->column_number_displayed) != current_column ()))
w->update_mode_line = Qt;
unbind_to (count1, Qnil);
the whole window. The assignment to this_line_start_pos prevents
the optimization directly below this if-statement. */
if (((!NILP (Vtransient_mark_mode)
- && !NILP (XBUFFER (w->buffer)->mark_active))
+ && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
!= !NILP (w->region_showing))
|| (!NILP (w->region_showing)
&& !EQ (w->region_showing,
- Fmarker_position (XBUFFER (w->buffer)->mark))))
+ Fmarker_position (BVAR (XBUFFER (w->buffer), mark)))))
CHARPOS (this_line_start_pos) = 0;
/* Optimize the case that only the line containing the cursor in the
if (!must_finish)
{
do_pending_window_change (1);
+ /* If selected_window changed, redisplay again. */
+ if (WINDOWP (selected_window)
+ && (w = XWINDOW (selected_window)) != sw)
+ goto retry;
/* We used to always goto end_of_redisplay here, but this
isn't enough if we have a blinking cursor. */
/* If highlighting the region, or if the cursor is in the echo area,
then we can't just move the cursor. */
else if (! (!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active))
- && (EQ (selected_window, current_buffer->last_selected_window)
+ && !NILP (BVAR (current_buffer, mark_active)))
+ && (EQ (selected_window, BVAR (current_buffer, last_selected_window))
|| highlight_nonselected_windows)
&& NILP (w->region_showing)
&& NILP (Vshow_trailing_whitespace)
/* Update the display. */
set_window_update_flags (XWINDOW (f->root_window), 1);
- pause |= update_frame (f, 0, 0);
+ pending |= update_frame (f, 0, 0);
f->updated_p = 1;
}
}
select_frame_for_redisplay (old_frame);
eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
- if (!pause)
+ if (!pending)
{
/* Do the mark_window_display_accurate after all windows have
been redisplayed because this call resets flags in buffers
goto retry;
XWINDOW (selected_window)->must_be_updated_p = 1;
- pause = update_frame (sf, 0, 0);
+ pending = update_frame (sf, 0, 0);
}
/* We may have called echo_area_display at the top of this
if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
{
XWINDOW (mini_window)->must_be_updated_p = 1;
- pause |= update_frame (mini_frame, 0, 0);
- if (!pause && hscroll_windows (mini_window))
+ pending |= update_frame (mini_frame, 0, 0);
+ if (!pending && hscroll_windows (mini_window))
goto retry;
}
}
/* If display was paused because of pending input, make sure we do a
thorough update the next time. */
- if (pause)
+ if (pending)
{
/* Prevent the optimization at the beginning of
redisplay_internal that tries a single-line update of the
redisplay constructing glyphs, so simply exposing a frame won't
display anything in this case. So, we have to display these
frames here explicitly. */
- if (!pause)
+ if (!pending)
{
Lisp_Object tail, frame;
int new_count = 0;
do_pending_window_change (1);
/* If we just did a pending size change, or have additional
- visible frames, redisplay again. */
- if (windows_or_buffers_changed && !pause)
+ visible frames, or selected_window changed, redisplay again. */
+ if ((windows_or_buffers_changed && !pending)
+ || (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw))
goto retry;
/* Clear the face and image caches.
}
\f
-/* Increment GLYPH until it reaches END or CONDITION fails while
- adding (GLYPH)->pixel_width to X. */
-
-#define SKIP_GLYPHS(glyph, end, x, condition) \
- do \
- { \
- (x) += (glyph)->pixel_width; \
- ++(glyph); \
- } \
- while ((glyph) < (end) && (condition))
-
-
/* Set cursor position of W. PT is assumed to be displayed in ROW.
DELTA and DELTA_BYTES are the numbers of characters and bytes by
which positions recorded in ROW differ from current buffer
&& 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;
EMACS_INT tem;
str = glyph->object;
- tem = string_buffer_position_lim (w, str, pos, pos_after, 0);
+ tem = string_buffer_position_lim (str, pos, pos_after, 0);
if (tem == 0 /* from overlay */
|| pos <= tem)
{
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;
/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
non-zero means only WINDOW is redisplayed in redisplay_internal.
- TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
+ TEMP_SCROLL_STEP has the same meaning as emacs_scroll_step, and is used
in redisplay_window to bring a partially visible line into view in
the case that only the cursor has moved.
static int
try_scrolling (Lisp_Object window, int just_this_one_p,
- EMACS_INT scroll_conservatively, EMACS_INT scroll_step,
+ EMACS_INT arg_scroll_conservatively, EMACS_INT scroll_step,
int temp_scroll_step, int last_line_misfit)
{
struct window *w = XWINDOW (window);
else
this_scroll_margin = 0;
- /* Force scroll_conservatively to have a reasonable value, to avoid
+ /* Force arg_scroll_conservatively to have a reasonable value, to avoid
overflow while computing how much to scroll. Note that the user
can supply scroll-conservatively equal to `most-positive-fixnum',
which can be larger than INT_MAX. */
- if (scroll_conservatively > scroll_limit)
+ if (arg_scroll_conservatively > scroll_limit)
{
- scroll_conservatively = scroll_limit;
+ arg_scroll_conservatively = scroll_limit;
scroll_max = INT_MAX;
}
- else if (scroll_step || scroll_conservatively || temp_scroll_step)
+ else if (scroll_step || arg_scroll_conservatively || temp_scroll_step)
/* Compute how much we should try to scroll maximally to bring
point into view. */
scroll_max = (max (scroll_step,
- max (scroll_conservatively, temp_scroll_step))
+ max (arg_scroll_conservatively, temp_scroll_step))
* FRAME_LINE_HEIGHT (f));
- else if (NUMBERP (current_buffer->scroll_down_aggressively)
- || NUMBERP (current_buffer->scroll_up_aggressively))
+ else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
+ || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
/* We're trying to scroll because of aggressive scrolling but no
scroll_step is set. Choose an arbitrary one. */
scroll_max = 10 * FRAME_LINE_HEIGHT (f);
/* Compute how many pixels below window bottom to stop searching
for PT. This avoids costly search for PT that is far away if
the user limited scrolling by a small number of lines, but
- always finds PT if scroll_conservatively is set to a large
+ always finds PT if arg_scroll_conservatively is set to a large
number, such as most-positive-fixnum. */
int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f));
int y_to_move =
window start down. If scrolling conservatively, move it just
enough down to make point visible. If scroll_step is set,
move it down by scroll_step. */
- if (scroll_conservatively)
+ if (arg_scroll_conservatively)
amount_to_scroll
= min (max (dy, FRAME_LINE_HEIGHT (f)),
- FRAME_LINE_HEIGHT (f) * scroll_conservatively);
+ FRAME_LINE_HEIGHT (f) * arg_scroll_conservatively);
else if (scroll_step || temp_scroll_step)
amount_to_scroll = scroll_max;
else
{
- aggressive = current_buffer->scroll_up_aggressively;
+ aggressive = BVAR (current_buffer, scroll_up_aggressively);
height = WINDOW_BOX_TEXT_HEIGHT (w);
if (NUMBERP (aggressive))
{
/* Compute new window start. */
start_display (&it, w, startp);
- if (scroll_conservatively)
+ if (arg_scroll_conservatively)
amount_to_scroll
= max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
else if (scroll_step || temp_scroll_step)
amount_to_scroll = scroll_max;
else
{
- aggressive = current_buffer->scroll_down_aggressively;
+ aggressive = BVAR (current_buffer, scroll_down_aggressively);
height = WINDOW_BOX_TEXT_HEIGHT (w);
if (NUMBERP (aggressive))
{
/* 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;
region exists, cursor movement has to do more than just
set the cursor. */
&& !(!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active))
+ && !NILP (BVAR (current_buffer, mark_active)))
&& NILP (w->region_showing)
&& NILP (Vshow_trailing_whitespace)
/* Right after splitting windows, last_point may be nil. */
&& row < w->current_matrix->rows
+ w->current_matrix->nrows - 1
&& MATRIX_ROW_START_CHARPOS (row+1) == PT
- && !cursor_row_p (w, row))
+ && !cursor_row_p (row))
++row;
/* If within the scroll margin, scroll. Note that
skip forward over overlay strings. */
while (MATRIX_ROW_BOTTOM_Y (row) < last_y
&& MATRIX_ROW_END_CHARPOS (row) == PT
- && !cursor_row_p (w, row))
+ && !cursor_row_p (row))
++row;
/* If within the scroll margin, scroll. */
must_scroll = 1;
}
else if (rc != CURSOR_MOVEMENT_SUCCESS
- && !NILP (XBUFFER (w->buffer)->bidi_display_reordering))
+ && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
{
/* If rows are bidi-reordered and point moved, back up
until we find a row that does not belong to a
else if (scroll_p)
rc = CURSOR_MOVEMENT_MUST_SCROLL;
else if (rc != CURSOR_MOVEMENT_SUCCESS
- && !NILP (XBUFFER (w->buffer)->bidi_display_reordering))
+ && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
{
/* With bidi-reordered rows, there could be more than
one candidate row whose start and end positions
{
if (MATRIX_ROW_START_CHARPOS (row) <= PT
&& PT <= MATRIX_ROW_END_CHARPOS (row)
- && cursor_row_p (w, row))
+ && cursor_row_p (row))
rv |= set_cursor_from_row (w, row, w->current_matrix,
0, 0, 0, 0);
/* As soon as we've found the first suitable row
}
while (MATRIX_ROW_BOTTOM_Y (row) < last_y
&& MATRIX_ROW_START_CHARPOS (row) == PT
- && cursor_row_p (w, row));
+ && cursor_row_p (row));
}
}
}
&& !(PT == XFASTINT (w->last_point)
&& XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
- && (XFASTINT (w->column_number_displayed)
- != (int) current_column ())) /* iftc */
+ && (XFASTINT (w->column_number_displayed) != current_column ()))
update_mode_line = 1;
/* Count number of windows showing the selected buffer. An indirect
struct Lisp_Char_Table *disptab = buffer_display_table ();
if (! disptab_matches_widthtab (disptab,
- XVECTOR (current_buffer->width_table)))
+ XVECTOR (BVAR (current_buffer, width_table))))
{
invalidate_region_cache (current_buffer,
current_buffer->width_run_cache,
/* If we are highlighting the region, then we just changed
the region, so redisplay to show it. */
if (!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active))
+ && !NILP (BVAR (current_buffer, mark_active)))
{
clear_glyph_matrix (w->desired_matrix);
if (!try_window (window, startp, 0))
/* Try to scroll by specified few lines. */
if ((scroll_conservatively
- || scroll_step
+ || emacs_scroll_step
|| temp_scroll_step
- || NUMBERP (current_buffer->scroll_up_aggressively)
- || NUMBERP (current_buffer->scroll_down_aggressively))
- && !current_buffer->clip_changed
+ || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
+ || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
&& CHARPOS (startp) >= BEGV
&& CHARPOS (startp) <= ZV)
{
/* The function returns -1 if new fonts were loaded, 1 if
successful, 0 if not successful. */
- int rc = try_scrolling (window, just_this_one_p,
+ int ss = try_scrolling (window, just_this_one_p,
scroll_conservatively,
- scroll_step,
+ emacs_scroll_step,
temp_scroll_step, last_line_misfit);
- switch (rc)
+ switch (ss)
{
case SCROLLING_SUCCESS:
goto done;
|| INTEGERP (w->base_line_pos)
/* Column number is displayed and different from the one displayed. */
|| (!NILP (w->column_number_displayed)
- && (XFASTINT (w->column_number_displayed)
- != (int) current_column ()))) /* iftc */
- /* This means that the window has a mode line. */
- && (WINDOW_WANTS_MODELINE_P (w)
- || WINDOW_WANTS_HEADER_LINE_P (w)))
+ && (XFASTINT (w->column_number_displayed) != current_column ())))
+ /* This means that the window has a mode line. */
+ && (WINDOW_WANTS_MODELINE_P (w)
+ || WINDOW_WANTS_HEADER_LINE_P (w)))
{
display_mode_lines (w);
try_window_reusing_current_matrix (struct window *w)
{
struct frame *f = XFRAME (w->frame);
- struct glyph_row *row, *bottom_row;
+ struct glyph_row *bottom_row;
struct it it;
struct run run;
struct text_pos start, new_start;
/* Can't do this if region may have changed. */
if ((!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active))
+ && !NILP (BVAR (current_buffer, mark_active)))
|| !NILP (w->region_showing)
|| !NILP (Vshow_trailing_whitespace))
return 0;
if (CHARPOS (new_start) <= CHARPOS (start))
{
- int first_row_y;
-
/* Don't use this method if the display starts with an ellipsis
displayed for invisible text. It's not easy to handle that case
below, and it's certainly not worth the effort since this is
text. Note that it.vpos == 0 if or if not there is a
header-line; it's not the same as the MATRIX_ROW_VPOS! */
start_display (&it, w, new_start);
- first_row_y = it.current_y;
w->cursor.vpos = -1;
last_text_row = last_reused_text_row = NULL;
have at least one reusable row. */
if (it.current_y < it.last_visible_y)
{
+ struct glyph_row *row;
+
/* IT.vpos always starts from 0; it counts text lines. */
nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
/* Can't use this optimization with bidi-reordered glyph
rows, unless cursor is already at point. */
- if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering))
+ if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
{
if (!(w->cursor.hpos >= 0
&& w->cursor.hpos < row->used[TEXT_AREA]
{
struct glyph *g;
- if (NILP (XBUFFER (w->buffer)->bidi_display_reordering)
+ if (NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
|| (!best_row && !row->continued_p))
return row;
/* In bidi-reordered rows, there could be several rows
/* Can't use this if highlighting a region because a cursor movement
will do more than just set the cursor. */
if (!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active))
+ && !NILP (BVAR (current_buffer, mark_active)))
GIVE_UP (9);
/* Likewise if highlighting trailing whitespace. */
wrapped line can change the wrap position, altering the line
above it. It might be worthwhile to handle this more
intelligently, but for now just redisplay from scratch. */
- if (!NILP (XBUFFER (w->buffer)->word_wrap))
+ if (!NILP (BVAR (XBUFFER (w->buffer), word_wrap)))
GIVE_UP (21);
/* Under bidi reordering, adding or deleting a character in the
to find the paragraph limits and widen the range of redisplayed
lines to that, but for now just give up this optimization and
redisplay from scratch. */
- if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering)
- && NILP (XBUFFER (w->buffer)->bidi_paragraph_direction))
+ if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
+ && NILP (BVAR (XBUFFER (w->buffer), bidi_paragraph_direction)))
GIVE_UP (22);
/* Make sure beg_unchanged and end_unchanged are up to date. Do it
|| (last_changed_charpos < CHARPOS (start) - 1
&& FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
{
- EMACS_INT Z_old, delta, Z_BYTE_old, delta_bytes;
+ EMACS_INT Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
struct glyph_row *r0;
/* Compute how many chars/bytes have been added to or removed
from the buffer. */
Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
- delta = Z - Z_old;
- delta_bytes = Z_BYTE - Z_BYTE_old;
+ Z_delta = Z - Z_old;
+ Z_delta_bytes = Z_BYTE - Z_BYTE_old;
/* Give up if PT is not in the window. Note that it already has
been checked at the start of try_window_id that PT is not in
front of the window start. */
- if (PT >= MATRIX_ROW_END_CHARPOS (row) + delta)
+ if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
GIVE_UP (13);
/* If window start is unchanged, we can reuse the whole matrix
as is, after adjusting glyph positions. No need to compute
the window end again, since its offset from Z hasn't changed. */
r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
- if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
- && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes
+ if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
+ && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
/* PT must not be in a partially visible line. */
- && !(PT >= MATRIX_ROW_START_CHARPOS (row) + delta
+ && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
&& MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
{
/* Adjust positions in the glyph matrix. */
- if (delta || delta_bytes)
+ if (Z_delta || Z_delta_bytes)
{
struct glyph_row *r1
= MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
increment_matrix_positions (w->current_matrix,
MATRIX_ROW_VPOS (r0, current_matrix),
MATRIX_ROW_VPOS (r1, current_matrix),
- delta, delta_bytes);
+ Z_delta, Z_delta_bytes);
}
/* Set the cursor. */
{
/* Terminal frame. In this case, dvpos gives the number of
lines to scroll by; dvpos < 0 means scroll up. */
- int first_unchanged_at_end_vpos
+ int from_vpos
= MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
- int from = WINDOW_TOP_EDGE_LINE (w) + first_unchanged_at_end_vpos;
+ int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
int end = (WINDOW_TOP_EDGE_LINE (w)
+ (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)
{
DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
doc: /* Like `format', but print result to stderr.
usage: (trace-to-stderr STRING &rest OBJECTS) */)
- (int nargs, Lisp_Object *args)
+ (size_t nargs, Lisp_Object *args)
{
Lisp_Object s = Fformat (nargs, args);
fprintf (stderr, "%s", SDATA (s));
it.glyph_row->used[TEXT_AREA] = 0;
SET_TEXT_POS (it.position, 0, 0);
- multibyte_p = !NILP (buffer->enable_multibyte_characters);
+ multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
p = arrow_string;
while (p < arrow_end)
{
compute_line_metrics (struct it *it)
{
struct glyph_row *row = it->glyph_row;
- int area, i;
if (FRAME_WINDOW_P (it->f))
{
}
/* Compute a hash code for this row. */
- row->hash = 0;
- for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
- for (i = 0; i < row->used[area]; ++i)
- row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
- + row->glyphs[area][i].u.val
- + row->glyphs[area][i].face_id
- + row->glyphs[area][i].padding_p
- + (row->glyphs[area][i].type << 2));
+ {
+ int area, i;
+ row->hash = 0;
+ for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+ for (i = 0; i < row->used[area]; ++i)
+ row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
+ + row->glyphs[area][i].u.val
+ + row->glyphs[area][i].face_id
+ + row->glyphs[area][i].padding_p
+ + (row->glyphs[area][i].type << 2));
+ }
it->max_ascent = it->max_descent = 0;
it->max_phys_ascent = it->max_phys_descent = 0;
}
-/* Value is non-zero if glyph row ROW in window W should be
+/* Value is non-zero if glyph row ROW should be
used to hold the cursor. */
static int
-cursor_row_p (struct window *w, struct glyph_row *row)
+cursor_row_p (struct glyph_row *row)
{
- int cursor_row_p = 1;
+ int result = 1;
if (PT == CHARPOS (row->end.pos))
{
if (CHARPOS (row->end.string_pos) >= 0)
{
if (row->continued_p)
- cursor_row_p = 1;
+ result = 1;
else
{
/* Check for `display' property. */
struct glyph *end = beg + row->used[TEXT_AREA] - 1;
struct glyph *glyph;
- cursor_row_p = 0;
+ result = 0;
for (glyph = end; glyph >= beg; --glyph)
if (STRINGP (glyph->object))
{
Lisp_Object prop
= Fget_char_property (make_number (PT),
Qdisplay, Qnil);
- cursor_row_p =
+ result =
(!NILP (prop)
&& display_prop_string_p (prop, glyph->object));
break;
That's because CHARPOS (ROW->end.pos) would equal
PT if PT is before the character. */
if (!row->ends_in_ellipsis_p)
- cursor_row_p = row->continued_p;
+ result = row->continued_p;
else
/* If the row ends in an ellipsis, then
CHARPOS (ROW->end.pos) will equal point after the
invisible text. We want that position to be displayed
after the ellipsis. */
- cursor_row_p = 0;
+ result = 0;
}
/* If the row ends at ZV, display the cursor at the end of that
row instead of at the start of the row below. */
else if (row->ends_at_zv_p)
- cursor_row_p = 1;
+ result = 1;
else
- cursor_row_p = 0;
+ result = 0;
}
- return cursor_row_p;
+ return result;
}
\f
if (min_pos <= ZV)
SET_TEXT_POS (row->minpos, min_pos, min_bpos);
else
- {
- /* We didn't find _any_ valid buffer positions in any of the
- glyphs, so we must trust the iterator's computed
- positions. */
+ /* We didn't find _any_ valid buffer positions in any of the
+ glyphs, so we must trust the iterator's computed positions. */
row->minpos = row->start.pos;
+ if (max_pos <= 0)
+ {
max_pos = CHARPOS (it->current.pos);
max_bpos = BYTEPOS (it->current.pos);
}
- if (!max_pos)
- abort ();
-
/* Here are the various use-cases for ending the row, and the
corresponding values for ROW->maxpos:
struct glyph_row *row = it->glyph_row;
Lisp_Object overlay_arrow_string;
struct it wrap_it;
- int may_wrap = 0, wrap_x;
- int wrap_row_used = -1, wrap_row_ascent, wrap_row_height;
- int wrap_row_phys_ascent, wrap_row_phys_height;
- int wrap_row_extra_line_spacing;
- EMACS_INT wrap_row_min_pos, wrap_row_min_bpos;
- EMACS_INT wrap_row_max_pos, wrap_row_max_bpos;
+ int may_wrap = 0, wrap_x IF_LINT (= 0);
+ int wrap_row_used = -1;
+ int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0);
+ int wrap_row_phys_ascent IF_LINT (= 0), wrap_row_phys_height IF_LINT (= 0);
+ int wrap_row_extra_line_spacing IF_LINT (= 0);
+ EMACS_INT wrap_row_min_pos IF_LINT (= 0), wrap_row_min_bpos IF_LINT (= 0);
+ EMACS_INT wrap_row_max_pos IF_LINT (= 0), wrap_row_max_bpos IF_LINT (= 0);
int cvpos;
- EMACS_INT min_pos = ZV + 1, min_bpos, max_pos = 0, max_bpos;
+ EMACS_INT min_pos = ZV + 1, max_pos = 0;
+ EMACS_INT min_bpos IF_LINT (= 0), max_bpos IF_LINT (= 0);
/* We always start displaying at hpos zero even if hscrolled. */
xassert (it->hpos == 0 && it->current_x == 0);
if the first glyph is partially visible or if we hit a line end. */
if (it->current_x < it->first_visible_x)
{
+ this_line_min_pos = row->start.pos;
move_it_in_display_line_to (it, ZV, it->first_visible_x,
MOVE_TO_POS | MOVE_TO_X);
+ /* Record the smallest positions seen while we moved over
+ display elements that are not visible. This is needed by
+ redisplay_internal for optimizing the case where the cursor
+ stays inside the same line. The rest of this function only
+ considers positions that are actually displayed, so
+ RECORD_MAX_MIN_POS will not otherwise record positions that
+ are hscrolled to the left of the left edge of the window. */
+ min_pos = CHARPOS (this_line_min_pos);
+ min_bpos = BYTEPOS (this_line_min_pos);
}
else
{
while (1)
{
int n_glyphs_before, hpos_before, x_before;
- int x, i, nglyphs;
+ int x, nglyphs;
int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
/* Retrieve the next thing to display. Value is zero if end of
row->glyphs[TEXT_AREA]->charpos = -1;
row->displays_text_p = 0;
- if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines)
+ if (!NILP (BVAR (XBUFFER (it->w->buffer), indicate_empty_lines))
&& (!MINI_WINDOW_P (it->w)
|| (minibuf_level && EQ (it->window, minibuf_window))))
row->indicate_empty_line_p = 1;
}
else
{
- int new_x;
+ int i, new_x;
struct glyph *glyph;
for (i = 0; i < nglyphs; ++i, x = new_x)
&& !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
&& PT >= MATRIX_ROW_START_CHARPOS (row)
&& PT <= MATRIX_ROW_END_CHARPOS (row)
- && cursor_row_p (it->w, row))
+ && cursor_row_p (row))
set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
/* Highlight trailing whitespace. */
See also `bidi-paragraph-direction'. */)
(Lisp_Object buffer)
{
- struct buffer *buf;
- struct buffer *old;
+ struct buffer *buf = current_buffer;
+ struct buffer *old = buf;
- if (NILP (buffer))
- buf = current_buffer;
- else
+ if (! NILP (buffer))
{
CHECK_BUFFER (buffer);
buf = XBUFFER (buffer);
- old = current_buffer;
}
- if (NILP (buf->bidi_display_reordering))
+ if (NILP (BVAR (buf, bidi_display_reordering)))
return Qleft_to_right;
- else if (!NILP (buf->bidi_paragraph_direction))
- return buf->bidi_paragraph_direction;
+ else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
+ return BVAR (buf, bidi_paragraph_direction);
else
{
/* Determine the direction from buffer text. We could try to
EMACS_INT bytepos = BUF_PT_BYTE (buf);
int c;
- if (buf != current_buffer)
- set_buffer_temp (buf);
+ set_buffer_temp (buf);
/* bidi_paragraph_init finds the base direction of the paragraph
by searching forward from paragraph start. We need the base
direction of the current or _previous_ paragraph, so we need
itb.paragraph_dir = NEUTRAL_DIR;
bidi_paragraph_init (NEUTRAL_DIR, &itb, 1);
- if (buf != current_buffer)
- set_buffer_temp (old);
+ set_buffer_temp (old);
switch (itb.paragraph_dir)
{
case L2R:
/* Select mode line face based on the real selected window. */
display_mode_line (w, CURRENT_MODE_LINE_FACE_ID_3 (sel_w, sel_w, w),
- current_buffer->mode_line_format);
+ BVAR (current_buffer, mode_line_format));
++n;
}
if (WINDOW_WANTS_HEADER_LINE_P (w))
{
display_mode_line (w, HEADER_LINE_FACE_ID,
- current_buffer->header_line_format);
+ BVAR (current_buffer, header_line_format));
++n;
}
{
case MODE_LINE_NOPROP:
case MODE_LINE_TITLE:
- n += store_mode_line_noprop (SDATA (elt), -1, prec);
+ n += store_mode_line_noprop (SSDATA (elt), -1, prec);
break;
case MODE_LINE_STRING:
n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
{
case MODE_LINE_NOPROP:
case MODE_LINE_TITLE:
- n += store_mode_line_noprop (SDATA (elt) + last_offset, 0, prec);
+ n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
break;
case MODE_LINE_STRING:
{
{
int multibyte;
EMACS_INT bytepos, charpos;
- const unsigned char *spec;
+ const char *spec;
Lisp_Object string;
bytepos = percent_position;
charpos = (STRING_MULTIBYTE (elt)
? string_byte_to_char (elt, bytepos)
: bytepos);
- spec = decode_mode_spec (it->w, c, field, prec, &string);
+ spec = decode_mode_spec (it->w, c, field, &string);
multibyte = STRINGP (string) && STRING_MULTIBYTE (string);
switch (mode_line_target)
First arg FORMAT specifies the mode line format (see `mode-line-format'
for details) to use.
-Optional second arg FACE specifies the face property to put
-on all characters for which no face is specified.
-The value t means whatever face the window's mode line currently uses
-\(either `mode-line' or `mode-line-inactive', depending).
-A value of nil means the default is no face property.
-If FACE is an integer, the value string has no text properties.
+By default, the format is evaluated for the currently selected window.
+
+Optional second arg FACE specifies the face property to put on all
+characters for which no face is specified. The value nil means the
+default face. The value t means whatever face the window's mode line
+currently uses (either `mode-line' or `mode-line-inactive',
+depending on whether the window is the selected window or not).
+An integer value means the value string has no text
+properties.
Optional third and fourth args WINDOW and BUFFER specify the window
and buffer to use as the context for the formatting (defaults
-are the selected window and the window's buffer). */)
- (Lisp_Object format, Lisp_Object face, Lisp_Object window, Lisp_Object buffer)
+are the selected window and the WINDOW's buffer). */)
+ (Lisp_Object format, Lisp_Object face,
+ Lisp_Object window, Lisp_Object buffer)
{
struct it it;
int len;
struct window *w;
struct buffer *old_buffer = NULL;
- int face_id = -1;
+ int face_id;
int no_props = INTEGERP (face);
int count = SPECPDL_INDEX ();
Lisp_Object str;
if (no_props)
face = Qnil;
- if (!NILP (face))
- {
- if (EQ (face, Qt))
- face = (EQ (window, selected_window) ? Qmode_line : Qmode_line_inactive);
- face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0);
- }
-
- if (face_id < 0)
- face_id = DEFAULT_FACE_ID;
+ face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
+ : EQ (face, Qt) ? (EQ (window, selected_window)
+ ? MODE_LINE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
+ : EQ (face, Qmode_line) ? MODE_LINE_FACE_ID
+ : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
+ : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
+ : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
+ : DEFAULT_FACE_ID;
if (XBUFFER (buffer) != current_buffer)
old_buffer = current_buffer;
the positive integer D to BUF using a minimal field width WIDTH. */
static void
-pint2str (register char *buf, register int width, register int d)
+pint2str (register char *buf, register int width, register EMACS_INT d)
{
register char *p = buf;
static const char power_letter[] =
{
- 0, /* not used */
+ 0, /* no letter */
'k', /* kilo */
'M', /* mega */
'G', /* giga */
p = psuffix = buf + max (width, length);
/* Print EXPONENT. */
- if (exponent)
- *psuffix++ = power_letter[exponent];
+ *psuffix++ = power_letter[exponent];
*psuffix = '\0';
/* Print TENTHS. */
decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_flag)
{
Lisp_Object val;
- int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+ int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
const unsigned char *eol_str;
int eol_str_len;
/* The EOL conversion we are using. */
}
/* Return a string for the output of a mode line %-spec for window W,
- generated by character C. PRECISION >= 0 means don't return a
- string longer than that value. FIELD_WIDTH > 0 means pad the
- string returned with spaces to that value. Return a Lisp string in
+ generated by character C. FIELD_WIDTH > 0 means pad the string
+ returned with spaces to that value. Return a Lisp string in
*STRING if the resulting string is taken from that Lisp string.
Note we operate on the current buffer for most purposes,
static const char *
decode_mode_spec (struct window *w, register int c, int field_width,
- int precision, Lisp_Object *string)
+ Lisp_Object *string)
{
Lisp_Object obj;
struct frame *f = XFRAME (WINDOW_FRAME (w));
switch (c)
{
case '*':
- if (!NILP (b->read_only))
+ if (!NILP (BVAR (b, read_only)))
return "%";
if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
return "*";
/* This differs from %* only for a modified read-only buffer. */
if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
return "*";
- if (!NILP (b->read_only))
+ if (!NILP (BVAR (b, read_only)))
return "%";
return "-";
}
case 'b':
- obj = b->name;
+ obj = BVAR (b, name);
break;
case 'c':
return "";
else
{
- int col = (int) current_column (); /* iftc */
+ EMACS_INT col = current_column ();
w->column_number_displayed = make_number (col);
pint2str (decode_mode_spec_buf, field_width, col);
return decode_mode_spec_buf;
case 'F':
/* %F displays the frame name. */
if (!NILP (f->title))
- return (char *) SDATA (f->title);
+ return SSDATA (f->title);
if (f->explicit_name || ! FRAME_WINDOW_P (f))
- return (char *) SDATA (f->name);
+ return SSDATA (f->name);
return "Emacs";
case 'f':
- obj = b->filename;
+ obj = BVAR (b, filename);
break;
case 'i':
break;
case 'm':
- obj = b->mode_name;
+ obj = BVAR (b, mode_name);
break;
case 'n':
{
int count = inhibit_garbage_collection ();
Lisp_Object val = call1 (intern ("file-remote-p"),
- current_buffer->directory);
+ BVAR (current_buffer, directory));
unbind_to (count, Qnil);
if (NILP (val))
}
case 't': /* indicate TEXT or BINARY */
-#ifdef MODE_LINE_BINARY_TEXT
- return MODE_LINE_BINARY_TEXT (b);
-#else
return "T";
-#endif
case 'z':
/* coding-system (not including end-of-line format) */
(FRAME_TERMINAL_CODING (f)->id),
p, 0);
}
- p = decode_mode_spec_coding (b->buffer_file_coding_system,
+ p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
p, eol_flag);
#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
if (STRINGP (obj))
{
*string = obj;
- return (char *) SDATA (obj);
+ return SSDATA (obj);
}
else
return "";
/* If we are not in selective display mode,
check only for newlines. */
- int selective_display = (!NILP (current_buffer->selective_display)
- && !INTEGERP (current_buffer->selective_display));
+ int selective_display = (!NILP (BVAR (current_buffer, selective_display))
+ && !INTEGERP (BVAR (current_buffer, selective_display)));
if (count > 0)
{
Value is the number of columns displayed. */
static int
-display_string (const unsigned char *string, Lisp_Object lisp_string, Lisp_Object face_string,
+display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
EMACS_INT face_string_pos, EMACS_INT start, struct it *it,
int field_width, int precision, int max_x, int multibyte)
{
{
if (!FRAME_WINDOW_P (it->f))
{
- int i, n;
+ int ii, n;
if (it->current_x > it->last_visible_x)
{
- for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
- if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
+ for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
+ if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
break;
- for (n = row->used[TEXT_AREA]; i < n; ++i)
+ for (n = row->used[TEXT_AREA]; ii < n; ++ii)
{
- row->used[TEXT_AREA] = i;
+ row->used[TEXT_AREA] = ii;
produce_special_glyphs (it, IT_TRUNCATION);
}
}
{
if (SCHARS (SYMBOL_NAME (prop)) == 2)
{
- char *unit = SDATA (SYMBOL_NAME (prop));
+ char *unit = SSDATA (SYMBOL_NAME (prop));
if (unit[0] == 'i' && unit[1] == 'n')
pixels = 1.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
int cmp_id = (row)->glyphs[area][START].u.cmp.id; \
struct composition *cmp = composition_table[cmp_id]; \
XChar2b *char2b; \
- struct glyph_string *first_s; \
+ struct glyph_string *first_s IF_LINT (= NULL); \
int n; \
\
char2b = (XChar2b *) alloca ((sizeof *char2b) * cmp->glyph_len); \
} 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; \
+ \
+ 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);
- int mouse_beg_col, mouse_end_col, check_mouse_face = 0;
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+ int mouse_beg_col IF_LINT (= 0), mouse_end_col IF_LINT (= 0);
+ int check_mouse_face = 0;
int dummy_x = 0;
/* If mouse highlighting is on, we may need to draw adjacent
{
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];
+ const char *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) ? SSDATA (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
+ {
+ /* FIXME: This code doesn't look right. It formerly was
+ missing the "lower_xoff = 0;", which couldn't have
+ been right since it left lower_xoff uninitialized. */
+ lower_xoff = 0;
+ 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
int ch = COMPOSITION_GLYPH (cmp, i);
int face_id;
struct face *this_face;
- int this_boff;
if (ch == '\t')
ch = ' ';
pcm = NULL;
else
{
- this_boff = font->baseline_offset;
- if (font->vertical_centering)
- this_boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
get_char_face_and_encoding (it->f, ch, face_id,
&char2b, it->multibyte_p, 0);
pcm = get_per_char_metric (it->f, font, &char2b);
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);
void
set_frame_cursor_types (struct frame *f, Lisp_Object arg)
{
- int width;
+ int width = 1;
Lisp_Object tem;
FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
}
+#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'
{
if (w == XWINDOW (echo_area_window))
{
- if (EQ (b->cursor_type, Qt) || NILP (b->cursor_type))
+ if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
{
*width = FRAME_CURSOR_WIDTH (f);
return FRAME_DESIRED_CURSOR (f);
}
else
- return get_specified_cursor_type (b->cursor_type, width);
+ return get_specified_cursor_type (BVAR (b, cursor_type), width);
}
*active_cursor = 0;
/* 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;
}
/* Never display a cursor in a window in which cursor-type is nil. */
- if (NILP (b->cursor_type))
+ if (NILP (BVAR (b, cursor_type)))
return NO_CURSOR;
/* Get the normal cursor type for this window. */
- if (EQ (b->cursor_type, Qt))
+ if (EQ (BVAR (b, cursor_type), Qt))
{
cursor_type = FRAME_DESIRED_CURSOR (f);
*width = FRAME_CURSOR_WIDTH (f);
}
else
- cursor_type = get_specified_cursor_type (b->cursor_type, width);
+ cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
/* Use cursor-in-non-selected-windows instead
for non-selected window or frame. */
if (non_selected)
{
- alt_cursor = b->cursor_in_non_selected_windows;
+ alt_cursor = BVAR (b, cursor_in_non_selected_windows);
if (!EQ (Qt, alt_cursor))
return get_specified_cursor_type (alt_cursor, width);
/* t means modify the normal cursor type. */
/* 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;
}
/* Cursor is blinked off, so determine how to "toggle" it. */
/* First look for an entry matching the buffer's cursor-type in blink-cursor-alist. */
- if ((alt_cursor = Fassoc (b->cursor_type, Vblink_cursor_alist), !NILP (alt_cursor)))
+ if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist), !NILP (alt_cursor)))
return get_specified_cursor_type (XCDR (alt_cursor), width);
/* Then see if frame has specified a specific blink off 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
/* Switch the display of W's cursor on or off, according to the value
of ON. */
-void
+static void
update_window_cursor (struct window *w, int on)
{
/* Don't update cursor in windows whose frame is in the process
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
face. BEFORE_STRING and AFTER_STRING, if non-nil, are a
before-string and after-string that must also be highlighted.
- DISPLAY_STRING, if non-nil, is a display string that may cover some
+ COVER_STRING, if non-nil, is a display string that may cover some
or all of the highlighted text. */
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,
Lisp_Object before_string,
Lisp_Object after_string,
- Lisp_Object display_string)
+ Lisp_Object cover_string)
{
struct window *w = XWINDOW (window);
struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
EMACS_INT ignore, pos;
int x;
- xassert (NILP (display_string) || STRINGP (display_string));
+ xassert (NILP (cover_string) || STRINGP (cover_string));
xassert (NILP (before_string) || STRINGP (before_string));
xassert (NILP (after_string) || STRINGP (after_string));
r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
/* If the before-string or display-string contains newlines,
rows_from_pos_range skips to its last row. Move back. */
- if (!NILP (before_string) || !NILP (display_string))
+ if (!NILP (before_string) || !NILP (cover_string))
{
struct glyph_row *prev;
while ((prev = r1 - 1, prev >= first)
while (--glyph >= beg && INTEGERP (glyph->object));
if (glyph < beg
|| !(EQ (glyph->object, before_string)
- || EQ (glyph->object, display_string)))
+ || EQ (glyph->object, cover_string)))
break;
r1 = prev;
}
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
+ AFTER_STRING, COVER_STRING, START_CHARPOS, and END_CHARPOS
could be anywhere in the row and in any order. The strategy
below is to find the leftmost and the rightmost glyph that
belongs to either of these 3 strings, or whose position is
x += glyph->pixel_width;
/* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
- or DISPLAY_STRING, and the first glyph from buffer whose
+ or COVER_STRING, and the first glyph from buffer whose
position is between START_CHARPOS and END_CHARPOS. */
for (; glyph < end
&& !INTEGERP (glyph->object)
- && !EQ (glyph->object, display_string)
+ && !EQ (glyph->object, cover_string)
&& !(BUFFERP (glyph->object)
&& (glyph->charpos >= start_charpos
&& glyph->charpos < end_charpos));
END_CHARPOS, or if they come from an overlay. */
if (EQ (glyph->object, before_string))
{
- pos = string_buffer_position (w, before_string,
+ pos = string_buffer_position (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)
+ pos = string_buffer_position (after_string, 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
{
;
/* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
- or DISPLAY_STRING, and the first glyph from buffer whose
+ or COVER_STRING, and the first glyph from buffer whose
position is between START_CHARPOS and END_CHARPOS. */
for (; glyph > end
&& !INTEGERP (glyph->object)
- && !EQ (glyph->object, display_string)
+ && !EQ (glyph->object, cover_string)
&& !(BUFFERP (glyph->object)
&& (glyph->charpos >= start_charpos
&& glyph->charpos < end_charpos));
END_CHARPOS, or if they come from an overlay. */
if (EQ (glyph->object, before_string))
{
- pos = string_buffer_position (w, before_string, start_charpos);
+ pos = string_buffer_position (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)
+ pos = string_buffer_position (after_string, 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
--end;
/* Scan the rest of the glyph row from the end, looking for the
first glyph that comes from BEFORE_STRING, AFTER_STRING, or
- DISPLAY_STRING, or whose position is between START_CHARPOS
+ COVER_STRING, or whose position is between START_CHARPOS
and END_CHARPOS */
for (--end;
end > glyph
&& !INTEGERP (end->object)
- && !EQ (end->object, display_string)
+ && !EQ (end->object, cover_string)
&& !(BUFFERP (end->object)
&& (end->charpos >= start_charpos
&& end->charpos < end_charpos));
END_CHARPOS, or if they come from an overlay. */
if (EQ (end->object, before_string))
{
- pos = string_buffer_position (w, before_string, start_charpos);
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ pos = string_buffer_position (before_string, start_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)
+ pos = string_buffer_position (after_string, 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
{
}
/* Scan the rest of the glyph row from the end, looking for the
first glyph that comes from BEFORE_STRING, AFTER_STRING, or
- DISPLAY_STRING, or whose position is between START_CHARPOS
+ COVER_STRING, or whose position is between START_CHARPOS
and END_CHARPOS */
for ( ;
end < glyph
&& !INTEGERP (end->object)
- && !EQ (end->object, display_string)
+ && !EQ (end->object, cover_string)
&& !(BUFFERP (end->object)
&& (end->charpos >= start_charpos
&& end->charpos < end_charpos));
END_CHARPOS, or if they come from an overlay. */
if (EQ (end->object, before_string))
{
- pos = string_buffer_position (w, before_string, start_charpos);
- if (!pos || pos >= start_charpos && pos < end_charpos)
+ pos = string_buffer_position (before_string, start_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)
+ pos = string_buffer_position (after_string, 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;
CONSP (hotspot))
&& (hotspot = XCDR (hotspot), CONSP (hotspot)))
{
- Lisp_Object area_id, plist;
+ Lisp_Object plist;
- area_id = XCAR (hotspot);
- /* Could check AREA_ID to see if we enter/leave this hot-spot.
+ /* Could check XCAR (hotspot) to see if we enter/leave this hot-spot.
If so, we could look for mouse-enter, mouse-leave
properties in PLIST (and do something...). */
hotspot = XCDR (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. */
EMACS_INT pos;
struct glyph *glyph;
Lisp_Object object;
- Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
+ Lisp_Object mouse_face = Qnil, position;
Lisp_Object *overlay_vec = NULL;
int noverlays;
struct buffer *obuf;
/* 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)
{
CONSP (hotspot))
&& (hotspot = XCDR (hotspot), CONSP (hotspot)))
{
- Lisp_Object area_id, plist;
+ Lisp_Object plist;
- area_id = XCAR (hotspot);
- /* Could check AREA_ID to see if we enter/leave this hot-spot.
+ /* Could check XCAR (hotspot) to see if we enter/leave
+ this hot-spot.
If so, we could look for mouse-enter, mouse-leave
properties in PLIST (and do something...). */
hotspot = XCDR (hotspot);
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;
+ Lisp_Object overlay = Qnil;
for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
{
mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
/* 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. */
{
/* The mouse-highlighting comes from a display string
with a mouse-face. */
- Lisp_Object b, e;
+ Lisp_Object s, e;
EMACS_INT ignore;
- b = Fprevious_single_property_change
+ s = Fprevious_single_property_change
(make_number (pos + 1), Qmouse_face, object, Qnil);
e = Fnext_single_property_change
(position, Qmouse_face, object, Qnil);
- if (NILP (b))
- b = make_number (0);
+ if (NILP (s))
+ s = make_number (0);
if (NILP (e))
e = make_number (SCHARS (object) - 1);
- mouse_face_from_string_pos (w, dpyinfo, object,
- XINT (b), XINT (e));
- dpyinfo->mouse_face_past_end = 0;
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id
+ mouse_face_from_string_pos (w, hlinfo, object,
+ XINT (s), XINT (e));
+ 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
{
/* The mouse-highlighting, if any, comes from an overlay
or text property in the buffer. */
- Lisp_Object buffer, display_string;
+ Lisp_Object buffer IF_LINT (= Qnil);
+ Lisp_Object cover_string IF_LINT (= Qnil);
if (STRINGP (object))
{
check if the text under it has one. */
struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
EMACS_INT start = MATRIX_ROW_START_CHARPOS (r);
- pos = string_buffer_position (w, object, start);
+ pos = string_buffer_position (object, start);
if (pos > 0)
{
mouse_face = get_char_property_and_overlay
(make_number (pos), Qmouse_face, w->buffer, &overlay);
buffer = w->buffer;
- display_string = object;
+ cover_string = object;
}
}
else
{
buffer = object;
- display_string = Qnil;
+ cover_string = Qnil;
}
if (!NILP (mouse_face))
necessarily display the character whose position
is the smallest. */
Lisp_Object lim1 =
- NILP (XBUFFER (buffer)->bidi_display_reordering)
+ NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
? Fmarker_position (w->start)
: Qnil;
Lisp_Object lim2 =
- NILP (XBUFFER (buffer)->bidi_display_reordering)
+ NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
? make_number (BUF_Z (XBUFFER (buffer))
- XFASTINT (w->window_end_pos))
: Qnil;
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,
- display_string);
+ cover_string);
cursor = No_Cursor;
}
}
}
else
{
- Lisp_Object object = glyph->object;
+ Lisp_Object obj = glyph->object;
EMACS_INT charpos = glyph->charpos;
/* Try text properties. */
- if (STRINGP (object)
+ if (STRINGP (obj)
&& charpos >= 0
- && charpos < SCHARS (object))
+ && charpos < SCHARS (obj))
{
help = Fget_text_property (make_number (charpos),
- Qhelp_echo, object);
+ Qhelp_echo, obj);
if (NILP (help))
{
/* If the string itself doesn't specify a help-echo,
struct glyph_row *r
= MATRIX_ROW (w->current_matrix, vpos);
EMACS_INT start = MATRIX_ROW_START_CHARPOS (r);
- EMACS_INT pos = string_buffer_position (w, object, start);
- if (pos > 0)
+ EMACS_INT p = string_buffer_position (obj, start);
+ if (p > 0)
{
- help = Fget_char_property (make_number (pos),
+ help = Fget_char_property (make_number (p),
Qhelp_echo, w->buffer);
if (!NILP (help))
{
- charpos = pos;
- object = w->buffer;
+ charpos = p;
+ obj = w->buffer;
}
}
}
}
- else if (BUFFERP (object)
+ else if (BUFFERP (obj)
&& charpos >= BEGV
&& charpos < ZV)
help = Fget_text_property (make_number (charpos), Qhelp_echo,
- object);
+ obj);
if (!NILP (help))
{
help_echo_string = help;
help_echo_window = window;
- help_echo_object = object;
+ help_echo_object = obj;
help_echo_pos = charpos;
}
}
}
+#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)
if (NILP (pointer))
{
- Lisp_Object object = glyph->object;
+ Lisp_Object obj = glyph->object;
EMACS_INT charpos = glyph->charpos;
/* Try text properties. */
- if (STRINGP (object)
+ if (STRINGP (obj)
&& charpos >= 0
- && charpos < SCHARS (object))
+ && charpos < SCHARS (obj))
{
pointer = Fget_text_property (make_number (charpos),
- Qpointer, object);
+ Qpointer, obj);
if (NILP (pointer))
{
/* If the string itself doesn't specify a pointer,
struct glyph_row *r
= MATRIX_ROW (w->current_matrix, vpos);
EMACS_INT start = MATRIX_ROW_START_CHARPOS (r);
- EMACS_INT pos = string_buffer_position (w, object,
- start);
- if (pos > 0)
- pointer = Fget_char_property (make_number (pos),
+ EMACS_INT p = string_buffer_position (obj, start);
+ if (p > 0)
+ pointer = Fget_char_property (make_number (p),
Qpointer, w->buffer);
}
}
- else if (BUFFERP (object)
+ else if (BUFFERP (obj)
&& charpos >= BEGV
&& charpos < ZV)
pointer = Fget_text_property (make_number (charpos),
- Qpointer, object);
+ Qpointer, obj);
}
}
+#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);
- note_mouse_highlight (f, x, y);
+ int mouse_x = hlinfo->mouse_face_mouse_x;
+ int mouse_y = hlinfo->mouse_face_mouse_y;
+ clear_mouse_face (hlinfo);
+ note_mouse_highlight (f, mouse_x, mouse_y);
}
}
}
staticpro (&Qarrow);
Qtext = intern_c_string ("text");
staticpro (&Qtext);
- Qrisky_local_variable = intern_c_string ("risky-local-variable");
- staticpro (&Qrisky_local_variable);
Qinhibit_free_realized_faces = intern_c_string ("inhibit-free-realized-faces");
staticpro (&Qinhibit_free_realized_faces);
staticpro (&Qleft_to_right);
#ifdef HAVE_WINDOW_SYSTEM
- DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
+ DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
For example, if a block cursor is over a tab, it will be drawn as
wide as that tab on the display. */);
x_stretch_cursor_p = 0;
#endif
- DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
+ DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
doc: /* *Non-nil means highlight trailing whitespace.
The face used for trailing whitespace is `trailing-whitespace'. */);
Vshow_trailing_whitespace = Qnil;
- DEFVAR_LISP ("nobreak-char-display", &Vnobreak_char_display,
+ DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
doc: /* *Control highlighting of nobreak space and soft hyphen.
A value of t means highlight the character itself (for nobreak space,
use face `nobreak-space').
space or ordinary hyphen. */);
Vnobreak_char_display = Qt;
- DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
+ DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
doc: /* *The pointer shape to show in void text areas.
A value of nil means to show the text pointer. Other options are `arrow',
`text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
Vvoid_text_area_pointer = Qarrow;
- DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
+ DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
doc: /* Non-nil means don't actually do any redisplay.
This is used for internal purposes. */);
Vinhibit_redisplay = Qnil;
- DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
+ DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
doc: /* String (or mode line construct) included (normally) in `mode-line-format'. */);
Vglobal_mode_string = Qnil;
- DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
+ DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
doc: /* Marker for where to display an arrow on top of the buffer text.
This must be the beginning of a line in order to work.
See also `overlay-arrow-string'. */);
Voverlay_arrow_position = Qnil;
- DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
+ DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
doc: /* String to display as an arrow in non-window frames.
See also `overlay-arrow-position'. */);
Voverlay_arrow_string = make_pure_c_string ("=>");
- DEFVAR_LISP ("overlay-arrow-variable-list", &Voverlay_arrow_variable_list,
+ DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
doc: /* List of variables (symbols) which hold markers for overlay arrows.
The symbols on this list are examined during redisplay to determine
where to display overlay arrows. */);
Voverlay_arrow_variable_list
= Fcons (intern_c_string ("overlay-arrow-position"), Qnil);
- DEFVAR_INT ("scroll-step", &scroll_step,
+ DEFVAR_INT ("scroll-step", emacs_scroll_step,
doc: /* *The number of lines to try scrolling a window by when point moves out.
If that fails to bring point back on frame, point is centered instead.
If this is zero, point is always centered after it moves off frame.
If you want scrolling to always be a line at a time, you should set
`scroll-conservatively' to a large value rather than set this to 1. */);
- DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
+ DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
doc: /* *Scroll up to this many lines, to bring point back on screen.
If point moves off-screen, redisplay will scroll by up to
`scroll-conservatively' lines in order to bring point just barely
A value of zero means always recenter point if it moves off screen. */);
scroll_conservatively = 0;
- DEFVAR_INT ("scroll-margin", &scroll_margin,
+ DEFVAR_INT ("scroll-margin", scroll_margin,
doc: /* *Number of lines of margin at the top and bottom of a window.
Recenter the window whenever point gets within this many lines
of the top or bottom of the window. */);
scroll_margin = 0;
- DEFVAR_LISP ("display-pixels-per-inch", &Vdisplay_pixels_per_inch,
+ DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
doc: /* Pixels per inch value for non-window system displays.
Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */);
Vdisplay_pixels_per_inch = make_float (72.0);
#if GLYPH_DEBUG
- DEFVAR_INT ("debug-end-pos", &debug_end_pos, doc: /* Don't ask. */);
+ DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: /* Don't ask. */);
#endif
DEFVAR_LISP ("truncate-partial-width-windows",
- &Vtruncate_partial_width_windows,
+ Vtruncate_partial_width_windows,
doc: /* Non-nil means truncate lines in windows narrower than the frame.
For an integer value, truncate lines in each window narrower than the
full frame width, provided the window width is less than that integer;
If `word-wrap' is enabled, you might want to reduce this. */);
Vtruncate_partial_width_windows = make_number (50);
- DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
+ DEFVAR_BOOL ("mode-line-inverse-video", mode_line_inverse_video,
doc: /* When nil, display the mode-line/header-line/menu-bar in the default face.
Any other value means to use the appropriate face, `mode-line',
`header-line', or `menu' respectively. */);
mode_line_inverse_video = 1;
- DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
+ DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
doc: /* *Maximum buffer size for which line number should be displayed.
If the buffer is bigger than this, the line number does not appear
in the mode line. A value of nil means no limit. */);
Vline_number_display_limit = Qnil;
DEFVAR_INT ("line-number-display-limit-width",
- &line_number_display_limit_width,
+ line_number_display_limit_width,
doc: /* *Maximum line width (in characters) for line number display.
If the average length of the lines near point is bigger than this, then the
line number may be omitted from the mode line. */);
line_number_display_limit_width = 200;
- DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
+ DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
doc: /* *Non-nil means highlight region even in nonselected windows. */);
highlight_nonselected_windows = 0;
- DEFVAR_BOOL ("multiple-frames", &multiple_frames,
+ DEFVAR_BOOL ("multiple-frames", multiple_frames,
doc: /* Non-nil if more than one frame is visible on this display.
Minibuffer-only frames don't count, but iconified frames do.
This variable is not guaranteed to be accurate except while processing
`frame-title-format' and `icon-title-format'. */);
- DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
+ DEFVAR_LISP ("frame-title-format", Vframe_title_format,
doc: /* Template for displaying the title bar of visible frames.
\(Assuming the window manager supports this feature.)
the %c and %l constructs are ignored. It is used only on frames for
which no explicit name has been set \(see `modify-frame-parameters'). */);
- DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
+ DEFVAR_LISP ("icon-title-format", Vicon_title_format,
doc: /* Template for displaying the title bar of an iconified frame.
\(Assuming the window manager supports this feature.)
This variable has the same structure as `mode-line-format' (which see),
Qnil)))),
Qnil)));
- DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
+ DEFVAR_LISP ("message-log-max", Vmessage_log_max,
doc: /* Maximum number of lines to keep in the message log buffer.
If nil, disable message logging. If t, log messages but don't truncate
the buffer when it becomes large. */);
Vmessage_log_max = make_number (100);
- DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
+ DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
doc: /* Functions called before redisplay, if window sizes have changed.
The value should be a list of functions that take one argument.
Just before redisplay, for each frame, if any of its windows have changed
all the functions in the list are called, with the frame as argument. */);
Vwindow_size_change_functions = Qnil;
- DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
+ DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
doc: /* List of functions to call before redisplaying a window with scrolling.
Each function is called with two arguments, the window and its new
display-start position. Note that these functions are also called by
Vwindow_scroll_functions = Qnil;
DEFVAR_LISP ("window-text-change-functions",
- &Vwindow_text_change_functions,
+ Vwindow_text_change_functions,
doc: /* Functions to call in redisplay when text in the window might change. */);
Vwindow_text_change_functions = Qnil;
- DEFVAR_LISP ("redisplay-end-trigger-functions", &Vredisplay_end_trigger_functions,
+ DEFVAR_LISP ("redisplay-end-trigger-functions", Vredisplay_end_trigger_functions,
doc: /* Functions called when redisplay of a window reaches the end trigger.
Each function is called with two arguments, the window and the end trigger value.
See `set-window-redisplay-end-trigger'. */);
Vredisplay_end_trigger_functions = Qnil;
- DEFVAR_LISP ("mouse-autoselect-window", &Vmouse_autoselect_window,
+ DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
doc: /* *Non-nil means autoselect window with mouse pointer.
If nil, do not autoselect windows.
A positive number means delay autoselection by that many seconds: a
`focus-follows-mouse' matches the behavior of your window manager. */);
Vmouse_autoselect_window = Qnil;
- DEFVAR_LISP ("auto-resize-tool-bars", &Vauto_resize_tool_bars,
+ DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
doc: /* *Non-nil means automatically resize tool-bars.
This dynamically changes the tool-bar's height to the minimum height
that is needed to make all tool-bar items visible.
automatically; to decrease the tool-bar height, use \\[recenter]. */);
Vauto_resize_tool_bars = Qt;
- DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
+ DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);
auto_raise_tool_bar_buttons_p = 1;
- DEFVAR_BOOL ("make-cursor-line-fully-visible", &make_cursor_line_fully_visible_p,
+ DEFVAR_BOOL ("make-cursor-line-fully-visible", make_cursor_line_fully_visible_p,
doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible. */);
make_cursor_line_fully_visible_p = 1;
- DEFVAR_LISP ("tool-bar-border", &Vtool_bar_border,
+ DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
doc: /* *Border below tool-bar in pixels.
If an integer, use it as the height of the border.
If it is one of `internal-border-width' or `border-width', use the
Otherwise, no border is added below the tool-bar. */);
Vtool_bar_border = Qinternal_border_width;
- DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
+ DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
doc: /* *Margin around tool-bar buttons in pixels.
If an integer, use that for both horizontal and vertical margins.
Otherwise, value should be a pair of integers `(HORZ . VERT)' with
vertical margin. */);
Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
- DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
+ DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
doc: /* *Relief thickness of tool-bar buttons. */);
tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
- DEFVAR_LISP ("tool-bar-style", &Vtool_bar_style,
- doc: /* *Tool bar style to use.
+ DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
+ doc: /* Tool bar style to use.
It can be one of
image - show images only
text - show text only
any other - use system default or image if no system default. */);
Vtool_bar_style = Qnil;
- DEFVAR_INT ("tool-bar-max-label-size", &tool_bar_max_label_size,
+ DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
doc: /* *Maximum number of characters a label can have to be shown.
The tool bar style must also show labels for this to have any effect, see
`tool-bar-style'. */);
tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
- DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
+ DEFVAR_LISP ("fontification-functions", Vfontification_functions,
doc: /* List of functions to call to fontify regions of text.
Each function is called with one argument POS. Functions must
fontify a region starting at POS in the current buffer, and give
Fmake_variable_buffer_local (Qfontification_functions);
DEFVAR_BOOL ("unibyte-display-via-language-environment",
- &unibyte_display_via_language_environment,
+ unibyte_display_via_language_environment,
doc: /* *Non-nil means display unibyte text according to language environment.
Specifically, this means that raw bytes in the range 160-255 decimal
are displayed by converting them to the equivalent multibyte characters
but does not change the fact they are interpreted as raw bytes. */);
unibyte_display_via_language_environment = 0;
- DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
+ DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
doc: /* *Maximum height for resizing mini-windows.
If a float, it specifies a fraction of the mini-window frame's height.
If an integer, it specifies a number of lines. */);
Vmax_mini_window_height = make_float (0.25);
- DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows,
+ DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
doc: /* *How to resize mini-windows.
A value of nil means don't automatically resize mini-windows.
A value of t means resize them to fit the text displayed in them.
go back to their normal size. */);
Vresize_mini_windows = Qgrow_only;
- DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist,
+ DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
doc: /* Alist specifying how to blink the cursor off.
Each element has the form (ON-STATE . OFF-STATE). Whenever the
`cursor-type' frame-parameter or variable equals ON-STATE,
the frame's other specifications determine how to blink the cursor off. */);
Vblink_cursor_alist = Qnil;
- DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
+ DEFVAR_BOOL ("auto-hscroll-mode", automatic_hscrolling_p,
doc: /* Allow or disallow automatic horizontal scrolling of windows.
If non-nil, windows are automatically scrolled horizontally to make
point visible. */);
Qauto_hscroll_mode = intern_c_string ("auto-hscroll-mode");
staticpro (&Qauto_hscroll_mode);
- DEFVAR_INT ("hscroll-margin", &hscroll_margin,
+ DEFVAR_INT ("hscroll-margin", hscroll_margin,
doc: /* *How many columns away from the window edge point is allowed to get
before automatic hscrolling will horizontally scroll the window. */);
hscroll_margin = 5;
- DEFVAR_LISP ("hscroll-step", &Vhscroll_step,
+ DEFVAR_LISP ("hscroll-step", Vhscroll_step,
doc: /* *How many columns to scroll the window when point gets too close to the edge.
When point is less than `hscroll-margin' columns from the window
edge, automatic hscrolling will scroll the window by the amount of columns
and `scroll-right' overrides this variable's effect. */);
Vhscroll_step = make_number (0);
- DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
+ DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
doc: /* If non-nil, messages are truncated instead of resizing the echo area.
Bind this around calls to `message' to let it take effect. */);
message_truncate_lines = 0;
- DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook,
+ DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
doc: /* Normal hook run to update the menu bar definitions.
Redisplay runs this hook before it redisplays the menu bar.
This is used to update submenus such as Buffers,
whose contents depend on various data. */);
Vmenu_bar_update_hook = Qnil;
- DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame,
+ DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
doc: /* Frame for which we are updating a menu.
The enable predicate for a menu binding should check this variable. */);
Vmenu_updating_frame = Qnil;
- DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
+ DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
doc: /* Non-nil means don't update menu bars. Internal use only. */);
inhibit_menubar_update = 0;
- DEFVAR_LISP ("wrap-prefix", &Vwrap_prefix,
+ DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
doc: /* Prefix prepended to all continuation lines at display time.
The value may be a string, an image, or a stretch-glyph; it is
interpreted in the same way as the value of a `display' text property.
Qwrap_prefix = intern_c_string ("wrap-prefix");
Fmake_variable_buffer_local (Qwrap_prefix);
- DEFVAR_LISP ("line-prefix", &Vline_prefix,
+ DEFVAR_LISP ("line-prefix", Vline_prefix,
doc: /* Prefix prepended to all non-continuation lines at display time.
The value may be a string, an image, or a stretch-glyph; it is
interpreted in the same way as the value of a `display' text property.
Qline_prefix = intern_c_string ("line-prefix");
Fmake_variable_buffer_local (Qline_prefix);
- DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
+ DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
doc: /* Non-nil means don't eval Lisp during redisplay. */);
inhibit_eval_during_redisplay = 0;
- DEFVAR_BOOL ("inhibit-free-realized-faces", &inhibit_free_realized_faces,
+ DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
doc: /* Non-nil means don't free realized faces. Internal use only. */);
inhibit_free_realized_faces = 0;
#if GLYPH_DEBUG
- DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id,
+ DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
doc: /* Inhibit try_window_id display optimization. */);
inhibit_try_window_id = 0;
- DEFVAR_BOOL ("inhibit-try-window-reusing", &inhibit_try_window_reusing,
+ DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
doc: /* Inhibit try_window_reusing display optimization. */);
inhibit_try_window_reusing = 0;
- DEFVAR_BOOL ("inhibit-try-cursor-movement", &inhibit_try_cursor_movement,
+ DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
doc: /* Inhibit try_cursor_movement display optimization. */);
inhibit_try_cursor_movement = 0;
#endif /* GLYPH_DEBUG */
- DEFVAR_INT ("overline-margin", &overline_margin,
+ DEFVAR_INT ("overline-margin", overline_margin,
doc: /* *Space between overline and text, in pixels.
The default value is 2: the height of the overline (1 pixel) plus 1 pixel
margin to the caracter height. */);
overline_margin = 2;
DEFVAR_INT ("underline-minimum-offset",
- &underline_minimum_offset,
+ underline_minimum_offset,
doc: /* Minimum distance between baseline and underline.
This can improve legibility of underlined text at small font sizes,
particularly when using variable `x-use-underline-position-properties'
baseline. The default value is 1. */);
underline_minimum_offset = 1;
- DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
+ DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
doc: /* Non-nil means show an hourglass pointer, when Emacs is busy.
This feature only works when on a window system that can change
cursor shapes. */);
display_hourglass_p = 1;
- DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
+ DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
doc: /* *Seconds to wait before displaying an hourglass pointer when Emacs is busy. */);
Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
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);
}
#endif
}
#endif /* ! WINDOWSNT */
-