X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/b6964cb031b5aa25c34b06ba77540ab06fab2005..a00634c20988215a47ec6c00cea85a2eac162597:/src/indent.c diff --git a/src/indent.c b/src/indent.c index ce78308c95..584f2179bc 100644 --- a/src/indent.c +++ b/src/indent.c @@ -485,7 +485,9 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos) : MOST_POSITIVE_FIXNUM); if ((prop = Fplist_get (plist, QCwidth), - RANGED_INTEGERP (0, prop, INT_MAX))) + RANGED_INTEGERP (0, prop, INT_MAX)) + || (prop = Fplist_get (plist, QCrelative_width), + RANGED_INTEGERP (0, prop, INT_MAX))) width = XINT (prop); else if (FLOATP (prop) && 0 <= XFLOAT_DATA (prop) && XFLOAT_DATA (prop) <= INT_MAX) @@ -504,6 +506,18 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos) *endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); else get_property_and_range (pos, Qdisplay, &val, &start, endpos, Qnil); + + /* For :relative-width, we need to multiply by the column + width of the character at POS, if it is greater than 1. */ + if (!NILP (Fplist_get (plist, QCrelative_width)) + && !NILP (BVAR (current_buffer, enable_multibyte_characters))) + { + int b, wd; + unsigned char *p = BYTE_POS_ADDR (CHAR_TO_BYTE (pos)); + + MULTIBYTE_BYTES_WIDTH (p, buffer_display_table (), b, wd); + width *= wd; + } return width; } } @@ -1984,7 +1998,6 @@ whether or not it is currently displayed in some window. */) struct window *w; Lisp_Object old_buffer; EMACS_INT old_charpos IF_LINT (= 0), old_bytepos IF_LINT (= 0); - struct gcpro gcpro1; Lisp_Object lcols; void *itdata = NULL; @@ -2000,7 +2013,6 @@ whether or not it is currently displayed in some window. */) w = decode_live_window (window); old_buffer = Qnil; - GCPRO1 (old_buffer); if (XBUFFER (w->contents) != current_buffer) { /* Set the window's buffer temporarily to the current buffer. */ @@ -2134,17 +2146,20 @@ whether or not it is currently displayed in some window. */) overshoot_handled = 1; } else if (IT_CHARPOS (it) == PT - 1 - && FETCH_BYTE (PT - 1) == '\n' - && nlines < 0) + && FETCH_BYTE (PT_BYTE - 1) == '\n' + && nlines <= 0) { /* The position we started from was covered by a display property, so we moved to position before the string, and - backed up one line, because the character at PT - 1 is a - newline. So we need one less line to go up. */ + backed up one line, because the character at PT - 1 is + a newline. So we need one less line to go up (or exactly + one line to go down if nlines == 0). */ nlines++; /* But we still need to record that one line, in order to return the correct value to the caller. */ vpos_init = -1; + + overshoot_handled = 1; } if (lcols_given) to_x = window_column_x (w, window, extract_float (lcols), lcols); @@ -2159,7 +2174,7 @@ whether or not it is currently displayed in some window. */) } else if (overshoot_handled) { - it.vpos = 0; + it.vpos = vpos_init; move_it_by_lines (&it, min (PTRDIFF_MAX, nlines)); } else @@ -2194,7 +2209,27 @@ whether or not it is currently displayed in some window. */) was originally hscrolled, the goal column is interpreted as an addition to the hscroll amount. */ if (lcols_given) - move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X); + { + move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X); + /* If we find ourselves in the middle of an overlay string + which includes a newline after current string position, + we need to move by lines until we get out of the string, + and then reposition point at the requested X coordinate; + if we don't, the cursor will be placed just after the + string, which might not be the requested column. */ + if (nlines > 0 && it.area == TEXT_AREA) + { + while (it.method == GET_FROM_STRING + && !it.string_from_display_prop_p + && memchr (SSDATA (it.string) + IT_STRING_BYTEPOS (it), + '\n', + SBYTES (it.string) - IT_STRING_BYTEPOS (it))) + { + move_it_by_lines (&it, 1); + move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X); + } + } + } SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); bidi_unshelve_cache (itdata, 0); @@ -2207,7 +2242,7 @@ whether or not it is currently displayed in some window. */) old_charpos, old_bytepos); } - RETURN_UNGCPRO (make_number (it.vpos)); + return make_number (it.vpos); }