X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/edf3d146cc73256b2c992a90e6379680c797d54e..1599821a5c8d6eee6066a0cfb497eaba7fc579e7:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index ab3aae5fb9..20e34d9417 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1,7 +1,7 @@ /* Display generation from window structure and buffer text. Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005 Free Software Foundation, Inc. + 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -269,6 +269,12 @@ int auto_raise_tool_bar_buttons_p; int make_cursor_line_fully_visible_p; +/* Margin below tool bar in pixels. 0 or nil means no margin. + If value is `internal-border-width' or `border-width', + the corresponding frame parameter is used. */ + +Lisp_Object Vtool_bar_border; + /* Margin around tool bar buttons in pixels. */ Lisp_Object Vtool_bar_button_margin; @@ -852,7 +858,7 @@ static void store_mode_line_noprop_char P_ ((char)); static int store_mode_line_noprop P_ ((const unsigned char *, int, int)); static void x_consider_frame_title P_ ((Lisp_Object)); static void handle_stop P_ ((struct it *)); -static int tool_bar_lines_needed P_ ((struct frame *)); +static int tool_bar_lines_needed P_ ((struct frame *, int *)); static int single_display_spec_intangible_p P_ ((Lisp_Object)); static void ensure_echo_area_buffers P_ ((void)); static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object)); @@ -963,7 +969,7 @@ static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *, static void update_tool_bar P_ ((struct frame *, int)); static void build_desired_tool_bar_string P_ ((struct frame *f)); static int redisplay_tool_bar P_ ((struct frame *)); -static void display_tool_bar_line P_ ((struct it *)); +static void display_tool_bar_line P_ ((struct it *, int)); static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area, int, int, int, int)); @@ -1348,7 +1354,7 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, exact_mode_line_heights_p) current_header_line_height = current_mode_line_height = -1; if (visible_p && XFASTINT (w->hscroll) > 0) - *x -= XFASTINT (w->hscroll); + *x -= XFASTINT (w->hscroll) * WINDOW_FRAME_COLUMN_WIDTH (w); return visible_p; } @@ -1768,15 +1774,20 @@ frame_to_window_pixel_xy (w, x, y) } /* EXPORT: - Return in *R the clipping rectangle for glyph string S. */ + Return in RECTS[] at most N clipping rectangles for glyph string S. + Return the number of stored rectangles. */ -void -get_glyph_string_clip_rect (s, nr) +int +get_glyph_string_clip_rects (s, rects, n) struct glyph_string *s; - NativeRectangle *nr; + NativeRectangle *rects; + int n; { XRectangle r; + if (n <= 0) + return 0; + if (s->row->full_width_p) { /* Draw full-width. X coordinates are relative to S->w->left_col. */ @@ -1819,10 +1830,27 @@ get_glyph_string_clip_rect (s, nr) /* If S draws overlapping rows, it's sufficient to use the top and bottom of the window for clipping because this glyph string intentionally draws over other lines. */ - if (s->for_overlaps_p) + if (s->for_overlaps) { r.y = WINDOW_HEADER_LINE_HEIGHT (s->w); r.height = window_text_bottom_y (s->w) - r.y; + + /* Alas, the above simple strategy does not work for the + environments with anti-aliased text: if the same text is + drawn onto the same place multiple times, it gets thicker. + If the overlap we are processing is for the erased cursor, we + take the intersection with the rectagle of the cursor. */ + if (s->for_overlaps & OVERLAPS_ERASED_CURSOR) + { + XRectangle rc, r_save = r; + + rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x); + rc.y = s->w->phys_cursor.y; + rc.width = s->w->phys_cursor_width; + rc.height = s->w->phys_cursor_height; + + x_intersect_rectangles (&r_save, &rc, &r); + } } else { @@ -1881,11 +1909,71 @@ get_glyph_string_clip_rect (s, nr) } } + if ((s->for_overlaps & OVERLAPS_BOTH) == 0 + || (s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1) + { #ifdef CONVERT_FROM_XRECT - CONVERT_FROM_XRECT (r, *nr); + CONVERT_FROM_XRECT (r, *rects); #else - *nr = r; + *rects = r; #endif + return 1; + } + else + { + /* If we are processing overlapping and allowed to return + multiple clipping rectangles, we exclude the row of the glyph + string from the clipping rectangle. This is to avoid drawing + the same text on the environment with anti-aliasing. */ +#ifdef CONVERT_FROM_XRECT + XRectangle rs[2]; +#else + XRectangle *rs = rects; +#endif + int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y); + + if (s->for_overlaps & OVERLAPS_PRED) + { + rs[i] = r; + if (r.y + r.height > row_y) + if (r.y < row_y) + rs[i].height = row_y - r.y; + else + rs[i].height = 0; + i++; + } + if (s->for_overlaps & OVERLAPS_SUCC) + { + rs[i] = r; + if (r.y < row_y + s->row->visible_height) + if (r.y + r.height > row_y + s->row->visible_height) + { + rs[i].y = row_y + s->row->visible_height; + rs[i].height = r.y + r.height - rs[i].y; + } + else + rs[i].height = 0; + i++; + } + + n = i; +#ifdef CONVERT_FROM_XRECT + for (i = 0; i < n; i++) + CONVERT_FROM_XRECT (rs[i], rects[i]); +#endif + return n; + } +} + +/* EXPORT: + Return in *NR the clipping rectangle for glyph string S. */ + +void +get_glyph_string_clip_rect (s, nr) + struct glyph_string *s; + NativeRectangle *nr; +{ + get_glyph_string_clip_rects (s, nr, 1); } @@ -1941,10 +2029,202 @@ get_phys_cursor_geometry (w, row, glyph, heightp) } } - *heightp = h - 1; + *heightp = h; return WINDOW_TO_FRAME_PIXEL_Y (w, y); } +/* + * Remember which glyph the mouse is over. + */ + +void +remember_mouse_glyph (f, gx, gy, rect) + struct frame *f; + int gx, gy; + NativeRectangle *rect; +{ + Lisp_Object window; + struct window *w; + struct glyph_row *r, *gr, *end_row; + enum window_part part; + enum glyph_row_area area; + int x, y, width, height; + + /* Try to determine frame pixel position and size of the glyph under + frame pixel coordinates X/Y on frame F. */ + + window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0); + if (NILP (window)) + { + width = FRAME_SMALLEST_CHAR_WIDTH (f); + height = FRAME_SMALLEST_FONT_HEIGHT (f); + goto virtual_glyph; + } + + w = XWINDOW (window); + width = WINDOW_FRAME_COLUMN_WIDTH (w); + height = WINDOW_FRAME_LINE_HEIGHT (w); + + r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); + end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); + + if (w->pseudo_window_p) + { + area = TEXT_AREA; + part = ON_MODE_LINE; /* Don't adjust margin. */ + goto text_glyph; + } + + switch (part) + { + case ON_LEFT_MARGIN: + area = LEFT_MARGIN_AREA; + goto text_glyph; + + case ON_RIGHT_MARGIN: + area = RIGHT_MARGIN_AREA; + goto text_glyph; + + case ON_HEADER_LINE: + case ON_MODE_LINE: + gr = (part == ON_HEADER_LINE + ? MATRIX_HEADER_LINE_ROW (w->current_matrix) + : MATRIX_MODE_LINE_ROW (w->current_matrix)); + gy = gr->y; + area = TEXT_AREA; + goto text_glyph_row_found; + + case ON_TEXT: + area = TEXT_AREA; + + text_glyph: + gr = 0; gy = 0; + for (; r <= end_row && r->enabled_p; ++r) + if (r->y + r->height > y) + { + gr = r; gy = r->y; + break; + } + + text_glyph_row_found: + if (gr && gy <= y) + { + struct glyph *g = gr->glyphs[area]; + struct glyph *end = g + gr->used[area]; + + height = gr->height; + for (gx = gr->x; g < end; gx += g->pixel_width, ++g) + if (gx + g->pixel_width > x) + break; + + if (g < end) + { + if (g->type == IMAGE_GLYPH) + { + /* Don't remember when mouse is over image, as + image may have hot-spots. */ + STORE_NATIVE_RECT (*rect, 0, 0, 0, 0); + return; + } + width = g->pixel_width; + } + else + { + /* Use nominal char spacing at end of line. */ + x -= gx; + gx += (x / width) * width; + } + + if (part != ON_MODE_LINE && part != ON_HEADER_LINE) + gx += window_box_left_offset (w, area); + } + else + { + /* Use nominal line height at end of window. */ + gx = (x / width) * width; + y -= gy; + gy += (y / height) * height; + } + break; + + case ON_LEFT_FRINGE: + gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) + ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w) + : window_box_right_offset (w, LEFT_MARGIN_AREA)); + width = WINDOW_LEFT_FRINGE_WIDTH (w); + goto row_glyph; + + case ON_RIGHT_FRINGE: + gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) + ? window_box_right_offset (w, RIGHT_MARGIN_AREA) + : window_box_right_offset (w, TEXT_AREA)); + width = WINDOW_RIGHT_FRINGE_WIDTH (w); + goto row_glyph; + + case ON_SCROLL_BAR: + gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) + ? 0 + : (window_box_right_offset (w, RIGHT_MARGIN_AREA) + + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) + ? WINDOW_RIGHT_FRINGE_WIDTH (w) + : 0))); + width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); + + row_glyph: + gr = 0, gy = 0; + for (; r <= end_row && r->enabled_p; ++r) + if (r->y + r->height > y) + { + gr = r; gy = r->y; + break; + } + + if (gr && gy <= y) + height = gr->height; + else + { + /* Use nominal line height at end of window. */ + y -= gy; + gy += (y / height) * height; + } + break; + + default: + ; + virtual_glyph: + /* If there is no glyph under the mouse, then we divide the screen + into a grid of the smallest glyph in the frame, and use that + as our "glyph". */ + + /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to + round down even for negative values. */ + if (gx < 0) + gx -= width - 1; + if (gy < 0) + gy -= height - 1; + + gx = (gx / width) * width; + gy = (gy / height) * height; + + goto store_rect; + } + + gx += WINDOW_LEFT_EDGE_X (w); + gy += WINDOW_TOP_EDGE_Y (w); + + store_rect: + STORE_NATIVE_RECT (*rect, gx, gy, width, height); + + /* Visible feedback for debugging. */ +#if 0 +#if HAVE_X_WINDOWS + XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + f->output_data.x->normal_gc, + gx, gy, width, height); +#endif +#endif +} + #endif /* HAVE_WINDOW_SYSTEM */ @@ -2704,11 +2984,13 @@ handle_stop (it) struct it *it; { enum prop_handled handled; - int handle_overlay_change_p = 1; + int handle_overlay_change_p; struct props *p; it->dpvec = NULL; it->current.dpvec_index = -1; + handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p; + it->ignore_overlay_strings_at_pos_p = 0; /* Use face of preceding text for ellipsis (if invisible) */ if (it->selective_display_ellipsis_p) @@ -2902,6 +3184,9 @@ handle_fontified_prop (it) Lisp_Object prop, pos; enum prop_handled handled = HANDLED_NORMALLY; + if (!NILP (Vmemory_full)) + return handled; + /* Get the value of the `fontified' property at IT's current buffer position. (The `fontified' property doesn't have a special meaning in strings.) If the value is nil, call functions from @@ -3335,6 +3620,11 @@ handle_invisible_prop (it) skip starting with next_stop. */ if (invis_p) IT_CHARPOS (*it) = next_stop; + + /* If there are adjacent invisible texts, don't lose the + second one's ellipsis. */ + if (invis_p == 2) + display_ellipsis_p = 1; } while (invis_p); @@ -3355,7 +3645,26 @@ handle_invisible_prop (it) it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p; } else if (display_ellipsis_p) - setup_for_ellipsis (it, 0); + { + /* Make sure that the glyphs of the ellipsis will get + correct `charpos' values. If we would not update + it->position here, the glyphs would belong to the + last visible character _before_ the invisible + text, which confuses `set_cursor_from_row'. + + We use the last invisible position instead of the + first because this way the cursor is always drawn on + the first "." of the ellipsis, whenever PT is inside + the invisible text. Otherwise the cursor would be + placed _after_ the ellipsis when the point is after the + first invisible character. */ + if (!STRINGP (it->object)) + { + it->position.charpos = IT_CHARPOS (*it) - 1; + it->position.bytepos = CHAR_TO_BYTE (it->position.charpos); + } + setup_for_ellipsis (it, 0); + } } } @@ -3428,7 +3737,7 @@ handle_display_prop (it) } else { - object = it->w->buffer; + XSETWINDOW (object, it->w); position = &it->current.pos; } @@ -3449,6 +3758,9 @@ handle_display_prop (it) if (NILP (prop)) return HANDLED_NORMALLY; + if (!STRINGP (it->string)) + object = it->w->buffer; + if (CONSP (prop) /* Simple properties. */ && !EQ (XCAR (prop), Qimage) @@ -3866,7 +4178,7 @@ handle_single_display_spec (it, spec, object, position, { it->method = GET_FROM_STRETCH; it->object = value; - it->current.pos = it->position = start_pos; + *position = it->position = start_pos; } #ifdef HAVE_WINDOW_SYSTEM else @@ -4804,7 +5116,8 @@ reseat_at_next_visible_line_start (it, on_newline_p) && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it), (double) it->selective)) /* iftc */ { - xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); + xassert (IT_BYTEPOS (*it) == BEGV + || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); newline_found_p = forward_to_next_line_start (it, &skipped_p); } @@ -5025,6 +5338,10 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) = display element from the current position of IT. Value is zero if end of buffer (or C string) is reached. */ +static struct frame *last_escape_glyph_frame = NULL; +static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS); +static int last_escape_glyph_merged_face_id = 0; + int get_next_display_element (it) struct it *it; @@ -5141,11 +5458,19 @@ get_next_display_element (it) face_id = merge_faces (it->f, Qt, lface_id, it->face_id); } + else if (it->f == last_escape_glyph_frame + && it->face_id == last_escape_glyph_face_id) + { + face_id = last_escape_glyph_merged_face_id; + } else { /* Merge the escape-glyph face into the current face. */ face_id = merge_faces (it->f, Qescape_glyph, 0, it->face_id); + last_escape_glyph_frame = it->f; + last_escape_glyph_face_id = it->face_id; + last_escape_glyph_merged_face_id = face_id; } XSETINT (it->ctl_chars[0], g); @@ -5192,11 +5517,19 @@ get_next_display_element (it) face_id = merge_faces (it->f, Qt, lface_id, it->face_id); } + else if (it->f == last_escape_glyph_frame + && it->face_id == last_escape_glyph_face_id) + { + face_id = last_escape_glyph_merged_face_id; + } else { /* Merge the escape-glyph face into the current face. */ face_id = merge_faces (it->f, Qescape_glyph, 0, it->face_id); + last_escape_glyph_frame = it->f; + last_escape_glyph_face_id = it->face_id; + last_escape_glyph_merged_face_id = face_id; } /* Handle soft hyphens in the mode where they only get @@ -5390,6 +5723,8 @@ set_iterator_to_next (it, reseat_p) if (it->dpvec + it->current.dpvec_index == it->dpend) { + int recheck_faces = it->ellipsis_p; + if (it->s) it->method = GET_FROM_C_STRING; else if (STRINGP (it->string)) @@ -5405,12 +5740,16 @@ set_iterator_to_next (it, reseat_p) reseat_at_next_visible_line_start (it, 1); else if (it->dpvec_char_len > 0) { + if (it->method == GET_FROM_STRING + && it->n_overlay_strings > 0) + it->ignore_overlay_strings_at_pos_p = 1; it->len = it->dpvec_char_len; set_iterator_to_next (it, reseat_p); } - /* Recheck faces after display vector */ - it->stop_charpos = IT_CHARPOS (*it); + /* Maybe recheck faces after display vector */ + if (recheck_faces) + it->stop_charpos = IT_CHARPOS (*it); } break; @@ -6522,6 +6861,7 @@ move_it_vertically (it, dy) /* If buffer ends in ZV without a newline, move to the start of the line to satisfy the post-condition. */ if (IT_CHARPOS (*it) == ZV + && ZV > BEGV && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n') move_it_by_lines (it, 0, 0); } @@ -6747,7 +7087,10 @@ message_log_maybe_newline () terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if nonzero, means interpret the contents of M as multibyte. This function calls low-level routines in order to bypass text property - hooks, etc. which might not be safe to run. */ + hooks, etc. which might not be safe to run. + + This may GC (insert may run before/after change hooks), + so the buffer M must NOT point to a Lisp string. */ void message_dolog (m, nbytes, nlflag, multibyte) @@ -6958,10 +7301,7 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte) out any existing message, and let the mini-buffer text show through. - The buffer M must continue to exist until after the echo area gets - cleared or some other message gets displayed there. This means do - not pass text that is stored in a Lisp string; do not pass text in - a buffer that was alloca'd. */ + This may GC, so the buffer M must NOT point to a Lisp string. */ void message2 (m, nbytes, multibyte) @@ -7058,7 +7398,15 @@ message3 (m, nbytes, multibyte) /* First flush out any partial line written with print. */ message_log_maybe_newline (); if (STRINGP (m)) - message_dolog (SDATA (m), nbytes, 1, multibyte); + { + char *buffer; + USE_SAFE_ALLOCA; + + SAFE_ALLOCA (buffer, char *, nbytes); + bcopy (SDATA (m), buffer, nbytes); + message_dolog (buffer, nbytes, 1, multibyte); + SAFE_FREE (); + } message3_nolog (m, nbytes, multibyte); UNGCPRO; @@ -8010,7 +8358,11 @@ truncate_message_1 (nchars, a2, a3, a4) If S is not null, set the message to the first LEN bytes of S. LEN zero means use the whole string. MULTIBYTE_P non-zero means S is - multibyte. Display the message multibyte in that case. */ + multibyte. Display the message multibyte in that case. + + Doesn't GC, as with_echo_area_buffer binds Qinhibit_modification_hooks + to t before calling set_message_1 (which calls insert). + */ void set_message (s, string, nbytes, multibyte_p) @@ -8325,7 +8677,7 @@ static Lisp_Object mode_line_string_face_prop; static Lisp_Object Vmode_line_unwind_vector; static Lisp_Object -format_mode_line_unwind_data (obuf) +format_mode_line_unwind_data (obuf, save_proptrans) struct buffer *obuf; { Lisp_Object vector; @@ -8341,7 +8693,7 @@ format_mode_line_unwind_data (obuf) AREF (vector, 0) = make_number (mode_line_target); AREF (vector, 1) = make_number (MODE_LINE_NOPROP_LEN (0)); AREF (vector, 2) = mode_line_string_list; - AREF (vector, 3) = mode_line_proptrans_alist; + AREF (vector, 3) = (save_proptrans ? mode_line_proptrans_alist : Qt); AREF (vector, 4) = mode_line_string_face; AREF (vector, 5) = mode_line_string_face_prop; @@ -8360,7 +8712,8 @@ unwind_format_mode_line (vector) mode_line_target = XINT (AREF (vector, 0)); mode_line_noprop_ptr = mode_line_noprop_buf + XINT (AREF (vector, 1)); mode_line_string_list = AREF (vector, 2); - mode_line_proptrans_alist = AREF (vector, 3); + if (! EQ (AREF (vector, 3), Qt)) + mode_line_proptrans_alist = AREF (vector, 3); mode_line_string_face = AREF (vector, 4); mode_line_string_face_prop = AREF (vector, 5); @@ -8483,7 +8836,7 @@ x_consider_frame_title (frame) mode_line_target so that display_mode_element will output into mode_line_noprop_buf; then display the title. */ record_unwind_protect (unwind_format_mode_line, - format_mode_line_unwind_data (current_buffer)); + format_mode_line_unwind_data (current_buffer, 0)); set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer)); fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; @@ -8708,14 +9061,15 @@ update_menu_bar (f, save_match_data) /* Redisplay the menu bar in case we changed it. */ #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ || defined (USE_GTK) - if (FRAME_WINDOW_P (f) -#if defined (MAC_OS) - /* All frames on Mac OS share the same menubar. So only the - selected frame should be allowed to set it. */ - && f == SELECTED_FRAME () + if (FRAME_WINDOW_P (f)) + { +#ifdef MAC_OS + /* All frames on Mac OS share the same menubar. So only + the selected frame should be allowed to set it. */ + if (f == SELECTED_FRAME ()) #endif - ) - set_frame_menubar (f, 0, 0); + set_frame_menubar (f, 0, 0); + } else /* On a terminal screen, the menu bar is an ordinary screen line, and this makes it get updated. */ @@ -9079,11 +9433,17 @@ build_desired_tool_bar_string (f) } -/* Display one line of the tool-bar of frame IT->f. */ +/* Display one line of the tool-bar of frame IT->f. + + HEIGHT specifies the desired height of the tool-bar line. + If the actual height of the glyph row is less than HEIGHT, the + row's height is increased to HEIGHT, and the icons are centered + vertically in the new height. */ static void -display_tool_bar_line (it) +display_tool_bar_line (it, height) struct it *it; + int height; { struct glyph_row *row = it->glyph_row; int max_x = it->last_visible_x; @@ -9139,11 +9499,22 @@ display_tool_bar_line (it) out:; row->displays_text_p = row->used[TEXT_AREA] != 0; + /* Use default face for the border below the tool bar. */ + if (!row->displays_text_p) + it->face_id = DEFAULT_FACE_ID; extend_face_to_end_of_line (it); last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1; last->right_box_line_p = 1; if (last == row->glyphs[TEXT_AREA]) last->left_box_line_p = 1; + + /* Make line the desired height and center it vertically. */ + if ((height -= it->max_ascent + it->max_descent) > 0) + { + it->max_ascent += height / 2; + it->max_descent += (height + 1) / 2; + } + compute_line_metrics (it); /* If line is empty, make it occupy the rest of the tool-bar. */ @@ -9167,11 +9538,13 @@ display_tool_bar_line (it) /* Value is the number of screen lines needed to make all tool-bar - items of frame F visible. */ + items of frame F visible. The number of actual rows needed is + returned in *N_ROWS if non-NULL. */ static int -tool_bar_lines_needed (f) +tool_bar_lines_needed (f, n_rows) struct frame *f; + int *n_rows; { struct window *w = XWINDOW (f->tool_bar_window); struct it it; @@ -9187,9 +9560,12 @@ tool_bar_lines_needed (f) { it.glyph_row = w->desired_matrix->rows; clear_glyph_row (it.glyph_row); - display_tool_bar_line (&it); + display_tool_bar_line (&it, 0); } + if (n_rows) + *n_rows = it.vpos; + return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f); } @@ -9218,7 +9594,7 @@ DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed, if (f->n_tool_bar_items) { build_desired_tool_bar_string (f); - nlines = tool_bar_lines_needed (f); + nlines = tool_bar_lines_needed (f, NULL); } } @@ -9263,9 +9639,50 @@ redisplay_tool_bar (f) build_desired_tool_bar_string (f); reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); + if (f->n_tool_bar_rows == 0) + { + (void)tool_bar_lines_needed (f, &f->n_tool_bar_rows); + if (f->n_tool_bar_rows == 0) + f->n_tool_bar_rows = -1; + } + /* Display as many lines as needed to display all tool-bar items. */ - while (it.current_y < it.last_visible_y) - display_tool_bar_line (&it); + + if (f->n_tool_bar_rows > 0) + { + int border, rows, height, extra; + + if (INTEGERP (Vtool_bar_border)) + border = XINT (Vtool_bar_border); + else if (EQ (Vtool_bar_border, Qinternal_border_width)) + border = FRAME_INTERNAL_BORDER_WIDTH (f); + else if (EQ (Vtool_bar_border, Qborder_width)) + border = f->border_width; + else + border = 0; + if (border < 0) + border = 0; + + rows = f->n_tool_bar_rows; + height = (it.last_visible_y - border) / rows; + extra = it.last_visible_y - border - height * rows; + + while (it.current_y < it.last_visible_y) + { + int h = 0; + if (extra > 0 && rows-- > 0) + { + h = (extra + rows - 1) / rows; + extra -= h; + } + display_tool_bar_line (&it, height + h); + } + } + else + { + while (it.current_y < it.last_visible_y) + display_tool_bar_line (&it, 0); + } /* It doesn't make much sense to try scrolling in the tool-bar window, so don't do it. */ @@ -9298,7 +9715,7 @@ redisplay_tool_bar (f) /* Resize windows as needed by changing the `tool-bar-lines' frame parameter. */ if (change_height_p - && (nlines = tool_bar_lines_needed (f), + && (nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows), nlines != WINDOW_TOTAL_LINES (w))) { extern Lisp_Object Qtool_bar_lines; @@ -10006,12 +10423,14 @@ overlay_arrow_at_row (it, row) if (FRAME_WINDOW_P (it->f) && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0) { +#ifdef HAVE_WINDOW_SYSTEM if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val)) { int fringe_bitmap; if ((fringe_bitmap = lookup_fringe_bitmap (val)) != 0) return make_number (fringe_bitmap); } +#endif return make_number (-1); /* Use default arrow bitmap */ } return overlay_arrow_string_or_property (var); @@ -10222,6 +10641,8 @@ redisplay_internal (preserve_echo_area) retry: pause = 0; reconsider_clip_changes (w, current_buffer); + last_escape_glyph_frame = NULL; + last_escape_glyph_face_id = (1 << FACE_ID_BITS); /* If new fonts have been loaded that make a glyph matrix adjustment necessary, do it. */ @@ -10278,7 +10699,8 @@ redisplay_internal (preserve_echo_area) clear_garbaged_frames (); /* Build menubar and tool-bar items. */ - prepare_menu_bars (); + if (NILP (Vmemory_full)) + prepare_menu_bars (); if (windows_or_buffers_changed) update_mode_lines++; @@ -10612,13 +11034,9 @@ redisplay_internal (preserve_echo_area) if (consider_all_windows_p) { Lisp_Object tail, frame; - int i, n = 0, size = 5; - struct frame **updated; FOR_EACH_FRAME (tail, frame) - size++; - - updated = (struct frame **) alloca (size * sizeof *updated); + XFRAME (frame)->updated_p = 0; /* Recompute # windows showing selected buffer. This will be incremented each time such a window is displayed. */ @@ -10680,15 +11098,7 @@ redisplay_internal (preserve_echo_area) break; #endif - if (n == size) - { - int nbytes = size * sizeof *updated; - struct frame **p = (struct frame **) alloca (2 * nbytes); - bcopy (updated, p, nbytes); - size *= 2; - } - - updated[n++] = f; + f->updated_p = 1; } } } @@ -10698,12 +11108,15 @@ redisplay_internal (preserve_echo_area) /* Do the mark_window_display_accurate after all windows have been redisplayed because this call resets flags in buffers which are needed for proper redisplay. */ - for (i = 0; i < n; ++i) + FOR_EACH_FRAME (tail, frame) { - struct frame *f = updated[i]; - mark_window_display_accurate (f->root_window, 1); - if (frame_up_to_date_hook) - frame_up_to_date_hook (f); + struct frame *f = XFRAME (frame); + if (f->updated_p) + { + mark_window_display_accurate (f->root_window, 1); + if (frame_up_to_date_hook) + frame_up_to_date_hook (f); + } } } } @@ -11365,6 +11778,7 @@ static int cursor_row_fully_visible_p (w, force_p, current_matrix_p) struct window *w; int force_p; + int current_matrix_p; { struct glyph_matrix *matrix; struct glyph_row *row; @@ -12837,7 +13251,8 @@ try_window (window, pos, check_margins) this_scroll_margin *= FRAME_LINE_HEIGHT (it.f); if ((w->cursor.y < this_scroll_margin - && CHARPOS (pos) > BEGV) + && CHARPOS (pos) > BEGV + && IT_CHARPOS (it) < ZV) /* rms: considering make_cursor_line_fully_visible_p here seems to give wrong results. We don't want to recenter when the last line is partly visible, we want to allow @@ -13085,7 +13500,7 @@ try_window_reusing_current_matrix (w) /* Disable lines in the current matrix which are now below the window. */ for (++row; row < bottom_row; ++row) - row->enabled_p = 0; + row->enabled_p = row->mode_line_p = 0; } /* Update window_end_pos etc.; last_reused_text_row is the last @@ -15388,7 +15803,9 @@ display_line (it) produce_special_glyphs (it, IT_CONTINUATION); row->continued_p = 1; + it->current_x = x_before; it->continuation_lines_width += x; + extend_face_to_end_of_line (it); if (nglyphs > 1 && i > 0) { @@ -15873,7 +16290,7 @@ display_mode_line (w, face_id, format) it.base_face_id = it.face_id = DEFAULT_FACE_ID; record_unwind_protect (unwind_format_mode_line, - format_mode_line_unwind_data (NULL)); + format_mode_line_unwind_data (NULL, 0)); mode_line_target = MODE_LINE_DISPLAY; @@ -15908,6 +16325,44 @@ display_mode_line (w, face_id, format) return it.glyph_row->height; } +/* Move element ELT in LIST to the front of LIST. + Return the updated list. */ + +static Lisp_Object +move_elt_to_front (elt, list) + Lisp_Object elt, list; +{ + register Lisp_Object tail, prev; + register Lisp_Object tem; + + tail = list; + prev = Qnil; + while (CONSP (tail)) + { + tem = XCAR (tail); + + if (EQ (elt, tem)) + { + /* Splice out the link TAIL. */ + if (NILP (prev)) + list = XCDR (tail); + else + Fsetcdr (prev, XCDR (tail)); + + /* Now make it the first. */ + Fsetcdr (tail, list); + return tail; + } + else + prev = tail; + tail = XCDR (tail); + QUIT; + } + + /* Not found--return unchanged LIST. */ + return list; +} + /* Contribute ELT to the mode line for window IT->w. How it translates into text depends on its data type. @@ -15955,9 +16410,10 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) { /* A string: output it and check for %-constructs within it. */ unsigned char c; - const unsigned char *this, *lisp_string; + int offset = 0; - if (!NILP (props) || risky) + if (SCHARS (elt) > 0 + && (!NILP (props) || risky)) { Lisp_Object oprops, aelt; oprops = Ftext_properties_at (make_number (0), elt); @@ -15988,14 +16444,22 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) aelt = Fassoc (elt, mode_line_proptrans_alist); if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt)))) { - mode_line_proptrans_alist - = Fcons (aelt, Fdelq (aelt, mode_line_proptrans_alist)); + /* AELT is what we want. Move it to the front + without consing. */ elt = XCAR (aelt); + mode_line_proptrans_alist + = move_elt_to_front (aelt, mode_line_proptrans_alist); } else { Lisp_Object tem; + /* If AELT has the wrong props, it is useless. + so get rid of it. */ + if (! NILP (aelt)) + mode_line_proptrans_alist + = Fdelq (aelt, mode_line_proptrans_alist); + elt = Fcopy_sequence (elt); Fset_text_properties (make_number (0), Flength (elt), props, elt); @@ -16013,8 +16477,7 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) } } - this = SDATA (elt); - lisp_string = this; + offset = 0; if (literal) { @@ -16037,42 +16500,44 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) break; } + /* Handle the non-literal case. */ + while ((precision <= 0 || n < precision) - && *this + && SREF (elt, offset) != 0 && (mode_line_target != MODE_LINE_DISPLAY || it->current_x < it->last_visible_x)) { - const unsigned char *last = this; + int last_offset = offset; /* Advance to end of string or next format specifier. */ - while ((c = *this++) != '\0' && c != '%') + while ((c = SREF (elt, offset++)) != '\0' && c != '%') ; - if (this - 1 != last) + if (offset - 1 != last_offset) { int nchars, nbytes; /* Output to end of string or up to '%'. Field width is length of string. Don't output more than PRECISION allows us. */ - --this; + offset--; - prec = c_string_width (last, this - last, precision - n, + prec = c_string_width (SDATA (elt) + last_offset, + offset - last_offset, precision - n, &nchars, &nbytes); switch (mode_line_target) { case MODE_LINE_NOPROP: case MODE_LINE_TITLE: - n += store_mode_line_noprop (last, 0, prec); + n += store_mode_line_noprop (SDATA (elt) + last_offset, 0, prec); break; case MODE_LINE_STRING: { - int bytepos = last - lisp_string; + int bytepos = last_offset; int charpos = string_byte_to_char (elt, bytepos); int endpos = (precision <= 0 - ? string_byte_to_char (elt, - this - lisp_string) + ? string_byte_to_char (elt, offset) : charpos + nchars); n += store_mode_line_string (NULL, @@ -16083,10 +16548,13 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) break; case MODE_LINE_DISPLAY: { - int bytepos = last - lisp_string; + int bytepos = last_offset; int charpos = string_byte_to_char (elt, bytepos); + + if (precision <= 0) + nchars = string_byte_to_char (elt, offset) - charpos; n += display_string (NULL, elt, Qnil, 0, charpos, - it, 0, prec, 0, + it, 0, nchars, 0, STRING_MULTIBYTE (elt)); } break; @@ -16094,12 +16562,12 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) } else /* c == '%' */ { - const unsigned char *percent_position = this; + int percent_position = offset; /* Get the specified minimum width. Zero means don't pad. */ field = 0; - while ((c = *this++) >= '0' && c <= '9') + while ((c = SREF (elt, offset++)) >= '0' && c <= '9') field = field * 10 + c - '0'; /* Don't pad beyond the total padding allowed. */ @@ -16119,7 +16587,7 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) int bytepos, charpos; unsigned char *spec; - bytepos = percent_position - lisp_string; + bytepos = percent_position; charpos = (STRING_MULTIBYTE (elt) ? string_byte_to_char (elt, bytepos) : bytepos); @@ -16519,8 +16987,11 @@ are the selected window and the window's buffer). */) if (XBUFFER (buffer) != current_buffer) old_buffer = current_buffer; + /* Save things including mode_line_proptrans_alist, + and set that to nil so that we don't alter the outer value. */ record_unwind_protect (unwind_format_mode_line, - format_mode_line_unwind_data (old_buffer)); + format_mode_line_unwind_data (old_buffer, 1)); + mode_line_proptrans_alist = Qnil; if (old_buffer) set_buffer_internal_1 (XBUFFER (buffer)); @@ -16905,6 +17376,18 @@ decode_mode_spec (w, c, field_width, precision, multibyte) return decode_mode_spec_buf; } + case 'e': +#ifndef SYSTEM_MALLOC + { + if (NILP (Vmemory_full)) + return ""; + else + return "!MEM FULL! "; + } +#else + return ""; +#endif + case 'F': /* %F displays the frame name. */ if (!NILP (f->title)) @@ -17320,7 +17803,7 @@ display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr) display them, and < 0 means obey the current buffer's value of enable_multibyte_characters. - Value is the number of glyphs produced. */ + Value is the number of columns displayed. */ static int display_string (string, lisp_string, face_string, face_string_pos, @@ -18010,22 +18493,23 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p) FACES is an array of faces for all components of this composition. S->gidx is the index of the first component for S. - OVERLAPS_P non-zero means S should draw the foreground only, and - use its physical height for clipping. + + OVERLAPS non-zero means S should draw the foreground only, and use + its physical height for clipping. See also draw_glyphs. Value is the index of a component not in S. */ static int -fill_composite_glyph_string (s, faces, overlaps_p) +fill_composite_glyph_string (s, faces, overlaps) struct glyph_string *s; struct face **faces; - int overlaps_p; + int overlaps; { int i; xassert (s); - s->for_overlaps_p = overlaps_p; + s->for_overlaps = overlaps; s->face = faces[s->gidx]; s->font = s->face->font; @@ -18069,16 +18553,16 @@ fill_composite_glyph_string (s, faces, overlaps_p) FACE_ID is the face id of the string. START is the index of the first glyph to consider, END is the index of the last + 1. - OVERLAPS_P non-zero means S should draw the foreground only, and - use its physical height for clipping. + OVERLAPS non-zero means S should draw the foreground only, and use + its physical height for clipping. See also draw_glyphs. Value is the index of the first glyph not in S. */ static int -fill_glyph_string (s, face_id, start, end, overlaps_p) +fill_glyph_string (s, face_id, start, end, overlaps) struct glyph_string *s; int face_id; - int start, end, overlaps_p; + int start, end, overlaps; { struct glyph *glyph, *last; int voffset; @@ -18088,7 +18572,7 @@ fill_glyph_string (s, face_id, start, end, overlaps_p) xassert (s->nchars == 0); xassert (start >= 0 && end > start); - s->for_overlaps_p = overlaps_p, + s->for_overlaps = overlaps, glyph = s->row->glyphs[s->area] + start; last = s->row->glyphs[s->area] + end; voffset = glyph->voffset; @@ -18423,19 +18907,15 @@ set_glyph_string_background_width (s, start, last_x) { /* If the face of this glyph string has to be drawn to the end of the drawing area, set S->extends_to_end_of_line_p. */ - struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID); if (start == s->row->used[s->area] && s->area == TEXT_AREA - && ((s->hl == DRAW_NORMAL_TEXT - && (s->row->fill_line_p - || s->face->background != default_face->background - || s->face->stipple != default_face->stipple - || s->row->mouse_face_p)) - || s->hl == DRAW_MOUSE_FACE - || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) - && s->row->fill_line_p))) - s->extends_to_end_of_line_p = 1; + && ((s->row->fill_line_p + && (s->hl == DRAW_NORMAL_TEXT + || s->hl == DRAW_IMAGE_RAISED + || s->hl == DRAW_IMAGE_SUNKEN)) + || s->hl == DRAW_MOUSE_FACE)) + s->extends_to_end_of_line_p = 1; /* If S extends its face to the end of the line, set its background_width to the distance to the right edge of the drawing @@ -18565,7 +19045,7 @@ compute_overhangs_and_x (s, x, backward_p) INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ append_glyph_string (&HEAD, &TAIL, s); \ s->x = (X); \ - START = fill_glyph_string (s, face_id, START, END, overlaps_p); \ + START = fill_glyph_string (s, face_id, START, END, overlaps); \ } \ while (0) @@ -18618,7 +19098,7 @@ compute_overhangs_and_x (s, x, backward_p) if (n == 0) \ first_s = s; \ \ - n = fill_composite_glyph_string (s, faces, overlaps_p); \ + n = fill_composite_glyph_string (s, faces, overlaps); \ } \ \ ++START; \ @@ -18687,20 +19167,26 @@ compute_overhangs_and_x (s, x, backward_p) DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it DRAW_IMAGE_RAISED draw an image with a raised relief around it - If OVERLAPS_P is non-zero, draw only the foreground of characters - and clip to the physical height of ROW. + If OVERLAPS is non-zero, draw only the foreground of characters and + clip to the physical height of ROW. Non-zero value also defines + the overlapping part to be drawn: + + OVERLAPS_PRED overlap with preceding rows + OVERLAPS_SUCC overlap with succeeding rows + OVERLAPS_BOTH overlap with both preceding/succeeding rows + OVERLAPS_ERASED_CURSOR overlap with erased cursor area Value is the x-position reached, relative to AREA of W. */ static int -draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) +draw_glyphs (w, x, row, area, start, end, hl, overlaps) struct window *w; int x; struct glyph_row *row; enum glyph_row_area area; int start, end; enum draw_glyphs_face hl; - int overlaps_p; + int overlaps; { struct glyph_string *head, *tail; struct glyph_string *s; @@ -18749,7 +19235,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) /* If there are any glyphs with lbearing < 0 or rbearing > width in the row, redraw some glyphs in front or following the glyph strings built above. */ - if (head && !overlaps_p && row->contains_overlapping_glyphs_p) + if (head && !overlaps && row->contains_overlapping_glyphs_p) { int dummy_x = 0; struct glyph_string *h, *t; @@ -18842,7 +19328,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) /* When drawing overlapping rows, only the glyph strings' foreground is drawn, which doesn't erase a cursor completely. */ - && !overlaps_p) + && !overlaps) { int x0 = clip_head ? clip_head->x : (head ? head->x : x); int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width @@ -19307,6 +19793,10 @@ produce_stretch_glyph (it) else ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font); + if (width > 0 && !it->truncate_lines_p + && it->current_x + width > it->last_visible_x) + width = it->last_visible_x - it->current_x - 1; + if (width > 0 && height > 0 && it->glyph_row) { Lisp_Object object = it->stack[it->sp - 1].string; @@ -19447,8 +19937,8 @@ calc_line_height_property (it, val, font, boff, override) /* RIF: Produce glyphs/get display metrics for the display element IT is - loaded with. See the description of struct display_iterator in - dispextern.h for an overview of struct display_iterator. */ + loaded with. See the description of struct it in dispextern.h + for an overview of struct it. */ void x_produce_glyphs (it) @@ -20408,8 +20898,13 @@ get_window_cursor_type (w, glyph, width, active_cursor) { if (w == XWINDOW (echo_area_window)) { - *width = FRAME_CURSOR_WIDTH (f); - return FRAME_DESIRED_CURSOR (f); + if (EQ (b->cursor_type, Qt) || NILP (b->cursor_type)) + { + *width = FRAME_CURSOR_WIDTH (f); + return FRAME_DESIRED_CURSOR (f); + } + else + return get_specified_cursor_type (b->cursor_type, width); } *active_cursor = 0; @@ -20438,7 +20933,7 @@ get_window_cursor_type (w, glyph, width, active_cursor) /* Use cursor-in-non-selected-windows for non-selected window or frame. */ if (non_selected) { - alt_cursor = XBUFFER (w->buffer)->cursor_in_non_selected_windows; + alt_cursor = b->cursor_in_non_selected_windows; return get_specified_cursor_type (alt_cursor, width); } @@ -20575,13 +21070,15 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1) #ifdef HAVE_WINDOW_SYSTEM /* EXPORT for RIF: - Fix the display of area AREA of overlapping row ROW in window W. */ + Fix the display of area AREA of overlapping row ROW in window W + with respect to the overlapping part OVERLAPS. */ void -x_fix_overlapping_area (w, row, area) +x_fix_overlapping_area (w, row, area, overlaps) struct window *w; struct glyph_row *row; enum glyph_row_area area; + int overlaps; { int i, x; @@ -20604,7 +21101,7 @@ x_fix_overlapping_area (w, row, area) draw_glyphs (w, start_x, row, area, start, i, - DRAW_NORMAL_TEXT, 1); + DRAW_NORMAL_TEXT, overlaps); } else { @@ -20646,13 +21143,17 @@ draw_phys_cursor_glyph (w, row, hl) are redrawn. */ else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p) { + w->phys_cursor_width = x1 - w->phys_cursor.x; + if (row > w->current_matrix->rows && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1)) - x_fix_overlapping_area (w, row - 1, TEXT_AREA); + x_fix_overlapping_area (w, row - 1, TEXT_AREA, + OVERLAPS_ERASED_CURSOR); if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w) && MATRIX_ROW_OVERLAPS_PRED_P (row + 1)) - x_fix_overlapping_area (w, row + 1, TEXT_AREA); + x_fix_overlapping_area (w, row + 1, TEXT_AREA, + OVERLAPS_ERASED_CURSOR); } } } @@ -20967,7 +21468,11 @@ show_mouse_face (dpyinfo, draw) if (row == last) end_hpos = dpyinfo->mouse_face_end_col; else - end_hpos = row->used[TEXT_AREA]; + { + end_hpos = row->used[TEXT_AREA]; + if (draw == DRAW_NORMAL_TEXT) + row->fill_line_p = 1; /* Clear to end of line */ + } if (end_hpos > start_hpos) { @@ -22443,13 +22948,13 @@ expose_overlaps (w, first_overlapping_row, last_overlapping_row) xassert (row->enabled_p && !row->mode_line_p); if (row->used[LEFT_MARGIN_AREA]) - x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA); + x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH); if (row->used[TEXT_AREA]) - x_fix_overlapping_area (w, row, TEXT_AREA); + x_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH); if (row->used[RIGHT_MARGIN_AREA]) - x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA); + x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH); } } @@ -23209,6 +23714,14 @@ otherwise. */); doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible. */); make_cursor_line_fully_visible_p = 1; + DEFVAR_LISP ("tool-bar-border", &Vtool_bar_border, + doc: /* *Border below tool-bar in pixels. +If an integer, use it as the height of the border. +If it is one of `internal-border-width' or `border-width', use the +value of the corresponding frame parameter. +Otherwise, no border is added below the tool-bar. */); + Vtool_bar_border = Qinternal_border_width; + DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin, doc: /* *Margin around tool-bar buttons in pixels. If an integer, use that for both horizontal and vertical margins. @@ -23258,7 +23771,11 @@ go back to their normal size. */); Each element has the form (ON-STATE . OFF-STATE). Whenever the `cursor-type' frame-parameter or variable equals ON-STATE, comparing using `equal', Emacs uses OFF-STATE to specify -how to blink it off. */); +how to blink it off. ON-STATE and OFF-STATE are values for +the `cursor-type' frame parameter. + +If a frame's ON-STATE has no entry in this list, +the frame's other specifications determine how to blink the cursor off. */); Vblink_cursor_alist = Qnil; DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,