X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/e6da77e898ea743bc416517542eae446e573b6b5..7238837d023af0b6461e905af99cad1a03931f9a:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 4a79521f65..90399c0603 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -198,8 +198,6 @@ Boston, MA 02111-1307, USA. */ #endif #ifdef MAC_OS #include "macterm.h" - -Cursor No_Cursor; #endif #ifndef FRAME_X_OUTPUT @@ -304,10 +302,11 @@ Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; Lisp_Object Qslice; Lisp_Object Qcenter; Lisp_Object Qmargin, Qpointer; -Lisp_Object Qline_height; +Lisp_Object Qline_height, Qtotal; extern Lisp_Object Qheight; extern Lisp_Object QCwidth, QCheight, QCascent; extern Lisp_Object Qscroll_bar; +extern Lisp_Object Qcursor; /* Non-nil means highlight trailing whitespace. */ @@ -672,10 +671,6 @@ EMACS_INT hscroll_margin; /* How much to scroll horizontally when point is inside the above margin. */ Lisp_Object Vhscroll_step; -/* A list of symbols, one for each supported image type. */ - -Lisp_Object Vimage_types; - /* The variable `resize-mini-windows'. If nil, don't resize mini-windows. If t, always resize them to fit the text they display. If `grow-only', let mini-windows grow only until they @@ -2069,6 +2064,9 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) { if (NATNUMP (current_buffer->extra_line_spacing)) it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing); + else if (FLOATP (current_buffer->extra_line_spacing)) + it->extra_line_spacing = (XFLOAT_DATA (current_buffer->extra_line_spacing) + * FRAME_LINE_HEIGHT (it->f)); else if (it->f->extra_line_spacing > 0) it->extra_line_spacing = it->f->extra_line_spacing; } @@ -2086,6 +2084,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil; it->space_width = Qnil; it->font_height = Qnil; + it->override_ascent = -1; /* Are control characters displayed as `^C'? */ it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow); @@ -2726,19 +2725,10 @@ next_overlay_change (pos) int noverlays; int endpos; Lisp_Object *overlays; - int len; int i; /* Get all overlays at the given position. */ - len = 10; - overlays = (Lisp_Object *) alloca (len * sizeof *overlays); - noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1); - if (noverlays > len) - { - len = noverlays; - overlays = (Lisp_Object *) alloca (len * sizeof *overlays); - noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1); - } + GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1); /* If any of these overlays ends before endpos, use its ending point instead. */ @@ -4564,6 +4554,14 @@ back_to_previous_visible_line_start (it) visible_p = 0; } + if (visible_p) + { + struct it it2 = *it; + + if (handle_display_prop (&it2) == HANDLED_RETURN) + visible_p = 0; + } + /* Back one more newline if the current one is invisible. */ if (!visible_p) back_to_previous_line_start (it); @@ -5648,9 +5646,13 @@ move_it_in_display_line_to (it, to_charpos, to_x, op) { int x, i, ascent = 0, descent = 0; - /* Stop when ZV or TO_CHARPOS reached. */ + /* Stop when ZV reached. + We used to stop here when TO_CHARPOS reached as well, but that is + too soon if this glyph does not fit on this line. So we handle it + explicitly below. */ if (!get_next_display_element (it) - || BUFFER_POS_REACHED_P ()) + || (it->truncate_lines_p + && BUFFER_POS_REACHED_P ())) { result = MOVE_POS_MATCH_OR_ZV; break; @@ -5710,6 +5712,8 @@ move_it_in_display_line_to (it, to_charpos, to_x, op) /* We want to leave anything reaching TO_X to the caller. */ if ((op & MOVE_TO_X) && new_x > to_x) { + if (BUFFER_POS_REACHED_P ()) + goto buffer_pos_reached; it->current_x = x; result = MOVE_X_REACHED; break; @@ -5737,12 +5741,19 @@ move_it_in_display_line_to (it, to_charpos, to_x, op) #ifdef HAVE_WINDOW_SYSTEM if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) { - if (!get_next_display_element (it) - || BUFFER_POS_REACHED_P ()) + if (!get_next_display_element (it)) { result = MOVE_POS_MATCH_OR_ZV; break; } + if (BUFFER_POS_REACHED_P ()) + { + if (ITERATOR_AT_END_OF_LINE_P (it)) + result = MOVE_POS_MATCH_OR_ZV; + else + result = MOVE_LINE_CONTINUED; + break; + } if (ITERATOR_AT_END_OF_LINE_P (it)) { result = MOVE_NEWLINE_OR_CR; @@ -5764,6 +5775,8 @@ move_it_in_display_line_to (it, to_charpos, to_x, op) result = MOVE_LINE_CONTINUED; break; } + else if (BUFFER_POS_REACHED_P ()) + goto buffer_pos_reached; else if (new_x > it->first_visible_x) { /* Glyph is visible. Increment number of glyphs that @@ -5780,6 +5793,15 @@ move_it_in_display_line_to (it, to_charpos, to_x, op) if (result != MOVE_UNDEFINED) break; } + else if (BUFFER_POS_REACHED_P ()) + { + buffer_pos_reached: + it->current_x = x; + it->max_ascent = ascent; + it->max_descent = descent; + result = MOVE_POS_MATCH_OR_ZV; + break; + } else if ((op & MOVE_TO_X) && it->current_x >= to_x) { /* Stop when TO_X specified and reached. This check is @@ -6314,6 +6336,7 @@ add_to_log (format, arg1, arg2) char *buffer; int len; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + USE_SAFE_ALLOCA; /* Do nothing if called asynchronously. Inserting text into a buffer may call after-change-functions and alike and @@ -6330,10 +6353,12 @@ add_to_log (format, arg1, arg2) msg = Fformat (3, args); len = SBYTES (msg) + 1; - buffer = (char *) alloca (len); + SAFE_ALLOCA (buffer, char *, len); bcopy (SDATA (msg), buffer, len); message_dolog (buffer, len - 1, 1, 0); + SAFE_FREE (len); + UNGCPRO; } @@ -10353,7 +10378,7 @@ redisplay_internal (preserve_echo_area) This is useful in situations where you need to redisplay but no user action has occurred, making it inappropriate for the message area to be cleared. See tracking_off and - wait_reading_process_input for examples of these situations. + wait_reading_process_output for examples of these situations. FROM_WHERE is an integer saying from where this function was called. This is useful for debugging. */ @@ -10619,6 +10644,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) { struct glyph *glyph = row->glyphs[TEXT_AREA]; struct glyph *end = glyph + row->used[TEXT_AREA]; + struct glyph *cursor = NULL; /* The first glyph that starts a sequence of glyphs from string. */ struct glyph *string_start; /* The X coordinate of string_start. */ @@ -10628,6 +10654,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) /* The last known character position before string_start. */ int string_before_pos; int x = row->x; + int cursor_x = x; + int cursor_from_overlay_pos = 0; int pt_old = PT - delta; /* Skip over glyphs not having an object at the start of the row. @@ -10653,6 +10681,12 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) string_start = NULL; x += glyph->pixel_width; ++glyph; + if (cursor_from_overlay_pos + && last_pos > cursor_from_overlay_pos) + { + cursor_from_overlay_pos = 0; + cursor = 0; + } } else { @@ -10660,12 +10694,40 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) string_start = glyph; string_start_x = x; /* Skip all glyphs from string. */ - SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object)); + do + { + int pos; + if ((cursor == NULL || glyph > cursor) + && !NILP (Fget_char_property (make_number ((glyph)->charpos), + Qcursor, (glyph)->object)) + && (pos = string_buffer_position (w, glyph->object, + string_before_pos), + (pos == 0 /* From overlay */ + || pos == pt_old))) + { + /* Estimate overlay buffer position from the buffer + positions of the glyphs before and after the overlay. + Add 1 to last_pos so that if point corresponds to the + glyph right after the overlay, we still use a 'cursor' + property found in that overlay. */ + cursor_from_overlay_pos = pos == 0 ? last_pos+1 : 0; + cursor = glyph; + cursor_x = x; + } + x += glyph->pixel_width; + ++glyph; + } + while (glyph < end && STRINGP (glyph->object)); } } - if (string_start - && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old)) + if (cursor != NULL) + { + glyph = cursor; + x = cursor_x; + } + else if (string_start + && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old)) { /* We may have skipped over point because the previous glyphs are from string. As there's no easy way to know the @@ -11003,7 +11065,12 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, aggressive = current_buffer->scroll_up_aggressively; height = WINDOW_BOX_TEXT_HEIGHT (w); if (NUMBERP (aggressive)) - amount_to_scroll = XFLOATINT (aggressive) * height; + { + double float_amount = XFLOATINT (aggressive) * height; + amount_to_scroll = float_amount; + if (amount_to_scroll == 0 && float_amount > 0) + amount_to_scroll = 1; + } } if (amount_to_scroll <= 0) @@ -11052,8 +11119,8 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, start_display (&it, w, startp); if (scroll_conservatively) - amount_to_scroll = - max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step)); + amount_to_scroll + = max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step)); else if (scroll_step || temp_scroll_step) amount_to_scroll = scroll_max; else @@ -11061,7 +11128,12 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, aggressive = current_buffer->scroll_down_aggressively; height = WINDOW_BOX_TEXT_HEIGHT (w); if (NUMBERP (aggressive)) - amount_to_scroll = XFLOATINT (aggressive) * height; + { + double float_amount = XFLOATINT (aggressive) * height; + amount_to_scroll = float_amount; + if (amount_to_scroll == 0 && float_amount > 0) + amount_to_scroll = 1; + } } if (amount_to_scroll <= 0) @@ -11256,7 +11328,7 @@ try_cursor_movement (window, startp, scroll_step) && (FRAME_WINDOW_P (f) || !overlay_arrow_in_current_buffer_p ())) { - int this_scroll_margin; + int this_scroll_margin, top_scroll_margin; struct glyph_row *row = NULL; #if GLYPH_DEBUG @@ -11269,6 +11341,10 @@ try_cursor_movement (window, startp, scroll_step) this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4); this_scroll_margin *= FRAME_LINE_HEIGHT (f); + top_scroll_margin = this_scroll_margin; + if (WINDOW_WANTS_HEADER_LINE_P (w)) + top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w); + /* Start with the row the cursor was displayed during the last not paused redisplay. Give up if that row is not valid. */ if (w->last_cursor.vpos < 0 @@ -11323,13 +11399,12 @@ try_cursor_movement (window, startp, scroll_step) else if (PT < XFASTINT (w->last_point)) { /* Cursor has to be moved backward. Note that PT >= - CHARPOS (startp) because of the outer - if-statement. */ + CHARPOS (startp) because of the outer if-statement. */ while (!row->mode_line_p && (MATRIX_ROW_START_CHARPOS (row) > PT || (MATRIX_ROW_START_CHARPOS (row) == PT && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row))) - && (row->y > this_scroll_margin + && (row->y > top_scroll_margin || CHARPOS (startp) == BEGV)) { xassert (row->enabled_p); @@ -11357,7 +11432,7 @@ try_cursor_movement (window, startp, scroll_step) ++row; /* If within the scroll margin, scroll. */ - if (row->y < this_scroll_margin + if (row->y < top_scroll_margin && CHARPOS (startp) != BEGV) scroll_p = 1; } @@ -11838,8 +11913,8 @@ redisplay_window (window, just_this_one_p) buffer. */ || !NILP (Vwindow_scroll_functions) || MINI_WINDOW_P (w) - || !(used_current_matrix_p = - try_window_reusing_current_matrix (w))) + || !(used_current_matrix_p + = try_window_reusing_current_matrix (w))) { IF_DEBUG (debug_method_add (w, "1")); try_window (window, startp); @@ -11968,8 +12043,8 @@ redisplay_window (window, just_this_one_p) || !NILP (Vwindow_scroll_functions) || !just_this_one_p || MINI_WINDOW_P (w) - || !(used_current_matrix_p = - try_window_reusing_current_matrix (w))) + || !(used_current_matrix_p + = try_window_reusing_current_matrix (w))) try_window (window, startp); /* If new fonts have been loaded (due to fontsets), give up. We @@ -12328,10 +12403,36 @@ try_window_reusing_current_matrix (w) last_text_row = last_reused_text_row = NULL; while (it.current_y < it.last_visible_y - && IT_CHARPOS (it) < CHARPOS (start) && !fonts_changed_p) - if (display_line (&it)) - last_text_row = it.glyph_row - 1; + { + /* If we have reached into the characters in the START row, + that means the line boundaries have changed. So we + can't start copying with the row START. Maybe it will + work to start copying with the following row. */ + while (IT_CHARPOS (it) > CHARPOS (start)) + { + /* Advance to the next row as the "start". */ + start_row++; + start = start_row->start.pos; + /* If there are no more rows to try, or just one, give up. */ + if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1 + || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row) + || CHARPOS (start) == ZV) + { + clear_glyph_matrix (w->desired_matrix); + return 0; + } + + start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix); + } + /* If we have reached alignment, + we can copy the rest of the rows. */ + if (IT_CHARPOS (it) == CHARPOS (start)) + break; + + if (display_line (&it)) + last_text_row = it.glyph_row - 1; + } /* A value of current_y < last_visible_y means that we stopped at the previous window start, which in turn means that we @@ -12339,12 +12440,12 @@ try_window_reusing_current_matrix (w) if (it.current_y < it.last_visible_y) { /* IT.vpos always starts from 0; it counts text lines. */ - nrows_scrolled = it.vpos; + nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix)); /* Find PT if not already found in the lines displayed. */ if (w->cursor.vpos < 0) { - int dy = it.current_y - first_row_y; + int dy = it.current_y - start_row->y; row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); row = row_containing_pos (w, PT, row, NULL, dy); @@ -12364,7 +12465,7 @@ try_window_reusing_current_matrix (w) scroll_run_hook will clear the cursor, and use the current matrix to get the height of the row the cursor is in. */ - run.current_y = first_row_y; + run.current_y = start_row->y; run.desired_y = it.current_y; run.height = it.last_visible_y - it.current_y; @@ -12530,9 +12631,8 @@ try_window_reusing_current_matrix (w) position. */ if (pt_row) { - w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row, - w->current_matrix); - w->cursor.y -= first_reusable_row->y; + w->cursor.vpos -= nrows_scrolled; + w->cursor.y -= first_reusable_row->y - start_row->y; } /* Scroll the display. */ @@ -12577,6 +12677,29 @@ try_window_reusing_current_matrix (w) for (row -= nrows_scrolled; row < bottom_row; ++row) row->enabled_p = 0; + /* Point may have moved to a different line, so we cannot assume that + the previous cursor position is valid; locate the correct row. */ + if (pt_row) + { + for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos); + row < bottom_row && PT >= MATRIX_ROW_END_CHARPOS (row); + row++) + { + w->cursor.vpos++; + w->cursor.y = row->y; + } + if (row < bottom_row) + { + struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos; + while (glyph->charpos < PT) + { + w->cursor.hpos++; + w->cursor.x += glyph->pixel_width; + glyph++; + } + } + } + /* Adjust window end. A null value of last_text_row means that the window end is in reused rows which in turn means that only its vpos can have changed. */ @@ -13360,9 +13483,9 @@ try_window_id (w) if ((w->cursor.y < this_scroll_margin && CHARPOS (start) > BEGV) - /* Don't take scroll margin into account at the bottom because - old redisplay didn't do it either. */ - || w->cursor.y + cursor_height > it.last_visible_y) + /* Old redisplay didn't take scroll margin into account at the bottom, + but then global-hl-line-mode doesn't scroll. KFS 2004-06-14 */ + || w->cursor.y + cursor_height + this_scroll_margin > it.last_visible_y) { w->cursor.vpos = -1; clear_glyph_matrix (w->desired_matrix); @@ -14201,7 +14324,7 @@ append_space_for_newline (it, default_face_p) PRODUCE_GLYPHS (it); - it->use_default_face = 0; + it->override_ascent = -1; it->constrain_row_ascent_descent_p = 0; it->current_x = saved_x; it->object = saved_object; @@ -14425,9 +14548,13 @@ display_line (it) /* We always start displaying at hpos zero even if hscrolled. */ xassert (it->hpos == 0 && it->current_x == 0); - /* We must not display in a row that's not a text row. */ - xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix) - < it->w->desired_matrix->nrows); + if (MATRIX_ROW_VPOS (row, it->w->desired_matrix) + >= it->w->desired_matrix->nrows) + { + it->w->nrows_scale_factor++; + fonts_changed_p = 1; + return 0; + } /* Is IT->w showing the region? */ it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil; @@ -15233,6 +15360,10 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) Lisp_Object oprops, aelt; oprops = Ftext_properties_at (make_number (0), elt); + /* If the starting string's properties are not what + we want, translate the string. Also, if the string + is risky, do that anyway. */ + if (NILP (Fequal (props, oprops)) || risky) { /* If the starting string has properties, @@ -15609,7 +15740,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) The mode_line_string_face face property is always added to the string. */ -static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props) +static int +store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props) char *string; Lisp_Object lisp_string; int copy_string; @@ -15691,15 +15823,16 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line, - 0, 3, 0, + 0, 4, 0, doc: /* Return the mode-line of selected window as a string. First optional arg FORMAT specifies a different format string (see `mode-line-format' for details) to use. If FORMAT is t, return the buffer's header-line. Second optional arg WINDOW specifies a different window to use as the context for the formatting. -If third optional arg NO-PROPS is non-nil, string is not propertized. */) - (format, window, no_props) - Lisp_Object format, window, no_props; +If third optional arg NO-PROPS is non-nil, string is not propertized. +Fourth optional arg BUFFER specifies which buffer to use. */) + (format, window, no_props, buffer) + Lisp_Object format, window, no_props, buffer; { struct it it; int len; @@ -15711,42 +15844,46 @@ If third optional arg NO-PROPS is non-nil, string is not propertized. */) window = selected_window; CHECK_WINDOW (window); w = XWINDOW (window); - CHECK_BUFFER (w->buffer); - if (XBUFFER (w->buffer) != current_buffer) + if (NILP (buffer)) + buffer = w->buffer; + + CHECK_BUFFER (buffer); + + if (XBUFFER (buffer) != current_buffer) { old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (w->buffer)); + set_buffer_internal_1 (XBUFFER (buffer)); } if (NILP (format) || EQ (format, Qt)) { - face_id = NILP (format) - ? CURRENT_MODE_LINE_FACE_ID (w) : - HEADER_LINE_FACE_ID; - format = NILP (format) - ? current_buffer->mode_line_format - : current_buffer->header_line_format; + face_id = (NILP (format) + ? CURRENT_MODE_LINE_FACE_ID (w) + : HEADER_LINE_FACE_ID); + format = (NILP (format) + ? current_buffer->mode_line_format + : current_buffer->header_line_format); } init_iterator (&it, w, -1, -1, NULL, face_id); if (NILP (no_props)) { - mode_line_string_face = - (face_id == MODE_LINE_FACE_ID ? Qmode_line : - face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive : - face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil); + mode_line_string_face + = (face_id == MODE_LINE_FACE_ID ? Qmode_line + : face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive + : face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil); - mode_line_string_face_prop = - NILP (mode_line_string_face) ? Qnil : - Fcons (Qface, Fcons (mode_line_string_face, Qnil)); + mode_line_string_face_prop + = (NILP (mode_line_string_face) ? Qnil + : Fcons (Qface, Fcons (mode_line_string_face, Qnil))); /* We need a dummy last element in mode_line_string_list to indicate we are building the propertized mode-line string. Using mode_line_string_face_prop here GC protects it. */ - mode_line_string_list = - Fcons (mode_line_string_face_prop, Qnil); + mode_line_string_list + = Fcons (mode_line_string_face_prop, Qnil); frame_title_ptr = NULL; } else @@ -16019,7 +16156,10 @@ decode_mode_spec_coding (coding_system, buf, eol_flag) 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. Return 1 in *MULTIBYTE - if the result is multibyte text. */ + if the result is multibyte text. + + Note we operate on the current buffer for most purposes, + the exception being w->base_line_pos. */ static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; @@ -16033,7 +16173,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte) Lisp_Object obj; struct frame *f = XFRAME (WINDOW_FRAME (w)); char *decode_mode_spec_buf = f->decode_mode_spec_buffer; - struct buffer *b = XBUFFER (w->buffer); + struct buffer *b = current_buffer; obj = Qnil; *multibyte = 0; @@ -16335,7 +16475,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte) case 's': /* status of process */ - obj = Fget_buffer_process (w->buffer); + obj = Fget_buffer_process (Fcurrent_buffer ()); if (NILP (obj)) return "no process"; #ifdef subprocesses @@ -16362,8 +16502,8 @@ decode_mode_spec (w, c, field_width, precision, multibyte) { /* No need to mention EOL here--the terminal never needs to do EOL conversion. */ - p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0); - p = decode_mode_spec_coding (terminal_coding.symbol, p, 0); + p = decode_mode_spec_coding (FRAME_KEYBOARD_CODING (f)->symbol, p, 0); + p = decode_mode_spec_coding (FRAME_TERMINAL_CODING (f)->symbol, p, 0); } p = decode_mode_spec_coding (b->buffer_file_coding_system, p, eol_flag); @@ -18098,6 +18238,11 @@ append_glyph (it) glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; } + else if (!fonts_changed_p) + { + it->w->ncols_scale_factor++; + fonts_changed_p = 1; + } } /* Store one glyph for the composition IT->cmp_id in IT->glyph_row. @@ -18135,6 +18280,11 @@ append_composite_glyph (it) glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; } + else if (!fonts_changed_p) + { + it->w->ncols_scale_factor++; + fonts_changed_p = 1; + } } @@ -18304,6 +18454,11 @@ produce_image_glyph (it) glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; } + else if (!fonts_changed_p) + { + it->w->ncols_scale_factor++; + fonts_changed_p = 1; + } } } @@ -18347,6 +18502,11 @@ append_stretch_glyph (it, object, width, height, ascent) glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; } + else if (!fonts_changed_p) + { + it->w->ncols_scale_factor++; + fonts_changed_p = 1; + } } @@ -18509,6 +18669,107 @@ produce_stretch_glyph (it) take_vertical_position_into_account (it); } +/* Calculate line-height and line-spacing properties. + An integer value specifies explicit pixel value. + A float value specifies relative value to current face height. + A cons (float . face-name) specifies relative value to + height of specified face font. + + Returns height in pixels, or nil. */ + +static Lisp_Object +calc_line_height_property (it, prop, font, boff, total) + struct it *it; + Lisp_Object prop; + XFontStruct *font; + int boff, *total; +{ + Lisp_Object position, val; + Lisp_Object face_name = Qnil; + int ascent, descent, height, override; + + if (STRINGP (it->object)) + position = make_number (IT_STRING_CHARPOS (*it)); + else + position = make_number (IT_CHARPOS (*it)); + + val = Fget_char_property (position, prop, it->object); + + if (NILP (val)) + return val; + + if (total && CONSP (val) && EQ (XCAR (val), Qtotal)) + { + *total = 1; + val = XCDR (val); + } + + if (INTEGERP (val)) + return val; + + if (CONSP (val)) + { + face_name = XCDR (val); + val = XCAR (val); + } + else if (SYMBOLP (val)) + { + face_name = val; + val = Qnil; + } + + override = EQ (prop, Qline_height); + + if (NILP (face_name)) + { + font = FRAME_FONT (it->f); + boff = FRAME_BASELINE_OFFSET (it->f); + } + else if (EQ (face_name, Qt)) + { + override = 0; + } + else + { + int face_id; + struct face *face; + struct font_info *font_info; + + face_id = lookup_named_face (it->f, face_name, ' '); + if (face_id < 0) + return make_number (-1); + + face = FACE_FROM_ID (it->f, face_id); + font = face->font; + if (font == NULL) + return make_number (-1); + + font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id); + boff = font_info->baseline_offset; + if (font_info->vertical_centering) + boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; + } + + ascent = FONT_BASE (font) + boff; + descent = FONT_DESCENT (font) - boff; + + if (override) + { + it->override_ascent = ascent; + it->override_descent = descent; + it->override_boff = boff; + } + + height = ascent + descent; + if (FLOATP (val)) + height = (int)(XFLOAT_DATA (val) * height); + else if (INTEGERP (val)) + height *= XINT (val); + + return make_number (height); +} + + /* RIF: Produce glyphs/get display metrics for the display element IT is loaded with. See the description of struct display_iterator in @@ -18595,17 +18856,20 @@ x_produce_glyphs (it) it->nglyphs = 1; - if (it->use_default_face) - { - font = FRAME_FONT (it->f); - boff = FRAME_BASELINE_OFFSET (it->f); - } - - pcm = FRAME_RIF (it->f)->per_char_metric + pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b, FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display)); - it->ascent = FONT_BASE (font) + boff; - it->descent = FONT_DESCENT (font) - boff; + if (it->override_ascent >= 0) + { + it->ascent = it->override_ascent; + it->descent = it->override_descent; + boff = it->override_boff; + } + else + { + it->ascent = FONT_BASE (font) + boff; + it->descent = FONT_DESCENT (font) - boff; + } if (pcm) { @@ -18708,26 +18972,27 @@ x_produce_glyphs (it) But if previous part of the line set a height, don't increase that height */ - Lisp_Object lsp, lh; + Lisp_Object height; + it->override_ascent = -1; it->pixel_width = 0; it->nglyphs = 0; - lh = Fget_text_property (make_number (IT_CHARPOS (*it)), - Qline_height, it->object); + height = calc_line_height_property(it, Qline_height, font, boff, 0); - if (EQ (lh, Qt)) + if (it->override_ascent >= 0) { - it->use_default_face = 1; - font = FRAME_FONT (it->f); - boff = FRAME_BASELINE_OFFSET (it->f); - font_info = NULL; + it->ascent = it->override_ascent; + it->descent = it->override_descent; + boff = it->override_boff; + } + else + { + it->ascent = FONT_BASE (font) + boff; + it->descent = FONT_DESCENT (font) - boff; } - it->ascent = FONT_BASE (font) + boff; - it->descent = FONT_DESCENT (font) - boff; - - if (EQ (lh, make_number (0))) + if (EQ (height, make_number(0))) { if (it->descent > it->max_descent) { @@ -18746,7 +19011,9 @@ x_produce_glyphs (it) } else { - int explicit_height = -1; + Lisp_Object spacing; + int total = 0; + it->phys_ascent = it->ascent; it->phys_descent = it->descent; @@ -18757,23 +19024,18 @@ x_produce_glyphs (it) it->ascent += face->box_line_width; it->descent += face->box_line_width; } - if (INTEGERP (lh)) - explicit_height = XINT (lh); - else if (FLOATP (lh)) - explicit_height = (it->phys_ascent + it->phys_descent) - * XFLOAT_DATA (lh); - - if (explicit_height > it->ascent + it->descent) - it->ascent = explicit_height - it->descent; - } + if (!NILP (height) + && XINT (height) > it->ascent + it->descent) + it->ascent = XINT (height) - it->descent; - lsp = Fget_text_property (make_number (IT_CHARPOS (*it)), - Qline_spacing, it->object); - if (INTEGERP (lsp)) - extra_line_spacing = XINT (lsp); - else if (FLOATP (lsp)) - extra_line_spacing = (it->phys_ascent + it->phys_descent) - * XFLOAT_DATA (lsp); + spacing = calc_line_height_property(it, Qline_spacing, font, boff, &total); + if (INTEGERP (spacing)) + { + extra_line_spacing = XINT (spacing); + if (total) + extra_line_spacing -= (it->phys_ascent + it->phys_descent); + } + } } else if (it->char_to_display == '\t') { @@ -19150,7 +19412,8 @@ x_produce_glyphs (it) if (it->area == TEXT_AREA) it->current_x += it->pixel_width; - it->descent += extra_line_spacing; + if (extra_line_spacing > 0) + it->descent += extra_line_spacing; it->max_ascent = max (it->max_ascent, it->ascent); it->max_descent = max (it->max_descent, it->descent); @@ -20520,11 +20783,7 @@ define_frame_cursor1 (f, cursor, pointer) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; } -#ifndef HAVE_CARBON if (cursor != No_Cursor) -#else - if (bcmp (&cursor, &No_Cursor, sizeof (Cursor))) -#endif FRAME_RIF (f)->define_frame_cursor (f, cursor); } @@ -20707,7 +20966,8 @@ note_mouse_highlight (f, x, y) if (part == ON_VERTICAL_BORDER) cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; - else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE) + else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE + || part == ON_SCROLL_BAR) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else cursor = FRAME_X_OUTPUT (f)->text_cursor; @@ -20725,7 +20985,7 @@ note_mouse_highlight (f, x, y) Lisp_Object object; Lisp_Object mouse_face = Qnil, overlay = Qnil, position; Lisp_Object *overlay_vec = NULL; - int len, noverlays; + int noverlays; struct buffer *obuf; int obegv, ozv, same_region; @@ -20812,19 +21072,8 @@ note_mouse_highlight (f, x, y) if (BUFFERP (object)) { - /* Put all the overlays we want in a vector in overlay_vec. - Store the length in len. If there are more than 10, make - enough space for all, and try again. */ - len = 10; - overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); - noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0); - if (noverlays > len) - { - len = noverlays; - overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); - noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0); - } - + /* Put all the overlays we want in a vector in overlay_vec. */ + GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0); /* Sort overlays into increasing priority order. */ noverlays = sort_overlays (overlay_vec, noverlays, w); } @@ -21798,6 +22047,8 @@ syms_of_xdisp () staticpro (&Qcenter); Qline_height = intern ("line-height"); staticpro (&Qline_height); + Qtotal = intern ("total"); + staticpro (&Qtotal); QCalign_to = intern (":align-to"); staticpro (&QCalign_to); QCrelative_width = intern (":relative-width"); @@ -22052,7 +22303,7 @@ 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, - doc: /* List of Functions to call before redisplaying a window with scrolling. + doc: /* 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. */); @@ -22158,11 +22409,6 @@ Note that the lower bound for automatic hscrolling specified by `scroll-left' and `scroll-right' overrides this variable's effect. */); Vhscroll_step = make_number (0); - DEFVAR_LISP ("image-types", &Vimage_types, - doc: /* 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, doc: /* If non-nil, messages are truncated instead of resizing the echo area. Bind this around calls to `message' to let it take effect. */);