/* 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 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GNU Emacs.
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 Qinhibit_point_motion_hooks;
Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
static Lisp_Object Vmessages_buffer_name;
-/* Index 0 is the buffer that holds the current (desired) echo area message,
- or nil if none is desired right now.
-
- Index 1 is the buffer that holds the previously displayed echo area message,
- or nil to indicate no message. This is normally what's on the screen now.
-
- These two can point to the same buffer. That happens when the last
- message output by the user (or made by echoing) has been displayed. */
+/* Current, index 0, and last displayed echo area message. Either
+ buffers from echo_buffers, or nil to indicate no message. */
Lisp_Object echo_area_buffer[2];
-/* Permanent pointers to the two buffers that are used for echo area
- purposes. Once the two buffers are made, and their pointers are
- placed here, these two slots remain unchanged unless those buffers
- need to be created afresh. */
+/* The buffers referenced from echo_area_buffer. */
static Lisp_Object echo_buffer[2];
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. */
static int clear_image_cache_count;
#endif
-/* Record the previous terminal frame we displayed. */
-
-static struct frame *previous_terminal_frame;
-
/* Non-zero while redisplay_internal is in progress. */
int redisplaying_p;
static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int));
static int store_mode_line_string P_ ((char *, Lisp_Object, int, int, int, Lisp_Object));
-static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
+static char *decode_mode_spec P_ ((struct window *, int, int, int, int *,
+ Lisp_Object *));
static void display_menu_bar P_ ((struct window *));
static int display_count_lines P_ ((int, int, int, int, int *));
static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
- int, int, struct it *, int, int, int, int));
+ EMACS_INT, EMACS_INT, struct it *, int, int, int, int));
static void compute_line_metrics P_ ((struct it *));
static void run_redisplay_end_trigger_hook P_ ((struct it *));
static int get_overlay_strings P_ ((struct it *, int));
static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
Lisp_Object));
static int face_before_or_after_it_pos P_ ((struct it *, int));
-static int next_overlay_change P_ ((int));
+static EMACS_INT next_overlay_change P_ ((EMACS_INT));
static int handle_single_display_spec P_ ((struct it *, Lisp_Object,
- Lisp_Object, struct text_pos *,
- int));
+ Lisp_Object, Lisp_Object,
+ struct text_pos *, int));
static int underlying_face_id P_ ((struct it *));
static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
struct window *));
visible_p = 1;
if (visible_p)
{
+ Lisp_Object window, prop;
+
+ XSETWINDOW (window, w);
+ prop = Fget_char_property (make_number (it.position.charpos),
+ Qinvisible, window);
+
+ /* If charpos coincides with invisible text covered with an
+ ellipsis, use the first glyph of the ellipsis to compute
+ the pixel positions. */
+ if (TEXT_PROP_MEANS_INVISIBLE (prop) == 2)
+ {
+ struct glyph_row *row = it.glyph_row;
+ struct glyph *glyph = row->glyphs[TEXT_AREA];
+ struct glyph *end = glyph + row->used[TEXT_AREA];
+ int x = row->x;
+
+ for (; glyph < end && glyph->charpos < charpos; glyph++)
+ x += glyph->pixel_width;
+
+ top_x = x;
+ }
+
*x = top_x;
*y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
*rtop = max (0, window_top_y - top_y);
/* If realized faces have been removed, e.g. because of face
attribute changes of named faces, recompute them. When running
- in batch mode, the face cache of Vterminal_frame is null. If
+ in batch mode, the face cache of the initial frame is null. If
we happen to get called, make a dummy face cache. */
- if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
+ if (FRAME_FACE_CACHE (it->f) == NULL)
init_frame_faces (it->f);
if (FRAME_FACE_CACHE (it->f)->used == 0)
recompute_basic_faces (it->f);
if (it->method == GET_FROM_DISPLAY_VECTOR)
handle_overlay_change_p = 0;
- /* Handle overlay changes. */
+ /* Handle overlay changes.
+ This sets HANDLED to HANDLED_RECOMPUTE_PROPS
+ if it finds overlays. */
if (handle_overlay_change_p)
handled = handle_overlay_change (it);
-
- /* Determine where to stop next. */
- if (handled == HANDLED_NORMALLY)
- compute_stop_pos (it);
}
}
while (handled == HANDLED_RECOMPUTE_PROPS);
+
+ /* Determine where to stop next. */
+ if (handled == HANDLED_NORMALLY)
+ compute_stop_pos (it);
}
follows. This is like `next-overlay-change' but doesn't use
xmalloc. */
-static int
+static EMACS_INT
next_overlay_change (pos)
- int pos;
+ EMACS_INT pos;
{
int noverlays;
- int endpos;
+ EMACS_INT endpos;
Lisp_Object *overlays;
int i;
for (i = 0; i < noverlays; ++i)
{
Lisp_Object oend;
- int oendpos;
+ EMACS_INT oendpos;
oend = OVERLAY_END (overlays[i]);
oendpos = OVERLAY_POSITION (oend);
handle_face_prop (it)
struct it *it;
{
- int new_face_id, next_stop;
+ int new_face_id;
+ EMACS_INT next_stop;
if (!STRINGP (it->string))
{
else
{
int base_face_id, bufpos;
+ int i;
+ Lisp_Object from_overlay
+ = (it->current.overlay_string_index >= 0
+ ? it->string_overlays[it->current.overlay_string_index]
+ : Qnil);
+
+ /* See if we got to this string directly or indirectly from
+ an overlay property. That includes the before-string or
+ after-string of an overlay, strings in display properties
+ provided by an overlay, their text properties, etc.
+
+ FROM_OVERLAY is the overlay that brought us here, or nil if none. */
+ if (! NILP (from_overlay))
+ for (i = it->sp - 1; i >= 0; i--)
+ {
+ if (it->stack[i].current.overlay_string_index >= 0)
+ from_overlay
+ = it->string_overlays[it->stack[i].current.overlay_string_index];
+ else if (! NILP (it->stack[i].from_overlay))
+ from_overlay = it->stack[i].from_overlay;
- if (it->current.overlay_string_index >= 0)
- bufpos = IT_CHARPOS (*it);
+ if (!NILP (from_overlay))
+ break;
+ }
+
+ if (! NILP (from_overlay))
+ {
+ bufpos = IT_CHARPOS (*it);
+ /* For a string from an overlay, the base face depends
+ only on text properties and ignores overlays. */
+ base_face_id
+ = face_for_overlay_string (it->w,
+ IT_CHARPOS (*it),
+ it->region_beg_charpos,
+ it->region_end_charpos,
+ &next_stop,
+ (IT_CHARPOS (*it)
+ + TEXT_PROP_DISTANCE_LIMIT),
+ 0,
+ from_overlay);
+ }
else
- bufpos = 0;
+ {
+ bufpos = 0;
- /* For strings from a buffer, i.e. overlay strings or strings
- from a `display' property, use the face at IT's current
- buffer position as the base face to merge with, so that
- overlay strings appear in the same face as surrounding
- text, unless they specify their own faces. */
- base_face_id = underlying_face_id (it);
+ /* For strings from a `display' property, use the face at
+ IT's current buffer position as the base face to merge
+ with, so that overlay strings appear in the same face as
+ surrounding text, unless they specify their own
+ faces. */
+ base_face_id = underlying_face_id (it);
+ }
new_face_id = face_at_string_position (it->w,
it->string,
int before_p;
{
int face_id, limit;
- int next_check_charpos;
+ EMACS_INT next_check_charpos;
struct text_pos pos;
xassert (it->s == NULL);
}
else
{
- int invis_p, newpos, next_stop, start_charpos;
+ int invis_p;
+ EMACS_INT newpos, next_stop, start_charpos;
Lisp_Object pos, prop, overlay;
/* First of all, is there invisible text at this position? */
it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
}
setup_for_ellipsis (it, 0);
+ /* Let the ellipsis display before
+ considering any properties of the following char.
+ Fixes jasonr@gnu.org 01 Oct 07 bug. */
+ handled = HANDLED_RETURN;
}
}
}
handle_display_prop (it)
struct it *it;
{
- Lisp_Object prop, object;
+ Lisp_Object prop, object, overlay;
struct text_pos *position;
/* Nonzero if some property replaces the display of the text itself. */
int display_replaced_p = 0;
if (!it->string_from_display_prop_p)
it->area = TEXT_AREA;
- prop = Fget_char_property (make_number (position->charpos),
- Qdisplay, object);
+ prop = get_char_property_and_overlay (make_number (position->charpos),
+ Qdisplay, object, &overlay);
if (NILP (prop))
return HANDLED_NORMALLY;
+ /* Now OVERLAY is the overlay that gave us this property, or nil
+ if it was a text property. */
if (!STRINGP (it->string))
object = it->w->buffer;
{
for (; CONSP (prop); prop = XCDR (prop))
{
- if (handle_single_display_spec (it, XCAR (prop), object,
+ if (handle_single_display_spec (it, XCAR (prop), object, overlay,
position, display_replaced_p))
- display_replaced_p = 1;
+ {
+ display_replaced_p = 1;
+ /* If some text in a string is replaced, `position' no
+ longer points to the position of `object'. */
+ if (STRINGP (object))
+ break;
+ }
}
}
else if (VECTORP (prop))
{
int i;
for (i = 0; i < ASIZE (prop); ++i)
- if (handle_single_display_spec (it, AREF (prop, i), object,
+ if (handle_single_display_spec (it, AREF (prop, i), object, overlay,
position, display_replaced_p))
- display_replaced_p = 1;
+ {
+ display_replaced_p = 1;
+ /* If some text in a string is replaced, `position' no
+ longer points to the position of `object'. */
+ if (STRINGP (object))
+ break;
+ }
}
else
{
- int ret = handle_single_display_spec (it, prop, object, position, 0);
+ int ret = handle_single_display_spec (it, prop, object, overlay,
+ position, 0);
if (ret < 0) /* Replaced by "", i.e. nothing. */
return HANDLED_RECOMPUTE_PROPS;
if (ret)
replaced text display with something else, for example an image;
we ignore such properties after the first one has been processed.
+ OVERLAY is the overlay this `display' property came from,
+ or nil if it was a text property.
+
If PROP is a `space' or `image' specification, and in some other
cases too, set *POSITION to the position where the `display'
property ends.
"something" is "nothing". */
static int
-handle_single_display_spec (it, spec, object, position,
+handle_single_display_spec (it, spec, object, overlay, position,
display_replaced_before_p)
struct it *it;
Lisp_Object spec;
Lisp_Object object;
+ Lisp_Object overlay;
struct text_pos *position;
int display_replaced_before_p;
{
&& EQ (XCAR (spec), Qheight)
&& CONSP (XCDR (spec)))
{
- if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+ if (!FRAME_WINDOW_P (it->f))
return 0;
it->font_height = XCAR (XCDR (spec));
return 0;
}
- /* Handle `(space_width WIDTH)'. */
+ /* Handle `(space-width WIDTH)'. */
if (CONSP (spec)
&& EQ (XCAR (spec), Qspace_width)
&& CONSP (XCDR (spec)))
{
- if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+ if (!FRAME_WINDOW_P (it->f))
return 0;
value = XCAR (XCDR (spec));
{
Lisp_Object tem;
- if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+ if (!FRAME_WINDOW_P (it->f))
return 0;
if (tem = XCDR (spec), CONSP (tem))
&& EQ (XCAR (spec), Qraise)
&& CONSP (XCDR (spec)))
{
- if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+ if (!FRAME_WINDOW_P (it->f))
return 0;
#ifdef HAVE_WINDOW_SYSTEM
int face_id = DEFAULT_FACE_ID;
int fringe_bitmap;
- if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+ if (!FRAME_WINDOW_P (it->f))
/* If we return here, POSITION has been advanced
across the text with this property. */
return 0;
it->position = start_pos;
it->object = NILP (object) ? it->w->buffer : object;
it->method = GET_FROM_IMAGE;
+ it->from_overlay = Qnil;
it->face_id = face_id;
/* Say that we haven't consumed the characters with
it->left_user_fringe_face_id = face_id;
}
else
- {
+ {
it->right_user_fringe_bitmap = fringe_bitmap;
it->right_user_fringe_face_id = face_id;
}
valid_p = (STRINGP (value)
#ifdef HAVE_WINDOW_SYSTEM
- || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
+ || (FRAME_WINDOW_P (it->f) && valid_image_p (value))
#endif /* not HAVE_WINDOW_SYSTEM */
- || (CONSP (value) && EQ (XCAR (value), Qspace)));
+ || (CONSP (value) && EQ (XCAR (value), Qspace)));
if (valid_p && !display_replaced_before_p)
{
it->position = *position;
push_it (it);
it->position = save_pos;
+ it->from_overlay = overlay;
if (NILP (location))
it->area = TEXT_AREA;
/* Say that we haven't consumed the characters with
`display' property yet. The call to pop_it in
set_iterator_to_next will clean this up. */
- *position = start_pos;
+ if (BUFFERP (object))
+ it->current.pos = start_pos;
}
else if (CONSP (value) && EQ (XCAR (value), Qspace))
{
it->method = GET_FROM_STRETCH;
it->object = value;
- *position = it->position = start_pos;
+ it->position = start_pos;
+ if (BUFFERP (object))
+ it->current.pos = start_pos;
}
#ifdef HAVE_WINDOW_SYSTEM
else
/* Say that we haven't consumed the characters with
`display' property yet. The call to pop_it in
set_iterator_to_next will clean this up. */
- *position = start_pos;
+ if (BUFFERP (object))
+ it->current.pos = start_pos;
}
#endif /* HAVE_WINDOW_SYSTEM */
}
-/* Check if SPEC is a display specification value whose text should be
+/* Check if SPEC is a display sub-property value whose text should be
treated as intangible. */
static int
if (FUNCTIONP (Vauto_composition_function))
{
- Lisp_Object val;
- EMACS_INT pos, this_pos;
+ Lisp_Object val = Qnil;
+ EMACS_INT pos, limit = -1;
if (STRINGP (it->string))
pos = IT_STRING_CHARPOS (*it);
else
pos = IT_CHARPOS (*it);
- this_pos = pos;
- val =Fget_char_property (make_number (pos), Qauto_composed, it->string);
+ val = Fget_text_property (make_number (pos), Qauto_composed, it->string);
if (! NILP (val))
{
- Lisp_Object limit = Qnil, next;
-
- /* As Fnext_single_char_property_change is very slow, we
- limit the search to the current line. */
- if (STRINGP (it->string))
- limit = make_number (SCHARS (it->string));
- else
- limit = make_number (find_next_newline_no_quit (pos, 1));
+ Lisp_Object cmp_prop;
+ EMACS_INT cmp_start, cmp_end;
- next = (Fnext_single_property_change
- (make_number (pos), Qauto_composed, it->string, limit));
- if (XINT (next) < XINT (limit))
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend
+ && get_property_and_range (pos, Qcomposition, &cmp_prop,
+ &cmp_start, &cmp_end, it->string)
+ && cmp_start == pos
+ && COMPOSITION_METHOD (cmp_prop) == COMPOSITION_WITH_GLYPH_STRING)
{
- /* The current point is auto-composed, but there exist
- characters not yet composed beyond the auto-composed
- region. There's a possiblity that the last
- characters in the region may be newly composed. */
- int charpos = XINT (next) - 1, bytepos, c;
+ Lisp_Object gstring = COMPOSITION_COMPONENTS (cmp_prop);
+ Lisp_Object font_object = LGSTRING_FONT (gstring);
+
+ if (! EQ (font_object,
+ font_at (-1, pos, FACE_FROM_ID (it->f, it->face_id),
+ it->w, it->string)))
+ /* We must re-compute the composition for the
+ different font. */
+ val = Qnil;
+ }
+#endif
+ if (! NILP (val))
+ {
+ Lisp_Object end;
+ /* As Fnext_single_char_property_change is very slow, we
+ limit the search to the current line. */
if (STRINGP (it->string))
- {
- bytepos = string_char_to_byte (it->string, charpos);
- c = SDATA (it->string)[bytepos];
- }
+ limit = SCHARS (it->string);
else
- {
- bytepos = CHAR_TO_BYTE (charpos);
- c = FETCH_BYTE (bytepos);
- }
- if (c != '\n')
- /* If the last character is not newline, it may be
- composed with the following characters. */
- val = Qnil, pos = charpos + 1;
+ limit = find_next_newline_no_quit (pos, 1);
+ end = Fnext_single_char_property_change (make_number (pos),
+ Qauto_composed,
+ it->string,
+ make_number (limit));
+
+ if (XINT (end) < limit)
+ /* The current point is auto-composed, but there exist
+ characters not yet composed beyond the
+ auto-composed region. There's a possiblity that
+ the last characters in the region may be newly
+ composed. */
+ val = Qnil;
}
}
if (NILP (val))
{
- int count = SPECPDL_INDEX ();
- Lisp_Object args[4];
-
- args[0] = Vauto_composition_function;
- specbind (Qauto_composition_function, Qnil);
- args[1] = make_number (pos);
- args[2] = it->string;
-#ifdef USE_FONT_BACKEND
- if (enable_font_backend)
+ if (limit < 0)
+ limit = (STRINGP (it->string) ? SCHARS (it->string)
+ : find_next_newline_no_quit (pos, 1));
+ if (pos < limit)
{
- struct face *face = FACE_FROM_ID (it->f, it->face_id);
- int c;
-
- if (STRINGP (it->string))
- {
- EMACS_INT pos_byte = IT_STRING_BYTEPOS (*it);
- const unsigned char *s = SDATA (it->string) + pos_byte;
+ int count = SPECPDL_INDEX ();
+ Lisp_Object args[5];
- if (STRING_MULTIBYTE (it->string))
- it->c = STRING_CHAR (s, 0);
- else
- it->c = *s;
- }
+ args[0] = Vauto_composition_function;
+ specbind (Qauto_composition_function, Qnil);
+ args[1] = make_number (pos);
+ args[2] = make_number (limit);
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ args[3] = it->window;
else
- {
- EMACS_INT pos_byte = IT_BYTEPOS (*it);
-
- it->c = FETCH_CHAR (pos_byte);
- }
- args[3] = font_at (it->c, this_pos, face, it->w, it->string);
- }
- else
#endif /* USE_FONT_BACKEND */
- args[3] = Qnil;
- safe_call (4, args);
- unbind_to (count, Qnil);
-
- if (this_pos == pos)
- {
- val = Fget_char_property (args[1], Qauto_composed, it->string);
- /* Return HANDLED_RECOMPUTE_PROPS only if function composed
- something. This avoids an endless loop if they failed to
- fontify the text for which reason ever. */
- if (! NILP (val))
- handled = HANDLED_RECOMPUTE_PROPS;
+ args[3] = Qnil;
+ args[4] = it->string;
+ safe_call (5, args);
+ unbind_to (count, Qnil);
}
- else
- handled = HANDLED_RECOMPUTE_PROPS;
}
}
if (STRINGP (it->string))
{
+ unsigned char *s;
+
pos = IT_STRING_CHARPOS (*it);
pos_byte = IT_STRING_BYTEPOS (*it);
string = it->string;
+ s = SDATA (string) + pos_byte;
+ it->c = STRING_CHAR (s, 0);
}
else
{
pos = IT_CHARPOS (*it);
pos_byte = IT_BYTEPOS (*it);
string = Qnil;
+ it->c = FETCH_CHAR (pos_byte);
}
/* If there's a valid composition and point is not inside of the
#ifdef USE_FONT_BACKEND
if (composition_table[id]->method == COMPOSITION_WITH_GLYPH_STRING)
{
+ /* FIXME: This doesn't do anything!?! */
Lisp_Object lgstring = AREF (XHASH_TABLE (composition_hash_table)
->key_and_value,
cmp->hash_index * 2);
-
- it->c = XINT (LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 0)));
}
else
#endif /* USE_FONT_BACKEND */
i = 0;
j = it->current.overlay_string_index;
while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
- it->overlay_strings[i++] = entries[j++].string;
+ {
+ it->overlay_strings[i] = entries[j].string;
+ it->string_overlays[i++] = entries[j++].overlay;
+ }
CHECK_IT (it);
}
string. */
IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
it->string = it->overlay_strings[0];
+ it->from_overlay = Qnil;
it->stop_charpos = 0;
xassert (STRINGP (it->string));
it->end_charpos = SCHARS (it->string);
p->face_id = it->face_id;
p->string = it->string;
p->method = it->method;
+ p->from_overlay = it->from_overlay;
switch (p->method)
{
case GET_FROM_IMAGE:
it->current = p->current;
it->position = p->position;
it->string = p->string;
+ it->from_overlay = p->from_overlay;
if (NILP (it->string))
SET_TEXT_POS (it->current.string_pos, -1, -1);
it->method = p->method;
{
struct it it2;
int pos;
- int beg, end;
+ EMACS_INT beg, end;
Lisp_Object val, overlay;
/* If newline is part of a composition, continue from start of composition */
int pos = (it->s ? -1
: STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
: IT_CHARPOS (*it));
-
+
it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string);
}
do_pending_window_change (0);
echo_area_display (1);
do_pending_window_change (0);
- if (frame_up_to_date_hook != 0 && ! gc_in_progress)
- (*frame_up_to_date_hook) (f);
+ if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+ (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
}
}
do_pending_window_change (0);
echo_area_display (1);
do_pending_window_change (0);
- if (frame_up_to_date_hook != 0 && ! gc_in_progress)
- (*frame_up_to_date_hook) (f);
+ if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+ (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
}
}
WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
suitable buffer from echo_buffer[] and clear it.
+ If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
+ that the current message becomes the last displayed one, make
+ choose a suitable buffer for echo_area_buffer[0], and clear it.
+
Value is what FN returns. */
static int
this_one = 0, the_other = 1;
else if (which > 0)
this_one = 1, the_other = 0;
+ else
+ {
+ this_one = 0, the_other = 1;
+ clear_buffer_p = 1;
+
+ /* We need a fresh one in case the current echo buffer equals
+ the one containing the last displayed echo area message. */
+ if (!NILP (echo_area_buffer[this_one])
+ && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
+ echo_area_buffer[this_one] = Qnil;
+ }
/* Choose a suitable buffer from echo_buffer[] is we don't
have one. */
struct window *w;
{
int i = 0;
- Lisp_Object vector;
+ Lisp_Object vector, tmp;
/* Reduce consing by keeping one vector in
Vwith_echo_area_save_vector. */
if (NILP (vector))
vector = Fmake_vector (make_number (7), Qnil);
- XSETBUFFER (AREF (vector, i), current_buffer); ++i;
- AREF (vector, i) = Vdeactivate_mark, ++i;
- AREF (vector, i) = make_number (windows_or_buffers_changed), ++i;
+ XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
+ ASET (vector, i, Vdeactivate_mark); ++i;
+ ASET (vector, i, make_number (windows_or_buffers_changed)); ++i;
if (w)
{
- XSETWINDOW (AREF (vector, i), w); ++i;
- AREF (vector, i) = w->buffer; ++i;
- AREF (vector, i) = make_number (XMARKER (w->pointm)->charpos); ++i;
- AREF (vector, i) = make_number (XMARKER (w->pointm)->bytepos); ++i;
+ XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
+ ASET (vector, i, w->buffer); ++i;
+ ASET (vector, i, make_number (XMARKER (w->pointm)->charpos)); ++i;
+ ASET (vector, i, make_number (XMARKER (w->pointm)->bytepos)); ++i;
}
else
{
int end = i + 4;
for (; i < end; ++i)
- AREF (vector, i) = Qnil;
+ ASET (vector, i, Qnil);
}
xassert (i == ASIZE (vector));
}
-/* Resize mini-window W to fit the size of its contents. EXACT:P
+/* Resize mini-window W to fit the size of its contents. EXACT_P
means size the window exactly to the size needed. Otherwise, it's
only enlarged until W's buffer is empty.
= ((s && multibyte_p)
|| (STRINGP (string) && STRING_MULTIBYTE (string)));
- with_echo_area_buffer (0, 0, set_message_1,
+ with_echo_area_buffer (0, -1, set_message_1,
(EMACS_INT) s, string, nbytes, multibyte_p);
message_buf_print = 0;
help_echo_showing_p = 0;
/* Insert new message at BEG. */
TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
- Ferase_buffer ();
if (STRINGP (string))
{
if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
return 0;
-/* The terminal frame is used as the first Emacs frame on the Mac OS. */
-#ifndef MAC_OS8
#ifdef HAVE_WINDOW_SYSTEM
- /* When Emacs starts, selected_frame may be a visible terminal
- frame, even if we run under a window system. If we let this
- through, a message would be displayed on the terminal. */
- if (EQ (selected_frame, Vterminal_frame)
- && !NILP (Vwindow_system))
+ /* When Emacs starts, selected_frame may be the initial terminal
+ frame. If we let this through, a message would be displayed on
+ the terminal. */
+ if (FRAME_INITIAL_P (XFRAME (selected_frame)))
return 0;
#endif /* HAVE_WINDOW_SYSTEM */
-#endif
/* Redraw garbaged frames. */
if (frame_garbaged)
Can do with a display update of the echo area,
unless we displayed some mode lines. */
update_single_window (w, 1);
- rif->flush_display (f);
+ FRAME_RIF (f)->flush_display (f);
}
else
update_frame (f, 1, 1);
else if (!EQ (mini_window, selected_window))
windows_or_buffers_changed++;
- /* The current message is now also the last one displayed. */
+ /* Last displayed message is now the current message. */
echo_area_buffer[1] = echo_area_buffer[0];
+ /* Inform read_char that we're not echoing. */
+ echo_message_buffer = Qnil;
/* Prevent redisplay optimization in redisplay_internal by resetting
this_line_start_pos. This is done because the mini-buffer now
format_mode_line_unwind_data (obuf, save_proptrans)
struct buffer *obuf;
{
- Lisp_Object vector;
+ Lisp_Object vector, tmp;
/* Reduce consing by keeping one vector in
Vwith_echo_area_save_vector. */
if (NILP (vector))
vector = Fmake_vector (make_number (7), Qnil);
- AREF (vector, 0) = make_number (mode_line_target);
- AREF (vector, 1) = make_number (MODE_LINE_NOPROP_LEN (0));
- AREF (vector, 2) = mode_line_string_list;
- AREF (vector, 3) = (save_proptrans ? mode_line_proptrans_alist : Qt);
- AREF (vector, 4) = mode_line_string_face;
- AREF (vector, 5) = mode_line_string_face_prop;
+ ASET (vector, 0, make_number (mode_line_target));
+ ASET (vector, 1, make_number (MODE_LINE_NOPROP_LEN (0)));
+ ASET (vector, 2, mode_line_string_list);
+ ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
+ ASET (vector, 4, mode_line_string_face);
+ ASET (vector, 5, mode_line_string_face_prop);
if (obuf)
- XSETBUFFER (AREF (vector, 6), obuf);
+ XSETBUFFER (tmp, obuf);
else
- AREF (vector, 6) = Qnil;
+ tmp = Qnil;
+ ASET (vector, 6, tmp);
return vector;
}
if (!NILP (AREF (vector, 6)))
{
set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
- AREF (vector, 6) = Qnil;
+ ASET (vector, 6, Qnil);
}
Vmode_line_unwind_vector = vector;
{
BLOCK_INPUT;
display_and_set_cursor (w, 1, hpos, vpos, x, y);
- if (rif->flush_display_optional)
- rif->flush_display_optional (SELECTED_FRAME ());
+ if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
+ FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ());
UNBLOCK_INPUT;
}
}
/* Scroll when cursor is inside this scroll margin. */
h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
- if ((XFASTINT (w->hscroll)
- && w->cursor.x <= h_margin)
- || (cursor_row->enabled_p
- && cursor_row->truncated_on_right_p
- && (w->cursor.x >= text_area_width - h_margin)))
+ if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->buffer))
+ && ((XFASTINT (w->hscroll)
+ && w->cursor.x <= h_margin)
+ || (cursor_row->enabled_p
+ && cursor_row->truncated_on_right_p
+ && (w->cursor.x >= text_area_width - h_margin))))
{
struct it it;
int hscroll;
hscroll_windows (window)
Lisp_Object window;
{
- int hscrolled_p;
-
- if (automatic_hscrolling_p)
- {
- hscrolled_p = hscroll_window_tree (window);
- if (hscrolled_p)
- clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
- }
- else
- hscrolled_p = 0;
+ int hscrolled_p = hscroll_window_tree (window);
+ if (hscrolled_p)
+ clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
return hscrolled_p;
}
Lisp_Object tail, sym, val;
Lisp_Object old = selected_frame;
+ xassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
+
selected_frame = frame;
- for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
- if (CONSP (XCAR (tail))
- && (sym = XCAR (XCAR (tail)),
- SYMBOLP (sym))
- && (sym = indirect_variable (sym),
- val = SYMBOL_VALUE (sym),
- (BUFFER_LOCAL_VALUEP (val)
- || SOME_BUFFER_LOCAL_VALUEP (val)))
- && XBUFFER_LOCAL_VALUE (val)->check_frame)
- /* Use find_symbol_value rather than Fsymbol_value
- to avoid an error if it is void. */
- find_symbol_value (sym);
-
- for (tail = XFRAME (old)->param_alist; CONSP (tail); tail = XCDR (tail))
- if (CONSP (XCAR (tail))
- && (sym = XCAR (XCAR (tail)),
- SYMBOLP (sym))
- && (sym = indirect_variable (sym),
- val = SYMBOL_VALUE (sym),
- (BUFFER_LOCAL_VALUEP (val)
- || SOME_BUFFER_LOCAL_VALUEP (val)))
- && XBUFFER_LOCAL_VALUE (val)->check_frame)
- find_symbol_value (sym);
+ do
+ {
+ for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
+ if (CONSP (XCAR (tail))
+ && (sym = XCAR (XCAR (tail)),
+ SYMBOLP (sym))
+ && (sym = indirect_variable (sym),
+ val = SYMBOL_VALUE (sym),
+ (BUFFER_LOCAL_VALUEP (val)))
+ && XBUFFER_LOCAL_VALUE (val)->check_frame)
+ /* Use find_symbol_value rather than Fsymbol_value
+ to avoid an error if it is void. */
+ find_symbol_value (sym);
+ } while (!EQ (frame, old) && (frame = old, 1));
}
int count, count1;
struct frame *sf;
int polling_stopped_here = 0;
+ Lisp_Object old_frame = selected_frame;
/* Non-zero means redisplay has to consider all windows on all
frames. Zero means, only selected_window is considered. */
}
retry:
+ 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.
+ selected_frame and selected_window to be temporarily out-of-sync so
+ when we come back here via `goto retry', we need to resync because we
+ may need to run Elisp code (via prepare_menu_bars). */
+ select_frame_for_redisplay (old_frame);
+
pause = 0;
reconsider_clip_changes (w, current_buffer);
last_escape_glyph_frame = NULL;
if (face_change_count)
++windows_or_buffers_changed;
- if (! FRAME_WINDOW_P (sf)
- && previous_terminal_frame != sf)
+ if (FRAME_TERMCAP_P (sf)
+ && FRAME_TTY (sf)->previous_frame != sf)
{
- /* Since frames on an ASCII terminal share the same display
- area, displaying a different frame means redisplay the whole
- thing. */
+ /* Since frames on a single ASCII terminal share the same
+ display area, displaying a different frame means redisplay
+ the whole thing. */
windows_or_buffers_changed++;
SET_FRAME_GARBAGED (sf);
- XSETFRAME (Vterminal_frame, sf);
+ FRAME_TTY (sf)->previous_frame = sf;
}
- previous_terminal_frame = sf;
/* Set the visible flags for all frames. Do this before checking
for resized or garbaged frames; they want to know if their frames
}
}
+
/* Notice any pending interrupt request to change frame size. */
do_pending_window_change (1);
{
struct frame *f = XFRAME (frame);
- if (FRAME_WINDOW_P (f) || f == sf)
+ if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
if (! EQ (frame, selected_frame))
/* Select the frame, for the sake of frame-local
/* Mark all the scroll bars to be removed; we'll redeem
the ones we want when we redisplay their windows. */
- if (condemn_scroll_bars_hook)
- condemn_scroll_bars_hook (f);
+ if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
+ FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
redisplay_windows (FRAME_ROOT_WINDOW (f));
/* Any scroll bars which redisplay_windows should have
nuked should now go away. */
- if (judge_scroll_bars_hook)
- judge_scroll_bars_hook (f);
+ if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
+ FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
/* If fonts changed, display again. */
/* ??? rms: I suspect it is a mistake to jump all the way
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
- if (f->updated_p)
- {
- mark_window_display_accurate (f->root_window, 1);
- if (frame_up_to_date_hook)
- frame_up_to_date_hook (f);
- }
+ if (f->updated_p)
+ {
+ mark_window_display_accurate (f->root_window, 1);
+ if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
+ FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
+ }
}
}
}
/* Say overlay arrows are up to date. */
update_overlay_arrows (1);
- if (frame_up_to_date_hook != 0)
- frame_up_to_date_hook (sf);
+ if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
+ FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
}
update_mode_lines = 0;
#ifdef HAVE_WINDOW_SYSTEM
if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
{
- Lisp_Object tail, frame;
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
- if (FRAME_WINDOW_P (f))
- clear_image_cache (f, 0);
- }
+ clear_image_caches (Qnil);
clear_image_cache_count = 0;
}
#endif /* HAVE_WINDOW_SYSTEM */
else
redisplay_internal (1);
- if (rif != NULL && rif->flush_display_optional)
- rif->flush_display_optional (NULL);
+ if (FRAME_RIF (SELECTED_FRAME ()) != NULL
+ && FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
+ FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (NULL);
}
redisplay_internal. Reset redisplaying_p to the value it had
before redisplay_internal was called, and clear
prevent_freeing_realized_faces_p. It also selects the previously
- selected frame. */
+ selected frame, unless it has been deleted (by an X connection
+ failure during redisplay, for example). */
static Lisp_Object
unwind_redisplay (val)
old_redisplaying_p = XCAR (val);
redisplaying_p = XFASTINT (old_redisplaying_p);
old_frame = XCDR (val);
- if (! EQ (old_frame, selected_frame))
+ if (! EQ (old_frame, selected_frame)
+ && FRAME_LIVE_P (XFRAME (old_frame)))
select_frame_for_redisplay (old_frame);
return Qnil;
}
minimum distance from the old window start. */
pos = it.current.pos;
min_distance = INFINITY;
- while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
+ while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
distance < min_distance)
{
min_distance = distance;
start = end = whole = 0;
/* Indicate what this scroll bar ought to be displaying now. */
- set_vertical_scroll_bar_hook (w, end - start, whole, start);
+ if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+ (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+ (w, end - start, whole, start);
}
*w->desired_matrix->method = 0;
#endif
- specbind (Qinhibit_point_motion_hooks, Qt);
-
+ restart:
reconsider_clip_changes (w, buffer);
/* Has the mode line to be updated? */
/* Really select the buffer, for the sake of buffer-local
variables. */
set_buffer_internal_1 (XBUFFER (w->buffer));
- SET_TEXT_POS (opoint, PT, PT_BYTE);
-
- beg_unchanged = BEG_UNCHANGED;
- end_unchanged = END_UNCHANGED;
current_matrix_up_to_date_p
= (!NILP (w->window_end_valid)
&& XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
+ /* Run the window-bottom-change-functions
+ if it is possible that the text on the screen has changed
+ (either due to modification of the text, or any other reason). */
+ if (!current_matrix_up_to_date_p
+ && !NILP (Vwindow_text_change_functions))
+ {
+ safe_run_hooks (Qwindow_text_change_functions);
+ goto restart;
+ }
+
+ beg_unchanged = BEG_UNCHANGED;
+ end_unchanged = END_UNCHANGED;
+
+ SET_TEXT_POS (opoint, PT, PT_BYTE);
+
+ specbind (Qinhibit_point_motion_hooks, Qt);
+
buffer_unchanged_p
= (!NILP (w->window_end_valid)
&& !current_buffer->clip_changed
display_menu_bar (w);
#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f))
+ {
#if defined (USE_GTK) || USE_MAC_TOOLBAR
- redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
+ redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
#else
- redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
- && (FRAME_TOOL_BAR_LINES (f) > 0
- || !NILP (Vauto_resize_tool_bars));
-
+ redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
+ && (FRAME_TOOL_BAR_LINES (f) > 0
+ || !NILP (Vauto_resize_tool_bars));
#endif
- if (redisplay_tool_bar_p && redisplay_tool_bar (f))
- {
- extern int ignore_mouse_drag_p;
- ignore_mouse_drag_p = 1;
- }
+ if (redisplay_tool_bar_p && redisplay_tool_bar (f))
+ {
+ extern int ignore_mouse_drag_p;
+ ignore_mouse_drag_p = 1;
+ }
+ }
#endif
}
/* Note that we actually used the scroll bar attached to this
window, so it shouldn't be deleted at the end of redisplay. */
- redeem_scroll_bar_hook (w);
+ if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
+ (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
}
/* Restore current_buffer and value of point in it. */
if (run.height > 0 && run.current_y != run.desired_y)
{
update_begin (f);
- rif->update_window_begin_hook (w);
- rif->clear_window_mouse_face (w);
- rif->scroll_run_hook (w, &run);
- rif->update_window_end_hook (w, 0, 0);
+ FRAME_RIF (f)->update_window_begin_hook (w);
+ FRAME_RIF (f)->clear_window_mouse_face (w);
+ FRAME_RIF (f)->scroll_run_hook (w, &run);
+ FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
update_end (f);
}
if (run.height)
{
update_begin (f);
- rif->update_window_begin_hook (w);
- rif->clear_window_mouse_face (w);
- rif->scroll_run_hook (w, &run);
- rif->update_window_end_hook (w, 0, 0);
+ FRAME_RIF (f)->update_window_begin_hook (w);
+ FRAME_RIF (f)->clear_window_mouse_face (w);
+ FRAME_RIF (f)->scroll_run_hook (w, &run);
+ FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
update_end (f);
}
/* Display must not have been paused, otherwise the current matrix
is not up to date. */
- if (NILP (w->window_end_valid))
- abort ();
+ eassert (!NILP (w->window_end_valid));
/* A value of window_end_pos >= END_UNCHANGED means that the window
end is in the range of changed text. If so, there is no
}
}
- if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
- abort ();
+ eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
return row_found;
}
/* Window must either use window-based redisplay or be full width. */
if (!FRAME_WINDOW_P (f)
- && (!line_ins_del_ok
+ && (!FRAME_LINE_INS_DEL_OK (f)
|| !WINDOW_FULL_WIDTH_P (w)))
GIVE_UP (4);
if (FRAME_WINDOW_P (f))
{
- rif->update_window_begin_hook (w);
- rif->clear_window_mouse_face (w);
- rif->scroll_run_hook (w, &run);
- rif->update_window_end_hook (w, 0, 0);
+ FRAME_RIF (f)->update_window_begin_hook (w);
+ FRAME_RIF (f)->clear_window_mouse_face (w);
+ FRAME_RIF (f)->scroll_run_hook (w, &run);
+ FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
}
else
{
{
/* Scroll last_unchanged_at_beg_row to the end of the
window down dvpos lines. */
- set_terminal_window (end);
+ set_terminal_window (f, end);
/* On dumb terminals delete dvpos lines at the end
before inserting dvpos empty lines. */
- if (!scroll_region_ok)
- ins_del_lines (end - dvpos, -dvpos);
+ if (!FRAME_SCROLL_REGION_OK (f))
+ ins_del_lines (f, end - dvpos, -dvpos);
/* Insert dvpos empty lines in front of
last_unchanged_at_beg_row. */
- ins_del_lines (from, dvpos);
+ ins_del_lines (f, from, dvpos);
}
else if (dvpos < 0)
{
/* Scroll up last_unchanged_at_beg_vpos to the end of
the window to last_unchanged_at_beg_vpos - |dvpos|. */
- set_terminal_window (end);
+ set_terminal_window (f, end);
/* Delete dvpos lines in front of
last_unchanged_at_beg_vpos. ins_del_lines will set
the cursor to the given vpos and emit |dvpos| delete
line sequences. */
- ins_del_lines (from + dvpos, dvpos);
+ ins_del_lines (f, from + dvpos, dvpos);
/* On a dumb terminal insert dvpos empty lines at the
end. */
- if (!scroll_region_ok)
- ins_del_lines (end + dvpos, -dvpos);
+ if (!FRAME_SCROLL_REGION_OK (f))
+ ins_del_lines (f, end + dvpos, -dvpos);
}
- set_terminal_window (0);
+ set_terminal_window (f, 0);
}
update_end (f);
/* Don't do all this for graphical frames. */
#ifdef HAVE_NTGUI
- if (!NILP (Vwindow_system))
+ if (FRAME_W32_P (f))
return;
#endif
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
break;
/* Remember where item was displayed. */
- AREF (items, i + 3) = make_number (it.hpos);
+ ASET (items, i + 3, make_number (it.hpos));
/* Display the item, pad with one space. */
if (it.current_x < it.last_visible_x)
/* Temporarily make frame's keyboard the current kboard so that
kboard-local variables in the mode_line_format will get the right
values. */
- push_frame_kboard (it.f);
+ push_kboard (FRAME_KBOARD (it.f));
record_unwind_save_match_data ();
display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
- pop_frame_kboard ();
+ pop_kboard ();
unbind_to (count, Qnil);
int multibyte;
int bytepos, charpos;
unsigned 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, &multibyte);
+ spec = decode_mode_spec (it->w, c, field, prec, &multibyte,
+ &string);
switch (mode_line_target)
{
break;
case MODE_LINE_STRING:
{
- int len = strlen (spec);
- Lisp_Object tem = make_string (spec, len);
+ if (NILP (string))
+ {
+ int len = strlen (spec);
+ string = make_string (spec, len);
+ }
props = Ftext_properties_at (make_number (charpos), elt);
/* Should only keep face property in props */
- n += store_mode_line_string (NULL, tem, 0, field, prec, props);
+ n += store_mode_line_string (NULL, string, 0, field, prec, props);
}
break;
case MODE_LINE_DISPLAY:
{
int nglyphs_before, nwritten;
+ if (STRINGP (string))
+ spec = NULL;
nglyphs_before = it->glyph_row->used[TEXT_AREA];
- nwritten = display_string (spec, Qnil, elt,
+ nwritten = display_string (spec, string, elt,
charpos, 0, it,
field, prec, 0,
multibyte);
buffer = w->buffer;
CHECK_BUFFER (buffer);
- if (NILP (format))
+ /* Make formatting the modeline a non-op when noninteractive, otherwise
+ there will be problems later caused by a partially initialized frame. */
+ if (NILP (format) || noninteractive)
return empty_unibyte_string;
if (no_props)
= (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
}
- push_frame_kboard (it.f);
+ push_kboard (FRAME_KBOARD (it.f));
display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
- pop_frame_kboard ();
+ pop_kboard ();
if (no_props)
{
static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
static char *
-decode_mode_spec (w, c, field_width, precision, multibyte)
+decode_mode_spec (w, c, field_width, precision, multibyte, string)
struct window *w;
register int c;
int field_width, precision;
int *multibyte;
+ Lisp_Object *string;
{
Lisp_Object obj;
struct frame *f = XFRAME (WINDOW_FRAME (w));
char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
struct buffer *b = current_buffer;
- obj = Qnil;
+ *string = obj = Qnil;
*multibyte = 0;
switch (c)
goto no_value;
}
- if (!NILP (w->base_line_number)
- && !NILP (w->base_line_pos)
+ if (INTEGERP (w->base_line_number)
+ && INTEGERP (w->base_line_pos)
&& XFASTINT (w->base_line_pos) <= startpos)
{
line = XFASTINT (w->base_line_number);
{
/* No need to mention EOL here--the terminal never needs
to do EOL conversion. */
- p = decode_mode_spec_coding (CODING_ID_NAME (keyboard_coding.id),
+ p = decode_mode_spec_coding (CODING_ID_NAME
+ (FRAME_KEYBOARD_CODING (f)->id),
p, 0);
- p = decode_mode_spec_coding (CODING_ID_NAME (terminal_coding.id),
+ p = decode_mode_spec_coding (CODING_ID_NAME
+ (FRAME_TERMINAL_CODING (f)->id),
p, 0);
}
p = decode_mode_spec_coding (b->buffer_file_coding_system,
if (STRINGP (obj))
{
*multibyte = STRING_MULTIBYTE (obj);
+ *string = obj;
return (char *) SDATA (obj);
}
else
unsigned char *string;
Lisp_Object lisp_string;
Lisp_Object face_string;
- int face_string_pos;
- int start;
+ EMACS_INT face_string_pos;
+ EMACS_INT start;
struct it *it;
int field_width, precision, max_x;
int multibyte;
from LISP_STRING, if that's given. */
if (STRINGP (face_string))
{
- int endptr;
+ EMACS_INT endptr;
struct face *face;
it->face_id
if (NILP (prop))
return OK_PIXELS (0);
+ xassert (FRAME_LIVE_P (it->f));
+
if (SYMBOLP (prop))
{
if (SCHARS (SYMBOL_NAME (prop)) == 2)
if (SYMBOLP (car))
{
#ifdef HAVE_WINDOW_SYSTEM
- if (valid_image_p (prop))
+ if (FRAME_WINDOW_P (it->f)
+ && valid_image_p (prop))
{
int id = lookup_image (it->f, prop);
struct image *img = IMAGE_FROM_ID (it->f, id);
else
STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
/* Maybe encode the character in *CHAR2B. */
- rif->encode_char (c, char2b, font_info, charset, NULL);
+ FRAME_RIF (f)->encode_char (c, char2b, font_info, charset, NULL);
}
/* Make sure X resources of the face are allocated. */
if (CHARSET_ID (charset) != charset_ascii)
{
glyph->font_type
- = rif->encode_char (glyph->u.ch, char2b, font_info, charset,
- two_byte_p);
+ = FRAME_RIF (f)->encode_char (glyph->u.ch, char2b, font_info,
+ charset, two_byte_p);
}
}
}
s->cmp->hash_index * 2);
s->face = base_face;
- s->font_info = s->cmp->font;
+ s->font_info = base_face->font_info;
s->font = s->font_info->font;
for (i = 0, s->nchars = 0; i < s->cmp->glyph_len; i++, s->nchars++)
{
Lisp_Object g = LGSTRING_GLYPH (gstring, i);
unsigned code;
XChar2b * store_pos;
- if (NILP (LGLYPH_FROM (g)))
+ if (NILP (g))
break;
- code = XUINT (LGLYPH_CODE (g));
+ code = LGLYPH_CODE (g);
store_pos = s->char2b + i;
STORE_XCHAR2B (store_pos, code >> 8, code & 0xFF);
}
if (c != '\t')
{
- int face_id = FACE_FOR_CHAR (s->f, base_face, c, -1, Qnil);
+ int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
+ -1, Qnil);
face = get_char_face_and_encoding (s->f, c, face_id,
s->char2b + i, 1, 1);
glyph = s->row->glyphs[s->area] + start;
last = s->row->glyphs[s->area] + end;
voffset = glyph->voffset;
-
+ s->padding_p = glyph->padding_p;
glyph_not_available_p = glyph->glyph_not_available_p;
while (glyph < last
++s->nchars;
xassert (s->nchars <= end - start);
s->width += glyph->pixel_width;
- ++glyph;
+ if (glyph++->padding_p != s->padding_p)
+ break;
}
s->font = s->face->font;
}
static XCharStruct *
-get_per_char_metric (font, font_info, char2b, font_type)
+get_per_char_metric (f, font, font_info, char2b, font_type)
+ struct frame *f;
XFontStruct *font;
struct font_info *font_info;
XChar2b *char2b;
return &pcm_value;
}
#endif /* USE_FONT_BACKEND */
- return rif->per_char_metric (font, char2b, font_type);
+ return FRAME_RIF (f)->per_char_metric (font, char2b, font_type);
}
/* EXPORT for RIF:
font = face->font;
font_info = FONT_INFO_FROM_FACE (f, face);
if (font /* ++KFS: Should this be font_info ? */
- && (pcm = get_per_char_metric (font, font_info, &char2b, glyph->font_type)))
+ && (pcm = get_per_char_metric (f, font, font_info, &char2b, glyph->font_type)))
{
if (pcm->rbearing > pcm->width)
*right = pcm->rbearing - pcm->width;
{
while (s)
{
- if (rif->compute_glyph_string_overhangs)
- rif->compute_glyph_string_overhangs (s);
+ if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
+ FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
x -= s->width;
s->x = x;
s = s->prev;
{
while (s)
{
- if (rif->compute_glyph_string_overhangs)
- rif->compute_glyph_string_overhangs (s);
+ if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
+ FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
s->x = x;
x += s->width;
s = s->next;
int n; \
\
char2b = (XChar2b *) alloca ((sizeof *char2b) * cmp->glyph_len); \
- base_face = base_face->ascii_face; \
\
/* Make glyph_strings for each glyph sequence that is drawable by \
the same face, and append them to HEAD/TAIL. */ \
struct glyph_string *h, *t;
/* Compute overhangs for all glyph strings. */
- if (rif->compute_glyph_string_overhangs)
+ if (FRAME_RIF (f)->compute_glyph_string_overhangs)
for (s = head; s; s = s->next)
- rif->compute_glyph_string_overhangs (s);
+ FRAME_RIF (f)->compute_glyph_string_overhangs (s);
/* Prepend glyph strings for glyphs in front of the first glyph
string that are overwritten because of the first glyph
/* Draw all strings. */
for (s = head; s; s = s->next)
- rif->draw_glyph_string (s);
+ FRAME_RIF (f)->draw_glyph_string (s);
if (area == TEXT_AREA
&& !row->full_width_p
{
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
- glyph->pixel_width = it->pixel_width;
+ if (it->pixel_width > 0)
+ {
+ glyph->pixel_width = it->pixel_width;
+ glyph->padding_p = 0;
+ }
+ else
+ {
+ /* Assure at least 1-pixel width. Otherwise, cursor can't
+ be displayed correctly. */
+ glyph->pixel_width = 1;
+ glyph->padding_p = 1;
+ }
glyph->ascent = it->ascent;
glyph->descent = it->descent;
glyph->voffset = it->voffset;
glyph->right_box_line_p = it->end_of_box_run_p;
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
- glyph->padding_p = 0;
glyph->glyph_not_available_p = it->glyph_not_available_p;
glyph->face_id = it->face_id;
glyph->u.ch = it->char_to_display;
}
if (it->start_of_box_run_p && slice.x == 0)
- it->pixel_width += abs (face->box_line_width);
+ it->pixel_width += eabs (face->box_line_width);
if (it->end_of_box_run_p && slice.x + slice.width == img->width)
- it->pixel_width += abs (face->box_line_width);
+ it->pixel_width += eabs (face->box_line_width);
}
take_vertical_position_into_account (it);
it->nglyphs = 1;
- pcm = get_per_char_metric (font, font_info, &char2b,
- FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
-
- if (it->override_ascent >= 0)
- {
- it->ascent = it->override_ascent;
- it->descent = it->override_descent;
- boff = it->override_boff;
- }
- else
- {
- it->ascent = FONT_BASE (font) + boff;
- it->descent = FONT_DESCENT (font) - boff;
- }
+ pcm = get_per_char_metric (it->f, font, font_info, &char2b,
+ FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
+
+ if (it->override_ascent >= 0)
+ {
+ it->ascent = it->override_ascent;
+ it->descent = it->override_descent;
+ boff = it->override_boff;
+ }
+ else
+ {
+ it->ascent = FONT_BASE (font) + boff;
+ it->descent = FONT_DESCENT (font) - boff;
+ }
if (pcm)
{
if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
it->glyph_row->contains_overlapping_glyphs_p = 1;
}
+ if (! stretched_p && it->pixel_width == 0)
+ /* We assure that all visible glyphs have at least 1-pixel
+ width. */
+ it->pixel_width = 1;
}
else if (it->char_to_display == '\n')
{
multiplying the width of font by the width of the
character. */
- pcm = get_per_char_metric (font, font_info, &char2b,
- FONT_TYPE_FOR_MULTIBYTE (font, it->c));
+ pcm = get_per_char_metric (it->f, font, font_info, &char2b,
+ FONT_TYPE_FOR_MULTIBYTE (font, it->c));
if (font_not_found_p || !pcm)
{
take_vertical_position_into_account (it);
+ if (it->ascent < 0)
+ it->ascent = 0;
+ if (it->descent < 0)
+ it->descent = 0;
+
if (it->glyph_row)
append_glyph (it);
+ if (it->pixel_width == 0)
+ /* We assure that all visible glyphs have at least 1-pixel
+ width. */
+ it->pixel_width = 1;
}
it->multibyte_p = saved_multibyte_p;
}
#ifdef USE_FONT_BACKEND
if (cmp->method == COMPOSITION_WITH_GLYPH_STRING)
{
- if (! cmp->font || cmp->font != font)
- font_prepare_composition (cmp);
+ PREPARE_FACE_FOR_DISPLAY (it->f, face);
+ font_prepare_composition (cmp, it->f);
}
else
#endif /* USE_FONT_BACKEND */
{
get_char_face_and_encoding (it->f, c, it->face_id,
&char2b, it->multibyte_p, 0);
- pcm = get_per_char_metric (font, font_info, &char2b,
+ pcm = get_per_char_metric (it->f, font, font_info, &char2b,
FONT_TYPE_FOR_MULTIBYTE (font, c));
}
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 (font, font_info, &char2b,
+ pcm = get_per_char_metric (it->f, font, font_info, &char2b,
FONT_TYPE_FOR_MULTIBYTE (font,
ch));
}
+ grefx * (rightmost - leftmost) / 2
- nrefx * width / 2
+ xoff);
-
+
btm = ((grefy == 0 ? highest
: grefy == 1 ? 0
: grefy == 2 ? lowest
it->pixel_width = cmp->pixel_width;
it->ascent = it->phys_ascent = cmp->ascent;
it->descent = it->phys_descent = cmp->descent;
-
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
it->ascent += overline_margin;
take_vertical_position_into_account (it);
+ if (it->ascent < 0)
+ it->ascent = 0;
+ if (it->descent < 0)
+ it->descent = 0;
if (it->glyph_row)
append_composite_glyph (it);
frame_x = window_box_left (w, updated_area) + output_cursor.x;
frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
- rif->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
- line_height, shift_by_width);
+ FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
+ line_height, shift_by_width);
/* Write the glyphs. */
hpos = start - row->glyphs[updated_area];
if (to_x > from_x && to_y > from_y)
{
BLOCK_INPUT;
- rif->clear_frame_area (f, from_x, from_y,
- to_x - from_x, to_y - from_y);
+ FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
+ to_x - from_x, to_y - from_y);
UNBLOCK_INPUT;
}
}
non_selected = 1;
}
- /* Nonselected window or nonselected frame. */
+ /* 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
if (NILP (b->cursor_type))
return NO_CURSOR;
- /* Use cursor-in-non-selected-windows for non-selected window or frame. */
- if (non_selected)
- {
- alt_cursor = b->cursor_in_non_selected_windows;
- return get_specified_cursor_type (alt_cursor, width);
- }
-
/* Get the normal cursor type for this window. */
if (EQ (b->cursor_type, Qt))
{
else
cursor_type = get_specified_cursor_type (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;
+ if (!EQ (Qt, alt_cursor))
+ return get_specified_cursor_type (alt_cursor, width);
+ /* t means modify the normal cursor type. */
+ if (cursor_type == FILLED_BOX_CURSOR)
+ cursor_type = HOLLOW_BOX_CURSOR;
+ else if (cursor_type == BAR_CURSOR && *width > 1)
+ --*width;
+ return cursor_type;
+ }
+
/* Use normal cursor if not blinked off. */
if (!w->cursor_off_p)
{
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x));
if (width > 0)
- rif->clear_frame_area (f, x, y, width, cursor_row->visible_height);
+ FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
}
/* Erase the cursor by redrawing the character underneath it. */
w->phys_cursor.vpos = vpos;
}
- rif->draw_window_cursor (w, glyph_row, x, y,
- new_cursor_type, new_cursor_width,
- on, active_cursor);
+ FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
+ new_cursor_type, new_cursor_width,
+ on, active_cursor);
}
/* Change the mouse cursor. */
if (draw == DRAW_NORMAL_TEXT && !EQ (dpyinfo->mouse_face_window, f->tool_bar_window))
- rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
+ FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
else if (draw == DRAW_MOUSE_FACE)
- rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
+ FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
else
- rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
+ FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
}
/* EXPORT:
goto found;
}
else if (best_glyph == NULL
- || ((abs (g->charpos - pos)
- < abs (best_glyph->charpos - pos))
+ || ((eabs (g->charpos - pos)
+ < eabs (best_glyph->charpos - pos))
&& (right_p
? g->charpos < pos
: g->charpos > pos)))
return inside;
}
}
- /* If we don't understand the format, pretend we're not in the hot-spot. */
return 0;
}
}
if (cursor != No_Cursor)
- rif->define_frame_cursor (f, cursor);
+ FRAME_RIF (f)->define_frame_cursor (f, cursor);
}
/* Take proper action when mouse has moved to the mode or header line
int gpos;
int gseq_length;
int total_pixel_width;
- int ignore;
+ EMACS_INT ignore;
int vpos, hpos;
/* Find the range of text around this char that
should be active. */
Lisp_Object before, after;
- int ignore;
+ EMACS_INT ignore;
before = Foverlay_start (overlay);
after = Foverlay_end (overlay);
/* Find the range of text around this char that
should be active. */
Lisp_Object before, after, beginning, end;
- int ignore;
+ EMACS_INT ignore;
beginning = Fmarker_position (w->start);
end = make_number (BUF_Z (XBUFFER (object))
else if (!NILP (mouse_face) && STRINGP (object))
{
Lisp_Object b, e;
- int ignore;
+ EMACS_INT ignore;
b = Fprevious_single_property_change (make_number (pos + 1),
Qmouse_face,
{
Lisp_Object before = Foverlay_start (overlay);
Lisp_Object after = Foverlay_end (overlay);
- int ignore;
+ EMACS_INT ignore;
/* Note that we might not be able to find position
BEFORE in the glyph matrix if the overlay is
{
XRectangle cr, result;
struct glyph *cursor_glyph;
+ struct glyph_row *row;
+
+ if (w->phys_cursor.vpos >= 0
+ && w->phys_cursor.vpos < w->current_matrix->nrows
+ && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
+ row->enabled_p)
+ && row->cursor_in_fringe_p)
+ {
+ /* Cursor is in the fringe. */
+ cr.x = window_box_right_offset (w,
+ (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+ ? RIGHT_MARGIN_AREA
+ : TEXT_AREA));
+ cr.y = row->y;
+ cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+ cr.height = row->height;
+ return x_intersect_rectangles (&cr, r, &result);
+ }
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph)
I assume the effect is the same -- and this is portable. */
return x_intersect_rectangles (&cr, r, &result);
}
- else
- return 0;
+ /* If we don't understand the format, pretend we're not in the hot-spot. */
+ return 0;
}
x_draw_vertical_border (w)
struct window *w;
{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+
/* We could do better, if we knew what type of scroll-bar the adjacent
windows (on either side) have... But we don't :-(
However, I think this works ok. ++KFS 2003-04-25 */
y1 -= 1;
if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
- x1 -= 1;
+ x1 -= 1;
- rif->draw_vertical_window_border (w, x1, y0, y1);
+ FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
}
else if (!WINDOW_LEFTMOST_P (w)
&& !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
y1 -= 1;
if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
- x0 -= 1;
+ x0 -= 1;
- rif->draw_vertical_window_border (w, x0, y0, y1);
+ FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
}
}
staticpro (&Qwindow_scroll_functions);
Qwindow_scroll_functions = intern ("window-scroll-functions");
+ staticpro (&Qwindow_text_change_functions);
+ Qwindow_text_change_functions = intern ("window-text-change-functions");
+
staticpro (&Qredisplay_end_trigger_functions);
Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
doc: /* *Scroll up to this many lines, to bring point back on screen.
-A value of zero means to scroll the text to center point vertically
-in the window. */);
+If point moves off-screen, redisplay will scroll by up to
+`scroll-conservatively' lines in order to bring point just barely
+onto the screen again. If that cannot be done, then redisplay
+recenters point as usual.
+
+A value of zero means always recenter point if it moves off screen. */);
scroll_conservatively = 0;
DEFVAR_INT ("scroll-margin", &scroll_margin,
is not valid when these functions are called. */);
Vwindow_scroll_functions = Qnil;
+ DEFVAR_LISP ("window-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,
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.
mouse pointer enters it.
Autoselection selects the minibuffer only if it is active, and never
-unselects the minibuffer if it is active. */);
+unselects the minibuffer if it is active.
+
+When customizing this variable make sure that the actual value of
+`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_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
doc: /* *Non-nil means scroll the display automatically to make point visible. */);
automatic_hscrolling_p = 1;
+ Qauto_hscroll_mode = intern ("auto-hscroll-mode");
+ staticpro (&Qauto_hscroll_mode);
DEFVAR_INT ("hscroll-margin", &hscroll_margin,
doc: /* *How many columns away from the window edge point is allowed to get