X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/308a74d8bdbc608748114c5fa35b2bc1f13a663d..018ba359ab456f6a43f3acea0c15df616aa0ad02:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 91b2a5e8a6..08a378e689 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -169,6 +169,7 @@ Boston, MA 02111-1307, USA. */ #include #include +#define DOC_STRINGS_IN_COMMENTS #include "lisp.h" #include "keyboard.h" #include "frame.h" @@ -198,9 +199,6 @@ Boston, MA 02111-1307, USA. */ #include "macterm.h" #endif -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define max(a, b) ((a) > (b) ? (a) : (b)) - #define INFINITY 10000000 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh) @@ -227,6 +225,7 @@ Lisp_Object QCeval, Qwhen, QCfile, QCdata; Lisp_Object Qfontified; Lisp_Object Qgrow_only; Lisp_Object Qinhibit_eval_during_redisplay; +Lisp_Object Qbuffer_position, Qposition, Qobject; /* Functions called to fontify regions of text. */ @@ -510,6 +509,11 @@ Lisp_Object Vmax_mini_window_height; int message_truncate_lines; Lisp_Object Qmessage_truncate_lines; +/* Set to 1 in clear_message to make redisplay_internal aware + of an emptied echo area. */ + +static int message_cleared_p; + /* Non-zero means we want a hollow cursor in windows that are not selected. Zero means there's no cursor in such windows. */ @@ -680,9 +684,6 @@ static void handle_stop P_ ((struct it *)); static int tool_bar_lines_needed P_ ((struct frame *)); static int single_display_prop_intangible_p P_ ((Lisp_Object)); static void ensure_echo_area_buffers P_ ((void)); -static struct glyph_row *row_containing_pos P_ ((struct window *, int, - struct glyph_row *, - struct glyph_row *)); static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object)); static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *)); static int with_echo_area_buffer P_ ((struct window *, int, @@ -705,13 +706,11 @@ static void insert_left_trunc_glyphs P_ ((struct it *)); static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *)); static void extend_face_to_end_of_line P_ ((struct it *)); static int append_space P_ ((struct it *, int)); -static void make_cursor_line_fully_visible P_ ((struct window *)); +static int make_cursor_line_fully_visible P_ ((struct window *)); static int try_scrolling P_ ((Lisp_Object, int, int, int, int)); static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *)); static int trailing_whitespace_p P_ ((int)); static int message_log_check_duplicate P_ ((int, int, int, int)); -int invisible_p P_ ((Lisp_Object, Lisp_Object)); -int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object)); static void push_it P_ ((struct it *)); static void pop_it P_ ((struct it *)); static void sync_frame_with_window_matrix_rows P_ ((struct window *)); @@ -726,7 +725,7 @@ static int display_line P_ ((struct it *)); static int display_mode_lines P_ ((struct window *)); static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object)); static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object)); -static char *decode_mode_spec P_ ((struct window *, int, int, int)); +static char *decode_mode_spec P_ ((struct window *, int, int, int, int *)); static void display_menu_bar P_ ((struct window *)); static int display_count_lines P_ ((int, int, int, int, int *)); static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object, @@ -748,8 +747,8 @@ static int next_element_from_composition P_ ((struct it *)); static int next_element_from_image P_ ((struct it *)); static int next_element_from_stretch P_ ((struct it *)); static void load_overlay_strings P_ ((struct it *, int)); -static void init_from_display_pos P_ ((struct it *, struct window *, - struct display_pos *)); +static int init_from_display_pos P_ ((struct it *, struct window *, + struct display_pos *)); static void reseat_to_string P_ ((struct it *, unsigned char *, Lisp_Object, int, int, int, int)); static enum move_it_result move_it_in_display_line_to P_ ((struct it *, @@ -757,8 +756,8 @@ static enum move_it_result move_it_in_display_line_to P_ ((struct it *, void move_it_vertically_backward P_ ((struct it *, int)); static void init_to_row_start P_ ((struct it *, struct window *, struct glyph_row *)); -static void init_to_row_end P_ ((struct it *, struct window *, - struct glyph_row *)); +static int init_to_row_end P_ ((struct it *, struct window *, + struct glyph_row *)); static void back_to_previous_line_start P_ ((struct it *)); static int forward_to_next_line_start P_ ((struct it *, int *)); static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos, @@ -1429,7 +1428,7 @@ check_window_end (w) at character position CHARPOS. CHARPOS < 0 means that no buffer position is specified which is useful when the iterator is assigned a position later. BYTEPOS is the byte position corresponding to - CHARPOS. BYTEPOS <= 0 means compute it from CHARPOS. + CHARPOS. BYTEPOS < 0 means compute it from CHARPOS. If ROW is not null, calls to produce_glyphs with IT as parameter will produce glyphs in that row. @@ -1455,7 +1454,8 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) /* Some precondition checks. */ xassert (w != NULL && it != NULL); - xassert (charpos < 0 || (charpos > 0 && charpos <= ZV)); + xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer) + && charpos <= ZV)); /* If face attributes have been changed since the last redisplay, free realized faces now because they depend on face definitions @@ -1535,7 +1535,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) /* Non-zero if we should highlight the region. */ highlight_region_p - = (!NILP (Vtransient_mark_mode) + = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active) && XMARKER (current_buffer->mark)->buffer != 0); @@ -1672,14 +1672,14 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) /* If a buffer position was specified, set the iterator there, getting overlays and face properties from that position. */ - if (charpos > 0) + if (charpos >= BUF_BEG (current_buffer)) { it->end_charpos = ZV; it->face_id = -1; IT_CHARPOS (*it) = charpos; /* Compute byte position if not specified. */ - if (bytepos <= 0) + if (bytepos < charpos) IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos); else IT_BYTEPOS (*it) = bytepos; @@ -1700,36 +1700,32 @@ start_display (it, w, pos) struct window *w; struct text_pos pos; { - int start_at_line_beg_p; struct glyph_row *row; int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0; - int first_y; row = w->desired_matrix->rows + first_vpos; init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID); - first_y = it->current_y; - - /* If window start is not at a line start, move back to the line - start. This makes sure that we take continuation lines into - account. */ - start_at_line_beg_p = (CHARPOS (pos) == BEGV - || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n'); - if (!start_at_line_beg_p) - reseat_at_previous_visible_line_start (it); - - /* If window start is not at a line start, skip forward to POS to - get the correct continuation_lines_width and current_x. */ - if (!start_at_line_beg_p) - { - move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS); - - /* If lines are continued, this line may end in the middle of a - multi-glyph character (e.g. a control character displayed as - \003, or in the middle of an overlay string). In this case - move_it_to above will not have taken us to the start of - the continuation line but to the end of the continued line. */ - if (!it->truncate_lines_p) + + if (!it->truncate_lines_p) + { + int start_at_line_beg_p; + int first_y = it->current_y; + + /* If window start is not at a line start, skip forward to POS to + get the correct continuation lines width. */ + start_at_line_beg_p = (CHARPOS (pos) == BEGV + || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n'); + if (!start_at_line_beg_p) { + reseat_at_previous_visible_line_start (it); + move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS); + + /* If lines are continued, this line may end in the middle + of a multi-glyph character (e.g. a control character + displayed as \003, or in the middle of an overlay + string). In this case move_it_to above will not have + taken us to the start of the continuation line but to the + end of the continued line. */ if (it->current_x > 0) { if (it->current.dpvec_index >= 0 @@ -1738,7 +1734,7 @@ start_display (it, w, pos) set_iterator_to_next (it, 1); move_it_in_display_line_to (it, -1, -1, 0); } - + it->continuation_lines_width += it->current_x; } @@ -1747,11 +1743,11 @@ start_display (it, w, pos) fields in the iterator structure. */ it->max_ascent = it->max_descent = 0; it->max_phys_ascent = it->max_phys_descent = 0; - } - it->current_y = first_y; - it->vpos = 0; - it->current_x = it->hpos = 0; + it->current_y = first_y; + it->vpos = 0; + it->current_x = it->hpos = 0; + } } #if 0 /* Don't assert the following because start_display is sometimes @@ -1793,9 +1789,7 @@ in_ellipses_for_invisible_text_p (pos, w) { prop = Fget_char_property (make_number (charpos - 1), Qinvisible, window); - if (TEXT_PROP_MEANS_INVISIBLE (prop) - && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop)) - ellipses_p = 1; + ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop); } return ellipses_p; @@ -1804,15 +1798,17 @@ in_ellipses_for_invisible_text_p (pos, w) /* Initialize IT for stepping through current_buffer in window W, starting at position POS that includes overlay string and display - vector/ control character translation position information. */ + vector/ control character translation position information. Value + is zero if there are overlay strings with newlines at POS. */ -static void +static int init_from_display_pos (it, w, pos) struct it *it; struct window *w; struct display_pos *pos; { int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos); + int i, overlay_strings_with_newlines = 0; /* If POS specifies a position in a display vector, this might be for an ellipsis displayed for invisible text. We won't @@ -1835,6 +1831,21 @@ init_from_display_pos (it, w, pos) after-string. */ init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID); + for (i = 0; i < it->n_overlay_strings; ++i) + { + char *s = XSTRING (it->overlay_strings[i])->data; + char *e = s + STRING_BYTES (XSTRING (it->overlay_strings[i])); + + while (s < e && *s != '\n') + ++s; + + if (s < e) + { + overlay_strings_with_newlines = 1; + break; + } + } + /* If position is within an overlay string, set up IT to the right overlay string. */ if (pos->overlay_string_index >= 0) @@ -1870,6 +1881,11 @@ init_from_display_pos (it, w, pos) it->current.string_pos = pos->string_pos; it->method = next_element_from_string; } + +#if 0 /* This is bogus because POS not having an overlay string + position does not mean it's after the string. Example: A + line starting with a before-string and initialization of IT + to the previous row's end position. */ else if (it->current.overlay_string_index >= 0) { /* If POS says we're already after an overlay string ending at @@ -1883,6 +1899,7 @@ init_from_display_pos (it, w, pos) if (CHARPOS (pos->pos) == ZV) it->overlay_strings_at_end_processed_p = 1; } +#endif /* 0 */ if (CHARPOS (pos->string_pos) >= 0) { @@ -1904,6 +1921,7 @@ init_from_display_pos (it, w, pos) } CHECK_IT (it); + return !overlay_strings_with_newlines; } @@ -1923,20 +1941,28 @@ init_to_row_start (it, w, row) /* Initialize IT for stepping through current_buffer in window W - starting in the line following ROW, i.e. starting at ROW->end. */ + starting in the line following ROW, i.e. starting at ROW->end. + Value is zero if there are overlay strings with newlines at ROW's + end position. */ -static void +static int init_to_row_end (it, w, row) struct it *it; struct window *w; struct glyph_row *row; { - init_from_display_pos (it, w, &row->end); - - if (row->continued_p) - it->continuation_lines_width = (row->continuation_lines_width - + row->pixel_width); - CHECK_IT (it); + int success = 0; + + if (init_from_display_pos (it, w, &row->end)) + { + if (row->continued_p) + it->continuation_lines_width + = row->continuation_lines_width + row->pixel_width; + CHECK_IT (it); + success = 1; + } + + return success; } @@ -2175,7 +2201,6 @@ handle_fontified_prop (it) val = Vfontification_functions; specbind (Qfontification_functions, Qnil); - specbind (Qafter_change_functions, Qnil); if (!CONSP (val) || EQ (XCAR (val), Qlambda)) safe_call1 (val, pos); @@ -2540,7 +2565,7 @@ handle_invisible_prop (it) } else { - int visible_p, newpos, next_stop, start_charpos; + int invis_p, newpos, next_stop, start_charpos; Lisp_Object pos, prop, overlay; /* First of all, is there invisible text at this position? */ @@ -2548,15 +2573,14 @@ handle_invisible_prop (it) pos = make_number (IT_CHARPOS (*it)); prop = get_char_property_and_overlay (pos, Qinvisible, it->window, &overlay); - + invis_p = TEXT_PROP_MEANS_INVISIBLE (prop); + /* If we are on invisible text, skip over it. */ - if (TEXT_PROP_MEANS_INVISIBLE (prop) - && IT_CHARPOS (*it) < it->end_charpos) + if (invis_p && IT_CHARPOS (*it) < it->end_charpos) { /* Record whether we have to display an ellipsis for the invisible text. */ - int display_ellipsis_p - = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop); + int display_ellipsis_p = invis_p == 2; handled = HANDLED_RECOMPUTE_PROPS; @@ -2576,26 +2600,26 @@ handle_invisible_prop (it) text in the first place. If everything to the end of the buffer was skipped, end the loop. */ if (newpos == IT_CHARPOS (*it) || newpos >= ZV) - visible_p = 1; + invis_p = 0; else { /* We skipped some characters but not necessarily all there are. Check if we ended up on visible text. Fget_char_property returns the property of the char before the given position, i.e. if we - get visible_p = 1, this means that the char at + get invis_p = 0, this means that the char at newpos is visible. */ pos = make_number (newpos); prop = Fget_char_property (pos, Qinvisible, it->window); - visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop); + invis_p = TEXT_PROP_MEANS_INVISIBLE (prop); } /* If we ended up on invisible text, proceed to skip starting with next_stop. */ - if (!visible_p) + if (invis_p) IT_CHARPOS (*it) = next_stop; } - while (!visible_p); + while (invis_p); /* The position newpos is now either ZV or on visible text. */ IT_CHARPOS (*it) = newpos; @@ -2796,26 +2820,22 @@ handle_single_display_prop (it, prop, object, position, if (!NILP (form) && !EQ (form, Qt)) { + int count = BINDING_STACK_SIZE (); struct gcpro gcpro1; - struct text_pos end_pos, pt; - - GCPRO1 (form); - end_pos = display_prop_end (it, object, *position); - /* Temporarily set point to the end position, and then evaluate - the form. This makes `(eolp)' work as FORM. */ - if (BUFFERP (object)) - { - CHARPOS (pt) = PT; - BYTEPOS (pt) = PT_BYTE; - TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos)); - } - + /* Bind `object' to the object having the `display' property, a + buffer or string. Bind `position' to the position in the + object where the property was found, and `buffer-position' + to the current position in the buffer. */ + specbind (Qobject, object); + specbind (Qposition, make_number (CHARPOS (*position))); + specbind (Qbuffer_position, + make_number (STRINGP (object) + ? IT_CHARPOS (*it) : CHARPOS (*position))); + GCPRO1 (form); form = safe_eval (form); - - if (BUFFERP (object)) - TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt)); - UNGCPRO; + UNGCPRO; + unbind_to (count, Qnil); } if (NILP (form)) @@ -3211,7 +3231,7 @@ string_buffer_position (w, string, around_charpos) if (!NILP (prop) && display_prop_string_p (prop, string)) found = 1; else - pos = Fnext_single_property_change (pos, Qdisplay, Qnil, limit); + pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil, limit); } if (!found) @@ -3224,8 +3244,8 @@ string_buffer_position (w, string, around_charpos) if (!NILP (prop) && display_prop_string_p (prop, string)) found = 1; else - pos = Fprevious_single_property_change (pos, Qdisplay, Qnil, - limit); + pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil, + limit); } } @@ -4009,6 +4029,7 @@ reseat_1 (it, pos, set_stop_p) IT_STRING_BYTEPOS (*it) = -1; it->string = Qnil; it->method = next_element_from_buffer; + it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters); it->sp = 0; it->face_before_selective_p = 0; @@ -5476,6 +5497,10 @@ move_it_by_lines (it, dvpos, need_y_p) struct it it2; int start_charpos, i; + /* Start at the beginning of the screen line containing IT's + position. */ + move_it_vertically_backward (it, 0); + /* Go back -DVPOS visible lines and reseat the iterator there. */ start_charpos = IT_CHARPOS (*it); for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i) @@ -5538,7 +5563,7 @@ add_to_log (format, arg1, arg2) len = STRING_BYTES (XSTRING (msg)) + 1; buffer = (char *) alloca (len); - strcpy (buffer, XSTRING (msg)->data); + bcopy (XSTRING (msg)->data, buffer, len); message_dolog (buffer, len - 1, 1, 0); UNGCPRO; @@ -6205,7 +6230,7 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4) /* Don't get confused by reusing the buffer used for echoing for a different purpose. */ - if (!echoing && EQ (buffer, echo_message_buffer)) + if (echo_kboard == NULL && EQ (buffer, echo_message_buffer)) cancel_echoing (); record_unwind_protect (unwind_with_echo_area_buffer, @@ -6228,6 +6253,7 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4) current_buffer->undo_list = Qt; current_buffer->read_only = Qnil; specbind (Qinhibit_read_only, Qt); + specbind (Qinhibit_modification_hooks, Qt); if (clear_buffer_p && Z > BEG) del_range (BEG, Z); @@ -6455,7 +6481,8 @@ display_echo_area_1 (a1, a2, a3, a4) /* Resize the echo area window to exactly the size needed for the - currently displayed message, if there is one. */ + currently displayed message, if there is one. If a mini-buffer + is active, don't shrink it. */ void resize_echo_area_exactly () @@ -6465,9 +6492,15 @@ resize_echo_area_exactly () { struct window *w = XWINDOW (echo_area_window); int resized_p; + Lisp_Object resize_exactly; + + if (minibuf_level == 0) + resize_exactly = Qt; + else + resize_exactly = Qnil; resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1, - (EMACS_INT) w, Qnil, 0, 0); + (EMACS_INT) w, resize_exactly, 0, 0); if (resized_p) { ++windows_or_buffers_changed; @@ -6480,16 +6513,17 @@ resize_echo_area_exactly () /* Callback function for with_echo_area_buffer, when used from resize_echo_area_exactly. A1 contains a pointer to the window to - resize, A2 to A4 are not used. Value is what resize_mini_window - returns. */ + resize, EXACTLY non-nil means resize the mini-window exactly to the + size of the text displayed. A3 and A4 are not used. Value is what + resize_mini_window returns. */ static int -resize_mini_window_1 (a1, a2, a3, a4) +resize_mini_window_1 (a1, exactly, a3, a4) EMACS_INT a1; - Lisp_Object a2; + Lisp_Object exactly; EMACS_INT a3, a4; { - return resize_mini_window ((struct window *) a1, 1); + return resize_mini_window ((struct window *) a1, !NILP (exactly)); } @@ -6542,7 +6576,7 @@ resize_mini_window (w, exact_p) /* Compute the max. number of lines specified by the user. */ if (FLOATP (Vmax_mini_window_height)) - max_height = XFLOATINT (Vmax_mini_window_height) * total_height; + max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_HEIGHT (f); else if (INTEGERP (Vmax_mini_window_height)) max_height = XINT (Vmax_mini_window_height); else @@ -6895,7 +6929,10 @@ clear_message (current_p, last_displayed_p) int current_p, last_displayed_p; { if (current_p) - echo_area_buffer[0] = Qnil; + { + echo_area_buffer[0] = Qnil; + message_cleared_p = 1; + } if (last_displayed_p) echo_area_buffer[1] = Qnil; @@ -7755,8 +7792,8 @@ tool_bar_lines_needed (f) DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed, 0, 1, 0, - "Return the number of lines occupied by the tool bar of FRAME.") - (frame) + /* Return the number of lines occupied by the tool bar of FRAME. */ + (frame)) Lisp_Object frame; { struct frame *f; @@ -7951,6 +7988,7 @@ hscroll_window_tree (window) &text_area_width, &text_area_height); /* Scroll when cursor is inside this scroll margin. */ + /* Shouldn't we export this `5' for customization ? -stef */ hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame)); if ((XFASTINT (w->hscroll) @@ -8151,6 +8189,23 @@ text_outside_line_unchanged_p (w, start, end) && XINT (current_buffer->selective_display) > 0 && (BEG_UNCHANGED < start || GPT <= start)) unchanged_p = 0; + + /* If there are overlays at the start or end of the line, these + may have overlay strings with newlines in them. A change at + START, for instance, may actually concern the display of such + overlay strings as well, and they are displayed on different + lines. So, quickly rule out this case. (For the future, it + might be desirable to implement something more telling than + just BEG/END_UNCHANGED.) */ + if (unchanged_p) + { + if (BEG + BEG_UNCHANGED == start + && overlay_touches_p (start)) + unchanged_p = 0; + if (END_UNCHANGED == end + && overlay_touches_p (Z - end)) + unchanged_p = 0; + } } return unchanged_p; @@ -8170,6 +8225,7 @@ redisplay () redisplay_internal (0); } + /* Return 1 if point moved out of or into a composition. Otherwise return 0. PREV_BUF and PREV_PT are the last point buffer and position. BUF and PT are the current point buffer and position. */ @@ -8208,6 +8264,7 @@ check_point_in_composition (prev_buf, prev_pt, buf, pt) && start < pt && end > pt); } + /* Reconsider the setting of B->clip_changed which is displayed in window W. */ @@ -8406,12 +8463,21 @@ redisplay_internal (preserve_echo_area) /* Normally the message* functions will have already displayed and updated the echo area, but the frame may have been trashed, or the update may have been preempted, so display the echo area - again here. Checking both message buffers captures the case that + again here. Checking message_cleared_p captures the case that the echo area should be cleared. */ - if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1])) + if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p) + || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p) + || (message_cleared_p && minibuf_level == 0)) { int window_height_changed_p = echo_area_display (0); must_finish = 1; + + /* If we don't display the current message, don't clear the + message_cleared_p flag, because, if we did, we wouldn't clear + the echo area in the next redisplay which doesn't preserve + the echo area. */ + if (!display_last_displayed_message_p) + message_cleared_p = 0; if (fonts_changed_p) goto retry; @@ -8992,9 +9058,11 @@ mark_window_display_accurate_1 (w, accurate_p) if (accurate_p) { w->window_end_valid = w->buffer; +#if 0 /* This is incorrect with variable-height lines. */ xassert (XINT (w->window_end_vpos) < (XINT (w->height) - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0))); +#endif w->update_mode_line = Qnil; } } @@ -9210,9 +9278,11 @@ run_window_scroll_functions (window, startp) /* Modify the desired matrix of window W and W->vscroll so that the - line containing the cursor is fully visible. */ + line containing the cursor is fully visible. If this requires + larger matrices than are allocated, set fonts_changed_p and return + 0. */ -static void +static int make_cursor_line_fully_visible (w) struct window *w; { @@ -9223,7 +9293,7 @@ make_cursor_line_fully_visible (w) /* It's not always possible to find the cursor, e.g, when a window is full of overlay strings. Don't do anything in that case. */ if (w->cursor.vpos < 0) - return; + return 1; matrix = w->desired_matrix; row = MATRIX_ROW (matrix, w->cursor.vpos); @@ -9231,13 +9301,13 @@ make_cursor_line_fully_visible (w) /* If the cursor row is not partially visible, there's nothing to do. */ if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row)) - return; + return 1; /* If the row the cursor is in is taller than the window's height, it's not clear what to do, so do nothing. */ window_height = window_box_height (w); if (row->height >= window_height) - return; + return 1; if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)) { @@ -9260,6 +9330,16 @@ make_cursor_line_fully_visible (w) the correct y-position. */ if (w == XWINDOW (selected_window)) this_line_y = w->cursor.y; + + /* If vscrolling requires a larger glyph matrix, arrange for a fresh + redisplay with larger matrices. */ + if (matrix->nrows < required_matrix_height (w)) + { + fonts_changed_p = 1; + return 0; + } + + return 1; } @@ -9278,6 +9358,13 @@ make_cursor_line_fully_visible (w) -1 if new fonts have been loaded so that we must interrupt redisplay, adjust glyph matrices, and try again. */ +enum +{ + SCROLLING_SUCCESS, + SCROLLING_FAILED, + SCROLLING_NEED_LARGER_MATRICES +}; + static int try_scrolling (window, just_this_one_p, scroll_conservatively, scroll_step, temp_scroll_step) @@ -9367,7 +9454,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, dy = 1 + it.current_y - y0; if (dy > scroll_max) - return 0; + return SCROLLING_FAILED; /* Move the window start down. If scrolling conservatively, move it just enough down to make point visible. If @@ -9390,7 +9477,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, } if (amount_to_scroll <= 0) - return 0; + return SCROLLING_FAILED; move_it_vertically (&it, amount_to_scroll); startp = it.current.pos; @@ -9424,7 +9511,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); dy = it.current_y - y0; if (dy > scroll_max) - return 0; + return SCROLLING_FAILED; /* Compute new window start. */ start_display (&it, w, startp); @@ -9444,7 +9531,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, } if (amount_to_scroll <= 0) - return 0; + return SCROLLING_FAILED; move_it_vertically (&it, - amount_to_scroll); startp = it.current.pos; @@ -9457,11 +9544,11 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, /* Display the window. Give up if new fonts are loaded, or if point doesn't appear. */ if (!try_window (window, startp)) - rc = -1; + rc = SCROLLING_NEED_LARGER_MATRICES; else if (w->cursor.vpos < 0) { clear_glyph_matrix (w->desired_matrix); - rc = 0; + rc = SCROLLING_FAILED; } else { @@ -9472,9 +9559,12 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, w->base_line_number = Qnil; /* If cursor ends up on a partially visible line, shift display - lines up or down. */ - make_cursor_line_fully_visible (w); - rc = 1; + lines up or down. If that fails because we need larger + matrices, give up. */ + if (!make_cursor_line_fully_visible (w)) + rc = SCROLLING_NEED_LARGER_MATRICES; + else + rc = SCROLLING_SUCCESS; } return rc; @@ -9556,13 +9646,25 @@ compute_window_start_on_continuation_line (w) /* Try cursor movement in case text has not changes in window WINDOW, with window start STARTP. Value is - 1 if successful + CURSOR_MOVEMENT_SUCCESS if successful - 0 if this method cannot be used - - -1 if we know we have to scroll the display. *SCROLL_STEP is - set to 1, under certain circumstances, if we want to scroll as - if scroll-step were set to 1. See the code. */ + CURSOR_MOVEMENT_CANNOT_BE_USED if this method cannot be used + + CURSOR_MOVEMENT_MUST_SCROLL if we know we have to scroll the + display. *SCROLL_STEP is set to 1, under certain circumstances, if + we want to scroll as if scroll-step were set to 1. See the code. + + CURSOR_MOVEMENT_NEED_LARGER_MATRICES if we need larger matrices, in + which case we have to abort this redisplay, and adjust matrices + first. */ + +enum +{ + CURSOR_MOVEMENT_SUCCESS, + CURSOR_MOVEMENT_CANNOT_BE_USED, + CURSOR_MOVEMENT_MUST_SCROLL, + CURSOR_MOVEMENT_NEED_LARGER_MATRICES +}; static int try_cursor_movement (window, startp, scroll_step) @@ -9572,7 +9674,7 @@ try_cursor_movement (window, startp, scroll_step) { struct window *w = XWINDOW (window); struct frame *f = XFRAME (w->frame); - int rc = 0; + int rc = CURSOR_MOVEMENT_CANNOT_BE_USED; /* Handle case where text has not changed, only point, and it has not moved off the frame. */ @@ -9630,17 +9732,17 @@ try_cursor_movement (window, startp, scroll_step) not paused redisplay. Give up if that row is not valid. */ if (w->last_cursor.vpos < 0 || w->last_cursor.vpos >= w->current_matrix->nrows) - rc = -1; + rc = CURSOR_MOVEMENT_MUST_SCROLL; else { row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos); if (row->mode_line_p) ++row; if (!row->enabled_p) - rc = -1; + rc = CURSOR_MOVEMENT_MUST_SCROLL; } - if (rc == 0) + if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED) { int scroll_p = 0; int last_y = window_text_bottom_y (w) - this_scroll_margin; @@ -9723,14 +9825,14 @@ try_cursor_movement (window, startp, scroll_step) || PT > MATRIX_ROW_END_CHARPOS (row)) { /* if PT is not in the glyph row, give up. */ - rc = -1; + rc = CURSOR_MOVEMENT_MUST_SCROLL; } else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row)) { if (PT == MATRIX_ROW_END_CHARPOS (row) && !row->ends_at_zv_p && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)) - rc = -1; + rc = CURSOR_MOVEMENT_MUST_SCROLL; else if (row->height > window_box_height (w)) { /* If we end up in a partially visible line, let's @@ -9738,22 +9840,24 @@ try_cursor_movement (window, startp, scroll_step) than the window, in which case we can't do much about it. */ *scroll_step = 1; - rc = -1; + rc = CURSOR_MOVEMENT_MUST_SCROLL; } else { set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); try_window (window, startp); - make_cursor_line_fully_visible (w); - rc = 1; + if (!make_cursor_line_fully_visible (w)) + rc = CURSOR_MOVEMENT_NEED_LARGER_MATRICES; + else + rc = CURSOR_MOVEMENT_SUCCESS; } } else if (scroll_p) - rc = -1; + rc = CURSOR_MOVEMENT_MUST_SCROLL; else { set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); - rc = 1; + rc = CURSOR_MOVEMENT_SUCCESS; } } } @@ -10027,11 +10131,12 @@ redisplay_window (window, just_this_one_p) { clear_glyph_matrix (w->desired_matrix); if (!try_window (window, startp)) - goto finish_scroll_bars; + goto need_larger_matrices; } } - make_cursor_line_fully_visible (w); + if (!make_cursor_line_fully_visible (w)) + goto need_larger_matrices; #if GLYPH_DEBUG debug_method_add (w, "forced window start"); #endif @@ -10042,12 +10147,22 @@ redisplay_window (window, just_this_one_p) not moved off the frame. */ if (current_matrix_up_to_date_p && (rc = try_cursor_movement (window, startp, &temp_scroll_step), - rc != 0)) + rc != CURSOR_MOVEMENT_CANNOT_BE_USED)) { - if (rc == -1) - goto try_to_scroll; - else - goto done; + switch (rc) + { + case CURSOR_MOVEMENT_SUCCESS: + goto done; + + case CURSOR_MOVEMENT_NEED_LARGER_MATRICES: + goto need_larger_matrices; + + case CURSOR_MOVEMENT_MUST_SCROLL: + goto try_to_scroll; + + default: + abort (); + } } /* If current starting point was originally the beginning of a line but no longer is, find a new starting point. */ @@ -10071,7 +10186,7 @@ redisplay_window (window, just_this_one_p) #endif if (fonts_changed_p) - goto finish_scroll_bars; + goto need_larger_matrices; if (tem > 0) goto done; @@ -10106,7 +10221,7 @@ redisplay_window (window, just_this_one_p) } if (fonts_changed_p) - goto finish_scroll_bars; + goto need_larger_matrices; if (w->cursor.vpos >= 0) { @@ -10116,7 +10231,8 @@ redisplay_window (window, just_this_one_p) /* Forget any recorded base line for line number display. */ w->base_line_number = Qnil; - make_cursor_line_fully_visible (w); + if (!make_cursor_line_fully_visible (w)) + goto need_larger_matrices; goto done; } else @@ -10151,10 +10267,20 @@ redisplay_window (window, just_this_one_p) scroll_conservatively, scroll_step, temp_scroll_step); - if (rc > 0) - goto done; - else if (rc < 0) - goto finish_scroll_bars; + switch (rc) + { + case SCROLLING_SUCCESS: + goto done; + + case SCROLLING_NEED_LARGER_MATRICES: + goto need_larger_matrices; + + case SCROLLING_FAILED: + break; + + default: + abort (); + } } /* Finally, just choose place to start which centers point */ @@ -10215,7 +10341,7 @@ redisplay_window (window, just_this_one_p) have to start a new redisplay since we need to re-adjust glyph matrices. */ if (fonts_changed_p) - goto finish_scroll_bars; + goto need_larger_matrices; /* If cursor did not appear assume that the middle of the window is in the first line of the window. Do it again with the next line. @@ -10255,7 +10381,8 @@ redisplay_window (window, just_this_one_p) set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); } - make_cursor_line_fully_visible (w); + if (!make_cursor_line_fully_visible (w)) + goto need_larger_matrices; done: @@ -10282,13 +10409,7 @@ redisplay_window (window, just_this_one_p) && (WINDOW_WANTS_MODELINE_P (w) || WINDOW_WANTS_HEADER_LINE_P (w))) { - Lisp_Object old_selected_frame; - - old_selected_frame = selected_frame; - - XSETFRAME (selected_frame, f); display_mode_lines (w); - selected_frame = old_selected_frame; /* If mode line height has changed, arrange for a thorough immediate redisplay using the correct mode line height. */ @@ -10311,7 +10432,7 @@ redisplay_window (window, just_this_one_p) } if (fonts_changed_p) - goto finish_scroll_bars; + goto need_larger_matrices; } if (!line_number_displayed @@ -10351,6 +10472,8 @@ redisplay_window (window, just_this_one_p) #endif } + need_larger_matrices: + ; finish_scroll_bars: if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) @@ -11059,7 +11182,7 @@ sync_frame_with_window_matrix_rows (w) all rows to the end of the display area of W. Value is the row containing CHARPOS or null. */ -static struct glyph_row * +struct glyph_row * row_containing_pos (w, charpos, start, end) struct window *w; int charpos; @@ -11366,14 +11489,16 @@ try_window_id (w) for instance. This is easier than to set up the iterator exactly, and it's not a frequent case, so the additional effort wouldn't really pay off. */ - while (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row) + while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row) + || last_unchanged_at_beg_row->ends_in_newline_from_string_p) && last_unchanged_at_beg_row > w->current_matrix->rows) --last_unchanged_at_beg_row; if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)) GIVE_UP (17); - - init_to_row_end (&it, w, last_unchanged_at_beg_row); + + if (init_to_row_end (&it, w, last_unchanged_at_beg_row) == 0) + GIVE_UP (18); start_pos = it.current.pos; /* Start displaying new lines in the desired matrix at the same @@ -11413,8 +11538,23 @@ try_window_id (w) stop_pos = 0; if (first_unchanged_at_end_row) { +#if GLYPH_DEBUG xassert (last_unchanged_at_beg_row == NULL || first_unchanged_at_end_row >= last_unchanged_at_beg_row); +#else + /* This is for the release of 21.1 only, and should be removed + after the release. + + This case means that unchanged information is probably bogus, + which leads to being unable to compute a correct + first_unchanged_at_end_row. At least that was the case in + one debugging session. I've fixed a bug that can lead to + wrong unchanged info, but didn't find a way to reproduce this + case. 2001-09-18 gerd. */ + if (last_unchanged_at_beg_row + && first_unchanged_at_end_row < last_unchanged_at_beg_row) + GIVE_UP (20); +#endif /* If this is a continuation line, move forward to the next one that isn't. Changes in lines above affect this line. @@ -11827,7 +11967,7 @@ try_window_id (w) #if GLYPH_DEBUG -void dump_glyph_row P_ ((struct glyph_matrix *, int, int)); +void dump_glyph_row P_ ((struct glyph_row *, int, int)); void dump_glyph_matrix P_ ((struct glyph_matrix *, int)); void dump_glyph P_ ((struct glyph_row *, struct glyph *, int)); @@ -11845,7 +11985,7 @@ dump_glyph_matrix (matrix, glyphs) { int i; for (i = 0; i < matrix->nrows; ++i) - dump_glyph_row (matrix, i, glyphs); + dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs); } @@ -11926,17 +12066,10 @@ dump_glyph (row, glyph, area) GLYPHS > 1 means show glyphs in long form. */ void -dump_glyph_row (matrix, vpos, glyphs) - struct glyph_matrix *matrix; +dump_glyph_row (row, vpos, glyphs) + struct glyph_row *row; int vpos, glyphs; { - struct glyph_row *row; - - if (vpos < 0 || vpos >= matrix->nrows) - return; - - row = MATRIX_ROW (matrix, vpos); - if (glyphs != 1) { fprintf (stderr, "Row Start End Used oEI>rows, + vpos, MATRIX_ROW_START_CHARPOS (row), MATRIX_ROW_END_CHARPOS (row), row->used[TEXT_AREA], @@ -12028,11 +12161,11 @@ dump_glyph_row (matrix, vpos, glyphs) DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix, Sdump_glyph_matrix, 0, 1, "p", - "Dump the current matrix of the selected window to stderr.\n\ -Shows contents of glyph row structures. With non-nil\n\ -parameter GLYPHS, dump glyphs as well. If GLYPHS is 1 show\n\ -glyphs in short form, otherwise show glyphs in long form.") - (glyphs) + /* Dump the current matrix of the selected window to stderr. +Shows contents of glyph row structures. With non-nil +parameter GLYPHS, dump glyphs as well. If GLYPHS is 1 show +glyphs in short form, otherwise show glyphs in long form. */ + (glyphs)) Lisp_Object glyphs; { struct window *w = XWINDOW (selected_window); @@ -12050,40 +12183,52 @@ glyphs in short form, otherwise show glyphs in long form.") DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "", - "Dump glyph row ROW to stderr.\n\ -GLYPH 0 means don't dump glyphs.\n\ -GLYPH 1 means dump glyphs in short form.\n\ -GLYPH > 1 or omitted means dump glyphs in long form.") - (row, glyphs) + /* Dump glyph row ROW to stderr. +GLYPH 0 means don't dump glyphs. +GLYPH 1 means dump glyphs in short form. +GLYPH > 1 or omitted means dump glyphs in long form. */ + (row, glyphs)) Lisp_Object row, glyphs; { + struct glyph_matrix *matrix; + int vpos; + CHECK_NUMBER (row, 0); - dump_glyph_row (XWINDOW (selected_window)->current_matrix, - XINT (row), - INTEGERP (glyphs) ? XINT (glyphs) : 2); + matrix = XWINDOW (selected_window)->current_matrix; + vpos = XINT (row); + if (vpos >= 0 && vpos < matrix->nrows) + dump_glyph_row (MATRIX_ROW (matrix, vpos), + vpos, + INTEGERP (glyphs) ? XINT (glyphs) : 2); return Qnil; } DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "", - "Dump glyph row ROW of the tool-bar of the current frame to stderr.\n\ -GLYPH 0 means don't dump glyphs.\n\ -GLYPH 1 means dump glyphs in short form.\n\ -GLYPH > 1 or omitted means dump glyphs in long form.") - (row, glyphs) + /* Dump glyph row ROW of the tool-bar of the current frame to stderr. +GLYPH 0 means don't dump glyphs. +GLYPH 1 means dump glyphs in short form. +GLYPH > 1 or omitted means dump glyphs in long form. */ + (row, glyphs)) Lisp_Object row, glyphs; { struct frame *sf = SELECTED_FRAME (); - struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)->current_matrix); - dump_glyph_row (m, XINT (row), INTEGERP (glyphs) ? XINT (glyphs) : 2); + struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix; + int vpos; + + CHECK_NUMBER (row, 0); + vpos = XINT (row); + if (vpos >= 0 && vpos < m->nrows) + dump_glyph_row (MATRIX_ROW (m, vpos), vpos, + INTEGERP (glyphs) ? XINT (glyphs) : 2); return Qnil; } DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P", - "Toggle tracing of redisplay.\n\ -With ARG, turn tracing on if and only if ARG is positive.") - (arg) + /* Toggle tracing of redisplay. +With ARG, turn tracing on if and only if ARG is positive. */ + (arg)) Lisp_Object arg; { if (NILP (arg)) @@ -12098,13 +12243,14 @@ With ARG, turn tracing on if and only if ARG is positive.") } -DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, 1, "", - "Print STRING to stderr.") - (string) - Lisp_Object string; +DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "", + /* Like `format', but print result to stderr. */ + (nargs, args)) + int nargs; + Lisp_Object *args; { - CHECK_STRING (string, 0); - fprintf (stderr, "%s", XSTRING (string)->data); + Lisp_Object s = Fformat (nargs, args); + fprintf (stderr, "%s", XSTRING (s)->data); return Qnil; } @@ -12853,6 +12999,8 @@ display_line (it) { int used_before = row->used[TEXT_AREA]; + row->ends_in_newline_from_string_p = STRINGP (it->object); + /* Add a space at the end of the line that is used to display the cursor there. */ append_space (it, 0); @@ -13125,7 +13273,6 @@ redisplay_mode_lines (window, force) || FRAME_GARBAGED_P (XFRAME (w->frame)) || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p) { - Lisp_Object old_selected_frame; struct text_pos lpoint; struct buffer *old = current_buffer; @@ -13148,10 +13295,6 @@ redisplay_mode_lines (window, force) TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt)); } - /* Temporarily set up the selected frame. */ - old_selected_frame = selected_frame; - selected_frame = w->frame; - /* Display mode lines. */ clear_glyph_matrix (w->desired_matrix); if (display_mode_lines (w)) @@ -13161,7 +13304,6 @@ redisplay_mode_lines (window, force) } /* Restore old settings. */ - selected_frame = old_selected_frame; set_buffer_internal_1 (old); TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint)); } @@ -13180,7 +13322,13 @@ static int display_mode_lines (w) struct window *w; { + Lisp_Object old_selected_window, old_selected_frame; int n = 0; + + old_selected_frame = selected_frame; + selected_frame = w->frame; + old_selected_window = selected_window; + XSETWINDOW (selected_window, w); /* These will be set while the mode line specs are processed. */ line_number_displayed = 0; @@ -13200,6 +13348,8 @@ display_mode_lines (w) ++n; } + selected_frame = old_selected_frame; + selected_window = old_selected_window; return n; } @@ -13313,15 +13463,21 @@ display_mode_element (it, depth, field_width, precision, elt) is length of string. Don't output more than PRECISION allows us. */ --this; - prec = strwidth (last, this - last); + + prec = chars_in_text (last, this - last); if (precision > 0 && prec > precision - n) prec = precision - n; if (frame_title_ptr) n += store_frame_title (last, 0, prec); else - n += display_string (NULL, elt, Qnil, 0, last - lisp_string, - it, 0, prec, 0, -1); + { + int bytepos = last - lisp_string; + int charpos = string_byte_to_char (elt, bytepos); + n += display_string (NULL, elt, Qnil, 0, charpos, + it, 0, prec, 0, + STRING_MULTIBYTE (elt)); + } } else /* c == '%' */ { @@ -13345,20 +13501,25 @@ display_mode_element (it, depth, field_width, precision, elt) Vglobal_mode_string); else if (c != 0) { + int multibyte; unsigned char *spec - = decode_mode_spec (it->w, c, field, prec); - + = decode_mode_spec (it->w, c, field, prec, &multibyte); + if (frame_title_ptr) n += store_frame_title (spec, field, prec); else { - int nglyphs_before - = it->glyph_row->used[TEXT_AREA]; - int charpos - = percent_position - XSTRING (elt)->data; - int nwritten - = display_string (spec, Qnil, elt, charpos, 0, it, - field, prec, 0, -1); + int nglyphs_before, bytepos, charpos, nwritten; + + nglyphs_before = it->glyph_row->used[TEXT_AREA]; + bytepos = percent_position - XSTRING (elt)->data; + charpos = (multibyte + ? string_byte_to_char (elt, bytepos) + : bytepos); + nwritten = display_string (spec, Qnil, elt, + charpos, 0, it, + field, prec, 0, + multibyte); /* Assign to the glyphs written above the string where the `%x' came from, position @@ -13405,7 +13566,7 @@ display_mode_element (it, depth, field_width, precision, elt) n += store_frame_title (XSTRING (tem)->data, -1, prec); else n += display_string (NULL, tem, Qnil, 0, 0, it, - 0, prec, 0, -1); + 0, prec, 0, STRING_MULTIBYTE (tem)); } else if (!EQ (tem, elt)) { @@ -13654,15 +13815,17 @@ decode_mode_spec_coding (coding_system, buf, eol_flag) /* Return a string for the output of a mode line %-spec for window W, generated by character C. PRECISION >= 0 means don't return a string longer than that value. FIELD_WIDTH > 0 means pad the - string returned with spaces to that value. */ + string returned with spaces to that value. Return 1 in *MULTIBYTE + if the result is multibyte text. */ static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; static char * -decode_mode_spec (w, c, field_width, precision) +decode_mode_spec (w, c, field_width, precision, multibyte) struct window *w; register int c; int field_width, precision; + int *multibyte; { Lisp_Object obj; struct frame *f = XFRAME (WINDOW_FRAME (w)); @@ -13670,6 +13833,7 @@ decode_mode_spec (w, c, field_width, precision) struct buffer *b = XBUFFER (w->buffer); obj = Qnil; + *multibyte = 0; switch (c) { @@ -14003,7 +14167,10 @@ decode_mode_spec (w, c, field_width, precision) } if (STRINGP (obj)) - return (char *) XSTRING (obj)->data; + { + *multibyte = STRING_MULTIBYTE (obj); + return (char *) XSTRING (obj)->data; + } else return ""; } @@ -14332,11 +14499,13 @@ display_string (string, lisp_string, face_string, face_string_pos, -/* This is like a combination of memq and assq. Return 1 if PROPVAL +/* This is like a combination of memq and assq. Return 1/2 if PROPVAL appears as an element of LIST or as the car of an element of LIST. If PROPVAL is a list, compare each element against LIST in that - way, and return 1 if any element of PROPVAL is found in LIST. - Otherwise return 0. This function cannot quit. */ + way, and return 1/2 if any element of PROPVAL is found in LIST. + Otherwise return 0. This function cannot quit. + The return value is 2 if the text is invisible but with an ellipsis + and 1 if it's invisible and without an ellipsis. */ int invisible_p (propval, list) @@ -14352,7 +14521,7 @@ invisible_p (propval, list) if (EQ (propval, tem)) return 1; if (CONSP (tem) && EQ (propval, XCAR (tem))) - return 1; + return NILP (XCDR (tem)) ? 1 : 2; } if (CONSP (propval)) @@ -14368,7 +14537,7 @@ invisible_p (propval, list) if (EQ (propelt, tem)) return 1; if (CONSP (tem) && EQ (propelt, XCAR (tem))) - return 1; + return NILP (XCDR (tem)) ? 1 : 2; } } } @@ -14376,46 +14545,6 @@ invisible_p (propval, list) return 0; } - -/* Return 1 if PROPVAL appears as the car of an element of LIST and - the cdr of that element is non-nil. If PROPVAL is a list, check - each element of PROPVAL in that way, and the first time some - element is found, return 1 if the cdr of that element is non-nil. - Otherwise return 0. This function cannot quit. */ - -int -invisible_ellipsis_p (propval, list) - register Lisp_Object propval; - Lisp_Object list; -{ - register Lisp_Object tail, proptail; - - for (tail = list; CONSP (tail); tail = XCDR (tail)) - { - register Lisp_Object tem; - tem = XCAR (tail); - if (CONSP (tem) && EQ (propval, XCAR (tem))) - return ! NILP (XCDR (tem)); - } - - if (CONSP (propval)) - for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail)) - { - Lisp_Object propelt; - propelt = XCAR (proptail); - for (tail = list; CONSP (tail); tail = XCDR (tail)) - { - register Lisp_Object tem; - tem = XCAR (tail); - if (CONSP (tem) && EQ (propelt, XCAR (tem))) - return ! NILP (XCDR (tem)); - } - } - - return 0; -} - - /*********************************************************************** Initialization @@ -14510,6 +14639,12 @@ syms_of_xdisp () staticpro (&Qinhibit_menubar_update); Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay"); staticpro (&Qinhibit_eval_during_redisplay); + Qposition = intern ("position"); + staticpro (&Qposition); + Qbuffer_position = intern ("buffer-position"); + staticpro (&Qbuffer_position); + Qobject = intern ("object"); + staticpro (&Qobject); last_arrow_position = Qnil; last_arrow_string = Qnil; @@ -14527,220 +14662,219 @@ syms_of_xdisp () Vmessages_buffer_name = build_string ("*Messages*"); staticpro (&Vmessages_buffer_name); - DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace, - "Non-nil means highlight trailing whitespace.\n\ -The face used for trailing whitespace is `trailing-whitespace'."); + DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace + /* Non-nil means highlight trailing whitespace. +The face used for trailing whitespace is `trailing-whitespace'. */); Vshow_trailing_whitespace = Qnil; - DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay, - "Non-nil means don't actually do any redisplay.\n\ -This is used for internal purposes."); + DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay + /* Non-nil means don't actually do any redisplay. +This is used for internal purposes. */); Vinhibit_redisplay = Qnil; - DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string, - "String (or mode line construct) included (normally) in `mode-line-format'."); + DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string + /* String (or mode line construct) included (normally) in `mode-line-format'. */); Vglobal_mode_string = Qnil; - DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position, - "Marker for where to display an arrow on top of the buffer text.\n\ -This must be the beginning of a line in order to work.\n\ -See also `overlay-arrow-string'."); + DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position + /* Marker for where to display an arrow on top of the buffer text. +This must be the beginning of a line in order to work. +See also `overlay-arrow-string'. */); Voverlay_arrow_position = Qnil; - DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string, - "String to display as an arrow. See also `overlay-arrow-position'."); + DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string + /* String to display as an arrow. See also `overlay-arrow-position'. */); Voverlay_arrow_string = Qnil; - DEFVAR_INT ("scroll-step", &scroll_step, - "*The number of lines to try scrolling a window by when point moves out.\n\ -If that fails to bring point back on frame, point is centered instead.\n\ -If this is zero, point is always centered after it moves off frame.\n\ -If you want scrolling to always be a line at a time, you should set\n\ - `scroll-conservatively' to a large value rather than set this to 1."); - - DEFVAR_INT ("scroll-conservatively", &scroll_conservatively, - "*Scroll up to this many lines, to bring point back on screen.\n\ -A value of zero means to scroll the text to center point vertically\n\ -in the window."); + DEFVAR_INT ("scroll-step", &scroll_step + /* *The number of lines to try scrolling a window by when point moves out. +If that fails to bring point back on frame, point is centered instead. +If this is zero, point is always centered after it moves off frame. +If you want scrolling to always be a line at a time, you should set +`scroll-conservatively' to a large value rather than set this to 1. */); + + DEFVAR_INT ("scroll-conservatively", &scroll_conservatively + /* *Scroll up to this many lines, to bring point back on screen. +A value of zero means to scroll the text to center point vertically +in the window. */); scroll_conservatively = 0; - DEFVAR_INT ("scroll-margin", &scroll_margin, - "*Number of lines of margin at the top and bottom of a window.\n\ -Recenter the window whenever point gets within this many lines\n\ -of the top or bottom of the window."); + DEFVAR_INT ("scroll-margin", &scroll_margin + /* *Number of lines of margin at the top and bottom of a window. +Recenter the window whenever point gets within this many lines +of the top or bottom of the window. */); scroll_margin = 0; #if GLYPH_DEBUG - DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask"); + DEFVAR_INT ("debug-end-pos", &debug_end_pos /* Don't ask. */); #endif DEFVAR_BOOL ("truncate-partial-width-windows", - &truncate_partial_width_windows, - "*Non-nil means truncate lines in all windows less than full frame wide."); + &truncate_partial_width_windows + /* *Non-nil means truncate lines in all windows less than full frame wide. */); truncate_partial_width_windows = 1; - DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video, - "nil means display the mode-line/header-line/menu-bar in the default face.\n\ -Any other value means to use the appropriate face, `mode-line',\n\ -`header-line', or `menu' respectively.\n\ -\n\ -This variable is deprecated; please change the above faces instead."); + DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video + /* nil means display the mode-line/header-line/menu-bar in the default face. +Any other value means to use the appropriate face, `mode-line', +`header-line', or `menu' respectively. + +This variable is deprecated; please change the above faces instead. */); mode_line_inverse_video = 1; - DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit, - "*Maximum buffer size for which line number should be displayed.\n\ -If the buffer is bigger than this, the line number does not appear\n\ -in the mode line. A value of nil means no limit."); + DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit + /* *Maximum buffer size for which line number should be displayed. +If the buffer is bigger than this, the line number does not appear +in the mode line. A value of nil means no limit. */); Vline_number_display_limit = Qnil; DEFVAR_INT ("line-number-display-limit-width", - &line_number_display_limit_width, - "*Maximum line width (in characters) for line number display.\n\ -If the average length of the lines near point is bigger than this, then the\n\ -line number may be omitted from the mode line."); + &line_number_display_limit_width + /* *Maximum line width (in characters) for line number display. +If the average length of the lines near point is bigger than this, then the +line number may be omitted from the mode line. */); line_number_display_limit_width = 200; - DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows, - "*Non-nil means highlight region even in nonselected windows."); + DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows + /* *Non-nil means highlight region even in nonselected windows. */); highlight_nonselected_windows = 0; - DEFVAR_BOOL ("multiple-frames", &multiple_frames, - "Non-nil if more than one frame is visible on this display.\n\ -Minibuffer-only frames don't count, but iconified frames do.\n\ -This variable is not guaranteed to be accurate except while processing\n\ -`frame-title-format' and `icon-title-format'."); - - DEFVAR_LISP ("frame-title-format", &Vframe_title_format, - "Template for displaying the title bar of visible frames.\n\ -\(Assuming the window manager supports this feature.)\n\ -This variable has the same structure as `mode-line-format' (which see),\n\ -and is used only on frames for which no explicit name has been set\n\ -\(see `modify-frame-parameters')."); - DEFVAR_LISP ("icon-title-format", &Vicon_title_format, - "Template for displaying the title bar of an iconified frame.\n\ -\(Assuming the window manager supports this feature.)\n\ -This variable has the same structure as `mode-line-format' (which see),\n\ -and is used only on frames for which no explicit name has been set\n\ -\(see `modify-frame-parameters')."); + DEFVAR_BOOL ("multiple-frames", &multiple_frames + /* Non-nil if more than one frame is visible on this display. +Minibuffer-only frames don't count, but iconified frames do. +This variable is not guaranteed to be accurate except while processing +`frame-title-format' and `icon-title-format'. */); + + DEFVAR_LISP ("frame-title-format", &Vframe_title_format + /* Template for displaying the title bar of visible frames. +\(Assuming the window manager supports this feature.) +This variable has the same structure as `mode-line-format' (which see), +and is used only on frames for which no explicit name has been set +\(see `modify-frame-parameters'). */); + DEFVAR_LISP ("icon-title-format", &Vicon_title_format + /* Template for displaying the title bar of an iconified frame. +\(Assuming the window manager supports this feature.) +This variable has the same structure as `mode-line-format' (which see), +and is used only on frames for which no explicit name has been set +\(see `modify-frame-parameters'). */); Vicon_title_format = Vframe_title_format = Fcons (intern ("multiple-frames"), Fcons (build_string ("%b"), - Fcons (Fcons (build_string (""), + Fcons (Fcons (empty_string, Fcons (intern ("invocation-name"), Fcons (build_string ("@"), Fcons (intern ("system-name"), Qnil)))), Qnil))); - DEFVAR_LISP ("message-log-max", &Vmessage_log_max, - "Maximum number of lines to keep in the message log buffer.\n\ -If nil, disable message logging. If t, log messages but don't truncate\n\ -the buffer when it becomes large."); + DEFVAR_LISP ("message-log-max", &Vmessage_log_max + /* Maximum number of lines to keep in the message log buffer. +If nil, disable message logging. If t, log messages but don't truncate +the buffer when it becomes large. */); Vmessage_log_max = make_number (50); - DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions, - "Functions called before redisplay, if window sizes have changed.\n\ -The value should be a list of functions that take one argument.\n\ -Just before redisplay, for each frame, if any of its windows have changed\n\ -size since the last redisplay, or have been split or deleted,\n\ -all the functions in the list are called, with the frame as argument."); + DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions + /* Functions called before redisplay, if window sizes have changed. +The value should be a list of functions that take one argument. +Just before redisplay, for each frame, if any of its windows have changed +size since the last redisplay, or have been split or deleted, +all the functions in the list are called, with the frame as argument. */); Vwindow_size_change_functions = Qnil; - DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions, - "List of Functions to call before redisplaying a window with scrolling.\n\ -Each function is called with two arguments, the window\n\ -and its new display-start position. Note that the value of `window-end'\n\ -is not valid when these functions are called."); + DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions + /* List of Functions to call before redisplaying a window with scrolling. +Each function is called with two arguments, the window +and its new display-start position. Note that the value of `window-end' +is not valid when these functions are called. */); Vwindow_scroll_functions = Qnil; - DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p, - "*Non-nil means automatically resize tool-bars.\n\ -This increases a tool-bar's height if not all tool-bar items are visible.\n\ -It decreases a tool-bar's height when it would display blank lines\n\ -otherwise."); + DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p + /* *Non-nil means automatically resize tool-bars. +This increases a tool-bar's height if not all tool-bar items are visible. +It decreases a tool-bar's height when it would display blank lines +otherwise. */); auto_resize_tool_bars_p = 1; - DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p, - "*Non-nil means raise tool-bar buttons when the mouse moves over them."); + DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p + /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */); auto_raise_tool_bar_buttons_p = 1; - DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin, - "*Margin around tool-bar buttons in pixels.\n\ -If an integer, use that for both horizontal and vertical margins.\n\ -Otherwise, value should be a pair of integers `(HORZ : VERT)' with\n\ -HORZ specifying the horizontal margin, and VERT specifying the\n\ -vertical margin."); + DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin + /* *Margin around tool-bar buttons in pixels. +If an integer, use that for both horizontal and vertical margins. +Otherwise, value should be a pair of integers `(HORZ : VERT)' with +HORZ specifying the horizontal margin, and VERT specifying the +vertical margin. */); Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN); - DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief, - "Relief thickness of tool-bar buttons."); + DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief + /* Relief thickness of tool-bar buttons. */); tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF; - DEFVAR_LISP ("fontification-functions", &Vfontification_functions, - "List of functions to call to fontify regions of text.\n\ -Each function is called with one argument POS. Functions must\n\ -fontify a region starting at POS in the current buffer, and give\n\ -fontified regions the property `fontified'.\n\ -This variable automatically becomes buffer-local when set."); + DEFVAR_LISP ("fontification-functions", &Vfontification_functions + /* List of functions to call to fontify regions of text. +Each function is called with one argument POS. Functions must +fontify a region starting at POS in the current buffer, and give +fontified regions the property `fontified'. */); Vfontification_functions = Qnil; Fmake_variable_buffer_local (Qfontification_functions); DEFVAR_BOOL ("unibyte-display-via-language-environment", - &unibyte_display_via_language_environment, - "*Non-nil means display unibyte text according to language environment.\n\ -Specifically this means that unibyte non-ASCII characters\n\ -are displayed by converting them to the equivalent multibyte characters\n\ -according to the current language environment. As a result, they are\n\ -displayed according to the current fontset."); + &unibyte_display_via_language_environment + /* *Non-nil means display unibyte text according to language environment. +Specifically this means that unibyte non-ASCII characters +are displayed by converting them to the equivalent multibyte characters +according to the current language environment. As a result, they are +displayed according to the current fontset. */); unibyte_display_via_language_environment = 0; - DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height, - "*Maximum height for resizing mini-windows.\n\ -If a float, it specifies a fraction of the mini-window frame's height.\n\ -If an integer, it specifies a number of lines."); + DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height + /* *Maximum height for resizing mini-windows. +If a float, it specifies a fraction of the mini-window frame's height. +If an integer, it specifies a number of lines. */); Vmax_mini_window_height = make_float (0.25); - DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows, - "*How to resize mini-windows.\n\ -A value of nil means don't automatically resize mini-windows.\n\ -A value of t means resize them to fit the text displayed in them.\n\ -A value of `grow-only', the default, means let mini-windows grow\n\ -only, until their display becomes empty, at which point the windows\n\ -go back to their normal size."); + DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows + /* *How to resize mini-windows. +A value of nil means don't automatically resize mini-windows. +A value of t means resize them to fit the text displayed in them. +A value of `grow-only', the default, means let mini-windows grow +only, until their display becomes empty, at which point the windows +go back to their normal size. */); Vresize_mini_windows = Qgrow_only; DEFVAR_BOOL ("cursor-in-non-selected-windows", - &cursor_in_non_selected_windows, - "*Non-nil means display a hollow cursor in non-selected windows.\n\ -Nil means don't display a cursor there."); + &cursor_in_non_selected_windows + /* *Non-nil means display a hollow cursor in non-selected windows. +Nil means don't display a cursor there. */); cursor_in_non_selected_windows = 1; - DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p, - "*Non-nil means scroll the display automatically to make point visible."); + DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p + /* *Non-nil means scroll the display automatically to make point visible. */); automatic_hscrolling_p = 1; - DEFVAR_LISP ("image-types", &Vimage_types, - "List of supported image types.\n\ -Each element of the list is a symbol for a supported image type."); + DEFVAR_LISP ("image-types", &Vimage_types + /* List of supported image types. +Each element of the list is a symbol for a supported image type. */); Vimage_types = Qnil; - DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines, - "If non-nil, messages are truncated instead of resizing the echo area.\n\ -Bind this around calls to `message' to let it take effect."); + DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines + /* If non-nil, messages are truncated instead of resizing the echo area. +Bind this around calls to `message' to let it take effect. */); message_truncate_lines = 0; - DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook, - "Normal hook run for clicks on menu bar, before displaying a submenu.\n\ -Can be used to update submenus whose contents should vary."); + DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook + /* Normal hook run for clicks on menu bar, before displaying a submenu. +Can be used to update submenus whose contents should vary. */); Vmenu_bar_update_hook = Qnil; - DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update, - "Non-nil means don't update menu bars. Internal use only."); + DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update + /* Non-nil means don't update menu bars. Internal use only. */); inhibit_menubar_update = 0; - DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay, - "Non-nil means don't eval Lisp during redisplay."); + DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay + /* Non-nil means don't eval Lisp during redisplay. */); inhibit_eval_during_redisplay = 0; }