Commit 855a0da7 authored by Stefan Monnier's avatar Stefan Monnier

Get rid of the direct_output optimizations.

* keyboard.c (nonundocount): Remove extern declaration.
(command_loop_1): Remove brittle optimisation for cheap and common operations.
* xdisp.c (redisplay_internal): Don't bother checking
redisplay_performed_directly_p any more.
* sysdep.c (init_sys_modes): Don't call direct_output_forward_char any more.
* dispnew.c (redisplay_performed_directly_p)
(direct_output_for_insert, direct_output_forward_char):
* dispextern.h (redisplay_performed_directly_p)
(direct_output_for_insert, direct_output_forward_char): Remove.
* cmds.c (nonundocount): Make it static.
parent dcf7843e
2010-03-31 Stefan Monnier <monnier@iro.umontreal.ca>
Get rid of the direct_output optimizations.
* keyboard.c (nonundocount): Remove extern declaration.
(command_loop_1): Remove brittle optimisation for cheap and
common operations.
* xdisp.c (redisplay_internal): Don't bother checking
redisplay_performed_directly_p any more.
* sysdep.c (init_sys_modes): Don't call direct_output_forward_char
any more.
* dispnew.c (redisplay_performed_directly_p)
(direct_output_for_insert, direct_output_forward_char):
* dispextern.h (redisplay_performed_directly_p)
(direct_output_for_insert, direct_output_forward_char): Remove.
* cmds.c (nonundocount): Make it static.
2010-03-31 Bernhard Herzog <bh@intevation.de> (tiny change)
* menu.c (Fx_popup_menu): Use last_event_timestamp (Bug#4930).
......@@ -9,8 +25,8 @@
2010-03-31 Adrian Robert <adrian.b.robert@gmail.com>
* xdisp.c (x_consider_frame_title, update_window_cursor): Remove
HAVE_NS conditionals.
* xdisp.c (x_consider_frame_title, update_window_cursor):
Remove HAVE_NS conditionals.
(prepare_menu_bars)[HAVE_NS]: Call ns_set_doc_edited.
* nsfns.m (x_implicitly_set_name): If frame-title-format is t, use
......
......@@ -317,7 +317,7 @@ N was explicitly specified. */)
return value;
}
int nonundocount;
static int nonundocount;
/* Note that there's code in command_loop_1 which typically avoids
calling this. */
......
......@@ -1102,17 +1102,9 @@ extern int cursor_in_echo_area;
extern int display_completed;
/* Non-zero means redisplay has been performed directly (see also
direct_output_for_insert and direct_output_forward_char), so that
no further updating has to be performed. The function
redisplay_internal checks this flag, and does nothing but reset it
to zero if it is non-zero. */
extern int redisplay_performed_directly_p;
/* A temporary storage area, including a row of glyphs. Initialized
in xdisp.c. Used for various purposes, as an example see
direct_output_for_insert. */
get_overlay_arrow_glyph_row. */
extern struct glyph_row scratch_glyph_row;
......@@ -3172,8 +3164,6 @@ extern void redraw_garbaged_frames P_ ((void));
extern void cancel_line P_ ((int, struct frame *));
extern void init_desired_glyphs P_ ((struct frame *));
extern int scroll_frame_lines P_ ((struct frame *, int, int, int, int));
extern int direct_output_for_insert P_ ((int));
extern int direct_output_forward_char P_ ((int));
extern int update_frame P_ ((struct frame *, int, int));
extern int scrolling P_ ((struct frame *));
extern void bitch_at_user P_ ((void));
......@@ -3200,8 +3190,6 @@ void set_window_update_flags P_ ((struct window *, int));
void redraw_frame P_ ((struct frame *));
void redraw_garbaged_frames P_ ((void));
int scroll_cost P_ ((struct frame *, int, int, int));
int direct_output_for_insert P_ ((int));
int direct_output_forward_char P_ ((int));
int update_frame P_ ((struct frame *, int, int));
void update_single_window P_ ((struct window *, int));
int scrolling P_ ((struct frame *));
......
......@@ -302,12 +302,6 @@ int updated_area;
struct glyph space_glyph;
/* Non-zero means update has been performed directly, so that there's
no need for redisplay_internal to do much work. Set by
direct_output_for_insert. */
int redisplay_performed_directly_p;
/* Counts of allocated structures. These counts serve to diagnose
memory leaks and double frees. */
......@@ -3454,401 +3448,6 @@ redraw_garbaged_frames ()
}
/***********************************************************************
Direct Operations
***********************************************************************/
/* Try to update display and current glyph matrix directly.
This function is called after a character G has been inserted into
current_buffer. It tries to update the current glyph matrix and
perform appropriate screen output to reflect the insertion. If it
succeeds, the global flag redisplay_performed_directly_p will be
set to 1, and thereby prevent the more costly general redisplay
from running (see redisplay_internal).
This function is not called for `hairy' character insertions.
In particular, it is not called when after or before change
functions exist, like they are used by font-lock. See keyboard.c
for details where this function is called. */
int
direct_output_for_insert (g)
int g;
{
register struct frame *f = SELECTED_FRAME ();
struct window *w = XWINDOW (selected_window);
struct it it, it2;
struct glyph_row *glyph_row;
struct glyph *glyphs, *glyph, *end;
int n;
/* Non-null means that redisplay of W is based on window matrices. */
int window_redisplay_p = FRAME_WINDOW_P (f);
/* Non-null means we are in overwrite mode. */
int overwrite_p = !NILP (current_buffer->overwrite_mode);
int added_width;
struct text_pos pos;
int delta, delta_bytes;
/* Not done directly. */
redisplay_performed_directly_p = 0;
/* Quickly give up for some common cases. */
if (cursor_in_echo_area
/* Give up if fonts have changed. */
|| fonts_changed_p
/* Give up if face attributes have been changed. */
|| face_change_count
/* Give up if cursor position not really known. */
|| !display_completed
/* Give up if buffer appears in two places. */
|| buffer_shared > 1
/* Give up if we need to reorder bidirectional text. */
|| !NILP (current_buffer->bidi_display_reordering)
/* Give up if currently displaying a message instead of the
minibuffer contents. */
|| (EQ (selected_window, minibuf_window)
&& EQ (minibuf_window, echo_area_window))
/* Give up for hscrolled mini-buffer because display of the prompt
is handled specially there (see display_line). */
|| (MINI_WINDOW_P (w) && XFASTINT (w->hscroll))
/* Give up if overwriting in the middle of a line. */
|| (overwrite_p
&& PT != ZV
&& FETCH_BYTE (PT) != '\n')
/* Give up for tabs and line ends. */
|| g == '\t'
|| g == '\n'
|| g == '\r'
|| (g == ' ' && !NILP (current_buffer->word_wrap))
/* Give up if unable to display the cursor in the window. */
|| w->cursor.vpos < 0
/* Give up if we are showing a message or just cleared the message
because we might need to resize the echo area window. */
|| !NILP (echo_area_buffer[0])
|| !NILP (echo_area_buffer[1])
|| (glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos),
/* Can't do it in a continued line because continuation
lines would change. */
(glyph_row->continued_p
|| glyph_row->exact_window_width_line_p
/* Can't use this method if the line overlaps others or is
overlapped by others because these other lines would
have to be redisplayed. */
|| glyph_row->overlapping_p
|| glyph_row->overlapped_p))
/* Can't do it for partial width windows on terminal frames
because we can't clear to eol in such a window. */
|| (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w)))
return 0;
/* If we can't insert glyphs, we can use this method only
at the end of a line. */
if (!FRAME_CHAR_INS_DEL_OK (f))
if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n')
return 0;
/* Set up a display iterator structure for W. Glyphs will be
produced in scratch_glyph_row. Current position is W's cursor
position. */
clear_glyph_row (&scratch_glyph_row);
SET_TEXT_POS (pos, PT, PT_BYTE);
DEC_TEXT_POS (pos, !NILP (current_buffer->enable_multibyte_characters));
init_iterator (&it, w, CHARPOS (pos), BYTEPOS (pos), &scratch_glyph_row,
DEFAULT_FACE_ID);
glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
if (glyph_row->mouse_face_p)
return 0;
/* Give up if highlighting trailing whitespace and we have trailing
whitespace in glyph_row. We would have to remove the trailing
whitespace face in that case. */
if (!NILP (Vshow_trailing_whitespace)
&& glyph_row->used[TEXT_AREA])
{
struct glyph *last;
last = glyph_row->glyphs[TEXT_AREA] + glyph_row->used[TEXT_AREA] - 1;
if (last->type == STRETCH_GLYPH
|| (last->type == CHAR_GLYPH
&& last->u.ch == ' '))
return 0;
}
/* Give up if there are overlay strings at pos. This would fail
if the overlay string has newlines in it. */
if (STRINGP (it.string))
return 0;
it.hpos = w->cursor.hpos;
it.vpos = w->cursor.vpos;
it.current_x = w->cursor.x + it.first_visible_x;
it.current_y = w->cursor.y;
it.end_charpos = PT;
it.stop_charpos = min (PT, it.stop_charpos);
it.stop_charpos = max (IT_CHARPOS (it), it.stop_charpos);
/* More than one display element may be returned for PT - 1 if
(i) it's a control character which is translated into `\003' or
`^C', or (ii) it has a display table entry, or (iii) it's a
combination of both. */
delta = delta_bytes = 0;
while (get_next_display_element (&it))
{
PRODUCE_GLYPHS (&it);
/* Give up if glyph doesn't fit completely on the line. */
if (it.current_x >= it.last_visible_x)
return 0;
/* Give up if new glyph has different ascent or descent than
the original row, or if it is not a character glyph. */
if (glyph_row->ascent != it.ascent
|| glyph_row->height != it.ascent + it.descent
|| glyph_row->phys_ascent != it.phys_ascent
|| glyph_row->phys_height != it.phys_ascent + it.phys_descent
|| it.what != IT_CHARACTER)
return 0;
delta += 1;
delta_bytes += it.len;
set_iterator_to_next (&it, 1);
}
/* Give up if we hit the right edge of the window. We would have
to insert truncation or continuation glyphs. */
added_width = it.current_x - (w->cursor.x + it.first_visible_x);
if (glyph_row->pixel_width + added_width >= it.last_visible_x)
return 0;
/* Give up if there is a \t following in the line. */
it2 = it;
it2.end_charpos = ZV;
it2.stop_charpos = min (it2.stop_charpos, ZV);
while (get_next_display_element (&it2)
&& !ITERATOR_AT_END_OF_LINE_P (&it2))
{
if (it2.c == '\t')
return 0;
set_iterator_to_next (&it2, 1);
}
/* Number of new glyphs produced. */
n = it.glyph_row->used[TEXT_AREA];
/* Start and end of glyphs in original row. */
glyphs = glyph_row->glyphs[TEXT_AREA] + w->cursor.hpos;
end = glyph_row->glyphs[1 + TEXT_AREA];
/* Make room for new glyphs, then insert them. */
xassert (end - glyphs - n >= 0);
safe_bcopy ((char *) glyphs, (char *) (glyphs + n),
(end - glyphs - n) * sizeof (*end));
bcopy (it.glyph_row->glyphs[TEXT_AREA], glyphs, n * sizeof *glyphs);
glyph_row->used[TEXT_AREA] = min (glyph_row->used[TEXT_AREA] + n,
end - glyph_row->glyphs[TEXT_AREA]);
/* Compute new line width. */
glyph = glyph_row->glyphs[TEXT_AREA];
end = glyph + glyph_row->used[TEXT_AREA];
glyph_row->pixel_width = glyph_row->x;
while (glyph < end)
{
glyph_row->pixel_width += glyph->pixel_width;
++glyph;
}
/* Increment buffer positions for glyphs following the newly
inserted ones. */
for (glyph = glyphs + n; glyph < end; ++glyph)
if (glyph->charpos > 0 && BUFFERP (glyph->object))
glyph->charpos += delta;
if (MATRIX_ROW_END_CHARPOS (glyph_row) > 0)
{
MATRIX_ROW_END_CHARPOS (glyph_row) += delta;
MATRIX_ROW_END_BYTEPOS (glyph_row) += delta_bytes;
}
/* Adjust positions in lines following the one we are in. */
increment_matrix_positions (w->current_matrix,
w->cursor.vpos + 1,
w->current_matrix->nrows,
delta, delta_bytes);
glyph_row->contains_overlapping_glyphs_p
|= it.glyph_row->contains_overlapping_glyphs_p;
glyph_row->displays_text_p = 1;
w->window_end_vpos = make_number (max (w->cursor.vpos,
XFASTINT (w->window_end_vpos)));
if (!NILP (Vshow_trailing_whitespace))
highlight_trailing_whitespace (it.f, glyph_row);
/* Write glyphs. If at end of row, we can simply call write_glyphs.
In the middle, we have to insert glyphs. Note that this is now
implemented for X frames. The implementation uses updated_window
and updated_row. */
updated_row = glyph_row;
updated_area = TEXT_AREA;
update_begin (f);
if (FRAME_RIF (f))
{
FRAME_RIF (f)->update_window_begin_hook (w);
if (glyphs == end - n
/* In front of a space added by append_space. */
|| (glyphs == end - n - 1
&& (end - n)->charpos <= 0))
FRAME_RIF (f)->write_glyphs (glyphs, n);
else
FRAME_RIF (f)->insert_glyphs (glyphs, n);
}
else
{
if (glyphs == end - n)
write_glyphs (f, glyphs, n);
else
insert_glyphs (f, glyphs, n);
}
w->cursor.hpos += n;
w->cursor.x = it.current_x - it.first_visible_x;
xassert (w->cursor.hpos >= 0
&& w->cursor.hpos < w->desired_matrix->matrix_w);
/* How to set the cursor differs depending on whether we are
using a frame matrix or a window matrix. Note that when
a frame matrix is used, cursor_to expects frame coordinates,
and the X and Y parameters are not used. */
if (window_redisplay_p)
FRAME_RIF (f)->cursor_to (w->cursor.vpos, w->cursor.hpos,
w->cursor.y, w->cursor.x);
else
{
int x, y;
x = (WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos)
+ (INTEGERP (w->left_margin_cols)
? XFASTINT (w->left_margin_cols)
: 0));
y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
cursor_to (f, y, x);
}
#ifdef HAVE_WINDOW_SYSTEM
update_window_fringes (w, 0);
#endif
if (FRAME_RIF (f))
FRAME_RIF (f)->update_window_end_hook (w, 1, 0);
update_end (f);
updated_row = NULL;
if (FRAME_TERMCAP_P (f))
fflush (FRAME_TTY (f)->output);
TRACE ((stderr, "direct output for insert\n"));
mark_window_display_accurate (it.window, 1);
redisplay_performed_directly_p = 1;
return 1;
}
/* Perform a direct display update for moving PT by N positions
left or right. N < 0 means a movement backwards. This function
is currently only called for N == 1 or N == -1. */
int
direct_output_forward_char (n)
int n;
{
struct frame *f = SELECTED_FRAME ();
struct window *w = XWINDOW (selected_window);
struct glyph_row *row;
/* Give up if point moved out of or into a composition. */
if (check_point_in_composition (current_buffer, XINT (w->last_point),
current_buffer, PT))
return 0;
/* Give up if face attributes have been changed. */
if (face_change_count)
return 0;
/* Give up if current matrix is not up to date or we are
displaying a message. */
if (!display_completed || cursor_in_echo_area)
return 0;
/* Give up if we need to reorder bidirectional text. */
if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering))
return 0;
/* Give up if the buffer's direction is reversed. */
if (!NILP (XBUFFER (w->buffer)->direction_reversed))
return 0;
/* Can't use direct output if highlighting a region. */
if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
return 0;
/* Can't use direct output if highlighting trailing whitespace. */
if (!NILP (Vshow_trailing_whitespace))
return 0;
/* Give up if we are showing a message or just cleared the message
because we might need to resize the echo area window. */
if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
return 0;
/* Give up if currently displaying a message instead of the
minibuffer contents. */
if (XWINDOW (minibuf_window) == w
&& EQ (minibuf_window, echo_area_window))
return 0;
/* Give up if we don't know where the cursor is. */
if (w->cursor.vpos < 0)
return 0;
row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
/* Give up if PT is outside of the last known cursor row. */
if (PT <= MATRIX_ROW_START_CHARPOS (row)
|| PT >= MATRIX_ROW_END_CHARPOS (row))
return 0;
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
w->last_cursor = w->cursor;
XSETFASTINT (w->last_point, PT);
xassert (w->cursor.hpos >= 0
&& w->cursor.hpos < w->desired_matrix->matrix_w);
if (FRAME_WINDOW_P (f))
FRAME_RIF (f)->cursor_to (w->cursor.vpos, w->cursor.hpos,
w->cursor.y, w->cursor.x);
else
{
int x, y;
x = (WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos)
+ (INTEGERP (w->left_margin_cols)
? XFASTINT (w->left_margin_cols)
: 0));
y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
cursor_to (f, y, x);
}
if (FRAME_TERMCAP_P (f))
fflush (FRAME_TTY (f)->output);
redisplay_performed_directly_p = 1;
return 1;
}
/***********************************************************************
Frame Update
......
......@@ -1520,8 +1520,6 @@ cancel_hourglass_unwind (arg)
}
#endif
extern int nonundocount; /* Declared in cmds.c. */
Lisp_Object
command_loop_1 ()
{
......@@ -1744,149 +1742,8 @@ command_loop_1 ()
}
else
{
if (NILP (current_kboard->Vprefix_arg))
{
/* In case we jump to directly_done. */
Vcurrent_prefix_arg = current_kboard->Vprefix_arg;
/* Recognize some common commands in common situations and
do them directly. */
if (EQ (Vthis_command, Qforward_char) && PT < ZV
&& NILP (Vthis_command_keys_shift_translated)
&& !CONSP (Vtransient_mark_mode))
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
lose = FETCH_CHAR (PT_BYTE);
SET_PT (PT + 1);
if (! NILP (Vpost_command_hook))
/* Put this before calling adjust_point_for_property
so it will only get called once in any case. */
goto directly_done;
if (current_buffer == prev_buffer
&& last_point_position != PT
&& NILP (Vdisable_point_adjustment)
&& NILP (Vglobal_disable_point_adjustment))
adjust_point_for_property (last_point_position, 0);
already_adjusted = 1;
if (PT == last_point_position + 1
&& (dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
: (NILP (DISP_CHAR_VECTOR (dp, lose))
&& (lose >= 0x20 && lose < 0x7f)))
: (lose >= 0x20 && lose < 0x7f))
/* To extract the case of continuation on
wide-column characters. */
&& ASCII_BYTE_P (lose)
&& (XFASTINT (XWINDOW (selected_window)->last_modified)
>= MODIFF)
&& (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
>= OVERLAY_MODIFF)
&& (XFASTINT (XWINDOW (selected_window)->last_point)
== PT - 1)
&& !windows_or_buffers_changed
&& EQ (current_buffer->selective_display, Qnil)
&& !detect_input_pending ()
&& NILP (XWINDOW (selected_window)->column_number_displayed)
&& NILP (Vexecuting_kbd_macro))
direct_output_forward_char (1);
goto directly_done;
}
else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV
&& NILP (Vthis_command_keys_shift_translated)
&& !CONSP (Vtransient_mark_mode))
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
SET_PT (PT - 1);
lose = FETCH_CHAR (PT_BYTE);
if (! NILP (Vpost_command_hook))
goto directly_done;
if (current_buffer == prev_buffer
&& last_point_position != PT
&& NILP (Vdisable_point_adjustment)
&& NILP (Vglobal_disable_point_adjustment))
adjust_point_for_property (last_point_position, 0);
already_adjusted = 1;
if (PT == last_point_position - 1
&& (dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
: (NILP (DISP_CHAR_VECTOR (dp, lose))
&& (lose >= 0x20 && lose < 0x7f)))
: (lose >= 0x20 && lose < 0x7f))
&& (XFASTINT (XWINDOW (selected_window)->last_modified)
>= MODIFF)
&& (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
>= OVERLAY_MODIFF)
&& (XFASTINT (XWINDOW (selected_window)->last_point)
== PT + 1)
&& !windows_or_buffers_changed
&& EQ (current_buffer->selective_display, Qnil)
&& !detect_input_pending ()
&& NILP (XWINDOW (selected_window)->column_number_displayed)
&& NILP (Vexecuting_kbd_macro))
direct_output_forward_char (-1);
goto directly_done;
}
else if (EQ (Vthis_command, Qself_insert_command)
/* Try this optimization only on char keystrokes. */
&& NATNUMP (last_command_event)
&& CHAR_VALID_P (XFASTINT (last_command_event), 0))
{
unsigned int c
= translate_char (Vtranslation_table_for_input,
XFASTINT (last_command_event));
int value;
if (NILP (Vexecuting_kbd_macro)
&& !EQ (minibuf_window, selected_window))
{
if (!nonundocount || nonundocount >= 20)
{
Fundo_boundary ();
nonundocount = 0;
}
nonundocount++;
}
lose = ((XFASTINT (XWINDOW (selected_window)->last_modified)
< MODIFF)
|| (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
< OVERLAY_MODIFF)
|| (XFASTINT (XWINDOW (selected_window)->last_point)
!= PT)
|| MODIFF <= SAVE_MODIFF
|| windows_or_buffers_changed
|| !EQ (current_buffer->selective_display, Qnil)
|| detect_input_pending ()
|| !NILP (XWINDOW (selected_window)->column_number_displayed)
|| !NILP (Vexecuting_kbd_macro));
value = internal_self_insert (c, 0);
if (value == 2)
nonundocount = 0;
frame_make_pointer_invisible ();
if (! NILP (Vpost_command_hook))
/* Put this before calling adjust_point_for_property
so it will only get called once in any case. */
goto directly_done;
/* VALUE == 1 when AFTER-CHANGE functions are
installed which is the case most of the time
because FONT-LOCK installs one. */
if (!lose && !value)
direct_output_for_insert (c);
goto directly_done;
}
}
/* Here for a command that isn't executed directly */
{
#ifdef HAVE_WINDOW_SYSTEM
int scount = SPECPDL_INDEX ();
......@@ -1898,7 +1755,6 @@ command_loop_1 ()
}
#endif
nonundocount = 0;