summaryrefslogtreecommitdiff
path: root/src/dispnew.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dispnew.c')
-rw-r--r--src/dispnew.c338
1 files changed, 123 insertions, 215 deletions
diff --git a/src/dispnew.c b/src/dispnew.c
index 71345775045..3ab8bcf3e64 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -72,7 +72,6 @@ struct dim
static void update_frame_line (struct frame *, int);
static int required_matrix_height (struct window *);
static int required_matrix_width (struct window *);
-static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool, bool);
static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
static void build_frame_matrix_from_window_tree (struct glyph_matrix *,
struct window *);
@@ -1108,10 +1107,10 @@ prepare_desired_row (struct window *w, struct glyph_row *row, bool mode_line_p)
/* Return a hash code for glyph row ROW, which may
be from current or desired matrix of frame F. */
-static int
+static unsigned
line_hash_code (struct frame *f, struct glyph_row *row)
{
- int hash = 0;
+ unsigned hash = 0;
if (row->enabled_p)
{
@@ -2015,12 +2014,12 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f)
/* Size of frame matrices must equal size of frame. Note
that we are called for X frames with window widths NOT equal
to the frame width (from CHANGE_FRAME_SIZE_1). */
- if (matrix_dim.width != FRAME_COLS (f)
- || matrix_dim.height != FRAME_LINES (f))
+ if (matrix_dim.width != FRAME_TOTAL_COLS (f)
+ || matrix_dim.height != FRAME_TOTAL_LINES (f))
return;
- eassert (matrix_dim.width == FRAME_COLS (f)
- && matrix_dim.height == FRAME_LINES (f));
+ eassert (matrix_dim.width == FRAME_TOTAL_COLS (f)
+ && matrix_dim.height == FRAME_TOTAL_LINES (f));
/* Pointers to glyph memory in glyph rows are exchanged during
the update phase of redisplay, which means in general that a
@@ -2122,11 +2121,11 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
w->left_col = 0;
w->pixel_top = FRAME_MENU_BAR_HEIGHT (f);
w->top_line = FRAME_MENU_BAR_LINES (f);
+ w->total_cols = FRAME_TOTAL_COLS (f);
w->pixel_width = (FRAME_PIXEL_WIDTH (f)
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
- w->total_cols = FRAME_TOTAL_COLS (f);
- w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f);
w->total_lines = FRAME_TOOL_BAR_LINES (f);
+ w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f);
allocate_matrices_for_window_redisplay (w);
}
#endif
@@ -2138,7 +2137,7 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
static void
adjust_decode_mode_spec_buffer (struct frame *f)
{
- ssize_t frame_message_buf_size = FRAME_MESSAGE_BUF_SIZE (f);
+ int frame_message_buf_size = FRAME_MESSAGE_BUF_SIZE (f);
eassert (frame_message_buf_size >= 0);
f->decode_mode_spec_buffer = xrealloc (f->decode_mode_spec_buffer,
@@ -2687,7 +2686,8 @@ mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlin
int i;
/* Make a copy of the original rows. */
- old_rows = alloca (nlines * sizeof *old_rows);
+ USE_SAFE_ALLOCA;
+ SAFE_NALLOCA (old_rows, 1, nlines);
memcpy (old_rows, new_rows, nlines * sizeof *old_rows);
/* Assign new rows, maybe clear lines. */
@@ -2709,6 +2709,8 @@ mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlin
if (frame_matrix_frame)
mirror_line_dance (XWINDOW (frame_matrix_frame->root_window),
unchanged_at_top, nlines, copy_from, retained_p);
+
+ SAFE_FREE ();
}
@@ -2801,7 +2803,8 @@ mirror_line_dance (struct window *w, int unchanged_at_top, int nlines, int *copy
struct glyph_row *old_rows;
/* Make a copy of the original rows of matrix m. */
- old_rows = alloca (m->nrows * sizeof *old_rows);
+ USE_SAFE_ALLOCA;
+ SAFE_NALLOCA (old_rows, 1, m->nrows);
memcpy (old_rows, m->rows, m->nrows * sizeof *old_rows);
for (i = 0; i < nlines; ++i)
@@ -2877,6 +2880,8 @@ mirror_line_dance (struct window *w, int unchanged_at_top, int nlines, int *copy
/* Check that no pointers are lost. */
CHECK_MATRIX (m);
+
+ SAFE_FREE ();
}
/* Next window on same level. */
@@ -2958,7 +2963,7 @@ window_to_frame_vpos (struct window *w, int vpos)
eassert (!FRAME_WINDOW_P (XFRAME (w->frame)));
eassert (vpos >= 0 && vpos <= w->desired_matrix->nrows);
vpos += WINDOW_TOP_EDGE_LINE (w);
- eassert (vpos >= 0 && vpos <= FRAME_LINES (XFRAME (w->frame)));
+ eassert (vpos >= 0 && vpos <= FRAME_TOTAL_LINES (XFRAME (w->frame)));
return vpos;
}
@@ -3423,7 +3428,7 @@ update_window (struct window *w, bool force_p)
mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix);
if (mode_line_row->mode_line_p && mode_line_row->enabled_p)
{
- mode_line_row->y = yb;
+ mode_line_row->y = yb + WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
desired_matrix),
&mouse_face_overwritten_p);
@@ -4539,7 +4544,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
}
}
- pause_p = 0 < i && i < FRAME_LINES (f) - 1;
+ pause_p = 0 < i && i < FRAME_TOTAL_LINES (f) - 1;
/* Now just clean up termcap drivers and set cursor, etc. */
if (!pause_p && set_cursor_p)
@@ -4572,7 +4577,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
cursor at the end of the prompt. If the mini-buffer
is several lines high, find the last line that has
any text on it. */
- row = FRAME_LINES (f);
+ row = FRAME_TOTAL_LINES (f);
do
{
--row;
@@ -4600,7 +4605,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
if (col >= FRAME_CURSOR_X_LIMIT (f))
{
/* If we have another row, advance cursor into it. */
- if (row < FRAME_LINES (f) - 1)
+ if (row < FRAME_TOTAL_LINES (f) - 1)
{
col = FRAME_LEFT_SCROLL_BAR_COLS (f);
row++;
@@ -4650,14 +4655,19 @@ scrolling (struct frame *frame)
int unchanged_at_top, unchanged_at_bottom;
int window_size;
int changed_lines;
- int *old_hash = alloca (FRAME_LINES (frame) * sizeof (int));
- int *new_hash = alloca (FRAME_LINES (frame) * sizeof (int));
- int *draw_cost = alloca (FRAME_LINES (frame) * sizeof (int));
- int *old_draw_cost = alloca (FRAME_LINES (frame) * sizeof (int));
- register int i;
- int free_at_end_vpos = FRAME_LINES (frame);
+ int i;
+ int height = FRAME_TOTAL_LINES (frame);
+ int free_at_end_vpos = height;
struct glyph_matrix *current_matrix = frame->current_matrix;
struct glyph_matrix *desired_matrix = frame->desired_matrix;
+ verify (sizeof (int) <= sizeof (unsigned));
+ verify (alignof (unsigned) % alignof (int) == 0);
+ unsigned *old_hash;
+ USE_SAFE_ALLOCA;
+ SAFE_NALLOCA (old_hash, 4, height);
+ unsigned *new_hash = old_hash + height;
+ int *draw_cost = (int *) (new_hash + height);
+ int *old_draw_cost = draw_cost + height;
eassert (current_matrix);
@@ -4666,12 +4676,15 @@ scrolling (struct frame *frame)
number of unchanged lines at the end. */
changed_lines = 0;
unchanged_at_top = 0;
- unchanged_at_bottom = FRAME_LINES (frame);
- for (i = 0; i < FRAME_LINES (frame); i++)
+ unchanged_at_bottom = height;
+ for (i = 0; i < height; i++)
{
/* Give up on this scrolling if some old lines are not enabled. */
if (!MATRIX_ROW_ENABLED_P (current_matrix, i))
- return 0;
+ {
+ SAFE_FREE ();
+ return false;
+ }
old_hash[i] = line_hash_code (frame, MATRIX_ROW (current_matrix, i));
if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
{
@@ -4689,7 +4702,7 @@ scrolling (struct frame *frame)
if (old_hash[i] != new_hash[i])
{
changed_lines++;
- unchanged_at_bottom = FRAME_LINES (frame) - i - 1;
+ unchanged_at_bottom = height - i - 1;
}
else if (i == unchanged_at_top)
unchanged_at_top++;
@@ -4699,10 +4712,13 @@ scrolling (struct frame *frame)
/* If changed lines are few, don't allow preemption, don't scroll. */
if ((!FRAME_SCROLL_REGION_OK (frame)
&& changed_lines < baud_rate / 2400)
- || unchanged_at_bottom == FRAME_LINES (frame))
- return 1;
+ || unchanged_at_bottom == height)
+ {
+ SAFE_FREE ();
+ return true;
+ }
- window_size = (FRAME_LINES (frame) - unchanged_at_top
+ window_size = (height - unchanged_at_top
- unchanged_at_bottom);
if (FRAME_SCROLL_REGION_OK (frame))
@@ -4710,27 +4726,25 @@ scrolling (struct frame *frame)
else if (FRAME_MEMORY_BELOW_FRAME (frame))
free_at_end_vpos = -1;
- /* If large window, fast terminal and few lines in common between
- current frame and desired frame, don't bother with i/d calc. */
- if (!FRAME_SCROLL_REGION_OK (frame)
- && window_size >= 18 && baud_rate > 2400
- && (window_size >=
- 10 * scrolling_max_lines_saved (unchanged_at_top,
- FRAME_LINES (frame) - unchanged_at_bottom,
- old_hash, new_hash, draw_cost)))
- return 0;
-
- if (window_size < 2)
- return 0;
-
- scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
- draw_cost + unchanged_at_top - 1,
- old_draw_cost + unchanged_at_top - 1,
- old_hash + unchanged_at_top - 1,
- new_hash + unchanged_at_top - 1,
- free_at_end_vpos - unchanged_at_top);
-
- return 0;
+ /* Do id/calc only if small window, or slow terminal, or many lines
+ in common between current frame and desired frame. But the
+ window size must be at least 2. */
+ if ((FRAME_SCROLL_REGION_OK (frame)
+ || window_size < 18 || baud_rate <= 2400
+ || (window_size
+ < 10 * scrolling_max_lines_saved (unchanged_at_top,
+ height - unchanged_at_bottom,
+ old_hash, new_hash, draw_cost)))
+ && 2 <= window_size)
+ scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
+ draw_cost + unchanged_at_top - 1,
+ old_draw_cost + unchanged_at_top - 1,
+ old_hash + unchanged_at_top - 1,
+ new_hash + unchanged_at_top - 1,
+ free_at_end_vpos - unchanged_at_top);
+
+ SAFE_FREE ();
+ return false;
}
@@ -5435,7 +5449,9 @@ handle_window_change_signal (int sig)
/* Record the new sizes, but don't reallocate the data
structures now. Let that be done later outside of the
signal handler. */
- change_frame_size (XFRAME (frame), width, height, 0, 1, 0, 0);
+ change_frame_size (XFRAME (frame), width,
+ height - FRAME_MENU_BAR_LINES (XFRAME (frame)),
+ 0, 1, 0, 0);
}
}
}
@@ -5476,52 +5492,11 @@ do_pending_window_change (bool safe)
}
}
-/* Change the frame height and/or width. Values may be given as zero to
- indicate no change is to take place.
-
- new_height and new_width refer to the text portion of the frame. It
- doesn't matter for new_height, since text and total portion are the
- same in that case. But new_width must be enlarged to get the total
- width of the frame.
-
- If DELAY, assume we're being called from a signal handler, and
- queue the change for later - perhaps the next redisplay.
- Since this tries to resize windows, we can't call it
- from a signal handler.
-
- SAFE means this function is called from a place where it's
- safe to change frame sizes while a redisplay is in progress. */
-
-void
-change_frame_size (struct frame *f, int new_width, int new_height,
- bool pretend, bool delay, bool safe, bool pixelwise)
-{
- Lisp_Object tail, frame;
-
- if (FRAME_MSDOS_P (f))
- {
- /* On MS-DOS, all frames use the same screen, so a change in
- size affects all frames. Termcap now supports multiple
- ttys. */
- FOR_EACH_FRAME (tail, frame)
- if (! FRAME_WINDOW_P (XFRAME (frame)))
- change_frame_size_1 (XFRAME (frame), new_width, new_height,
- pretend, delay, safe, pixelwise);
- }
- else
- change_frame_size_1 (f, new_width, new_height, pretend, delay, safe,
- pixelwise);
-}
static void
change_frame_size_1 (struct frame *f, int new_width, int new_height,
bool pretend, bool delay, bool safe, bool pixelwise)
{
- int new_text_width, new_text_height, new_root_width;
- int old_root_width = WINDOW_PIXEL_WIDTH (XWINDOW (FRAME_ROOT_WINDOW (f)));
- int new_cols, new_lines;
- ptrdiff_t count = SPECPDL_INDEX ();
-
/* If we can't deal with the change now, queue it for later. */
if (delay || (redisplaying_p && !safe))
{
@@ -5529,125 +5504,63 @@ change_frame_size_1 (struct frame *f, int new_width, int new_height,
f->new_height = new_height;
f->new_pixelwise = pixelwise;
delayed_size_change = 1;
- return;
- }
-
- /* This size-change overrides any pending one for this frame. */
- f->new_height = 0;
- f->new_width = 0;
- f->new_pixelwise = 0;
-
- /* If an argument is zero, set it to the current value. */
- if (pixelwise)
- {
- new_text_width = (new_width == 0) ? FRAME_TEXT_WIDTH (f) : new_width;
- new_text_height = (new_height == 0) ? FRAME_TEXT_HEIGHT (f) : new_height;
}
else
{
- new_cols = (new_width == 0) ? FRAME_COLS (f) : new_width;
- new_lines = (new_height == 0) ? FRAME_LINES (f) : new_height;
- new_text_width = new_cols * FRAME_COLUMN_WIDTH (f);
- new_text_height = new_lines * FRAME_LINE_HEIGHT (f);
- }
-
- /* Compute width of windows in F. */
- /* Round up to the smallest acceptable size. */
- check_frame_size (f, &new_text_width, &new_text_height, 1);
- /* Recompute the dimensions in character units, since
- check_frame_size might have changed the pixel dimensions. */
- /* Consider rounding here: Currently, the root window can be
- larger than the frame in terms of columns/lines. */
- new_cols = new_text_width / FRAME_COLUMN_WIDTH (f);
- new_lines = new_text_height / FRAME_LINE_HEIGHT (f);
-
- /* This is the width of the frame without vertical scroll bars and
- fringe columns. Do this after rounding - see discussion of
- bug#9723. */
- new_root_width = (new_text_width
- + FRAME_SCROLL_BAR_AREA_WIDTH (f)
- + FRAME_TOTAL_FRINGE_WIDTH (f));
- /* If we're not changing the frame size, quit now. */
- /* Frame width may be unchanged but the text portion may change, for
- example, fullscreen and remove/add scroll bar. */
- if (new_text_height == FRAME_TEXT_HEIGHT (f)
- && new_text_width == FRAME_TEXT_WIDTH (f)
- && new_root_width == old_root_width
- && (FRAME_PIXEL_HEIGHT (f) ==
- FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height))
- && (FRAME_PIXEL_WIDTH (f) ==
- FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width)))
- return;
+ /* This size-change overrides any pending one for this frame. */
+ f->new_height = 0;
+ f->new_width = 0;
+ f->new_pixelwise = 0;
- block_input ();
-
-#ifdef MSDOS
- /* We only can set screen dimensions to certain values supported
- by our video hardware. Try to find the smallest size greater
- or equal to the requested dimensions. */
- dos_set_window_size (&new_lines, &new_cols);
-#endif
-
- if (new_text_height != FRAME_TEXT_HEIGHT (f))
- {
- resize_frame_windows (f, new_text_height, 0, 1);
-
- /* MSDOS frames cannot PRETEND, as they change frame size by
- manipulating video hardware. */
- if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
- FrameRows (FRAME_TTY (f)) = new_lines;
- }
-
- if (new_text_width != FRAME_TEXT_WIDTH (f)
- || new_root_width != old_root_width)
- {
- resize_frame_windows (f, new_root_width, 1, 1);
-
- /* MSDOS frames cannot PRETEND, as they change frame size by
- manipulating video hardware. */
- if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
- FrameCols (FRAME_TTY (f)) = new_cols;
-
-#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
- if (WINDOWP (f->tool_bar_window))
+ /* If an argument is zero, set it to the current value. */
+ if (pixelwise)
{
- XWINDOW (f->tool_bar_window)->total_cols = new_cols;
- XWINDOW (f->tool_bar_window)->pixel_width = new_root_width;
+ new_width = (new_width <= 0) ? FRAME_TEXT_WIDTH (f) : new_width;
+ new_height = (new_height <= 0) ? FRAME_TEXT_HEIGHT (f) : new_height;
+ }
+ else
+ {
+ new_width = (((new_width <= 0) ? FRAME_COLS (f) : new_width)
+ * FRAME_COLUMN_WIDTH (f));
+ new_height = (((new_height <= 0) ? FRAME_LINES (f) : new_height)
+ * FRAME_LINE_HEIGHT (f));
}
-#endif
- }
-
- SET_FRAME_COLS (f, new_cols);
- FRAME_LINES (f) = new_lines;
- FRAME_TEXT_WIDTH (f) = new_text_width;
- FRAME_TEXT_HEIGHT (f) = new_text_height;
- FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width);
- FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height);
- {
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
- int text_area_x, text_area_y, text_area_width, text_area_height;
-
- window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
- &text_area_height);
- if (w->cursor.x >= text_area_x + text_area_width)
- w->cursor.hpos = w->cursor.x = 0;
- if (w->cursor.y >= text_area_y + text_area_height)
- w->cursor.vpos = w->cursor.y = 0;
- }
+ /* Adjust frame size but make sure x_set_window_size does not
+ get called. */
+ adjust_frame_size (f, new_width, new_height, 5, pretend);
+ }
+}
- adjust_frame_glyphs (f);
- calculate_costs (f);
- SET_FRAME_GARBAGED (f);
- f->resized_p = 1;
- unblock_input ();
+/* Change text height/width of frame F. Values may be given as zero to
+ indicate that no change is needed.
- record_unwind_current_buffer ();
+ If DELAY, assume we're being called from a signal handler, and queue
+ the change for later - perhaps the next redisplay. Since this tries
+ to resize windows, we can't call it from a signal handler.
- run_window_configuration_change_hook (f);
+ SAFE means this function is called from a place where it's safe to
+ change frame sizes while a redisplay is in progress. */
+void
+change_frame_size (struct frame *f, int new_width, int new_height,
+ bool pretend, bool delay, bool safe, bool pixelwise)
+{
+ Lisp_Object tail, frame;
- unbind_to (count, Qnil);
+ if (FRAME_MSDOS_P (f))
+ {
+ /* On MS-DOS, all frames use the same screen, so a change in
+ size affects all frames. Termcap now supports multiple
+ ttys. */
+ FOR_EACH_FRAME (tail, frame)
+ if (! FRAME_WINDOW_P (XFRAME (frame)))
+ change_frame_size_1 (XFRAME (frame), new_width, new_height,
+ pretend, delay, safe, pixelwise);
+ }
+ else
+ change_frame_size_1 (f, new_width, new_height, pretend, delay, safe,
+ pixelwise);
}
/***********************************************************************
@@ -5698,16 +5611,13 @@ the currently selected frame. In batch mode, STRING is sent to stdout
when TERMINAL is nil. */)
(Lisp_Object string, Lisp_Object terminal)
{
- struct terminal *t = get_terminal (terminal, 1);
+ struct terminal *t = decode_live_terminal (terminal);
FILE *out;
/* ??? Perhaps we should do something special for multibyte strings here. */
CHECK_STRING (string);
block_input ();
- if (!t)
- error ("Unknown terminal device");
-
if (t->type == output_initial)
out = stdout;
else if (t->type != output_termcap && t->type != output_msdos_raw)
@@ -6178,7 +6088,8 @@ init_display (void)
t->display_info.tty->top_frame = selected_frame;
change_frame_size (XFRAME (selected_frame),
FrameCols (t->display_info.tty),
- FrameRows (t->display_info.tty), 0, 0, 1, 0);
+ FrameRows (t->display_info.tty)
+ - FRAME_MENU_BAR_LINES (f), 0, 0, 1, 0);
/* Delete the initial terminal. */
if (--initial_terminal->reference_count == 0
@@ -6186,21 +6097,18 @@ init_display (void)
(*initial_terminal->delete_terminal_hook) (initial_terminal);
/* Update frame parameters to reflect the new type. */
- Fmodify_frame_parameters
- (selected_frame, list1 (Fcons (Qtty_type,
- Ftty_type (selected_frame))));
- if (t->display_info.tty->name)
- Fmodify_frame_parameters
- (selected_frame,
- list1 (Fcons (Qtty, build_string (t->display_info.tty->name))));
- else
- Fmodify_frame_parameters (selected_frame, list1 (Fcons (Qtty, Qnil)));
+ AUTO_FRAME_ARG (tty_type_arg, Qtty_type, Ftty_type (selected_frame));
+ Fmodify_frame_parameters (selected_frame, tty_type_arg);
+ AUTO_FRAME_ARG (tty_arg, Qtty, (t->display_info.tty->name
+ ? build_string (t->display_info.tty->name)
+ : Qnil));
+ Fmodify_frame_parameters (selected_frame, tty_arg);
}
{
struct frame *sf = SELECTED_FRAME ();
int width = FRAME_TOTAL_COLS (sf);
- int height = FRAME_LINES (sf);
+ int height = FRAME_TOTAL_LINES (sf);
/* If these sizes are so big they cause overflow, just ignore the
change. It's not clear what better we could do. The rest of