X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/019b1f0e337b2994e33a7350da95f64f0777b3a6..8389b33fa2a8cdcee34adc84bd86b85ec8a101e3:/src/dispnew.c diff --git a/src/dispnew.c b/src/dispnew.c index 279c1f10e5..63a8a3a313 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -1,6 +1,6 @@ /* Updating of data structures for redisplay. - Copyright (C) 1985,86,87,88,93,94,95,97,98,1999,2000,01,02,2003 - Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -1513,12 +1513,14 @@ row_equal_p (w, a, b, mouse_face_p) return 0; } - if (a->truncated_on_left_p != b->truncated_on_left_p - || a->fill_line_p != b->fill_line_p - || a->truncated_on_right_p != b->truncated_on_right_p + if (a->fill_line_p != b->fill_line_p + || a->cursor_in_fringe_p != b->cursor_in_fringe_p + || a->left_fringe_bitmap != b->left_fringe_bitmap + || a->left_fringe_face_id != b->left_fringe_face_id + || a->right_fringe_bitmap != b->right_fringe_bitmap + || a->right_fringe_face_id != b->right_fringe_face_id || a->overlay_arrow_p != b->overlay_arrow_p - || a->continued_p != b->continued_p - || a->indicate_empty_line_p != b->indicate_empty_line_p + || a->exact_window_width_line_p != b->exact_window_width_line_p || a->overlapped_p != b->overlapped_p || (MATRIX_ROW_CONTINUATION_LINE_P (a) != MATRIX_ROW_CONTINUATION_LINE_P (b)) @@ -1909,10 +1911,10 @@ allocate_matrices_for_frame_redisplay (window, x, y, dim_only_p, || dim.width != w->desired_matrix->matrix_w || dim.height != w->desired_matrix->matrix_h || (margin_glyphs_to_reserve (w, dim.width, - w->right_margin_cols) + w->left_margin_cols) != w->desired_matrix->left_margin_glyphs) || (margin_glyphs_to_reserve (w, dim.width, - w->left_margin_cols) + w->right_margin_cols) != w->desired_matrix->right_margin_glyphs)) *window_change_flags |= CHANGED_LEAF_MATRIX; @@ -1980,7 +1982,7 @@ required_matrix_height (w) 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) + / ch_height) * w->nrows_scale_factor /* One partially visible line at the top and bottom of the window. */ + 2 @@ -2008,7 +2010,7 @@ required_matrix_width (w) /* Compute number of glyphs needed in a glyph row. */ return (((window_pixel_width + ch_width - 1) - / ch_width) + / ch_width) * w->ncols_scale_factor /* 2 partially visible columns in the text area. */ + 2 /* One partially visible column at the right @@ -2775,6 +2777,7 @@ build_frame_matrix_from_leaf_window (frame_matrix, w) SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph); } +#if GLYPH_DEBUG /* Window row window_y must be a slice of frame row frame_y. */ xassert (glyph_row_slice_p (window_row, frame_row)); @@ -2782,7 +2785,6 @@ build_frame_matrix_from_leaf_window (frame_matrix, w) /* If rows are in sync, we don't have to copy glyphs because frame and window share glyphs. */ -#if GLYPH_DEBUG strcpy (w->current_matrix->method, w->desired_matrix->method); add_window_display_history (w, w->current_matrix->method, 0); #endif @@ -3450,6 +3452,7 @@ direct_output_for_insert (g) /* Can't do it in a continued line because continuation lines would change. */ (glyph_row->continued_p + || glyph_row->exact_window_width_line_p /* Can't use this method if the line overlaps others or is overlapped by others because these other lines would have to be redisplayed. */ @@ -3655,6 +3658,10 @@ direct_output_for_insert (g) cursor_to (y, x); } +#ifdef HAVE_WINDOW_SYSTEM + update_window_fringes (w, 0); +#endif + if (rif) rif->update_window_end_hook (w, 1, 0); update_end (f); @@ -3822,10 +3829,15 @@ update_frame (f, force_p, inhibit_hairy_id_p) paused_p = update_window_tree (root_window, force_p); update_end (f); -#if 0 /* This flush is a performance bottleneck under X, - and it doesn't seem to be necessary anyway. */ - rif->flush_display (f); -#endif + /* This flush is a performance bottleneck under X, + and it doesn't seem to be necessary anyway (in general). + It is necessary when resizing the window with the mouse, or + at least the fringes are not redrawn in a timely manner. ++kfs */ + if (f->force_flush_display_p) + { + rif->flush_display (f); + f->force_flush_display_p = 0; + } } else { @@ -4053,17 +4065,17 @@ update_window (w, force_p) extern Lisp_Object do_mouse_tracking; #if GLYPH_DEBUG struct frame *f = XFRAME (WINDOW_FRAME (w)); -#endif /* Check that W's frame doesn't have glyph matrices. */ xassert (FRAME_WINDOW_P (f)); xassert (updating_frame != NULL); +#endif /* Check pending input the first time so that we can quickly return. */ if (redisplay_dont_pause) force_p = 1; else - detect_input_pending (); + detect_input_pending_ignore_squeezables (); /* If forced to complete the update, or if no input is pending, do the update. */ @@ -4118,19 +4130,11 @@ 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 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) - { - header_line_row->y = 0; - update_window_line (w, 0, &mouse_face_overwritten_p); - changed_p = 1; + { + /* We've scrolled the display. */ + force_p = 1; + changed_p = 1; + } } /* Update the rest of the lines. */ @@ -4145,7 +4149,7 @@ update_window (w, force_p) scrolling large windows with repeated scroll-up commands will too quickly pause redisplay. */ if (!force_p && ++n_updated % preempt_count == 0) - detect_input_pending (); + detect_input_pending_ignore_squeezables (); changed_p |= update_window_line (w, vpos, &mouse_face_overwritten_p); @@ -4169,6 +4173,16 @@ update_window (w, force_p) set_cursor: + /* 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) + { + header_line_row->y = 0; + update_window_line (w, 0, &mouse_face_overwritten_p); + changed_p = 1; + } + /* Fix the appearance of overlapping/overlapped rows. */ if (!paused_p && !w->pseudo_window_p) { @@ -4192,6 +4206,10 @@ update_window (w, force_p) strcpy (w->current_matrix->method, w->desired_matrix->method); #endif +#ifdef HAVE_WINDOW_SYSTEM + update_window_fringes (w, 0); +#endif + /* 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 @@ -4510,13 +4528,11 @@ update_window_line (w, vpos, mouse_face_overwritten_p) if (!current_row->enabled_p || desired_row->y != current_row->y || desired_row->visible_height != current_row->visible_height + || desired_row->cursor_in_fringe_p != current_row->cursor_in_fringe_p || desired_row->overlay_arrow_p != current_row->overlay_arrow_p - || desired_row->truncated_on_left_p != current_row->truncated_on_left_p - || desired_row->truncated_on_right_p != current_row->truncated_on_right_p - || desired_row->continued_p != current_row->continued_p + || current_row->redraw_fringe_bitmaps_p || desired_row->mode_line_p != current_row->mode_line_p - || (desired_row->indicate_empty_line_p - != current_row->indicate_empty_line_p) + || desired_row->exact_window_width_line_p != current_row->exact_window_width_line_p || (MATRIX_ROW_CONTINUATION_LINE_P (desired_row) != MATRIX_ROW_CONTINUATION_LINE_P (current_row))) rif->after_update_window_line_hook (desired_row); @@ -4769,6 +4785,7 @@ scrolling_window (w, header_line_p) if (c->enabled_p && d->enabled_p + && !d->redraw_fringe_bitmaps_p && c->y == d->y && MATRIX_ROW_BOTTOM_Y (c) <= yb && MATRIX_ROW_BOTTOM_Y (d) <= yb @@ -4824,6 +4841,7 @@ scrolling_window (w, header_line_p) && MATRIX_ROW (current_matrix, i - 1)->enabled_p && (MATRIX_ROW (current_matrix, i - 1)->y == MATRIX_ROW (desired_matrix, j - 1)->y) + && !MATRIX_ROW (desired_matrix, j - 1)->redraw_fringe_bitmaps_p && row_equal_p (w, MATRIX_ROW (desired_matrix, i - 1), MATRIX_ROW (current_matrix, j - 1), 1)) @@ -5016,6 +5034,13 @@ scrolling_window (w, header_line_p) to = MATRIX_ROW (current_matrix, r->desired_vpos + j); from = MATRIX_ROW (desired_matrix, r->desired_vpos + j); to_overlapped_p = to->overlapped_p; + if (!from->mode_line_p && !w->pseudo_window_p + && (to->left_fringe_bitmap != from->left_fringe_bitmap + || to->right_fringe_bitmap != from->right_fringe_bitmap + || to->left_fringe_face_id != from->left_fringe_face_id + || to->right_fringe_face_id != from->right_fringe_face_id + || to->overlay_arrow_p != from->overlay_arrow_p)) + from->redraw_fringe_bitmaps_p = 1; assign_row (to, from); to->enabled_p = 1, from->enabled_p = 0; to->overlapped_p = to_overlapped_p; @@ -5026,8 +5051,8 @@ scrolling_window (w, header_line_p) for (i = 0; i < row_entry_idx; ++i) row_table[row_entry_pool[i].bucket] = NULL; - /* Value is non-zero to indicate that we scrolled the display. */ - return 1; + /* Value is > 0 to indicate that we scrolled the display. */ + return nruns; } @@ -5068,7 +5093,7 @@ update_frame_1 (f, force_p, inhibit_id_p) if (redisplay_dont_pause) force_p = 1; - else if (!force_p && detect_input_pending ()) + else if (!force_p && detect_input_pending_ignore_squeezables ()) { pause = 1; goto do_pause; @@ -5124,7 +5149,7 @@ update_frame_1 (f, force_p, inhibit_id_p) } if ((i - 1) % preempt_count == 0) - detect_input_pending (); + detect_input_pending_ignore_squeezables (); update_frame_line (f, i); } @@ -5687,23 +5712,27 @@ update_frame_line (f, vpos) ***********************************************************************/ /* 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 positions. */ + Return the object (string or buffer) that's there. + Return in *POS the position in that object. + Adjust *X and *Y to character positions. */ -void -buffer_posn_from_coords (w, x, y, dx, dy, object, pos) +Lisp_Object +buffer_posn_from_coords (w, x, y, pos, object, dx, dy, width, height) struct window *w; int *x, *y; - int *dx, *dy; - Lisp_Object *object; struct display_pos *pos; + Lisp_Object *object; + int *dx, *dy; + int *width, *height; { struct it it; struct buffer *old_current_buffer = current_buffer; struct text_pos startp; + Lisp_Object string; struct glyph_row *row; - struct image *img; +#ifdef HAVE_WINDOW_SYSTEM + struct image *img = 0; +#endif int x0, x1; current_buffer = XBUFFER (w->buffer); @@ -5716,42 +5745,84 @@ buffer_posn_from_coords (w, x, y, dx, dy, object, pos) move_it_to (&it, -1, x0 + it.first_visible_x, *y, -1, MOVE_TO_X | MOVE_TO_Y); - /* Add extra (default width) columns if clicked after EOL. */ - x1 = max(0, it.current_x + it.pixel_width - it.first_visible_x); - if (x0 > x1) - it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w); - current_buffer = old_current_buffer; *dx = x0 + it.first_visible_x - it.current_x; *dy = *y - it.current_y; + string = w->buffer; + if (STRINGP (it.string)) + string = it.string; + *pos = it.current; + #ifdef HAVE_WINDOW_SYSTEM - if (it.what == IT_IMAGE - && (img = IMAGE_FROM_ID (it.f, it.image_id)) != NULL - && !NILP (img->spec)) - *object = img->spec; - else + if (it.what == IT_IMAGE) + { + if ((img = IMAGE_FROM_ID (it.f, it.image_id)) != NULL + && !NILP (img->spec)) + *object = img->spec; + } #endif - *object = STRINGP (it.string) ? it.string : w->buffer; - *pos = it.current; + + row = MATRIX_ROW (w->current_matrix, it.vpos); + if (row->enabled_p) + { + if (it.hpos < row->used[TEXT_AREA]) + { + struct glyph *glyph = row->glyphs[TEXT_AREA] + it.hpos; +#ifdef HAVE_WINDOW_SYSTEM + if (img) + { + *dy -= row->ascent - glyph->ascent; + *dx += glyph->slice.x; + *dy += glyph->slice.y; + /* Image slices positions are still relative to the entire image */ + *width = img->width; + *height = img->height; + } + else +#endif + { + *width = glyph->pixel_width; + *height = glyph->ascent + glyph->descent; + } + } + else + { + *width = 0; + *height = row->height; + } + } + else + { + *width = *height = 0; + } + + /* Add extra (default width) columns if clicked after EOL. */ + x1 = max(0, it.current_x + it.pixel_width - it.first_visible_x); + if (x0 > x1) + it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w); + *x = it.hpos; *y = it.vpos; + + return string; } /* Value is the string under window-relative coordinates X/Y in the - 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. */ + mode line or header line (PART says which) of window W, or nil if none. + *CHARPOS is set to the position in the string returned. */ Lisp_Object -mode_line_string (w, x, y, dx, dy, part, charpos) +mode_line_string (w, part, x, y, charpos, object, dx, dy, width, height) struct window *w; - int *x, *y; - int *dx, *dy; enum window_part part; + int *x, *y; int *charpos; + Lisp_Object *object; + int *dx, *dy; + int *width, *height; { struct glyph_row *row; struct glyph *glyph, *end; @@ -5771,29 +5842,43 @@ mode_line_string (w, x, y, dx, dy, part, charpos) it's the one we were looking for. */ glyph = row->glyphs[TEXT_AREA]; end = glyph + row->used[TEXT_AREA]; - for (x0 = *x; glyph < end && x0 > glyph->pixel_width; ++glyph) + for (x0 = *x; glyph < end && x0 >= glyph->pixel_width; ++glyph) x0 -= glyph->pixel_width; *x = glyph - row->glyphs[TEXT_AREA]; if (glyph < end) { string = glyph->object; *charpos = glyph->charpos; + *width = glyph->pixel_width; + *height = glyph->ascent + glyph->descent; +#ifdef HAVE_WINDOW_SYSTEM + if (glyph->type == IMAGE_GLYPH) + { + struct image *img; + img = IMAGE_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id); + if (img != NULL) + *object = img->spec; + y0 -= row->ascent - glyph->ascent; + } +#endif } else - /* Add extra (default width) columns if clicked after EOL. */ - *x += x0 / WINDOW_FRAME_COLUMN_WIDTH (w); + { + /* Add extra (default width) columns if clicked after EOL. */ + *x += x0 / WINDOW_FRAME_COLUMN_WIDTH (w); + *width = 0; + *height = row->height; + } } else { *x = 0; x0 = 0; + *width = *height = 0; } - if (dx) - { - *dx = x0; - *dy = y0; - } + *dx = x0; + *dy = y0; return string; } @@ -5804,12 +5889,14 @@ mode_line_string (w, x, y, dx, dy, part, charpos) the string returned. */ Lisp_Object -marginal_area_string (w, x, y, dx, dy, part, charpos) +marginal_area_string (w, part, x, y, charpos, object, dx, dy, width, height) struct window *w; - int *x, *y; - int *dx, *dy; enum window_part part; + int *x, *y; int *charpos; + Lisp_Object *object; + int *dx, *dy; + int *width, *height; { struct glyph_row *row = w->current_matrix->rows; struct glyph *glyph, *end; @@ -5836,40 +5923,56 @@ marginal_area_string (w, x, y, dx, dy, part, charpos) it's the one we were looking for. */ if (area == RIGHT_MARGIN_AREA) x0 = ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) - ? WINDOW_LEFT_FRINGE_WIDTH (w) + ? WINDOW_LEFT_FRINGE_WIDTH (w) : WINDOW_TOTAL_FRINGE_WIDTH (w)) + window_box_width (w, LEFT_MARGIN_AREA) + window_box_width (w, TEXT_AREA)); else x0 = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) - ? WINDOW_LEFT_FRINGE_WIDTH (w) + ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0); glyph = row->glyphs[area]; end = glyph + row->used[area]; - for (x0 = *x - x0; glyph < end && x0 > glyph->pixel_width; ++glyph) + for (x0 = *x - x0; glyph < end && x0 >= glyph->pixel_width; ++glyph) x0 -= glyph->pixel_width; *x = glyph - row->glyphs[area]; if (glyph < end) { string = glyph->object; *charpos = glyph->charpos; + *width = glyph->pixel_width; + *height = glyph->ascent + glyph->descent; +#ifdef HAVE_WINDOW_SYSTEM + if (glyph->type == IMAGE_GLYPH) + { + struct image *img; + img = IMAGE_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id); + if (img != NULL) + *object = img->spec; + y0 -= row->ascent - glyph->ascent; + x0 += glyph->slice.x; + y0 += glyph->slice.y; + } +#endif } else - /* Add extra (default width) columns if clicked after EOL. */ - *x += x0 / WINDOW_FRAME_COLUMN_WIDTH (w); + { + /* Add extra (default width) columns if clicked after EOL. */ + *x += x0 / WINDOW_FRAME_COLUMN_WIDTH (w); + *width = 0; + *height = row->height; + } } else { x0 = 0; *x = 0; + *width = *height = 0; } - if (dx) - { - *dx = x0; - *dy = y0; - } + *dx = x0; + *dy = y0; return string; } @@ -5891,6 +5994,9 @@ window_change_signal (signalnum) /* If we don't have an argument, */ #endif int old_errno = errno; + signal (SIGWINCH, window_change_signal); + SIGNAL_THREAD_CHECK (signalnum); + get_frame_size (&width, &height); /* The frame size change obviously applies to a termcap-controlled @@ -5913,7 +6019,6 @@ window_change_signal (signalnum) /* If we don't have an argument, */ } } - signal (SIGWINCH, window_change_signal); errno = old_errno; } #endif /* SIGWINCH */ @@ -6228,52 +6333,13 @@ Emacs was built without floating point support. if (sec < 0 || (sec == 0 && usec == 0)) return Qnil; - { - Lisp_Object zero; - - XSETFASTINT (zero, 0); - wait_reading_process_input (sec, usec, zero, 0); - } - - /* We should always have wait_reading_process_input; we have a dummy - implementation for systems which don't support subprocesses. */ -#if 0 - /* No wait_reading_process_input */ - immediate_quit = 1; - QUIT; - -#ifdef VMS - sys_sleep (sec); -#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'. */ -#ifdef HAVE_SELECT - EMACS_GET_TIME (end_time); - EMACS_SET_SECS_USECS (timeout, sec, usec); - EMACS_ADD_TIME (end_time, end_time, timeout); - - while (1) - { - EMACS_GET_TIME (timeout); - EMACS_SUB_TIME (timeout, end_time, timeout); - if (EMACS_TIME_NEG_P (timeout) - || !select (1, 0, 0, 0, &timeout)) - break; - } -#else /* not HAVE_SELECT */ - sleep (sec); -#endif /* HAVE_SELECT */ -#endif /* not VMS */ - - immediate_quit = 0; -#endif /* no subprocesses */ + wait_reading_process_output (sec, usec, 0, 0, Qnil, NULL, 0); return Qnil; } -/* This is just like wait_reading_process_input, except that +/* This is just like wait_reading_process_output, except that it does the redisplay. It's also much like Fsit_for, except that it can be used for @@ -6283,8 +6349,6 @@ Lisp_Object sit_for (sec, usec, reading, display, initial_display) int sec, usec, reading, display, initial_display; { - Lisp_Object read_kbd; - swallow_events (display); if (detect_input_pending_run_timers (display) || !NILP (Vexecuting_macro)) @@ -6300,8 +6364,8 @@ sit_for (sec, usec, reading, display, initial_display) gobble_input (0); #endif - XSETINT (read_kbd, reading ? -1 : 1); - wait_reading_process_input (sec, usec, read_kbd, display); + wait_reading_process_output (sec, usec, reading ? -1 : 1, display, + Qnil, NULL, 0); return detect_input_pending () ? Qnil : Qt; }