/* Updating of data structures for redisplay.
-Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
+Inc.
This file is part of GNU Emacs.
#define DISPEXTERN_INLINE EXTERN_INLINE
-#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
#include <unistd.h>
#include "lisp.h"
#include "termchar.h"
-#include "termopts.h"
/* cm.h must come after dispextern.h on Windows. */
#include "dispextern.h"
#include "cm.h"
#include "syssignal.h"
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#endif /* HAVE_X_WINDOWS */
-
-#ifdef HAVE_NTGUI
-#include "w32term.h"
-#endif /* HAVE_NTGUI */
-
-#ifdef HAVE_NS
-#include "nsterm.h"
-#endif
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
#include "systime.h"
#include <errno.h>
-#ifdef DISPNEW_NEEDS_STDIO_EXT
-#include <stdio_ext.h>
-#endif
+#include <fpending.h>
#if defined (HAVE_TERM_H) && defined (GNU_LINUX)
#include <term.h> /* for tgetent */
#endif
+
+#ifdef WINDOWSNT
+#include "w32.h"
+#endif
\f
/* Structure to pass dimensions around. Used for character bounding
boxes, glyph matrix dimensions and alike. */
struct window *);
static void build_frame_matrix_from_leaf_window (struct glyph_matrix *,
struct window *);
-static void adjust_frame_message_buffer (struct frame *);
static void adjust_decode_mode_spec_buffer (struct frame *);
static void fill_up_glyph_row_with_spaces (struct glyph_row *);
static void clear_window_matrices (struct window *, bool);
static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
static void adjust_frame_glyphs_for_frame_redisplay (struct frame *);
-\f
-/* Redisplay preemption timers. */
-
-static EMACS_TIME preemption_period;
-static EMACS_TIME preemption_next_check;
-
/* True upon entry to redisplay means do not assume anything about
current contents of actual terminal frame; clear and redraw it. */
static bool delayed_size_change;
-/* 1 means glyph initialization has been completed at startup. */
-
-static bool glyphs_initialized_initially_p;
-
/* Updated window if != 0. Set by update_window. */
struct window *updated_window;
void
__executable_start (void)
{
- abort ();
+ emacs_abort ();
}
#endif
\f
/* Detect the case that more matrices are freed than were
allocated. */
if (--glyph_matrix_count < 0)
- abort ();
+ emacs_abort ();
/* Free glyph memory if MATRIX owns it. */
if (matrix->pool == NULL)
are invalidated below. */
if (INTEGERP (w->window_end_vpos)
&& XFASTINT (w->window_end_vpos) >= i)
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
while (i < matrix->nrows)
matrix->rows[i++].enabled_p = 0;
else
{
clear_glyph_matrix (w->current_matrix);
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
}
}
these should all go together for the row's hash value to be
correct. */
-static inline void
+static void
swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b)
{
int i;
that glyph pointers, the `used' counts, and the hash values in the
structures are left unchanged. */
-static inline void
+static void
copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
{
struct glyph *pointers[1 + LAST_AREA];
exchanged between TO and FROM. Pointers must be exchanged to avoid
a memory leak. */
-static inline void
+static void
assign_row (struct glyph_row *to, struct glyph_row *from)
{
swap_glyph_pointers (to, from);
/* Return true if the glyph rows A and B have equal contents.
MOUSE_FACE_P means compare the mouse_face_p flags of A and B, too. */
-static inline bool
+static bool
row_equal_p (struct glyph_row *a, struct glyph_row *b, bool mouse_face_p)
{
eassert (verify_row_hash (a));
{
/* Block input so that expose events and other events that access
glyph matrices are not processed while we are changing them. */
- BLOCK_INPUT;
+ block_input ();
if (f)
adjust_frame_glyphs (f);
adjust_frame_glyphs (XFRAME (lisp_frame));
}
- UNBLOCK_INPUT;
-}
-
-
-/* Adjust frame glyphs when Emacs is initialized.
-
- To be called from init_display.
-
- We need a glyph matrix because redraw will happen soon.
- Unfortunately, window sizes on selected_frame are not yet set to
- meaningful values. I believe we can assume that there are only two
- windows on the frame---the mini-buffer and the root window. Frame
- height and width seem to be correct so far. So, set the sizes of
- windows to estimated values. */
-
-static void
-adjust_frame_glyphs_initially (void)
-{
- struct frame *sf = SELECTED_FRAME ();
- struct window *root = XWINDOW (sf->root_window);
- struct window *mini = XWINDOW (root->next);
- int frame_lines = FRAME_LINES (sf);
- int frame_cols = FRAME_COLS (sf);
- int top_margin = FRAME_TOP_MARGIN (sf);
-
- /* Do it for the root window. */
- wset_top_line (root, make_number (top_margin));
- wset_total_lines (root, make_number (frame_lines - 1 - top_margin));
- wset_total_cols (root, make_number (frame_cols));
-
- /* Do it for the mini-buffer window. */
- wset_top_line (mini, make_number (frame_lines - 1));
- wset_total_lines (mini, make_number (1));
- wset_total_cols (mini, make_number (frame_cols));
-
- adjust_frame_glyphs (sf);
- glyphs_initialized_initially_p = 1;
+ unblock_input ();
}
-
/* Allocate/reallocate glyph matrices of a single frame F. */
static void
else
adjust_frame_glyphs_for_frame_redisplay (f);
- /* Don't forget the message buffer and the buffer for
- decode_mode_spec. */
- adjust_frame_message_buffer (f);
+ /* Don't forget the buffer for decode_mode_spec. */
adjust_decode_mode_spec_buffer (f);
f->glyphs_initialized_p = 1;
}
-/* Adjust/ allocate message buffer of frame F.
-
- Note that the message buffer is never freed. Since I could not
- find a free in 19.34, I assume that freeing it would be
- problematic in some way and don't do it either.
-
- (Implementation note: It should be checked if we can free it
- eventually without causing trouble). */
-
-static void
-adjust_frame_message_buffer (struct frame *f)
-{
- FRAME_MESSAGE_BUF (f) = xrealloc (FRAME_MESSAGE_BUF (f),
- FRAME_MESSAGE_BUF_SIZE (f) + 1);
-}
-
-
/* Re-allocate buffer for decode_mode_spec on frame F. */
static void
{
/* Block interrupt input so that we don't get surprised by an X
event while we're in an inconsistent state. */
- BLOCK_INPUT;
+ block_input ();
f->glyphs_initialized_p = 0;
/* Release window sub-matrices. */
f->desired_pool = f->current_pool = NULL;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
/* Check that nothing is left allocated. */
if (glyph_matrix_count)
- abort ();
+ emacs_abort ();
if (glyph_pool_count)
- abort ();
+ emacs_abort ();
}
function must be called before updates to make explicit that we are
working on frame matrices or not. */
-static inline void
+static void
set_frame_matrix_frame (struct frame *f)
{
frame_matrix_frame = f;
done in frame matrices, and that we have to perform analogous
operations in window matrices of frame_matrix_frame. */
-static inline void
+static void
make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_matrix, int row)
{
struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
{
if (!glyph_row_slice_p (window_matrix->rows + i,
frame_matrix->rows + j))
- abort ();
+ emacs_abort ();
++i, ++j;
}
}
Redrawing Frames
**********************************************************************/
-DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
- doc: /* Clear frame FRAME and output again what is supposed to appear on it. */)
- (Lisp_Object frame)
-{
- struct frame *f;
-
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
-
- /* Ignore redraw requests, if frame has no glyphs yet.
- (Implementation note: It still has to be checked why we are
- called so early here). */
- if (!glyphs_initialized_initially_p)
- return Qnil;
+/* Redraw frame F. */
+void
+redraw_frame (struct frame *f)
+{
+ /* Error if F has no glyphs. */
+ eassert (f->glyphs_initialized_p);
update_begin (f);
#ifdef MSDOS
if (FRAME_MSDOS_P (f))
mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
set_window_update_flags (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
f->garbaged = 0;
- return Qnil;
}
-
-/* Redraw frame F. This is nothing more than a call to the Lisp
- function redraw-frame. */
-
-void
-redraw_frame (struct frame *f)
+DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 0, 1, 0,
+ doc: /* Clear frame FRAME and output again what is supposed to appear on it.
+If FRAME is omitted or nil, the selected frame is used. */)
+ (Lisp_Object frame)
{
- Lisp_Object frame;
- XSETFRAME (frame, f);
- Fredraw_frame (frame);
+ redraw_frame (decode_live_frame (frame));
+ return Qnil;
}
-
DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
doc: /* Clear and redisplay all visible frames. */)
(void)
FOR_EACH_FRAME (tail, frame)
if (FRAME_VISIBLE_P (XFRAME (frame)))
- Fredraw_frame (frame);
+ redraw_frame (XFRAME (frame));
return Qnil;
}
if (redisplay_dont_pause)
force_p = 1;
- else if (NILP (Vredisplay_preemption_period))
- force_p = 1;
- else if (!force_p && NUMBERP (Vredisplay_preemption_period))
+ else if (!force_p && detect_input_pending_ignore_squeezables ())
{
- double p = XFLOATINT (Vredisplay_preemption_period);
-
- if (detect_input_pending_ignore_squeezables ())
- {
- paused_p = 1;
- goto do_pause;
- }
-
- preemption_period = EMACS_TIME_FROM_DOUBLE (p);
- preemption_next_check = add_emacs_time (current_emacs_time (),
- preemption_period);
+ paused_p = 1;
+ goto do_pause;
}
if (FRAME_WINDOW_P (f))
if (redisplay_dont_pause)
force_p = 1;
- else if (NILP (Vredisplay_preemption_period))
- force_p = 1;
- else if (!force_p && NUMBERP (Vredisplay_preemption_period))
- {
- double p = XFLOATINT (Vredisplay_preemption_period);
- preemption_period = EMACS_TIME_FROM_DOUBLE (p);
- preemption_next_check = add_emacs_time (current_emacs_time (),
- preemption_period);
- }
/* Update W. */
update_begin (f);
if (!last_seen_p && MATRIX_ROW_BOTTOM_Y (row) >= yb)
last_seen_p = 1;
else if (last_seen_p && row->enabled_p)
- abort ();
+ emacs_abort ();
}
}
{
struct glyph_matrix *desired_matrix = w->desired_matrix;
bool paused_p;
-#if !PERIODIC_PREEMPTION_CHECKING
int preempt_count = baud_rate / 2400 + 1;
-#endif
struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
#ifdef GLYPH_DEBUG
/* Check that W's frame doesn't have glyph matrices. */
#endif
/* Check pending input the first time so that we can quickly return. */
-#if !PERIODIC_PREEMPTION_CHECKING
if (!force_p)
detect_input_pending_ignore_squeezables ();
-#endif
/* If forced to complete the update, or if no input is pending, do
the update. */
struct glyph_row *header_line_row;
int yb;
bool changed_p = 0, mouse_face_overwritten_p = 0;
-#if ! PERIODIC_PREEMPTION_CHECKING
int n_updated = 0;
-#endif
rif->update_window_begin_hook (w);
yb = window_text_bottom_y (w);
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 = current_emacs_time ();
- if (EMACS_TIME_LT (preemption_next_check, tm))
- {
- preemption_next_check = add_emacs_time (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);
{
changed_p = 1;
update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
+ /* Setting this flag will ensure the vertical border, if
+ any, between this window and the one on its left will be
+ redrawn. This is necessary because updating the left
+ margin area can potentially draw over the border. */
+ current_row->redraw_fringe_bitmaps_p = 1;
}
/* Update the display of the text area. */
vpos = w->cursor.vpos;
}
- /* Window cursor can be out of sync for horizontally split windows. */
- hpos = max (-1, hpos); /* -1 is for when cursor is on the left fringe */
- hpos = min (w->current_matrix->matrix_w - 1, hpos);
- vpos = max (0, vpos);
- vpos = min (w->current_matrix->nrows - 1, vpos);
+ /* Window cursor can be out of sync for horizontally split windows.
+ Horizontal position is -1 when cursor is on the left fringe. */
+ hpos = clip_to_bounds (-1, hpos, w->current_matrix->matrix_w - 1);
+ vpos = clip_to_bounds (0, vpos, w->current_matrix->nrows - 1);
rif->cursor_to (vpos, hpos, cy, cx);
}
/* Add glyph row ROW to the scrolling hash table. */
-static inline struct row_entry *
+static struct row_entry *
add_row_entry (struct glyph_row *row)
{
struct row_entry *entry;
if (preempt_count <= 0)
preempt_count = 1;
-#if !PERIODIC_PREEMPTION_CHECKING
if (!force_p && detect_input_pending_ignore_squeezables ())
{
pause_p = 1;
goto do_pause;
}
-#endif
/* If we cannot insert/delete lines, it's no use trying it. */
if (!FRAME_LINE_INS_DEL_OK (f))
FILE *display_output = FRAME_TTY (f)->output;
if (display_output)
{
- int outq = PENDING_OUTPUT_COUNT (display_output);
+ ptrdiff_t outq = __fpending (display_output);
if (outq > 900
|| (outq > 20 && ((i - 1) % preempt_count == 0)))
- {
- fflush (display_output);
- if (preempt_count == 1)
- {
-#ifdef EMACS_OUTQSIZE
- if (EMACS_OUTQSIZE (0, &outq) < 0)
- /* Probably not a tty. Ignore the error and reset
- the outq count. */
- outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output));
-#endif
- outq *= 10;
- if (baud_rate <= outq && baud_rate > 0)
- sleep (outq / baud_rate);
- }
- }
+ fflush (display_output);
}
}
-#if PERIODIC_PREEMPTION_CHECKING
- if (!force_p)
- {
- EMACS_TIME tm = current_emacs_time ();
- if (EMACS_TIME_LT (preemption_next_check, tm))
- {
- preemption_next_check = add_emacs_time (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);
}
}
+ lint_assume (0 <= FRAME_LINES (f));
pause_p = 0 < i && i < FRAME_LINES (f) - 1;
/* Now just clean up termcap drivers and set cursor, etc. */
}
}
-#if !PERIODIC_PREEMPTION_CHECKING
do_pause:
-#endif
clear_desired_matrices (f);
return pause_p;
struct glyph_matrix *desired_matrix = frame->desired_matrix;
if (!current_matrix)
- abort ();
+ emacs_abort ();
/* Compute hash codes of all the lines. Also calculate number of
changed lines, number of unchanged lines at the beginning, and
else if (part == ON_RIGHT_MARGIN)
area = RIGHT_MARGIN_AREA;
else
- abort ();
+ emacs_abort ();
for (i = 0; row->enabled_p && i < w->current_matrix->nrows; ++i, ++row)
if (wy >= row->y && wy < MATRIX_ROW_BOTTOM_Y (row))
#ifdef SIGWINCH
+static void deliver_window_change_signal (int);
+
static void
-window_change_signal (int signalnum) /* If we don't have an argument, */
- /* some compilers complain in signal calls. */
+handle_window_change_signal (int sig)
{
int width, height;
- int old_errno = errno;
-
struct tty_display_info *tty;
- signal (SIGWINCH, window_change_signal);
- SIGNAL_THREAD_CHECK (signalnum);
-
/* The frame size change obviously applies to a single
termcap-controlled terminal, but we can't decide which.
Therefore, we resize the frames corresponding to each tty.
change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
}
}
+}
- errno = old_errno;
+static void
+deliver_window_change_signal (int sig)
+{
+ deliver_process_signal (sig, handle_window_change_signal);
}
#endif /* SIGWINCH */
void
do_pending_window_change (bool safe)
{
- /* If window_change_signal should have run before, run it now. */
+ /* If window change signal handler should have run before, run it now. */
if (redisplaying_p && !safe)
return;
&& new_frame_total_cols == FRAME_TOTAL_COLS (f))
return;
- BLOCK_INPUT;
+ block_input ();
#ifdef MSDOS
/* We only can set screen dimensions to certain values supported
SET_FRAME_GARBAGED (f);
f->resized_p = 1;
- UNBLOCK_INPUT;
+ unblock_input ();
record_unwind_current_buffer ();
if (tty->termscript != 0)
{
- BLOCK_INPUT;
+ block_input ();
fclose (tty->termscript);
- UNBLOCK_INPUT;
+ unblock_input ();
}
tty->termscript = 0;
/* ??? Perhaps we should do something special for multibyte strings here. */
CHECK_STRING (string);
- BLOCK_INPUT;
+ block_input ();
if (!t)
error ("Unknown terminal device");
}
fwrite (SDATA (string), 1, SBYTES (string), out);
fflush (out);
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
TIMEOUT is number of seconds to wait (float or integer),
or t to wait forever.
READING is true if reading input.
- If DO_DISPLAY is >0 display process output while waiting.
- If DO_DISPLAY is >1 perform an initial redisplay before waiting.
+ If DISPLAY_OPTION is >0 display process output while waiting.
+ If DISPLAY_OPTION is >1 perform an initial redisplay before waiting.
*/
Lisp_Object
-sit_for (Lisp_Object timeout, bool reading, int do_display)
+sit_for (Lisp_Object timeout, bool reading, int display_option)
{
intmax_t sec;
int nsec;
+ bool do_display = display_option > 0;
swallow_events (do_display);
|| !NILP (Vexecuting_kbd_macro))
return Qnil;
- if (do_display >= 2)
+ if (display_option > 1)
redisplay_preserve_echo_area (2);
if (INTEGERP (timeout))
wrong_type_argument (Qnumberp, timeout);
-#ifdef SIGIO
- gobble_input (0);
+#ifdef USABLE_SIGIO
+ gobble_input ();
#endif
wait_reading_process_output (sec, nsec, reading ? -1 : 1, do_display,
inverse_video = 0;
cursor_in_echo_area = 0;
- terminal_type = (char *) 0;
/* Now is the time to initialize this; it's used by init_sys_modes
during startup. */
#ifndef CANNOT_DUMP
if (initialized)
#endif /* CANNOT_DUMP */
- signal (SIGWINCH, window_change_signal);
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_window_change_signal);
+ sigaction (SIGWINCH, &action, 0);
+ }
#endif /* SIGWINCH */
/* If running as a daemon, no need to initialize any frames/terminal. */
So call tgetent. */
{ char b[2044]; tgetent (b, "xterm");}
#endif
- adjust_frame_glyphs_initially ();
return;
}
#endif /* HAVE_X_WINDOWS */
{
Vinitial_window_system = Qw32;
Vwindow_system_version = make_number (1);
- adjust_frame_glyphs_initially ();
return;
}
#endif /* HAVE_NTGUI */
{
Vinitial_window_system = Qns;
Vwindow_system_version = make_number (10);
- adjust_frame_glyphs_initially ();
return;
}
#endif
#ifdef WINDOWSNT
terminal_type = "w32console";
#else
- /* Look at the TERM variable. */
- terminal_type = (char *) getenv ("TERM");
+ terminal_type = getenv ("TERM");
#endif
if (!terminal_type)
{
struct terminal *t;
struct frame *f = XFRAME (selected_frame);
+ init_foreground_group ();
+
/* Open a display on the controlling tty. */
t = init_tty (0, terminal_type, 1); /* Errors are fatal. */
/* Convert the initial frame to use the new display. */
if (f->output_method != output_initial)
- abort ();
+ emacs_abort ();
f->output_method = t->type;
f->terminal = t;
fatal ("screen size %dx%d too big", width, height);
}
- adjust_frame_glyphs_initially ();
calculate_costs (XFRAME (selected_frame));
/* Set up faces of the initial terminal frame of a dumped Emacs. */
/* Don't change cursor state while redisplaying. This could confuse
output routines. */
if (!redisplaying_p)
- {
- if (NILP (window))
- window = selected_window;
- else
- CHECK_WINDOW (window);
-
- XWINDOW (window)->cursor_off_p = NILP (show);
- }
-
+ decode_any_window (window)->cursor_off_p = NILP (show);
return Qnil;
}
WINDOW nil or omitted means report on the selected window. */)
(Lisp_Object window)
{
- struct window *w;
-
- if (NILP (window))
- window = selected_window;
- else
- CHECK_WINDOW (window);
-
- w = XWINDOW (window);
- return w->cursor_off_p ? Qnil : Qt;
+ return decode_any_window (window)->cursor_off_p ? Qnil : Qt;
}
DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
doc: /* Non-nil means display update isn't paused when input is detected. */);
redisplay_dont_pause = 1;
-#if PERIODIC_PREEMPTION_CHECKING
- DEFVAR_LISP ("redisplay-preemption-period", Vredisplay_preemption_period,
- doc: /* Period in seconds between checking for input during redisplay.
-This has an effect only if `redisplay-dont-pause' is nil; in that
-case, arriving input preempts redisplay until the input is processed.
-If the value is nil, redisplay is never preempted. */);
- Vredisplay_preemption_period = make_float (0.10);
-#endif
-
#ifdef CANNOT_DUMP
if (noninteractive)
#endif