/* 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;
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 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,
static int face_before_or_after_it_pos P_ ((struct it *, int));
static int next_overlay_change P_ ((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);
XSETWINDOW (it->window, w);
it->w = w;
it->f = XFRAME (w->frame);
-
+
/* Extra space between lines (on window systems only). */
if (base_face_id == DEFAULT_FACE_ID
&& FRAME_WINDOW_P (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);
}
int pos;
{
int noverlays;
- int endpos;
+ EMACS_INT endpos;
Lisp_Object *overlays;
int i;
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,
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;
{
return 0;
}
- /* Handle `(space_width WIDTH)'. */
+ /* Handle `(space-width WIDTH)'. */
if (CONSP (spec)
&& EQ (XCAR (spec), Qspace_width)
&& CONSP (XCDR (spec)))
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->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 */
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)
+ {
+ 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))
{
- /* 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 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
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);
}
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.
{
Lisp_Object tail, frame;
int changed_count = 0;
-
+
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
-
+
if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
{
if (f->resized_p)
f->resized_p = 0;
}
}
-
+
frame_garbaged = 0;
if (changed_count)
++windows_or_buffers_changed;
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 the initial terminal
frame. If we let this through, a message would be displayed on
if (FRAME_INITIAL_P (XFRAME (selected_frame)))
return 0;
#endif /* HAVE_WINDOW_SYSTEM */
-#endif
/* Redraw garbaged frames. */
if (frame_garbaged)
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;
/* 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;
}
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));
}
}
}
-
+
/* Notice any pending interrupt request to change frame size. */
do_pending_window_change (1);
#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 */
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;
*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 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;
}
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)
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)
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
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);
}
-/* Get face and two-byte form of character C in face FACE_ID on frame
- F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
- means we want to display multibyte text. DISPLAY_P non-zero means
- make sure that X resources for the face returned are allocated.
- Value is a pointer to a realized face that is ready for display if
- DISPLAY_P is non-zero. */
-
-static INLINE struct face *
-get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
- struct frame *f;
- int c, face_id;
- XChar2b *char2b;
- int multibyte_p, display_p;
-{
- struct face *face = FACE_FROM_ID (f, face_id);
-
- if (!multibyte_p)
- {
- /* Unibyte case. We don't have to encode, but we have to make
- sure to use a face suitable for unibyte. */
- STORE_XCHAR2B (char2b, 0, c);
- face_id = FACE_FOR_CHAR (f, face, c);
- face = FACE_FROM_ID (f, face_id);
- }
- else if (c < 128)
- {
- /* Case of ASCII in a face known to fit ASCII. */
- STORE_XCHAR2B (char2b, 0, c);
- }
- else
- {
- int c1, c2, charset;
-
- /* Split characters into bytes. If c2 is -1 afterwards, C is
- really a one-byte character so that byte1 is zero. */
- SPLIT_CHAR (c, charset, c1, c2);
- if (c2 > 0)
- STORE_XCHAR2B (char2b, c1, c2);
- else
- STORE_XCHAR2B (char2b, 0, c1);
-
- /* Maybe encode the character in *CHAR2B. */
- if (face->font != NULL)
- {
- struct font_info *font_info
- = FONT_INFO_FROM_ID (f, face->font_info_id);
- if (font_info)
- FRAME_RIF (f)->encode_char (c, char2b, font_info, 0);
- }
- }
-
- /* Make sure X resources of the face are allocated. */
-#ifdef HAVE_X_WINDOWS
- if (display_p)
-#endif
- {
- xassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
- }
-
- return face;
-}
-
-
/* Set background width of glyph string S. START is the index of the
first glyph following S. LAST_X is the right-most x-position + 1
in the drawing area. */
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. */ \
}
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);
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);
}
#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 */
+ 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);
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)))
{
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)
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 */
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.
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