diff options
Diffstat (limited to 'src/dispnew.c')
-rw-r--r-- | src/dispnew.c | 338 |
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 |