/* Updating of data structures for redisplay.
- Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
+ 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#include <signal.h>
int redisplay_dont_pause;
+/* Define PERIODIC_PREEMPTION_CHECKING to 1, if micro-second timers
+ are supported, so we can check for input during redisplay at
+ regular intervals. */
+#ifdef EMACS_HAS_USECS
+#define PERIODIC_PREEMPTION_CHECKING 1
+#else
+#define PERIODIC_PREEMPTION_CHECKING 0
+#endif
+
+#if PERIODIC_PREEMPTION_CHECKING
+
+/* If a number (float), check for user input every N seconds. */
+
+Lisp_Object Vredisplay_preemption_period;
+
+/* Redisplay preemption timers. */
+
+static EMACS_TIME preemption_period;
+static EMACS_TIME preemption_next_check;
+
+#endif
+
/* Nonzero upon entry to redisplay means do not assume anything about
current contents of actual terminal frame; clear and redraw it. */
static void add_frame_display_history P_ ((struct frame *, int));
static void add_window_display_history P_ ((struct window *, char *, int));
-
-
+\f
/* Add to the redisplay history how window W has been displayed.
MSG is a trace containing the information how W's glyph matrix
has been constructed. PAUSED_P non-zero means that the update
MATRIX_ROW_END_CHARPOS (row) += delta;
MATRIX_ROW_END_BYTEPOS (row) += delta_bytes;
+ if (!row->enabled_p)
+ return;
+
/* Increment positions in glyphs. */
for (area = 0; area < LAST_AREA; ++area)
for (i = 0; i < row->used[area]; ++i)
|| a->left_fringe_face_id != b->left_fringe_face_id
|| a->right_fringe_bitmap != b->right_fringe_bitmap
|| a->right_fringe_face_id != b->right_fringe_face_id
- || a->overlay_arrow_p != b->overlay_arrow_p
+ || a->overlay_arrow_bitmap != b->overlay_arrow_bitmap
|| a->exact_window_width_line_p != b->exact_window_width_line_p
|| a->overlapped_p != b->overlapped_p
|| (MATRIX_ROW_CONTINUATION_LINE_P (a)
X and Y are column/row within the frame glyph matrix where
sub-matrices for the window tree rooted at WINDOW must be
- allocated. CH_DIM contains the dimensions of the smallest
- character that could be used during display. DIM_ONLY_P non-zero
- means that the caller of this function is only interested in the
- result matrix dimension, and matrix adjustments should not be
- performed.
+ allocated. DIM_ONLY_P non-zero means that the caller of this
+ function is only interested in the result matrix dimension, and
+ matrix adjustments should not be performed.
The function returns the total width/height of the sub-matrices of
the window tree. If called on a frame root window, the computation
/* Allocate window matrices for window-based redisplay. W is the
- window whose matrices must be allocated/reallocated. CH_DIM is the
- size of the smallest character that could potentially be used on W. */
+ window whose matrices must be allocated/reallocated. */
static void
allocate_matrices_for_window_redisplay (w)
adjust_frame_glyphs_for_frame_redisplay (f)
struct frame *f;
{
- struct dim ch_dim;
struct dim matrix_dim;
int pool_changed_p;
int window_change_flags;
if (!FRAME_LIVE_P (f))
return;
- /* Determine the smallest character in any font for F. On
- console windows, all characters have dimension (1, 1). */
- ch_dim.width = ch_dim.height = 1;
-
top_window_y = FRAME_TOP_MARGIN (f);
/* Allocate glyph pool structures if not already done. */
adjust_frame_glyphs_for_window_redisplay (f)
struct frame *f;
{
- struct dim ch_dim;
struct window *w;
xassert (FRAME_WINDOW_P (f) && FRAME_LIVE_P (f));
- /* Get minimum sizes. */
-#ifdef HAVE_WINDOW_SYSTEM
- ch_dim.width = FRAME_SMALLEST_CHAR_WIDTH (f);
- ch_dim.height = FRAME_SMALLEST_FONT_HEIGHT (f);
-#else
- ch_dim.width = ch_dim.height = 1;
-#endif
-
/* Allocate/reallocate window matrices. */
allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)));
+#ifdef HAVE_X_WINDOWS
/* Allocate/ reallocate matrices of the dummy window used to display
the menu bar under X when no X toolkit support is available. */
#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
XSETFASTINT (w->total_cols, FRAME_TOTAL_COLS (f));
allocate_matrices_for_window_redisplay (w);
}
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
+#endif /* HAVE_X_WINDOWS */
#ifndef USE_GTK
/* Allocate/ reallocate matrices of the tool bar window. If we
if (!WINDOW_RIGHTMOST_P (w))
{
struct Lisp_Char_Table *dp = window_display_table (w);
- right_border_glyph = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
- ? XINT (DISP_BORDER_GLYPH (dp))
- : '|');
+
+ right_border_glyph
+ = ((dp && INTEGERP (DISP_BORDER_GLYPH (dp)))
+ ? spec_glyph_lookup_face (w, XINT (DISP_BORDER_GLYPH (dp)))
+ : '|');
+
+ if (FAST_GLYPH_FACE (right_border_glyph) <= 0)
+ right_border_glyph
+ = FAST_MAKE_GLYPH (right_border_glyph, VERTICAL_BORDER_FACE_ID);
}
}
else
}
}
+/* Given a user-specified glyph, possibly including a Lisp-level face
+ ID, return a glyph that has a realized face ID.
+ This is used for glyphs displayed specially and not part of the text;
+ for instance, vertical separators, truncation markers, etc. */
+
+GLYPH
+spec_glyph_lookup_face (w, glyph)
+ struct window *w;
+ GLYPH glyph;
+{
+ int lface_id = FAST_GLYPH_FACE (glyph);
+ /* Convert the glyph's specified face to a realized (cache) face. */
+ if (lface_id > 0)
+ {
+ int face_id = merge_faces (XFRAME (w->frame),
+ Qt, lface_id, DEFAULT_FACE_ID);
+ glyph
+ = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), face_id);
+ }
+ return glyph;
+}
/* Add spaces to a glyph row ROW in a window matrix.
struct window *w;
int hpos;
{
- struct frame *f = XFRAME (w->frame);
-
- xassert (!FRAME_WINDOW_P (f));
+ xassert (!FRAME_WINDOW_P (XFRAME (w->frame)));
hpos += WINDOW_LEFT_EDGE_COL (w);
return hpos;
}
int paused_p;
struct window *root_window = XWINDOW (f->root_window);
+#if PERIODIC_PREEMPTION_CHECKING
+ if (!force_p && NUMBERP (Vredisplay_preemption_period))
+ {
+ EMACS_TIME tm;
+ double p = XFLOATINT (Vredisplay_preemption_period);
+ int sec, usec;
+
+ if (detect_input_pending_ignore_squeezables ())
+ {
+ paused_p = 1;
+ goto do_pause;
+ }
+
+ sec = (int) p;
+ usec = (p - sec) * 1000000;
+
+ EMACS_GET_TIME (tm);
+ EMACS_SET_SECS_USECS (preemption_period, sec, usec);
+ EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+ }
+#endif
+
if (FRAME_WINDOW_P (f))
{
/* We are working on window matrix basis. All windows whose
#endif
}
+ do_pause:
/* Reset flags indicating that a window should be updated. */
set_window_update_flags (root_window, 0);
/* Record that this is not a frame-based redisplay. */
set_frame_matrix_frame (NULL);
+#if PERIODIC_PREEMPTION_CHECKING
+ if (!force_p && NUMBERP (Vredisplay_preemption_period))
+ {
+ EMACS_TIME tm;
+ double p = XFLOATINT (Vredisplay_preemption_period);
+ int sec, usec;
+
+ sec = (int) p;
+ usec = (p - sec) * 1000000;
+
+ EMACS_GET_TIME (tm);
+ EMACS_SET_SECS_USECS (preemption_period, sec, usec);
+ EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+ }
+#endif
+
/* Update W. */
update_begin (f);
update_window (w, force_p);
}
}
+#ifdef HAVE_WINDOW_SYSTEM
/* Redraw lines from the current matrix of window W that are
overlapped by other rows. YB is bottom-most y-position in W. */
if (row->overlapping_p && i > 0 && bottom_y < yb)
{
- if (row->used[LEFT_MARGIN_AREA])
- rif->fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
-
- if (row->used[TEXT_AREA])
- rif->fix_overlapping_area (w, row, TEXT_AREA);
-
- if (row->used[RIGHT_MARGIN_AREA])
- rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
-
- /* Record in neighbour rows that ROW overwrites part of their
- display. */
- if (row->phys_ascent > row->ascent && i > 0)
- MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
- if ((row->phys_height - row->phys_ascent
- > row->height - row->ascent)
- && bottom_y < yb)
- MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p = 1;
+ int overlaps = 0;
+
+ if (MATRIX_ROW_OVERLAPS_PRED_P (row)
+ && !MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p)
+ overlaps |= OVERLAPS_PRED;
+ if (MATRIX_ROW_OVERLAPS_SUCC_P (row)
+ && !MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p)
+ overlaps |= OVERLAPS_SUCC;
+
+ if (overlaps)
+ {
+ if (row->used[LEFT_MARGIN_AREA])
+ rif->fix_overlapping_area (w, row, LEFT_MARGIN_AREA, overlaps);
+
+ if (row->used[TEXT_AREA])
+ rif->fix_overlapping_area (w, row, TEXT_AREA, overlaps);
+
+ if (row->used[RIGHT_MARGIN_AREA])
+ rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, overlaps);
+
+ /* Record in neighbour rows that ROW overwrites part of
+ their display. */
+ if (overlaps & OVERLAPS_PRED)
+ MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
+ if (overlaps & OVERLAPS_SUCC)
+ MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p = 1;
+ }
}
if (bottom_y >= yb)
}
}
+#endif /* HAVE_WINDOW_SYSTEM */
+
#ifdef GLYPH_DEBUG
{
struct glyph_matrix *desired_matrix = w->desired_matrix;
int paused_p;
+#if !PERIODIC_PREEMPTION_CHECKING
int preempt_count = baud_rate / 2400 + 1;
+#endif
extern int input_pending;
extern Lisp_Object do_mouse_tracking;
#if GLYPH_DEBUG
- struct frame *f = XFRAME (WINDOW_FRAME (w));
-
/* Check that W's frame doesn't have glyph matrices. */
- xassert (FRAME_WINDOW_P (f));
+ xassert (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))));
xassert (updating_frame != NULL);
#endif
/* Check pending input the first time so that we can quickly return. */
if (redisplay_dont_pause)
force_p = 1;
- else
+#if PERIODIC_PREEMPTION_CHECKING
+ else if (NILP (Vredisplay_preemption_period))
+ force_p = 1;
+#else
+ else if (!force_p)
detect_input_pending_ignore_squeezables ();
+#endif
/* If forced to complete the update, or if no input is pending, do
the update. */
update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
desired_matrix),
&mouse_face_overwritten_p);
- changed_p = 1;
}
/* Find first enabled row. Optimizations in redisplay_internal
detect_input_pending. If it's done too often,
scrolling large windows with repeated scroll-up
commands will too quickly pause redisplay. */
+#if PERIODIC_PREEMPTION_CHECKING
+ if (!force_p)
+ {
+ EMACS_TIME tm, dif;
+ EMACS_GET_TIME (tm);
+ EMACS_SUB_TIME (dif, preemption_next_check, tm);
+ if (EMACS_TIME_NEG_P (dif))
+ {
+ EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+ if (detect_input_pending_ignore_squeezables ())
+ break;
+ }
+ }
+#else
if (!force_p && ++n_updated % preempt_count == 0)
detect_input_pending_ignore_squeezables ();
-
+#endif
changed_p |= update_window_line (w, vpos,
&mouse_face_overwritten_p);
{
header_line_row->y = 0;
update_window_line (w, 0, &mouse_face_overwritten_p);
- changed_p = 1;
}
/* Fix the appearance of overlapping/overlapped rows. */
if (!paused_p && !w->pseudo_window_p)
{
+#ifdef HAVE_WINDOW_SYSTEM
if (changed_p && rif->fix_overlapping_area)
{
redraw_overlapped_rows (w, yb);
redraw_overlapping_rows (w, yb);
}
+#endif
/* Make cursor visible at cursor position of W. */
set_window_cursor_after_update (w);
|| desired_row->phys_height != current_row->phys_height
|| desired_row->visible_height != current_row->visible_height
|| current_row->overlapped_p
+#if 0
+ /* This causes excessive flickering when mouse is moved across
+ the mode line. Luckily everything seems to work just fine
+ without doing this. KFS 2006-09-17. */
|| current_row->mouse_face_p
+#endif
|| current_row->x != desired_row->x)
{
rif->cursor_to (vpos, 0, desired_row->y, desired_row->x);
int overlapping_glyphs_p = current_row->contains_overlapping_glyphs_p;
int desired_stop_pos = desired_row->used[TEXT_AREA];
- /* If the desired row extends its face to the text area end,
+ /* If the desired row extends its face to the text area end, and
+ unless the current row also does so at the same position,
make sure we write at least one glyph, so that the face
extension actually takes place. */
- if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
+ if (MATRIX_ROW_EXTENDS_FACE_P (desired_row)
+ && (desired_stop_pos < current_row->used[TEXT_AREA]
+ || (desired_stop_pos == current_row->used[TEXT_AREA]
+ && !MATRIX_ROW_EXTENDS_FACE_P (current_row))))
--desired_stop_pos;
stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
has to be cleared, if and only if we did a write_glyphs
above. This is made sure by setting desired_stop_pos
appropriately above. */
- xassert (i < desired_row->used[TEXT_AREA]);
+ xassert (i < desired_row->used[TEXT_AREA]
+ || ((desired_row->used[TEXT_AREA]
+ == current_row->used[TEXT_AREA])
+ && MATRIX_ROW_EXTENDS_FACE_P (current_row)));
}
else if (MATRIX_ROW_EXTENDS_FACE_P (current_row))
{
|| desired_row->y != current_row->y
|| desired_row->visible_height != current_row->visible_height
|| desired_row->cursor_in_fringe_p != current_row->cursor_in_fringe_p
- || desired_row->overlay_arrow_p != current_row->overlay_arrow_p
+ || desired_row->overlay_arrow_bitmap != current_row->overlay_arrow_bitmap
|| current_row->redraw_fringe_bitmaps_p
|| desired_row->mode_line_p != current_row->mode_line_p
|| desired_row->exact_window_width_line_p != current_row->exact_window_width_line_p
|| to->right_fringe_bitmap != from->right_fringe_bitmap
|| to->left_fringe_face_id != from->left_fringe_face_id
|| to->right_fringe_face_id != from->right_fringe_face_id
- || to->overlay_arrow_p != from->overlay_arrow_p))
+ || to->overlay_arrow_bitmap != from->overlay_arrow_bitmap))
from->redraw_fringe_bitmaps_p = 1;
assign_row (to, from);
to->enabled_p = 1, from->enabled_p = 0;
if (redisplay_dont_pause)
force_p = 1;
+#if PERIODIC_PREEMPTION_CHECKING
+ else if (NILP (Vredisplay_preemption_period))
+ force_p = 1;
+#else
else if (!force_p && detect_input_pending_ignore_squeezables ())
{
pause = 1;
goto do_pause;
}
+#endif
/* If we cannot insert/delete lines, it's no use trying it. */
if (!line_ins_del_ok)
}
}
- if ((i - 1) % preempt_count == 0)
+#if PERIODIC_PREEMPTION_CHECKING
+ if (!force_p)
+ {
+ EMACS_TIME tm, dif;
+ EMACS_GET_TIME (tm);
+ EMACS_SUB_TIME (dif, preemption_next_check, tm);
+ if (EMACS_TIME_NEG_P (dif))
+ {
+ EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+ if (detect_input_pending_ignore_squeezables ())
+ break;
+ }
+ }
+#else
+ if (!force_p && (i - 1) % preempt_count == 0)
detect_input_pending_ignore_squeezables ();
+#endif
update_frame_line (f, i);
}
}
#endif
- row = MATRIX_ROW (w->current_matrix, it.vpos);
- if (row->enabled_p)
+ if (it.vpos < w->current_matrix->nrows
+ && (row = MATRIX_ROW (w->current_matrix, it.vpos),
+ row->enabled_p))
{
if (it.hpos < row->used[TEXT_AREA])
{
#ifndef EMACS_HAS_USECS
if (sec == 0 && usec != 0)
- error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
+ error ("Millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
#endif
/* Assure that 0 <= usec < 1000000. */
/* This is just like wait_reading_process_output, except that
- it does the redisplay.
+ it does redisplay.
- It's also much like Fsit_for, except that it can be used for
- waiting for input as well. */
+ TIMEOUT is number of seconds to wait (float or integer),
+ or t to wait forever.
+ READING is 1 if reading input.
+ If DO_DISPLAY is >0 display process output while waiting.
+ If DO_DISPLAY is >1 perform an initial redisplay before waiting.
+*/
Lisp_Object
-sit_for (sec, usec, reading, display, initial_display)
- int sec, usec, reading, display, initial_display;
+sit_for (timeout, reading, do_display)
+ Lisp_Object timeout;
+ int reading, do_display;
{
- swallow_events (display);
+ int sec, usec;
- if (detect_input_pending_run_timers (display) || !NILP (Vexecuting_macro))
+ swallow_events (do_display);
+
+ if ((detect_input_pending_run_timers (do_display))
+ || !NILP (Vexecuting_kbd_macro))
return Qnil;
- if (initial_display)
+ if (do_display >= 2)
redisplay_preserve_echo_area (2);
- if (sec == 0 && usec == 0)
+ if (INTEGERP (timeout))
+ {
+ sec = XINT (timeout);
+ usec = 0;
+ }
+ else if (FLOATP (timeout))
+ {
+ double seconds = XFLOAT_DATA (timeout);
+ sec = (int) seconds;
+ usec = (int) ((seconds - sec) * 1000000);
+ }
+ else if (EQ (timeout, Qt))
+ {
+ sec = 0;
+ usec = 0;
+ }
+ else
+ wrong_type_argument (Qnumberp, timeout);
+
+ if (sec == 0 && usec == 0 && !EQ (timeout, Qt))
return Qt;
#ifdef SIGIO
gobble_input (0);
#endif
- wait_reading_process_output (sec, usec, reading ? -1 : 1, display,
+ wait_reading_process_output (sec, usec, reading ? -1 : 1, do_display,
Qnil, NULL, 0);
return detect_input_pending () ? Qnil : Qt;
}
-DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
- doc: /* Perform redisplay, then wait for SECONDS seconds or until input is available.
-SECONDS may be a floating-point value, meaning that you can wait for a
-fraction of a second.
-\(Not all operating systems support waiting for a fraction of a second.)
-Optional arg NODISP non-nil means don't redisplay, just wait for input.
-Redisplay is preempted as always if input arrives, and does not happen
-if input is available before it starts.
-Value is t if waited the full time with no input arriving.
-
-An obsolete but still supported form is
-\(sit-for SECONDS &optional MILLISECONDS NODISP)
-Where the optional arg MILLISECONDS specifies an additional wait period,
-in milliseconds; this was useful when Emacs was built without
-floating point support.
-usage: (sit-for SECONDS &optional NODISP OLD-NODISP) */)
-
-/* The `old-nodisp' stuff is there so that the arglist has the correct
- length. Otherwise, `defdvice' will redefine it with fewer args. */
- (seconds, milliseconds, nodisp)
- Lisp_Object seconds, milliseconds, nodisp;
+DEFUN ("redisplay", Fredisplay, Sredisplay, 0, 1, 0,
+ doc: /* Perform redisplay if no input is available.
+If optional arg FORCE is non-nil or `redisplay-dont-pause' is non-nil,
+perform a full redisplay even if input is available.
+Return t if redisplay was performed, nil otherwise. */)
+ (force)
+ Lisp_Object force;
{
- int sec, usec;
-
- if (NILP (nodisp) && !NUMBERP (milliseconds))
- { /* New style. */
- nodisp = milliseconds;
- milliseconds = Qnil;
- }
-
- if (NILP (milliseconds))
- XSETINT (milliseconds, 0);
- else
- CHECK_NUMBER (milliseconds);
- usec = XINT (milliseconds) * 1000;
-
- {
- double duration = extract_float (seconds);
- sec = (int) duration;
- usec += (duration - sec) * 1000000;
- }
+ int count;
-#ifndef EMACS_HAS_USECS
- if (usec != 0 && sec == 0)
- error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
-#endif
+ swallow_events (1);
+ if ((detect_input_pending_run_timers (1)
+ && NILP (force) && !redisplay_dont_pause)
+ || !NILP (Vexecuting_kbd_macro))
+ return Qnil;
- return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp));
+ count = SPECPDL_INDEX ();
+ if (!NILP (force) && !redisplay_dont_pause)
+ specbind (Qredisplay_dont_pause, Qt);
+ redisplay_preserve_echo_area (2);
+ unbind_to (count, Qnil);
+ return Qt;
}
/* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
session's frames, frame names, buffers, buffer-read-only flags, and
- buffer-modified-flags, and a trailing sentinel (so we don't need to
- add length checks). */
+ buffer-modified-flags. */
static Lisp_Object frame_and_buffer_state;
DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
- Sframe_or_buffer_changed_p, 0, 0, 0,
+ Sframe_or_buffer_changed_p, 0, 1, 0,
doc: /* Return non-nil if the frame and buffer state appears to have changed.
-The state variable is an internal vector containing all frames and buffers,
+VARIABLE is a variable name whose value is either nil or a state vector
+that will be updated to contain all frames and buffers,
aside from buffers whose names start with space,
-along with the buffers' read-only and modified flags, which allows a fast
-check to see whether the menu bars might need to be recomputed.
+along with the buffers' read-only and modified flags. This allows a fast
+check to see whether buffer menus might need to be recomputed.
If this function returns non-nil, it updates the internal vector to reflect
-the current state. */)
- ()
+the current state.
+
+If VARIABLE is nil, an internal variable is used. Users should not
+pass nil for VARIABLE. */)
+ (variable)
+ Lisp_Object variable;
{
- Lisp_Object tail, frame, buf;
- Lisp_Object *vecp;
+ Lisp_Object state, tail, frame, buf;
+ Lisp_Object *vecp, *end;
int n;
- vecp = XVECTOR (frame_and_buffer_state)->contents;
+ if (! NILP (variable))
+ {
+ CHECK_SYMBOL (variable);
+ state = Fsymbol_value (variable);
+ if (! VECTORP (state))
+ goto changed;
+ }
+ else
+ state = frame_and_buffer_state;
+
+ vecp = XVECTOR (state)->contents;
+ end = vecp + XVECTOR (state)->size;
+
FOR_EACH_FRAME (tail, frame)
{
+ if (vecp == end)
+ goto changed;
if (!EQ (*vecp++, frame))
goto changed;
+ if (vecp == end)
+ goto changed;
if (!EQ (*vecp++, XFRAME (frame)->name))
goto changed;
}
- /* Check that the buffer info matches.
- No need to test for the end of the vector
- because the last element of the vector is lambda
- and that will always cause a mismatch. */
+ /* Check that the buffer info matches. */
for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
{
buf = XCDR (XCAR (tail));
/* Ignore buffers that aren't included in buffer lists. */
if (SREF (XBUFFER (buf)->name, 0) == ' ')
continue;
+ if (vecp == end)
+ goto changed;
if (!EQ (*vecp++, buf))
goto changed;
+ if (vecp == end)
+ goto changed;
if (!EQ (*vecp++, XBUFFER (buf)->read_only))
goto changed;
+ if (vecp == end)
+ goto changed;
if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
goto changed;
}
+ if (vecp == end)
+ goto changed;
/* Detect deletion of a buffer at the end of the list. */
if (EQ (*vecp, Qlambda))
return Qnil;
+
+ /* Come here if we decide the data has changed. */
changed:
- /* Start with 1 so there is room for at least one lambda at the end. */
+ /* Count the size we will need.
+ Start with 1 so there is room for at least one lambda at the end. */
n = 1;
FOR_EACH_FRAME (tail, frame)
n += 2;
for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
n += 3;
- /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
- if (n > XVECTOR (frame_and_buffer_state)->size
- || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
+ /* Reallocate the vector if data has grown to need it,
+ or if it has shrunk a lot. */
+ if (! VECTORP (state)
+ || n > XVECTOR (state)->size
+ || n + 20 < XVECTOR (state)->size / 2)
/* Add 20 extra so we grow it less often. */
- frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
- vecp = XVECTOR (frame_and_buffer_state)->contents;
+ {
+ state = Fmake_vector (make_number (n + 20), Qlambda);
+ if (! NILP (variable))
+ Fset (variable, state);
+ else
+ frame_and_buffer_state = state;
+ }
+
+ /* Record the new data in the (possibly reallocated) vector. */
+ vecp = XVECTOR (state)->contents;
FOR_EACH_FRAME (tail, frame)
{
*vecp++ = frame;
}
/* Fill up the vector with lambdas (always at least one). */
*vecp++ = Qlambda;
- while (vecp - XVECTOR (frame_and_buffer_state)->contents
- < XVECTOR (frame_and_buffer_state)->size)
+ while (vecp - XVECTOR (state)->contents
+ < XVECTOR (state)->size)
*vecp++ = Qlambda;
/* Make sure we didn't overflow the vector. */
- if (vecp - XVECTOR (frame_and_buffer_state)->contents
- > XVECTOR (frame_and_buffer_state)->size)
+ if (vecp - XVECTOR (state)->contents
+ > XVECTOR (state)->size)
abort ();
return Qt;
}
try to use X, and die with an error message if that doesn't work. */
#ifdef HAVE_X_WINDOWS
- if (! display_arg)
+ if (! inhibit_window_system && ! display_arg)
{
char *display;
#ifdef VMS
#endif
display_arg = (display != 0 && *display != 0);
+
+ if (display_arg && !x_display_ok (display))
+ {
+ fprintf (stderr, "Display %s unavailable, simulating -nw\n",
+ display);
+ inhibit_window_system = 1;
+ }
}
if (!inhibit_window_system && display_arg
For types defined in VMS, use set term /device=TYPE.\n\
For types not defined in VMS, use define emacs_term \"TYPE\".\n\
\(The quotation marks are necessary since terminal types are lower case.)\n");
-#else
- fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
-#endif
+#else /* not VMS */
+
+#ifdef HAVE_WINDOW_SYSTEM
+ if (! inhibit_window_system)
+ fprintf (stderr, "Please set the environment variable DISPLAY or TERM (see `tset').\n");
+ else
+#endif /* HAVE_WINDOW_SYSTEM */
+ fprintf (stderr, "Please set the environment variable TERM; see `tset'.\n");
+#endif /* not VMS */
exit (1);
}
defsubr (&Sframe_or_buffer_changed_p);
defsubr (&Sopen_termscript);
defsubr (&Sding);
- defsubr (&Ssit_for);
+ defsubr (&Sredisplay);
defsubr (&Ssleep_for);
defsubr (&Ssend_string_to_terminal);
defsubr (&Sinternal_show_cursor);
doc: /* *Non-nil means update isn't paused when input is detected. */);
redisplay_dont_pause = 0;
- /* Initialize `window-system', unless init_display already decided it. */
+#if PERIODIC_PREEMPTION_CHECKING
+ DEFVAR_LISP ("redisplay-preemption-period", &Vredisplay_preemption_period,
+ doc: /* *The period in seconds between checking for input during redisplay.
+If input is detected, redisplay is pre-empted, and the input is processed.
+If nil, never pre-empt redisplay. */);
+ Vredisplay_preemption_period = make_float (0.10);
+#endif
+
#ifdef CANNOT_DUMP
if (noninteractive)
#endif