X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/93962bfac7ad2890ec3bf6b2278a1b7508c66d27..8030369ccb5c871d3ce11b96c220f318bc741ed8:/src/dispnew.c diff --git a/src/dispnew.c b/src/dispnew.c index e7df852bcf..1d9ae986a3 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -1,5 +1,5 @@ /* Updating of data structures for redisplay. - Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000 + Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -60,9 +60,9 @@ Boston, MA 02111-1307, USA. */ #include "w32term.h" #endif /* HAVE_NTGUI */ -#ifdef macintosh +#ifdef MAC_OS #include "macterm.h" -#endif /* macintosh */ +#endif /* MAC_OS */ /* Include systime.h after xterm.h to avoid double inclusion of time.h. */ @@ -75,9 +75,6 @@ Boston, MA 02111-1307, USA. */ #include #endif -#define max(a, b) ((a) > (b) ? (a) : (b)) -#define min(a, b) ((a) < (b) ? (a) : (b)) - /* Get number of chars of output now in the buffer of a stdio stream. This ought to be built in in stdio, but it isn't. Some s- files override this because their stdio internals differ. */ @@ -104,7 +101,7 @@ Boston, MA 02111-1307, USA. */ #endif #endif /* not __GNU_LIBRARY__ */ -#if defined (LINUX) && defined (HAVE_LIBNCURSES) +#if defined(HAVE_TERM_H) && defined (GNU_LINUX) && defined (HAVE_LIBNCURSES) #include /* for tgetent */ #endif @@ -120,7 +117,8 @@ struct dim /* Function prototypes. */ -static void save_or_restore_current_matrix P_ ((struct frame *, int)); +static struct glyph_matrix *save_current_matrix P_ ((struct frame *)); +static void restore_current_matrix P_ ((struct frame *, struct glyph_matrix *)); static void fake_current_matrices P_ ((Lisp_Object)); static void redraw_overlapping_rows P_ ((struct window *, int)); static void redraw_overlapped_rows P_ ((struct window *, int)); @@ -130,9 +128,8 @@ static int count_match P_ ((struct glyph *, struct glyph *, static unsigned line_draw_cost P_ ((struct glyph_matrix *, int)); static void update_frame_line P_ ((struct frame *, int)); static struct dim allocate_matrices_for_frame_redisplay - P_ ((Lisp_Object, int, int, struct dim, int, int *)); -static void allocate_matrices_for_window_redisplay P_ ((struct window *, - struct dim)); + P_ ((Lisp_Object, int, int, int, int *)); +static void allocate_matrices_for_window_redisplay P_ ((struct window *)); static int realloc_glyph_pool P_ ((struct glyph_pool *, struct dim)); static void adjust_frame_glyphs P_ ((struct frame *)); struct glyph_matrix *new_glyph_matrix P_ ((struct glyph_pool *)); @@ -214,7 +211,7 @@ int inverse_video; /* Line speed of the terminal. */ -int baud_rate; +EMACS_INT baud_rate; /* Either nil or a symbol naming the window system under which Emacs is running. */ @@ -241,7 +238,7 @@ Lisp_Object Vglyph_table; Lisp_Object Vstandard_display_table; /* Nonzero means reading single-character input with prompt so put - cursor on mini-buffer after the prompt. positive means at end of + cursor on mini-buffer after the prompt. Positive means at end of text in echo area; negative means at beginning of line. */ int cursor_in_echo_area; @@ -361,7 +358,7 @@ static void add_window_display_history P_ ((struct window *, char *, int)); /* 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 contructed. PAUSED_P non-zero means that the update + has been constructed. PAUSED_P non-zero means that the update has been interrupted for pending input. */ static void @@ -382,7 +379,7 @@ add_window_display_history (w, msg, paused_p) w, ((BUFFERP (w->buffer) && STRINGP (XBUFFER (w->buffer)->name)) - ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data + ? (char *) SDATA (XBUFFER (w->buffer)->name) : "???"), paused_p ? " ***paused***" : ""); strcat (buf, msg); @@ -413,7 +410,7 @@ add_frame_display_history (f, paused_p) DEFUN ("dump-redisplay-history", Fdump_redisplay_history, Sdump_redisplay_history, 0, 0, "", - "Dump redisplay history to stderr.") + doc: /* Dump redisplay history to stderr. */) () { int i; @@ -443,7 +440,8 @@ DEFUN ("dump-redisplay-history", Fdump_redisplay_history, void safe_bcopy (from, to, size) - char *from, *to; + const char *from; + char *to; int size; { if (size <= 0 || from == to) @@ -458,7 +456,7 @@ safe_bcopy (from, to, size) /* Otherwise, we'll copy from the end. */ else { - register char *endf = from + size; + register const char *endf = from + size; register char *endt = to + size; /* If TO - FROM is large, then we should break the copy into @@ -627,7 +625,7 @@ adjust_glyph_matrix (w, matrix, x, y, dim) int left = -1, right = -1; int window_x, window_y, window_width = -1, window_height; - /* See if W had a top line that has disappeared now, or vice versa. */ + /* See if W had a header line that has disappeared now, or vice versa. */ if (w) { header_line_p = WINDOW_WANTS_HEADER_LINE_P (w); @@ -774,44 +772,62 @@ adjust_glyph_matrix (w, matrix, x, y, dim) matrix->nrows = dim.height; xassert (matrix->nrows >= 0); - /* Mark rows in a current matrix of a window as not having valid - contents. It's important to not do this for desired matrices. - When Emacs starts, it may already be building desired matrices - when this function runs. */ - if (w && matrix == w->current_matrix) + if (w) { - if (window_width < 0) - window_width = window_box_width (w, -1); - - /* Optimize the case that only the height has changed (C-x 2, - upper window). Invalidate all rows that are no longer part - of the window. */ - if (!marginal_areas_changed_p - && matrix->window_left_x == XFASTINT (w->left) - && matrix->window_top_y == XFASTINT (w->top) - && matrix->window_width == window_box_width (w, -1)) + if (matrix == w->current_matrix) { - i = 0; - while (matrix->rows[i].enabled_p - && (MATRIX_ROW_BOTTOM_Y (matrix->rows + i) - < matrix->window_height)) - ++i; - - /* Window end is invalid, if inside of the rows that - are invalidated. */ - if (INTEGERP (w->window_end_vpos) - && XFASTINT (w->window_end_vpos) >= i) - w->window_end_valid = Qnil; + /* Mark rows in a current matrix of a window as not having + valid contents. It's important to not do this for + desired matrices. When Emacs starts, it may already be + building desired matrices when this function runs. */ + if (window_width < 0) + window_width = window_box_width (w, -1); + + /* Optimize the case that only the height has changed (C-x 2, + upper window). Invalidate all rows that are no longer part + of the window. */ + if (!marginal_areas_changed_p + && !header_line_changed_p + && new_rows == 0 + && dim.width == matrix->matrix_w + && matrix->window_left_x == XFASTINT (w->left) + && matrix->window_top_y == XFASTINT (w->top) + && matrix->window_width == window_width) + { + /* Find the last row in the window. */ + for (i = 0; i < matrix->nrows && matrix->rows[i].enabled_p; ++i) + if (MATRIX_ROW_BOTTOM_Y (matrix->rows + i) >= window_height) + { + ++i; + break; + } + + /* Window end is invalid, if inside of the rows that + are invalidated below. */ + if (INTEGERP (w->window_end_vpos) + && XFASTINT (w->window_end_vpos) >= i) + w->window_end_valid = Qnil; - while (i < matrix->nrows) - matrix->rows[i++].enabled_p = 0; + while (i < matrix->nrows) + matrix->rows[i++].enabled_p = 0; + } + else + { + for (i = 0; i < matrix->nrows; ++i) + matrix->rows[i].enabled_p = 0; + } } - else + else if (matrix == w->desired_matrix) { + /* Rows in desired matrices always have to be cleared; + redisplay expects this is the case when it runs, so it + had better be the case when we adjust matrices between + redisplays. */ for (i = 0; i < matrix->nrows; ++i) matrix->rows[i].enabled_p = 0; } } + /* Remember last values to be able to optimize frame redraws. */ matrix->matrix_x = x; @@ -975,13 +991,12 @@ shift_glyph_matrix (w, matrix, start, end, dy) struct glyph_row *row = &matrix->rows[start]; row->y += dy; + row->visible_height = row->height; if (row->y < min_y) - row->visible_height = row->height - (min_y - row->y); - else if (row->y + row->height > max_y) - row->visible_height = row->height - (row->y + row->height - max_y); - else - row->visible_height = row->height; + row->visible_height -= min_y - row->y; + if (row->y + row->height > max_y) + row->visible_height -= row->y + row->height - max_y; } } @@ -1110,7 +1125,7 @@ clear_glyph_row (row) Redisplay outputs such glyphs, and flickering effects were the result. This also depended on the contents of memory returned by xmalloc. If flickering happens again, activate - the code below If the flickering is gone with that, chances + the code below. If the flickering is gone with that, chances are that the flickering has the same reason as here. */ bzero (p[0], (char *) p[LAST_AREA] - (char *) p[0]); #endif @@ -1135,13 +1150,12 @@ blank_row (w, row, y) row->y = y; row->ascent = row->phys_ascent = 0; row->height = row->phys_height = CANON_Y_UNIT (XFRAME (w->frame)); - + row->visible_height = row->height; + if (row->y < min_y) - row->visible_height = row->height - (min_y - row->y); - else if (row->y + row->height > max_y) - row->visible_height = row->height - (row->y + row->height - max_y); - else - row->visible_height = row->height; + row->visible_height -= min_y - row->y; + if (row->y + row->height > max_y) + row->visible_height -= row->y + row->height - max_y; row->enabled_p = 1; } @@ -1372,38 +1386,29 @@ line_hash_code (row) if (row->enabled_p) { - if (row->inverse_p) - { - /* Give all highlighted lines the same hash code - so as to encourage scrolling to leave them in place. */ - hash = -1; - } - else - { - struct glyph *glyph = row->glyphs[TEXT_AREA]; - struct glyph *end = glyph + row->used[TEXT_AREA]; - - while (glyph < end) - { - int c = glyph->u.ch; - int face_id = glyph->face_id; - if (must_write_spaces) - c -= SPACEGLYPH; - hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c; - hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id; - ++glyph; - } + struct glyph *glyph = row->glyphs[TEXT_AREA]; + struct glyph *end = glyph + row->used[TEXT_AREA]; - if (hash == 0) - hash = 1; - } + while (glyph < end) + { + int c = glyph->u.ch; + int face_id = glyph->face_id; + if (must_write_spaces) + c -= SPACEGLYPH; + hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c; + hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id; + ++glyph; + } + + if (hash == 0) + hash = 1; } return hash; } -/* Return the cost of drawing line VPOS In MATRIX. The cost equals +/* Return the cost of drawing line VPOS in MATRIX. The cost equals the number of characters in the line. If must_write_spaces is zero, leading and trailing spaces are ignored. */ @@ -1505,7 +1510,6 @@ row_equal_p (w, a, b, mouse_face_p) } if (a->truncated_on_left_p != b->truncated_on_left_p - || a->inverse_p != b->inverse_p || a->fill_line_p != b->fill_line_p || a->truncated_on_right_p != b->truncated_on_right_p || a->overlay_arrow_p != b->overlay_arrow_p @@ -1568,7 +1572,7 @@ free_glyph_pool (pool) { if (pool) { - /* More freed than allocated? */ + /* More freed than allocated? */ --glyph_pool_count; xassert (glyph_pool_count >= 0); @@ -1616,7 +1620,7 @@ realloc_glyph_pool (pool, matrix_dim) pool->nglyphs = needed; } - /* Remember the number of rows and columns because (a) we use then + /* Remember the number of rows and columns because (a) we use them to do sanity checks, and (b) the number of columns determines where rows in the frame matrix start---this must be available to determine pointers to rows of window sub-matrices. */ @@ -1779,7 +1783,7 @@ check_matrix_invariants (w) CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of any window in the tree will be changed or have been changed (see - DIM_ONLY_P). + DIM_ONLY_P) *WINDOW_CHANGE_FLAGS must be initialized by the caller of this function. @@ -1840,11 +1844,10 @@ check_matrix_invariants (w) #define CHANGED_LEAF_MATRIX (1 << 1) static struct dim -allocate_matrices_for_frame_redisplay (window, x, y, ch_dim, - dim_only_p, window_change_flags) +allocate_matrices_for_frame_redisplay (window, x, y, dim_only_p, + window_change_flags) Lisp_Object window; int x, y; - struct dim ch_dim; int dim_only_p; int *window_change_flags; { @@ -1872,13 +1875,13 @@ allocate_matrices_for_frame_redisplay (window, x, y, ch_dim, w = XWINDOW (window); /* Get the dimension of the window sub-matrix for W, depending - on whether this a combination or a leaf window. */ + on whether this is a combination or a leaf window. */ if (!NILP (w->hchild)) - dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, ch_dim, + dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, dim_only_p, window_change_flags); else if (!NILP (w->vchild)) - dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, ch_dim, + dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, dim_only_p, window_change_flags); else @@ -1893,8 +1896,8 @@ allocate_matrices_for_frame_redisplay (window, x, y, ch_dim, /* Width and height MUST be chosen so that there are no holes in the frame matrix. */ - dim.width = XINT (w->width); - dim.height = XINT (w->height); + dim.width = required_matrix_width (w); + dim.height = required_matrix_height (w); /* Will matrix be re-allocated? */ if (x != w->desired_matrix->matrix_x @@ -1959,28 +1962,78 @@ allocate_matrices_for_frame_redisplay (window, x, y, ch_dim, } +/* Return the required height of glyph matrices for window W. */ + +int +required_matrix_height (w) + struct window *w; +{ +#ifdef HAVE_WINDOW_SYSTEM + struct frame *f = XFRAME (w->frame); + + if (FRAME_WINDOW_P (f)) + { + int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f); + int window_pixel_height = window_box_height (w) + abs (w->vscroll); + return (((window_pixel_height + ch_height - 1) + / ch_height) + /* One partially visible line at the top and + bottom of the window. */ + + 2 + /* 2 for header and mode line. */ + + 2); + } +#endif /* HAVE_WINDOW_SYSTEM */ + + return XINT (w->height); +} + + +/* Return the required width of glyph matrices for window W. */ + +int +required_matrix_width (w) + struct window *w; +{ +#ifdef HAVE_WINDOW_SYSTEM + struct frame *f = XFRAME (w->frame); + if (FRAME_WINDOW_P (f)) + { + int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f); + int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f); + + /* Compute number of glyphs needed in a glyph row. */ + return (((window_pixel_width + ch_width - 1) + / ch_width) + /* 2 partially visible columns in the text area. */ + + 2 + /* One partially visible column at the right + edge of each marginal area. */ + + 1 + 1); + } +#endif /* HAVE_WINDOW_SYSTEM */ + + return XINT (w->width); +} + + /* 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. */ static void -allocate_matrices_for_window_redisplay (w, ch_dim) +allocate_matrices_for_window_redisplay (w) struct window *w; - struct dim ch_dim; { - struct frame *f = XFRAME (w->frame); - while (w) { if (!NILP (w->vchild)) - allocate_matrices_for_window_redisplay (XWINDOW (w->vchild), ch_dim); + allocate_matrices_for_window_redisplay (XWINDOW (w->vchild)); else if (!NILP (w->hchild)) - allocate_matrices_for_window_redisplay (XWINDOW (w->hchild), ch_dim); + allocate_matrices_for_window_redisplay (XWINDOW (w->hchild)); else { /* W is a leaf window. */ - int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f); - int window_pixel_height = window_box_height (w) + abs (w->vscroll); struct dim dim; /* If matrices are not yet allocated, allocate them now. */ @@ -1990,25 +2043,8 @@ allocate_matrices_for_window_redisplay (w, ch_dim) w->current_matrix = new_glyph_matrix (NULL); } - /* Compute number of glyphs needed in a glyph row. */ - dim.width = (((window_pixel_width + ch_dim.width - 1) - / ch_dim.width) - /* 2 partially visible columns in the text area. */ - + 2 - /* One partially visible column at the right - edge of each marginal area. */ - + 1 + 1); - - /* Compute number of glyph rows needed. */ - dim.height = (((window_pixel_height + ch_dim.height - 1) - / ch_dim.height) - /* One partially visible line at the top and - bottom of the window. */ - + 2 - /* 2 for top and mode line. */ - + 2); - - /* Change matrices. */ + dim.width = required_matrix_width (w); + dim.height = required_matrix_height (w); adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim); adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim); } @@ -2145,7 +2181,6 @@ fake_current_matrices (window) - r->used[LEFT_MARGIN_AREA] - r->used[RIGHT_MARGIN_AREA]); r->mode_line_p = 0; - r->inverse_p = fr->inverse_p; } } } @@ -2153,38 +2188,63 @@ fake_current_matrices (window) } -/* Save or restore the contents of frame F's current frame matrix. - SAVE_P non-zero means save it. */ +/* Save away the contents of frame F's current frame matrix. Value is + a glyph matrix holding the contents of F's current frame matrix. */ -static void -save_or_restore_current_matrix (f, save_p) +static struct glyph_matrix * +save_current_matrix (f) struct frame *f; - int save_p; { - struct glyph_row *from, *to, *end; + int i; + struct glyph_matrix *saved; - if (save_p) - { - from = f->current_matrix->rows; - end = from + f->current_matrix->nrows; - to = f->desired_matrix->rows; - } - else + saved = (struct glyph_matrix *) xmalloc (sizeof *saved); + bzero (saved, sizeof *saved); + saved->nrows = f->current_matrix->nrows; + saved->rows = (struct glyph_row *) xmalloc (saved->nrows + * sizeof *saved->rows); + bzero (saved->rows, saved->nrows * sizeof *saved->rows); + + for (i = 0; i < saved->nrows; ++i) { - from = f->desired_matrix->rows; - end = from + f->desired_matrix->nrows; - to = f->current_matrix->rows; + struct glyph_row *from = f->current_matrix->rows + i; + struct glyph_row *to = saved->rows + i; + size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph); + to->glyphs[TEXT_AREA] = (struct glyph *) xmalloc (nbytes); + bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes); + to->used[TEXT_AREA] = from->used[TEXT_AREA]; } - - for (; from < end; ++from, ++to) + + return saved; +} + + +/* Restore the contents of frame F's current frame matrix from SAVED, + and free memory associated with SAVED. */ + +static void +restore_current_matrix (f, saved) + struct frame *f; + struct glyph_matrix *saved; +{ + int i; + + for (i = 0; i < saved->nrows; ++i) { + struct glyph_row *from = saved->rows + i; + struct glyph_row *to = f->current_matrix->rows + i; size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph); bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes); to->used[TEXT_AREA] = from->used[TEXT_AREA]; + xfree (from->glyphs[TEXT_AREA]); } + + xfree (saved->rows); + xfree (saved); } + /* Allocate/reallocate glyph matrices of a single frame F for frame-based redisplay. */ @@ -2231,7 +2291,7 @@ adjust_frame_glyphs_for_frame_redisplay (f) matrix_dim = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f), 0, top_window_y, - ch_dim, 1, + 1, &window_change_flags); /* Add in menu bar lines, if any. */ @@ -2247,7 +2307,7 @@ adjust_frame_glyphs_for_frame_redisplay (f) { /* Do it for window matrices. */ allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f), - 0, top_window_y, ch_dim, 0, + 0, top_window_y, 0, &window_change_flags); /* Size of frame matrices must equal size of frame. Note @@ -2256,9 +2316,6 @@ adjust_frame_glyphs_for_frame_redisplay (f) xassert (matrix_dim.width == FRAME_WIDTH (f) && matrix_dim.height == FRAME_HEIGHT (f)); - /* Resize frame matrices. */ - adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim); - /* Pointers to glyph memory in glyph rows are exchanged during the update phase of redisplay, which means in general that a frame's current matrix consists of pointers into both the @@ -2273,13 +2330,15 @@ adjust_frame_glyphs_for_frame_redisplay (f) && matrix_dim.width == f->current_matrix->matrix_w && matrix_dim.height == f->current_matrix->matrix_h) { - save_or_restore_current_matrix (f, 1); + struct glyph_matrix *copy = save_current_matrix (f); + adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim); adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim); - save_or_restore_current_matrix (f, 0); + restore_current_matrix (f, copy); fake_current_matrices (FRAME_ROOT_WINDOW (f)); } else { + adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim); adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim); SET_FRAME_GARBAGED (f); } @@ -2308,8 +2367,7 @@ adjust_frame_glyphs_for_window_redisplay (f) #endif /* Allocate/reallocate window matrices. */ - allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)), - ch_dim); + allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f))); /* Allocate/ reallocate matrices of the dummy window used to display the menu bar under X when no X toolkit support is available. */ @@ -2332,7 +2390,7 @@ adjust_frame_glyphs_for_window_redisplay (f) XSETFASTINT (w->left, 0); XSETFASTINT (w->height, FRAME_MENU_BAR_LINES (f)); XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f)); - allocate_matrices_for_window_redisplay (w, ch_dim); + allocate_matrices_for_window_redisplay (w); } #endif /* not USE_X_TOOLKIT */ @@ -2352,7 +2410,7 @@ adjust_frame_glyphs_for_window_redisplay (f) XSETFASTINT (w->left, 0); XSETFASTINT (w->height, FRAME_TOOL_BAR_LINES (f)); XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f)); - allocate_matrices_for_window_redisplay (w, ch_dim); + allocate_matrices_for_window_redisplay (w); } @@ -2730,9 +2788,6 @@ build_frame_matrix_from_leaf_window (frame_matrix, w) frame_row->used[TEXT_AREA] = window_matrix->matrix_x + window_matrix->matrix_w; - /* Or in other flags. */ - frame_row->inverse_p |= window_row->inverse_p; - /* Next row. */ ++window_y; ++frame_y; @@ -2943,7 +2998,7 @@ mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from, new_rows[i].enabled_p = 0; } - /* Do the same for window matrices, if MATRIX Is a frame matrix. */ + /* Do the same for window matrices, if MATRIX is a frame matrix. */ if (frame_matrix_frame) mirror_line_dance (XWINDOW (frame_matrix_frame->root_window), unchanged_at_top, nlines, copy_from, retained_p); @@ -2951,8 +3006,7 @@ mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from, /* Synchronize glyph pointers in the current matrix of window W with - the current frame matrix. W must be full-width, and be on a tty - frame. */ + the current frame matrix. */ static void sync_window_with_frame_matrix_rows (w) @@ -2960,27 +3014,31 @@ sync_window_with_frame_matrix_rows (w) { struct frame *f = XFRAME (w->frame); struct glyph_row *window_row, *window_row_end, *frame_row; + int left, right, x, width; - /* Preconditions: W must be a leaf window and full-width. Its frame - must have a frame matrix. */ + /* Preconditions: W must be a leaf window on a tty frame. */ xassert (NILP (w->hchild) && NILP (w->vchild)); - xassert (WINDOW_FULL_WIDTH_P (w)); xassert (!FRAME_WINDOW_P (f)); - /* If W is a full-width window, glyph pointers in W's current matrix - have, by definition, to be the same as glyph pointers in the - corresponding frame matrix. */ + left = margin_glyphs_to_reserve (w, 1, w->left_margin_width); + right = margin_glyphs_to_reserve (w, 1, w->right_margin_width); + x = w->current_matrix->matrix_x; + width = w->current_matrix->matrix_w; + window_row = w->current_matrix->rows; window_row_end = window_row + w->current_matrix->nrows; frame_row = f->current_matrix->rows + XFASTINT (w->top); - while (window_row < window_row_end) + + for (; window_row < window_row_end; ++window_row, ++frame_row) { - int area; - - for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area) - window_row->glyphs[area] = frame_row->glyphs[area]; - - ++window_row, ++frame_row; + window_row->glyphs[LEFT_MARGIN_AREA] + = frame_row->glyphs[0] + x; + window_row->glyphs[TEXT_AREA] + = window_row->glyphs[LEFT_MARGIN_AREA] + left; + window_row->glyphs[LAST_AREA] + = window_row->glyphs[LEFT_MARGIN_AREA] + width; + window_row->glyphs[RIGHT_MARGIN_AREA] + = window_row->glyphs[LAST_AREA] - right; } } @@ -3214,7 +3272,7 @@ window_to_frame_vpos (w, vpos) /* Translate horizontal position HPOS which is relative to window W to - a vertical position relative to W's frame. */ + a horizontal position relative to W's frame. */ static int window_to_frame_hpos (w, hpos) @@ -3237,13 +3295,13 @@ window_to_frame_hpos (w, hpos) **********************************************************************/ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0, - "Clear frame FRAME and output again what is supposed to appear on it.") - (frame) + doc: /* Clear frame FRAME and output again what is supposed to appear on it. */) + (frame) Lisp_Object frame; { struct frame *f; - CHECK_LIVE_FRAME (frame, 0); + CHECK_LIVE_FRAME (frame); f = XFRAME (frame); /* Ignore redraw requests, if frame has no glyphs yet. @@ -3283,8 +3341,8 @@ redraw_frame (f) DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "", - "Clear and redisplay all visible frames.") - () + doc: /* Clear and redisplay all visible frames. */) + () { Lisp_Object tail, frame; @@ -3340,7 +3398,7 @@ direct_output_for_insert (g) struct glyph_row *glyph_row; struct glyph *glyphs, *glyph, *end; int n; - /* Non-null means that Redisplay of W is based on window matrices. */ + /* 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); @@ -3378,6 +3436,10 @@ direct_output_for_insert (g) || g == '\r' /* 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. */ @@ -3392,6 +3454,12 @@ direct_output_for_insert (g) || (!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 (!char_ins_del_ok) + 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. */ @@ -3431,6 +3499,7 @@ direct_output_for_insert (g) 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 @@ -3535,12 +3604,16 @@ direct_output_for_insert (g) implemented for X frames. The implementation uses updated_window and updated_row. */ updated_row = glyph_row; + updated_area = TEXT_AREA; update_begin (f); if (rif) { rif->update_window_begin_hook (w); - if (glyphs == end - n) + if (glyphs == end - n + /* In front of a space added by append_space. */ + || (glyphs == end - n - 1 + && (end - n)->charpos <= 0)) rif->write_glyphs (glyphs, n); else rif->insert_glyphs (glyphs, n); @@ -3583,14 +3656,7 @@ direct_output_for_insert (g) fflush (stdout); TRACE ((stderr, "direct output for insert\n")); - - UNCHANGED_MODIFIED = MODIFF; - BEG_UNCHANGED = GPT - BEG; - XSETFASTINT (w->last_point, PT); - w->last_cursor = w->cursor; - XSETFASTINT (w->last_modified, MODIFF); - XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF); - + mark_window_display_accurate (it.window, 1); redisplay_performed_directly_p = 1; return 1; } @@ -3652,8 +3718,8 @@ direct_output_forward_char (n) 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_BYTEPOS (row) - || PT >= MATRIX_ROW_END_BYTEPOS (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); @@ -3727,12 +3793,13 @@ update_frame (f, force_p, inhibit_hairy_id_p) /* Update the tool-bar window, if present. */ if (WINDOWP (f->tool_bar_window)) { - Lisp_Object tem; struct window *w = XWINDOW (f->tool_bar_window); /* Update tool-bar window. */ if (w->must_be_updated_p) { + Lisp_Object tem; + update_window (w, 1); w->must_be_updated_p = 0; @@ -3924,7 +3991,7 @@ redraw_overlapping_rows (w, yb) if (row->used[RIGHT_MARGIN_AREA]) rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA); - /* Record in neighbor rows that ROW overwrites part of their + /* 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; @@ -3999,18 +4066,24 @@ update_window (w, force_p) { struct glyph_row *row, *end; struct glyph_row *mode_line_row; - struct glyph_row *header_line_row = NULL; + struct glyph_row *header_line_row; int yb, changed_p = 0, mouse_face_overwritten_p = 0, n_updated; rif->update_window_begin_hook (w); yb = window_text_bottom_y (w); - /* If window has a top line, update it before everything else. - Adjust y-positions of other rows by the top line height. */ + /* If window has a header line, update it before everything else. + Adjust y-positions of other rows by the header line height. */ row = desired_matrix->rows; end = row + desired_matrix->nrows - 1; + if (row->mode_line_p) - header_line_row = row++; + { + header_line_row = row; + ++row; + } + else + header_line_row = NULL; /* Update the mode line, if necessary. */ mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix); @@ -4040,11 +4113,12 @@ update_window (w, force_p) goto set_cursor; } else if (rc > 0) + /* We've scrolled the display. */ force_p = 1; changed_p = 1; } - /* Update the top mode line after scrolling because a new top + /* Update the header line after scrolling because a new header line would otherwise overwrite lines at the top of the window that can be scrolled. */ if (header_line_row && header_line_row->enabled_p) @@ -4061,7 +4135,7 @@ update_window (w, force_p) int vpos = MATRIX_ROW_VPOS (row, desired_matrix); int i; - /* We'll Have to play a little bit with when to + /* We'll have to play a little bit with when to detect_input_pending. If it's done too often, scrolling large windows with repeated scroll-up commands will too quickly pause redisplay. */ @@ -4090,7 +4164,7 @@ update_window (w, force_p) set_cursor: - /* Fix the appearance of overlapping(overlapped rows. */ + /* Fix the appearance of overlapping/overlapped rows. */ if (!paused_p && !w->pseudo_window_p) { if (changed_p && rif->fix_overlapping_area) @@ -4113,14 +4187,17 @@ update_window (w, force_p) strcpy (w->current_matrix->method, w->desired_matrix->method); #endif - /* End of update of window W. */ - rif->update_window_end_hook (w, 1, mouse_face_overwritten_p); + /* End the update of window W. Don't set the cursor if we + paused updating the display because in this case, + set_window_cursor_after_update hasn't been called, and + output_cursor doesn't contain the cursor location. */ + rif->update_window_end_hook (w, !paused_p, mouse_face_overwritten_p); } else paused_p = 1; #if GLYPH_DEBUG - check_current_matrix_flags (w); + /* check_current_matrix_flags (w); */ add_window_display_history (w, w->current_matrix->method, paused_p); #endif @@ -4191,6 +4268,16 @@ update_text_area (w, vpos) /* Clear to end of window. */ rif->clear_end_of_line (-1); changed_p = 1; + + /* This erases the cursor. We do this here because + notice_overwritten_cursor cannot easily check this, which + might indicate that the whole functionality of + notice_overwritten_cursor would better be implemented here. + On the other hand, we need notice_overwritten_cursor as long + as mouse highlighting is done asynchronously outside of + redisplay. */ + if (vpos == w->phys_cursor.vpos) + w->phys_cursor_on_p = 0; } else { @@ -4198,18 +4285,20 @@ update_text_area (w, vpos) struct glyph *current_glyph = current_row->glyphs[TEXT_AREA]; struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA]; 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, make sure we write at least one glyph, so that the face extension actually takes place. */ - int desired_stop_pos = (desired_row->used[TEXT_AREA] - - (MATRIX_ROW_EXTENDS_FACE_P (desired_row) - ? 1 : 0)); + if (MATRIX_ROW_EXTENDS_FACE_P (desired_row)) + --desired_stop_pos; stop = min (current_row->used[TEXT_AREA], desired_stop_pos); i = 0; x = desired_row->x; - + + /* Loop over glyphs that current and desired row may have + in common. */ while (i < stop) { int can_skip_p = 1; @@ -4472,22 +4561,21 @@ set_window_cursor_after_update (w) int yb = window_text_bottom_y (w); last_row = NULL; - for (row = MATRIX_ROW (w->current_matrix, 0); - row->enabled_p; - ++row) + row = w->current_matrix->rows; + while (row->enabled_p + && (last_row == NULL + || MATRIX_ROW_BOTTOM_Y (row) <= yb)) { if (row->used[TEXT_AREA] && row->glyphs[TEXT_AREA][0].charpos >= 0) last_row = row; - - if (MATRIX_ROW_BOTTOM_Y (row) >= yb) - break; + ++row; } if (last_row) { - struct glyph *start = row->glyphs[TEXT_AREA]; - struct glyph *last = start + row->used[TEXT_AREA] - 1; + struct glyph *start = last_row->glyphs[TEXT_AREA]; + struct glyph *last = start + last_row->used[TEXT_AREA] - 1; while (last > start && last->charpos < 0) --last; @@ -4600,10 +4688,6 @@ static int runs_size; static struct run **runs; -static struct row_entry *add_row_entry P_ ((struct window *, - struct glyph_row *)); - - /* Add glyph row ROW to the scrolling hash table during the scrolling of window W. */ @@ -4635,7 +4719,7 @@ add_row_entry (w, row) /* Try to reuse part of the current display of W by scrolling lines. - HEADER_LINE_P non-zero means W has a top mode line. + HEADER_LINE_P non-zero means W has a header line. The algorithm is taken from Communications of the ACM, Apr78 "A Technique for Isolating Differences Between Files." It should take @@ -5024,7 +5108,7 @@ update_frame_1 (f, force_p, inhibit_id_p) #ifdef EMACS_OUTQSIZE if (EMACS_OUTQSIZE (0, &outq) < 0) /* Probably not a tty. Ignore the error and reset - * the outq count. */ + the outq count. */ outq = PENDING_OUTPUT_COUNT (stdout); #endif outq *= 10; @@ -5286,35 +5370,25 @@ extern int *char_ins_del_vector; /* Perform a frame-based update on line VPOS in frame FRAME. */ static void -update_frame_line (frame, vpos) - register struct frame *frame; +update_frame_line (f, vpos) + struct frame *f; int vpos; { struct glyph *obody, *nbody, *op1, *op2, *np1, *nend; int tem; int osp, nsp, begmatch, endmatch, olen, nlen; - struct glyph_matrix *current_matrix = frame->current_matrix; - struct glyph_matrix *desired_matrix = frame->desired_matrix; + struct glyph_matrix *current_matrix = f->current_matrix; + struct glyph_matrix *desired_matrix = f->desired_matrix; struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos); struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos); int must_write_whole_line_p; int write_spaces_p = must_write_spaces; - int colored_spaces_p = (FACE_FROM_ID (frame, DEFAULT_FACE_ID)->background + int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background != FACE_TTY_DEFAULT_BG_COLOR); if (colored_spaces_p) write_spaces_p = 1; - if (desired_row->inverse_p - != (current_row->enabled_p && current_row->inverse_p)) - { - int n = current_row->enabled_p ? current_row->used[TEXT_AREA] : 0; - change_line_highlight (desired_row->inverse_p, vpos, vpos, n); - current_row->enabled_p = 0; - } - else - reassert_line_highlight (desired_row->inverse_p, vpos); - /* Current row not enabled means it has unknown contents. We must write the whole desired line in that case. */ must_write_whole_line_p = !current_row->enabled_p; @@ -5328,26 +5402,14 @@ update_frame_line (frame, vpos) obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos); olen = current_row->used[TEXT_AREA]; - if (!current_row->inverse_p) - { - /* Ignore trailing spaces, if we can. */ - if (!write_spaces_p) - while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1])) - olen--; - } - else - { - /* For an inverse-video line, make sure it's filled with - spaces all the way to the frame edge so that the reverse - video extends all the way across. */ - while (olen < FRAME_WIDTH (frame) - 1) - obody[olen++] = space_glyph; - } + /* Ignore trailing spaces, if we can. */ + if (!write_spaces_p) + while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1])) + olen--; } current_row->enabled_p = 1; current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA]; - current_row->inverse_p = desired_row->inverse_p; /* If desired line is empty, just clear the line. */ if (!desired_row->enabled_p) @@ -5378,10 +5440,10 @@ update_frame_line (frame, vpos) /* Don't call clear_end_of_line if we already wrote the whole line. The cursor will not be at the right margin in that case but in the line below. */ - if (nlen < FRAME_WINDOW_WIDTH (frame)) + if (nlen < FRAME_WINDOW_WIDTH (f)) { cursor_to (vpos, nlen); - clear_end_of_line (FRAME_WINDOW_WIDTH (frame)); + clear_end_of_line (FRAME_WINDOW_WIDTH (f)); } else /* Make sure we are in the right row, otherwise cursor movement @@ -5394,20 +5456,9 @@ update_frame_line (frame, vpos) /* Pretend trailing spaces are not there at all, unless for one reason or another we must write all spaces. */ - if (!desired_row->inverse_p) - { - if (!write_spaces_p) - while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1])) - nlen--; - } - else - { - /* For an inverse-video line, give it extra trailing spaces all - the way to the frame edge so that the reverse video extends - all the way across. */ - while (nlen < FRAME_WIDTH (frame) - 1) - nbody[nlen++] = space_glyph; - } + if (!write_spaces_p) + while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1])) + nlen--; /* If there's no i/d char, quickly do the best we can without it. */ if (!char_ins_del_ok) @@ -5456,7 +5507,7 @@ update_frame_line (frame, vpos) { /* If current line is blank, skip over initial spaces, if possible, and write the rest. */ - if (write_spaces_p || desired_row->inverse_p) + if (write_spaces_p) nsp = 0; else nsp = count_blanks (nbody, nlen); @@ -5474,9 +5525,7 @@ update_frame_line (frame, vpos) /* Compute number of leading blanks in old and new contents. */ osp = count_blanks (obody, olen); - nsp = (desired_row->inverse_p || colored_spaces_p - ? 0 - : count_blanks (nbody, nlen)); + nsp = (colored_spaces_p ? 0 : count_blanks (nbody, nlen)); /* Compute number of matching chars starting with first non-blank. */ begmatch = count_match (obody + osp, obody + olen, @@ -5515,7 +5564,7 @@ update_frame_line (frame, vpos) tem = (nlen - nsp) - (olen - osp); if (endmatch && tem - && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem])) + && (!char_ins_del_ok || endmatch <= char_ins_del_cost (f)[tem])) endmatch = 0; /* nsp - osp is the distance to insert or delete. @@ -5525,7 +5574,7 @@ update_frame_line (frame, vpos) if (nsp != osp && (!char_ins_del_ok - || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp])) + || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp])) { begmatch = 0; endmatch = 0; @@ -5559,16 +5608,23 @@ update_frame_line (frame, vpos) tem = nsp + begmatch + endmatch; if (nlen != tem || olen != tem) { - cursor_to (vpos, nsp + begmatch); if (!endmatch || nlen == olen) { - /* If new text being written reaches right margin, - there is no need to do clear-to-eol at the end. - (and it would not be safe, since cursor is not - going to be "at the margin" after the text is done) */ - if (nlen == FRAME_WINDOW_WIDTH (frame)) + /* If new text being written reaches right margin, there is + no need to do clear-to-eol at the end of this function + (and it would not be safe, since cursor is not going to + be "at the margin" after the text is done). */ + if (nlen == FRAME_WINDOW_WIDTH (f)) olen = 0; - write_glyphs (nbody + nsp + begmatch, nlen - tem); + + /* Function write_glyphs is prepared to do nothing + if passed a length <= 0. Check it here to avoid + unnecessary cursor movement. */ + if (nlen - tem > 0) + { + cursor_to (vpos, nsp + begmatch); + write_glyphs (nbody + nsp + begmatch, nlen - tem); + } } else if (nlen > olen) { @@ -5582,18 +5638,25 @@ update_frame_line (frame, vpos) int out = olen - tem; /* Columns to be overwritten originally. */ int del; + cursor_to (vpos, nsp + begmatch); + /* Calculate columns we can actually overwrite. */ - while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out])) out--; + while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out])) + out--; write_glyphs (nbody + nsp + begmatch, out); + /* If we left columns to be overwritten, we must delete them. */ del = olen - tem - out; - if (del > 0) delete_glyphs (del); + if (del > 0) + delete_glyphs (del); + /* At last, we insert columns not yet written out. */ insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del); olen = nlen; } else if (olen > nlen) { + cursor_to (vpos, nsp + begmatch); write_glyphs (nbody + nsp + begmatch, nlen - tem); delete_glyphs (olen - nlen); olen = nlen; @@ -5618,14 +5681,17 @@ update_frame_line (frame, vpos) X/Y Position -> Buffer Position ***********************************************************************/ -/* Return the character position of the character at window relative - pixel position (*X, *Y). *X and *Y are adjusted to character - boundaries. */ +/* Determine what's under window-relative pixel position (*X, *Y). + Return in *OBJECT the object (string or buffer) that's there. + Return in *POS the position in that object. Adjust *X and *Y + to character boundaries. */ -int -buffer_posn_from_coords (w, x, y) +void +buffer_posn_from_coords (w, x, y, object, pos) struct window *w; int *x, *y; + Lisp_Object *object; + struct display_pos *pos; { struct it it; struct buffer *old_current_buffer = current_buffer; @@ -5645,12 +5711,14 @@ buffer_posn_from_coords (w, x, y) *x = it.current_x - it.first_visible_x + left_area_width; *y = it.current_y; current_buffer = old_current_buffer; - return IT_CHARPOS (it); + + *object = STRINGP (it.string) ? it.string : w->buffer; + *pos = it.current; } /* Value is the string under window-relative coordinates X/Y in the - mode or top line of window W, or nil if none. MODE_LINE_P non-zero + mode or header line of window W, or nil if none. MODE_LINE_P non-zero means look at the mode line. *CHARPOS is set to the position in the string returned. */ @@ -5673,12 +5741,12 @@ mode_line_string (w, x, y, mode_line_p, charpos) if (row->mode_line_p && row->enabled_p) { - /* The mode lines are displayed over scroll bars and bitmap - areas, and X is window-relative. Correct X by the scroll bar - and bitmap area width. */ + /* The mode lines are displayed over scroll bars and fringes, + and X is window-relative. Correct X by the scroll bar + and fringe width. */ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) x += FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f); - x += FRAME_LEFT_FLAGS_AREA_WIDTH (f); + x += FRAME_LEFT_FRINGE_WIDTH (f); /* Find the glyph under X. If we find one with a string object, it's the one we were looking for. */ @@ -5697,6 +5765,57 @@ mode_line_string (w, x, y, mode_line_p, charpos) } +/* Value is the string under window-relative coordinates X/Y in either + marginal area, or nil if none. *CHARPOS is set to the position in + the string returned. */ + +Lisp_Object +marginal_area_string (w, x, y, area, charpos) + struct window *w; + int x, y; + int area; + int *charpos; +{ + struct glyph_row *row = w->current_matrix->rows; + struct glyph *glyph, *end; + int x0, i, wy = y; + Lisp_Object string = Qnil; + + if (area == 6) + area = LEFT_MARGIN_AREA; + else if (area == 7) + area = RIGHT_MARGIN_AREA; + else + abort (); + + for (i = 0; row->enabled_p && i < w->current_matrix->nrows; ++i, ++row) + if (wy >= row->y && wy < MATRIX_ROW_BOTTOM_Y (row)) + break; + + if (row->enabled_p) + { + /* Find the glyph under X. If we find one with a string object, + it's the one we were looking for. */ + glyph = row->glyphs[area]; + end = glyph + row->used[area]; + if (area == RIGHT_MARGIN_AREA) + x0 = (window_box_width (w, TEXT_AREA) + + window_box_width (w, LEFT_MARGIN_AREA)); + else + x0 = 0; + for (; glyph < end; x0 += glyph->pixel_width, ++glyph) + if (x >= x0 && x < x0 + glyph->pixel_width) + { + string = glyph->object; + *charpos = glyph->charpos; + break; + } + } + + return string; +} + + /*********************************************************************** Changing Frame Sizes ***********************************************************************/ @@ -5810,7 +5929,7 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe) int newheight, newwidth, pretend, delay, safe; { int new_frame_window_width; - int count = specpdl_ptr - specpdl; + int count = SPECPDL_INDEX (); /* If we can't deal with the change now, queue it for later. */ if (delay || (redisplaying_p && !safe)) @@ -5906,8 +6025,9 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe) } adjust_glyphs (f); - SET_FRAME_GARBAGED (f); calculate_costs (f); + SET_FRAME_GARBAGED (f); + f->resized_p = 1; UNBLOCK_INPUT; @@ -5927,10 +6047,10 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe) ***********************************************************************/ DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript, - 1, 1, "FOpen termscript file: ", - "Start writing all terminal output to FILE as well as the terminal.\n\ -FILE = nil means just close any termscript file currently open.") - (file) + 1, 1, "FOpen termscript file: ", + doc: /* Start writing all terminal output to FILE as well as the terminal. +FILE = nil means just close any termscript file currently open. */) + (file) Lisp_Object file; { if (termscript != 0) fclose (termscript); @@ -5939,7 +6059,7 @@ FILE = nil means just close any termscript file currently open.") if (! NILP (file)) { file = Fexpand_file_name (file, Qnil); - termscript = fopen (XSTRING (file)->data, "w"); + termscript = fopen (SDATA (file), "w"); if (termscript == 0) report_file_error ("Opening termscript", Fcons (file, Qnil)); } @@ -5948,19 +6068,19 @@ FILE = nil means just close any termscript file currently open.") DEFUN ("send-string-to-terminal", Fsend_string_to_terminal, - Ssend_string_to_terminal, 1, 1, 0, - "Send STRING to the terminal without alteration.\n\ -Control characters in STRING will have terminal-dependent effects.") - (string) + Ssend_string_to_terminal, 1, 1, 0, + doc: /* Send STRING to the terminal without alteration. +Control characters in STRING will have terminal-dependent effects. */) + (string) Lisp_Object string; { /* ??? Perhaps we should do something special for multibyte strings here. */ - CHECK_STRING (string, 0); - fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)), stdout); + CHECK_STRING (string); + fwrite (SDATA (string), 1, SBYTES (string), stdout); fflush (stdout); if (termscript) { - fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)), + fwrite (SDATA (string), 1, SBYTES (string), termscript); fflush (termscript); } @@ -5969,10 +6089,10 @@ Control characters in STRING will have terminal-dependent effects.") DEFUN ("ding", Fding, Sding, 0, 1, 0, - "Beep, or flash the screen.\n\ -Also, unless an argument is given,\n\ -terminate any keyboard macro currently executing.") - (arg) + doc: /* Beep, or flash the screen. +Also, unless an argument is given, +terminate any keyboard macro currently executing. */) + (arg) Lisp_Object arg; { if (!NILP (arg)) @@ -6008,13 +6128,13 @@ bitch_at_user () ***********************************************************************/ DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0, - "Pause, without updating display, for SECONDS seconds.\n\ -SECONDS may be a floating-point value, meaning that you can wait for a\n\ -fraction of a second. Optional second arg MILLISECONDS specifies an\n\ -additional wait period, in milliseconds; this may be useful if your\n\ -Emacs was built without floating point support.\n\ -\(Not all operating systems support waiting for a fraction of a second.)") - (seconds, milliseconds) + doc: /* Pause, without updating display, for SECONDS seconds. +SECONDS may be a floating-point value, meaning that you can wait for a +fraction of a second. Optional second arg MILLISECONDS specifies an +additional wait period, in milliseconds; this may be useful if your +Emacs was built without floating point support. +\(Not all operating systems support waiting for a fraction of a second.) */) + (seconds, milliseconds) Lisp_Object seconds, milliseconds; { int sec, usec; @@ -6022,7 +6142,7 @@ Emacs was built without floating point support.\n\ if (NILP (milliseconds)) XSETINT (milliseconds, 0); else - CHECK_NUMBER (milliseconds, 1); + CHECK_NUMBER (milliseconds); usec = XINT (milliseconds) * 1000; { @@ -6039,7 +6159,7 @@ Emacs was built without floating point support.\n\ /* Assure that 0 <= usec < 1000000. */ if (usec < 0) { - /* We can't rely on the rounding being correct if user is negative. */ + /* We can't rely on the rounding being correct if usec is negative. */ if (-1000000 < usec) sec--, usec += 1000000; else @@ -6070,7 +6190,7 @@ Emacs was built without floating point support.\n\ #else /* not VMS */ /* The reason this is done this way (rather than defined (H_S) && defined (H_T)) - is because the VMS preprocessor doesn't grok `defined' */ + is because the VMS preprocessor doesn't grok `defined'. */ #ifdef HAVE_SELECT EMACS_GET_TIME (end_time); EMACS_SET_SECS_USECS (timeout, sec, usec); @@ -6110,11 +6230,11 @@ sit_for (sec, usec, reading, display, initial_display) swallow_events (display); - if (detect_input_pending_run_timers (display)) + if (detect_input_pending_run_timers (display) || !NILP (Vexecuting_macro)) return Qnil; if (initial_display) - redisplay_preserve_echo_area (); + redisplay_preserve_echo_area (2); if (sec == 0 && usec == 0) return Qt; @@ -6131,17 +6251,17 @@ sit_for (sec, usec, reading, display, initial_display) DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0, - "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\ -SECONDS may be a floating-point value, meaning that you can wait for a\n\ -fraction of a second. Optional second arg MILLISECONDS specifies an\n\ -additional wait period, in milliseconds; this may be useful if your\n\ -Emacs was built without floating point support.\n\ -\(Not all operating systems support waiting for a fraction of a second.)\n\ -Optional third arg NODISP non-nil means don't redisplay, just wait for input.\n\ -Redisplay is preempted as always if input arrives, and does not happen\n\ -if input is available before it starts.\n\ -Value is t if waited the full time with no input arriving.") - (seconds, milliseconds, nodisp) + 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. Optional second arg MILLISECONDS specifies an +additional wait period, in milliseconds; this may be useful if your +Emacs was built without floating point support. +\(Not all operating systems support waiting for a fraction of a second.) +Optional third 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. */) + (seconds, milliseconds, nodisp) Lisp_Object seconds, milliseconds, nodisp; { int sec, usec; @@ -6149,7 +6269,7 @@ Value is t if waited the full time with no input arriving.") if (NILP (milliseconds)) XSETINT (milliseconds, 0); else - CHECK_NUMBER (milliseconds, 1); + CHECK_NUMBER (milliseconds); usec = XINT (milliseconds) * 1000; { @@ -6181,15 +6301,15 @@ 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, - "Return non-nil if the frame and buffer state appears to have changed.\n\ -The state variable is an internal vector containing all frames and buffers,\n\ -aside from buffers whose names start with space,\n\ -along with the buffers' read-only and modified flags, which allows a fast\n\ -check to see whether the menu bars might need to be recomputed.\n\ -If this function returns non-nil, it updates the internal vector to reflect\n\ -the current state.\n") - () + Sframe_or_buffer_changed_p, 0, 0, 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, +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. +If this function returns non-nil, it updates the internal vector to reflect +the current state. */) + () { Lisp_Object tail, frame, buf; Lisp_Object *vecp; @@ -6211,7 +6331,7 @@ the current state.\n") { buf = XCDR (XCAR (tail)); /* Ignore buffers that aren't included in buffer lists. */ - if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ') + if (SREF (XBUFFER (buf)->name, 0) == ' ') continue; if (!EQ (*vecp++, buf)) goto changed; @@ -6245,7 +6365,7 @@ the current state.\n") { buf = XCDR (XCAR (tail)); /* Ignore buffers that aren't included in buffer lists. */ - if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ') + if (SREF (XBUFFER (buf)->name, 0) == ' ') continue; *vecp++ = buf; *vecp++ = XBUFFER (buf)->read_only; @@ -6329,7 +6449,7 @@ init_display () #else Vwindow_system_version = make_number (10); #endif -#if defined (LINUX) && defined (HAVE_LIBNCURSES) +#if defined (GNU_LINUX) && defined (HAVE_LIBNCURSES) /* In some versions of ncurses, tputs crashes if we have not called tgetent. So call tgetent. */ @@ -6350,7 +6470,7 @@ init_display () } #endif /* HAVE_NTGUI */ -#ifdef macintosh +#ifdef MAC_OS if (!inhibit_window_system) { Vwindow_system = intern ("mac"); @@ -6358,7 +6478,7 @@ init_display () adjust_frame_glyphs_initially (); return; } -#endif /* macintosh */ +#endif /* MAC_OS */ /* If no window system has been specified, try to use the terminal. */ if (! isatty (0)) @@ -6367,7 +6487,7 @@ init_display () exit (1); } - /* Look at the TERM variable */ + /* Look at the TERM variable. */ terminal_type = (char *) getenv ("TERM"); if (!terminal_type) { @@ -6454,11 +6574,11 @@ For types not defined in VMS, use define emacs_term \"TYPE\".\n\ DEFUN ("internal-show-cursor", Finternal_show_cursor, Sinternal_show_cursor, 2, 2, 0, - "Set the cursor-visibility flag of WINDOW to SHOW.\n\ -WINDOW nil means use the selected window. SHOW non-nil means\n\ -show a cursor in WINDOW in the next redisplay. SHOW nil means\n\ -don't show a cursor.") - (window, show) + doc: /* Set the cursor-visibility flag of WINDOW to SHOW. +WINDOW nil means use the selected window. SHOW non-nil means +show a cursor in WINDOW in the next redisplay. SHOW nil means +don't show a cursor. */) + (window, show) Lisp_Object window, show; { /* Don't change cursor state while redisplaying. This could confuse @@ -6468,7 +6588,7 @@ don't show a cursor.") if (NILP (window)) window = selected_window; else - CHECK_WINDOW (window, 2); + CHECK_WINDOW (window); XWINDOW (window)->cursor_off_p = NILP (show); } @@ -6479,9 +6599,9 @@ don't show a cursor.") DEFUN ("internal-show-cursor-p", Finternal_show_cursor_p, Sinternal_show_cursor_p, 0, 1, 0, - "Value is non-nil if next redisplay will display a cursor in WINDOW.\n\ -WINDOW nil or omitted means report on the selected window.") - (window) + doc: /* Value is non-nil if next redisplay will display a cursor in WINDOW. +WINDOW nil or omitted means report on the selected window. */) + (window) Lisp_Object window; { struct window *w; @@ -6489,7 +6609,7 @@ WINDOW nil or omitted means report on the selected window.") if (NILP (window)) window = selected_window; else - CHECK_WINDOW (window, 2); + CHECK_WINDOW (window); w = XWINDOW (window); return w->cursor_off_p ? Qnil : Qt; @@ -6527,51 +6647,55 @@ syms_of_display () staticpro (&Qredisplay_dont_pause); DEFVAR_INT ("baud-rate", &baud_rate, - "*The output baud rate of the terminal.\n\ -On most systems, changing this value will affect the amount of padding\n\ -and the other strategic decisions made during redisplay."); + doc: /* *The output baud rate of the terminal. +On most systems, changing this value will affect the amount of padding +and the other strategic decisions made during redisplay. */); DEFVAR_BOOL ("inverse-video", &inverse_video, - "*Non-nil means invert the entire frame display.\n\ -This means everything is in inverse video which otherwise would not be."); + doc: /* *Non-nil means invert the entire frame display. +This means everything is in inverse video which otherwise would not be. */); DEFVAR_BOOL ("visible-bell", &visible_bell, - "*Non-nil means try to flash the frame to represent a bell."); + doc: /* *Non-nil means try to flash the frame to represent a bell. + +See also `ring-bell-function'. */); DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter, - "*Non-nil means no need to redraw entire frame after suspending.\n\ -A non-nil value is useful if the terminal can automatically preserve\n\ -Emacs's frame display when you reenter Emacs.\n\ -It is up to you to set this variable if your terminal can do that."); + doc: /* *Non-nil means no need to redraw entire frame after suspending. +A non-nil value is useful if the terminal can automatically preserve +Emacs's frame display when you reenter Emacs. +It is up to you to set this variable if your terminal can do that. */); DEFVAR_LISP ("window-system", &Vwindow_system, - "A symbol naming the window-system under which Emacs is running\n\ -\(such as `x'), or nil if emacs is running on an ordinary terminal."); + doc: /* Name of window system that Emacs is displaying through. +The value is a symbol--for instance, `x' for X windows. +The value is nil if Emacs is using a text-only terminal. */); DEFVAR_LISP ("window-system-version", &Vwindow_system_version, - "The version number of the window system in use.\n\ -For X windows, this is 10 or 11."); + doc: /* The version number of the window system in use. +For X windows, this is 10 or 11. */); DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area, - "Non-nil means put cursor in minibuffer, at end of any message there."); + doc: /* Non-nil means put cursor in minibuffer, at end of any message there. */); DEFVAR_LISP ("glyph-table", &Vglyph_table, - "Table defining how to output a glyph code to the frame.\n\ -If not nil, this is a vector indexed by glyph code to define the glyph.\n\ -Each element can be:\n\ - integer: a glyph code which this glyph is an alias for.\n\ - string: output this glyph using that string (not impl. in X windows).\n\ - nil: this glyph mod 256 is char code to output,\n\ - and this glyph / 256 is face code for X windows (see `face-id')."); + doc: /* Table defining how to output a glyph code to the frame. +If not nil, this is a vector indexed by glyph code to define the glyph. +Each element can be: + integer: a glyph code which this glyph is an alias for. + string: output this glyph using that string (not impl. in X windows). + nil: this glyph mod 524288 is the code of a character to output, + and this glyph / 524288 is the face number (see `face-id') to use + while outputting it. */); Vglyph_table = Qnil; DEFVAR_LISP ("standard-display-table", &Vstandard_display_table, - "Display table to use for buffers that specify none.\n\ -See `buffer-display-table' for more information."); + doc: /* Display table to use for buffers that specify none. +See `buffer-display-table' for more information. */); Vstandard_display_table = Qnil; DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause, - "*Non-nil means update isn't paused when input is detected."); + 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. */