X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/518eab2f7db71929e4877daa5ebd06b1416e69e6..bf5ddded70c11edaf3514b25da27fc71cfb8e965:/src/indent.c diff --git a/src/indent.c b/src/indent.c index ce78308c95..bc59239f20 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1,13 +1,13 @@ /* Indentation functions. - Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2015 Free Software + Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,10 +26,8 @@ along with GNU Emacs. If not, see . */ #include "category.h" #include "composite.h" #include "indent.h" -#include "keyboard.h" #include "frame.h" #include "window.h" -#include "termchar.h" #include "disptab.h" #include "intervals.h" #include "dispextern.h" @@ -485,7 +483,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 +504,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; } } @@ -1983,8 +1995,7 @@ whether or not it is currently displayed in some window. */) struct text_pos pt; struct window *w; Lisp_Object old_buffer; - EMACS_INT old_charpos IF_LINT (= 0), old_bytepos IF_LINT (= 0); - struct gcpro gcpro1; + EMACS_INT old_charpos UNINIT, old_bytepos UNINIT; Lisp_Object lcols; void *itdata = NULL; @@ -2000,7 +2011,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. */ @@ -2026,8 +2036,8 @@ whether or not it is currently displayed in some window. */) bool disp_string_at_start_p = 0; ptrdiff_t nlines = XINT (lines); int vpos_init = 0; - double start_col; - int start_x IF_LINT (= 0); + double start_col UNINIT; + int start_x UNINIT; int to_x = -1; bool start_x_given = !NILP (cur_col); @@ -2120,6 +2130,15 @@ whether or not it is currently displayed in some window. */) && it.method == GET_FROM_BUFFER && it.c == '\n') it_overshoot_count = 1; + else if (it_overshoot_count == 1 && it.vpos == 0 + && it.current_x < it.last_visible_x) + { + /* If we came to the same screen line as the one where + we started, we didn't overshoot the line, and won't + need to backtrack after all. This happens, for + example, when PT is in the middle of a composition. */ + it_overshoot_count = 0; + } else if (disp_string_at_start_p && it.vpos > 0) { /* This is the case of a display string that spans @@ -2128,29 +2147,38 @@ whether or not it is currently displayed in some window. */) screen lines we need to backtrack. */ it_overshoot_count = it.vpos; } + /* We will overshoot if lines are truncated and point lies + beyond the right margin of the window. */ + if (it.line_wrap == TRUNCATE && it.current_x >= it.last_visible_x + && it_overshoot_count == 0) + it_overshoot_count = 1; if (it_overshoot_count > 0) move_it_by_lines (&it, -it_overshoot_count); 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); if (nlines <= 0) { it.vpos = vpos_init; + it.current_y = 0; /* Do this even if LINES is 0, so that we move back to the beginning of the current line as we ought. */ if ((nlines < 0 && IT_CHARPOS (it) > 0) @@ -2159,7 +2187,8 @@ whether or not it is currently displayed in some window. */) } else if (overshoot_handled) { - it.vpos = 0; + it.vpos = vpos_init; + it.current_y = 0; move_it_by_lines (&it, min (PTRDIFF_MAX, nlines)); } else @@ -2173,6 +2202,7 @@ whether or not it is currently displayed in some window. */) while (IT_CHARPOS (it) <= it_start) { it.vpos = 0; + it.current_y = 0; move_it_by_lines (&it, 1); } if (nlines > 1) @@ -2181,6 +2211,7 @@ whether or not it is currently displayed in some window. */) else /* it_start = ZV */ { it.vpos = 0; + it.current_y = 0; move_it_by_lines (&it, min (PTRDIFF_MAX, nlines)); /* We could have some display or overlay string at ZV, in which case it.vpos will be nonzero now, while @@ -2194,7 +2225,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 +2258,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); }