X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/a8101f663e6cbff953b67b8bef33bc0171818477..91af3942e9ab5540b3ab4dde6733bc883dc2abdd:/src/indent.c diff --git a/src/indent.c b/src/indent.c index 970904cba7..07a54c0c1b 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1,6 +1,5 @@ /* Indentation functions. - Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1998, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2011 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -38,11 +37,6 @@ along with GNU Emacs. If not, see . */ #include "dispextern.h" #include "region-cache.h" -/* Indentation can insert tabs if this is non-zero; - otherwise always uses spaces. */ - -static int indent_tabs_mode; - #define CR 015 /* These three values memorize the current column to avoid recalculation. */ @@ -51,7 +45,7 @@ static int indent_tabs_mode; Some things in set last_known_column_point to -1 to mark the memorized value as invalid. */ -static double last_known_column; +static EMACS_INT last_known_column; /* Value of point when current_column was called. */ @@ -61,8 +55,8 @@ EMACS_INT last_known_column_point; static int last_known_column_modified; -static double current_column_1 (void); -static double position_indentation (int); +static EMACS_INT current_column_1 (void); +static EMACS_INT position_indentation (ptrdiff_t); /* Cache of beginning of line found by the last call of current_column. */ @@ -76,7 +70,7 @@ buffer_display_table (void) { Lisp_Object thisbuf; - thisbuf = current_buffer->display_table; + thisbuf = BVAR (current_buffer, display_table); if (DISP_TABLE_P (thisbuf)) return XCHAR_TABLE (thisbuf); if (DISP_TABLE_P (Vstandard_display_table)) @@ -99,7 +93,7 @@ character_width (int c, struct Lisp_Char_Table *dp) /* Everything can be handled by the display table, if it's present and the element is right. */ if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt))) - return XVECTOR (elt)->size; + return ASIZE (elt); /* Some characters are special. */ if (c == '\n' || c == '\t' || c == '\015') @@ -127,7 +121,7 @@ disptab_matches_widthtab (struct Lisp_Char_Table *disptab, struct Lisp_Vector *w { int i; - if (widthtab->size != 256) + if (widthtab->header.size != 256) abort (); for (i = 0; i < 256; i++) @@ -146,10 +140,10 @@ recompute_width_table (struct buffer *buf, struct Lisp_Char_Table *disptab) int i; struct Lisp_Vector *widthtab; - if (!VECTORP (buf->width_table)) - buf->width_table = Fmake_vector (make_number (256), make_number (0)); - widthtab = XVECTOR (buf->width_table); - if (widthtab->size != 256) + if (!VECTORP (BVAR (buf, width_table))) + BVAR (buf, width_table) = Fmake_vector (make_number (256), make_number (0)); + widthtab = XVECTOR (BVAR (buf, width_table)); + if (widthtab->header.size != 256) abort (); for (i = 0; i < 256; i++) @@ -162,17 +156,17 @@ recompute_width_table (struct buffer *buf, struct Lisp_Char_Table *disptab) static void width_run_cache_on_off (void) { - if (NILP (current_buffer->cache_long_line_scans) + if (NILP (BVAR (current_buffer, cache_long_line_scans)) /* And, for the moment, this feature doesn't work on multibyte characters. */ - || !NILP (current_buffer->enable_multibyte_characters)) + || !NILP (BVAR (current_buffer, enable_multibyte_characters))) { /* It should be off. */ if (current_buffer->width_run_cache) { free_region_cache (current_buffer->width_run_cache); current_buffer->width_run_cache = 0; - current_buffer->width_table = Qnil; + BVAR (current_buffer, width_table) = Qnil; } } else @@ -277,25 +271,22 @@ skip_invisible (EMACS_INT pos, EMACS_INT *next_boundary_p, EMACS_INT to, Lisp_Ob DP is a display table or NULL. - This macro is used in current_column_1, Fmove_to_column, and + This macro is used in scan_for_column and in compute_motion. */ -#define MULTIBYTE_BYTES_WIDTH(p, dp) \ +#define MULTIBYTE_BYTES_WIDTH(p, dp, bytes, width) \ do { \ - int c; \ + int ch; \ \ - wide_column = 0; \ - c = STRING_CHAR_AND_LENGTH (p, bytes); \ + ch = STRING_CHAR_AND_LENGTH (p, bytes); \ if (BYTES_BY_CHAR_HEAD (*p) != bytes) \ width = bytes * 4; \ else \ { \ - if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \ - width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \ + if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, ch))) \ + width = sanitize_char_width (ASIZE (DISP_CHAR_VECTOR (dp, ch))); \ else \ - width = CHAR_WIDTH (c); \ - if (width > 1) \ - wide_column = width; \ + width = CHAR_WIDTH (ch); \ } \ } while (0) @@ -315,7 +306,7 @@ Text that has an invisible property is considered as having width 0, unless (void) { Lisp_Object temp; - XSETFASTINT (temp, (int) current_column ()); /* iftc */ + XSETFASTINT (temp, current_column ()); return temp; } @@ -327,16 +318,16 @@ invalidate_current_column (void) last_known_column_point = 0; } -double +EMACS_INT current_column (void) { - register int col; + register EMACS_INT col; register unsigned char *ptr, *stop; register int tab_seen; - int post_tab; + EMACS_INT post_tab; register int c; - register int tab_width = XINT (current_buffer->tab_width); - int ctl_arrow = !NILP (current_buffer->ctl_arrow); + int tab_width = SANE_TAB_WIDTH (current_buffer); + int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow)); register struct Lisp_Char_Table *dp = buffer_display_table (); if (PT == last_known_column_point @@ -365,9 +356,6 @@ current_column (void) else stop = GAP_END_ADDR; - if (tab_width <= 0 || tab_width > 1000) - tab_width = 8; - col = 0, tab_seen = 0, post_tab = 0; while (1) @@ -423,7 +411,7 @@ current_column (void) col++; else if (c == '\n' || (c == '\r' - && EQ (current_buffer->selective_display, Qt))) + && EQ (BVAR (current_buffer, selective_display), Qt))) { ptr++; goto start_of_line_found; @@ -483,7 +471,7 @@ check_display_width (EMACS_INT pos, EMACS_INT col, EMACS_INT *endpos) if (CONSP (val = get_char_property_and_overlay (make_number (pos), Qdisplay, Qnil, &overlay)) && EQ (Qspace, XCAR (val))) - { /* FIXME: Use calc_pixel_width_or_height, as in term.c. */ + { /* FIXME: Use calc_pixel_width_or_height. */ Lisp_Object plist = XCDR (val), prop; int width = -1; @@ -518,10 +506,10 @@ check_display_width (EMACS_INT pos, EMACS_INT col, EMACS_INT *endpos) static void scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol) { - register EMACS_INT tab_width = XINT (current_buffer->tab_width); - register int ctl_arrow = !NILP (current_buffer->ctl_arrow); + int tab_width = SANE_TAB_WIDTH (current_buffer); + register int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow)); register struct Lisp_Char_Table *dp = buffer_display_table (); - int multibyte = !NILP (current_buffer->enable_multibyte_characters); + int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); struct composition_it cmp_it; Lisp_Object window; struct window *w; @@ -544,7 +532,6 @@ scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol) window = Fget_buffer_window (Fcurrent_buffer (), Qnil); w = ! NILP (window) ? XWINDOW (window) : NULL; - if (tab_width <= 0 || tab_width > 1000) tab_width = 8; memset (&cmp_it, 0, sizeof cmp_it); cmp_it.id = -1; composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil); @@ -575,14 +562,14 @@ scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol) prev_col = col; { /* Check display property. */ - EMACS_INT end; - int width = check_display_width (scan, col, &end); + EMACS_INT endp; + int width = check_display_width (scan, col, &endp); if (width >= 0) { col += width; - if (end > scan) /* Avoid infinite loops with 0-width overlays. */ + if (endp > scan) /* Avoid infinite loops with 0-width overlays. */ { - scan = end; scan_byte = charpos_to_bytepos (scan); + scan = endp; scan_byte = charpos_to_bytepos (scan); continue; } } @@ -643,7 +630,7 @@ scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol) if (c == '\n') goto endloop; - if (c == '\r' && EQ (current_buffer->selective_display, Qt)) + if (c == '\r' && EQ (BVAR (current_buffer, selective_display), Qt)) goto endloop; if (c == '\t') { @@ -661,7 +648,7 @@ scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol) if (c == '\n') goto endloop; - if (c == '\r' && EQ (current_buffer->selective_display, Qt)) + if (c == '\r' && EQ (BVAR (current_buffer, selective_display), Qt)) goto endloop; if (c == '\t') { @@ -672,10 +659,10 @@ scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol) { /* Start of multi-byte form. */ unsigned char *ptr; - int bytes, width, wide_column; + int bytes, width; ptr = BYTE_POS_ADDR (scan_byte); - MULTIBYTE_BYTES_WIDTH (ptr, dp); + MULTIBYTE_BYTES_WIDTH (ptr, dp, bytes, width); /* Subtract one to compensate for the increment that is going to happen below. */ scan_byte += bytes - 1; @@ -711,7 +698,7 @@ scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol) This function handles characters that are invisible due to text properties or overlays. */ -static double +static EMACS_INT current_column_1 (void) { EMACS_INT col = MOST_POSITIVE_FIXNUM; @@ -729,15 +716,14 @@ current_column_1 (void) If END is nil, that stands for the end of STRING. */ static double -string_display_width (string, beg, end) - Lisp_Object string, beg, end; +string_display_width (Lisp_Object string, Lisp_Object beg, Lisp_Object end) { register int col; register unsigned char *ptr, *stop; register int tab_seen; int post_tab; register int c; - register int tab_width = XINT (current_buffer->tab_width); + int tab_width = SANE_TAB_WIDTH (current_buffer); int ctl_arrow = !NILP (current_buffer->ctl_arrow); register struct Lisp_Char_Table *dp = buffer_display_table (); int b, e; @@ -764,8 +750,6 @@ string_display_width (string, beg, end) going backwards from point. */ stop = SDATA (string) + b; - if (tab_width <= 0 || tab_width > 1000) tab_width = 8; - col = 0, tab_seen = 0, post_tab = 0; while (1) @@ -775,7 +759,7 @@ string_display_width (string, beg, end) c = *--ptr; if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) - col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; + col += ASIZE (DISP_CHAR_VECTOR (dp, c)); else if (c >= 040 && c < 0177) col++; else if (c == '\n') @@ -813,9 +797,9 @@ even if that goes past COLUMN; by default, MINIMUM is zero. The return value is COLUMN. */) (Lisp_Object column, Lisp_Object minimum) { - int mincol; - register int fromcol; - register int tab_width = XINT (current_buffer->tab_width); + EMACS_INT mincol; + register EMACS_INT fromcol; + int tab_width = SANE_TAB_WIDTH (current_buffer); CHECK_NUMBER (column); if (NILP (minimum)) @@ -829,8 +813,6 @@ The return value is COLUMN. */) if (fromcol == mincol) return make_number (mincol); - if (tab_width <= 0 || tab_width > 1000) tab_width = 8; - if (indent_tabs_mode) { Lisp_Object n; @@ -855,8 +837,6 @@ The return value is COLUMN. */) } -static double position_indentation (int); - DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation, 0, 0, 0, doc: /* Return the indentation of the current line. @@ -865,28 +845,26 @@ following any initial whitespace. */) (void) { Lisp_Object val; - int opoint = PT, opoint_byte = PT_BYTE; + EMACS_INT opoint = PT, opoint_byte = PT_BYTE; scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1); - XSETFASTINT (val, (int) position_indentation (PT_BYTE)); /* iftc */ + XSETFASTINT (val, position_indentation (PT_BYTE)); SET_PT_BOTH (opoint, opoint_byte); return val; } -static double -position_indentation (register int pos_byte) +static EMACS_INT +position_indentation (ptrdiff_t pos_byte) { register EMACS_INT column = 0; - register EMACS_INT tab_width = XINT (current_buffer->tab_width); + int tab_width = SANE_TAB_WIDTH (current_buffer); register unsigned char *p; register unsigned char *stop; unsigned char *start; EMACS_INT next_boundary_byte = pos_byte; EMACS_INT ceiling = next_boundary_byte; - if (tab_width <= 0 || tab_width > 1000) tab_width = 8; - p = BYTE_POS_ADDR (pos_byte); /* STOP records the value of P at which we will need to think about the gap, or about invisible text, @@ -930,7 +908,7 @@ position_indentation (register int pos_byte) switch (*p++) { case 0240: - if (! NILP (current_buffer->enable_multibyte_characters)) + if (! NILP (BVAR (current_buffer, enable_multibyte_characters))) return column; case ' ': column++; @@ -940,7 +918,7 @@ position_indentation (register int pos_byte) break; default: if (ASCII_BYTE_P (p[-1]) - || NILP (current_buffer->enable_multibyte_characters)) + || NILP (BVAR (current_buffer, enable_multibyte_characters))) return column; { int c; @@ -964,10 +942,10 @@ position_indentation (register int pos_byte) preceding line. */ int -indented_beyond_p (int pos, int pos_byte, double column) +indented_beyond_p (EMACS_INT pos, EMACS_INT pos_byte, EMACS_INT column) { - double val; - int opoint = PT, opoint_byte = PT_BYTE; + EMACS_INT val; + EMACS_INT opoint = PT, opoint_byte = PT_BYTE; SET_PT_BOTH (pos, pos_byte); while (PT > BEGV && FETCH_BYTE (PT_BYTE) == '\n') @@ -975,7 +953,7 @@ indented_beyond_p (int pos, int pos_byte, double column) val = position_indentation (PT_BYTE); SET_PT_BOTH (opoint, opoint_byte); - return val >= column; /* hmm, float comparison */ + return val >= column; } DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p", @@ -1055,7 +1033,7 @@ The return value is the current column. */) /* compute_motion: compute buffer posn given screen posn and vice versa */ -struct position val_compute_motion; +static struct position val_compute_motion; /* Scan the current buffer forward from offset FROM, pretending that this is at line FROMVPOS, column FROMHPOS, until reaching buffer @@ -1113,8 +1091,8 @@ struct position val_compute_motion; WINDOW_HAS_VERTICAL_SCROLL_BAR (window) and frame_cols = FRAME_COLS (XFRAME (window->frame)) - Or you can let window_box_text_cols do this all for you, and write: - window_box_text_cols (w) - 1 + Or you can let window_body_cols do this all for you, and write: + window_body_cols (w) - 1 The `-1' accounts for the continuation-line backslashes; the rest accounts for window borders if the window is split horizontally, and @@ -1129,16 +1107,16 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ register EMACS_INT pos; EMACS_INT pos_byte; register int c = 0; - register EMACS_INT tab_width = XFASTINT (current_buffer->tab_width); - register int ctl_arrow = !NILP (current_buffer->ctl_arrow); + int tab_width = SANE_TAB_WIDTH (current_buffer); + register int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow)); register struct Lisp_Char_Table *dp = window_display_table (win); - int selective - = (INTEGERP (current_buffer->selective_display) - ? XINT (current_buffer->selective_display) - : !NILP (current_buffer->selective_display) ? -1 : 0); + EMACS_INT selective + = (INTEGERP (BVAR (current_buffer, selective_display)) + ? XINT (BVAR (current_buffer, selective_display)) + : !NILP (BVAR (current_buffer, selective_display)) ? -1 : 0); int selective_rlen = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp)) - ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0); + ? ASIZE (DISP_INVIS_VECTOR (dp)) : 0); /* The next location where the `invisible' property changes, or an overlay starts or ends. */ EMACS_INT next_boundary = from; @@ -1157,7 +1135,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ EMACS_INT next_width_run = from; Lisp_Object window; - int multibyte = !NILP (current_buffer->enable_multibyte_characters); + int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); /* If previous char scanned was a wide character, this is the column where it ended. Otherwise, this is 0. */ EMACS_INT wide_column_end_hpos = 0; @@ -1176,21 +1154,18 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ width_run_cache_on_off (); if (dp == buffer_display_table ()) - width_table = (VECTORP (current_buffer->width_table) - ? XVECTOR (current_buffer->width_table)->contents + width_table = (VECTORP (BVAR (current_buffer, width_table)) + ? XVECTOR (BVAR (current_buffer, width_table))->contents : 0); else /* If the window has its own display table, we can't use the width run cache, because that's based on the buffer's display table. */ width_table = 0; - if (tab_width <= 0 || tab_width > 1000) - tab_width = 8; - /* Negative width means use all available text columns. */ if (width < 0) { - width = window_box_text_cols (win); + width = window_body_cols (win); /* We must make room for continuation marks if we don't have fringes. */ #ifdef HAVE_WINDOW_SYSTEM if (!FRAME_WINDOW_P (XFRAME (win->frame))) @@ -1254,9 +1229,9 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ to be changed here. */ { unsigned char *ovstr; - int ovlen = overlay_strings (pos, win, &ovstr); + EMACS_INT ovlen = overlay_strings (pos, win, &ovstr); hpos += ((multibyte && ovlen > 0) - ? strwidth (ovstr, ovlen) : ovlen); + ? strwidth ((char *) ovstr, ovlen) : ovlen); } did_motion = 0; @@ -1343,7 +1318,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ } if (hscroll || truncate - || !NILP (current_buffer->truncate_lines)) + || !NILP (BVAR (current_buffer, truncate_lines))) { /* Truncating: skip to newline, unless we are already past TO (we need to go back below). */ @@ -1448,7 +1423,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ the text character-by-character. */ if (current_buffer->width_run_cache && pos >= next_width_run) { - int run_end; + ptrdiff_t run_end; int common_width = region_cache_forward (current_buffer, current_buffer->width_run_cache, @@ -1459,7 +1434,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ want to skip over it for some other reason. */ if (common_width != 0) { - int run_end_hpos; + EMACS_INT run_end_hpos; /* Don't go past the final buffer posn the user requested. */ @@ -1568,7 +1543,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ n = 1; } - for (i = n - 1; i >= 0; --i) + for (i = 0; i < n; ++i) { if (VECTORP (charvec)) { @@ -1596,8 +1571,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ else if (c == '\n') { if (selective > 0 - && indented_beyond_p (pos, pos_byte, - (double) selective)) /* iftc */ + && indented_beyond_p (pos, pos_byte, selective)) { /* If (pos == to), we don't have to take care of selective display. */ @@ -1613,7 +1587,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ } while (pos < to && indented_beyond_p (pos, pos_byte, - (double) selective)); /* iftc */ + selective)); /* Allow for the " ..." that is displayed for them. */ if (selective_rlen) { @@ -1666,15 +1640,15 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ { /* Start of multi-byte form. */ unsigned char *ptr; - int bytes, width, wide_column; + int mb_bytes, mb_width; pos_byte--; /* rewind POS_BYTE */ ptr = BYTE_POS_ADDR (pos_byte); - MULTIBYTE_BYTES_WIDTH (ptr, dp); - pos_byte += bytes; - if (wide_column) - wide_column_end_hpos = hpos + wide_column; - hpos += width; + MULTIBYTE_BYTES_WIDTH (ptr, dp, mb_bytes, mb_width); + pos_byte += mb_bytes; + if (mb_width > 1 && BYTES_BY_CHAR_HEAD (*ptr) == mb_bytes) + wide_column_end_hpos = hpos + mb_width; + hpos += mb_width; } else if (VECTORP (charvec)) ++hpos; @@ -1701,7 +1675,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ val_compute_motion.prevhpos = contin_hpos; else val_compute_motion.prevhpos = prev_hpos; - /* We alalways handle all of them here; none of them remain to do. */ + /* We always handle all of them here; none of them remain to do. */ val_compute_motion.ovstring_chars_done = 0; /* Nonzero if have just continued a line */ @@ -1759,7 +1733,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) struct window *w; Lisp_Object bufpos, hpos, vpos, prevhpos; struct position *pos; - int hscroll, tab_offset; + EMACS_INT hscroll, tab_offset; CHECK_NUMBER_COERCE_MARKER (from); CHECK_CONS (frompos); @@ -1804,7 +1778,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) ? window_internal_height (w) : XINT (XCDR (topos))), (NILP (topos) - ? (window_box_text_cols (w) + ? (window_body_cols (w) - ( #ifdef HAVE_WINDOW_SYSTEM FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 : @@ -1830,7 +1804,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) /* Fvertical_motion and vmotion */ -struct position val_vmotion; +static struct position val_vmotion; struct position * vmotion (register EMACS_INT from, register EMACS_INT vtarget, struct window *w) @@ -1843,10 +1817,10 @@ vmotion (register EMACS_INT from, register EMACS_INT vtarget, struct window *w) register EMACS_INT first; EMACS_INT from_byte; EMACS_INT lmargin = hscroll > 0 ? 1 - hscroll : 0; - int selective - = (INTEGERP (current_buffer->selective_display) - ? XINT (current_buffer->selective_display) - : !NILP (current_buffer->selective_display) ? -1 : 0); + EMACS_INT selective + = (INTEGERP (BVAR (current_buffer, selective_display)) + ? XINT (BVAR (current_buffer, selective_display)) + : !NILP (BVAR (current_buffer, selective_display)) ? -1 : 0); Lisp_Object window; EMACS_INT start_hpos = 0; int did_motion; @@ -1878,7 +1852,7 @@ vmotion (register EMACS_INT from, register EMACS_INT vtarget, struct window *w) && ((selective > 0 && indented_beyond_p (prevline, CHAR_TO_BYTE (prevline), - (double) selective)) /* iftc */ + selective)) /* Watch out for newlines with `invisible' property. When moving upward, check the newline before. */ || (propval = Fget_char_property (make_number (prevline - 1), @@ -1935,7 +1909,7 @@ vmotion (register EMACS_INT from, register EMACS_INT vtarget, struct window *w) && ((selective > 0 && indented_beyond_p (prevline, CHAR_TO_BYTE (prevline), - (double) selective)) /* iftc */ + selective)) /* Watch out for newlines with `invisible' property. When moving downward, check the newline after. */ || (propval = Fget_char_property (make_number (prevline), @@ -2002,9 +1976,11 @@ whether or not it is currently displayed in some window. */) struct text_pos pt; struct window *w; Lisp_Object old_buffer; - struct gcpro gcpro1; + EMACS_INT old_charpos IF_LINT (= 0), old_bytepos IF_LINT (= 0); + struct gcpro gcpro1, gcpro2, gcpro3; Lisp_Object lcols = Qnil; - double cols; + double cols IF_LINT (= 0); + void *itdata = NULL; /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */ if (CONSP (lines) && (NUMBERP (XCAR (lines)))) @@ -2022,12 +1998,16 @@ whether or not it is currently displayed in some window. */) w = XWINDOW (window); old_buffer = Qnil; - GCPRO1 (old_buffer); + GCPRO3 (old_buffer, old_charpos, old_bytepos); if (XBUFFER (w->buffer) != current_buffer) { /* Set the window's buffer temporarily to the current buffer. */ old_buffer = w->buffer; + old_charpos = XMARKER (w->pointm)->charpos; + old_bytepos = XMARKER (w->pointm)->bytepos; XSETBUFFER (w->buffer, current_buffer); + set_marker_both + (w->pointm, w->buffer, BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer)); } if (noninteractive) @@ -2038,30 +2018,34 @@ whether or not it is currently displayed in some window. */) } else { - int it_start, first_x, it_overshoot_expected; + EMACS_INT it_start; + int first_x, it_overshoot_count = 0; + int overshoot_handled = 0; + itdata = bidi_shelve_cache (); SET_TEXT_POS (pt, PT, PT_BYTE); start_display (&it, w, pt); first_x = it.first_visible_x; it_start = IT_CHARPOS (it); /* See comments below for why we calculate this. */ - if (XINT (lines) > 0) + if (it.cmp_it.id >= 0) + it_overshoot_count = 0; + else if (it.method == GET_FROM_STRING) { - if (it.cmp_it.id >= 0) - it_overshoot_expected = 1; - else if (it.method == GET_FROM_STRING) + const char *s = SSDATA (it.string); + const char *e = s + SBYTES (it.string); + while (s < e) { - const char *s = SDATA (it.string); - const char *e = s + SBYTES (it.string); - while (s < e && *s != '\n') - ++s; - it_overshoot_expected = (s == e) ? -1 : 0; + if (*s++ == '\n') + it_overshoot_count++; } - else - it_overshoot_expected = (it.method == GET_FROM_IMAGE - || it.method == GET_FROM_STRETCH); + if (!it_overshoot_count) + it_overshoot_count = -1; } + else + it_overshoot_count = + !(it.method == GET_FROM_IMAGE || it.method == GET_FROM_STRETCH); /* Scan from the start of the line containing PT. If we don't do this, we start moving with IT->current_x == 0, while PT is @@ -2075,55 +2059,58 @@ whether or not it is currently displayed in some window. */) tell, and it causes Bug#2694 . -- cyd */ move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); + /* IT may move too far if truncate-lines is on and PT lies + beyond the right margin. IT may also move too far if the + starting point is on a Lisp string that has embedded + newlines. In these cases, backtrack. */ + if (IT_CHARPOS (it) > it_start) + { + /* We need to backtrack also if the Lisp string contains no + newlines, but there is a newline right after it. In this + case, IT overshoots if there is an after-string just + before the newline. */ + if (it_overshoot_count < 0 + && it.method == GET_FROM_BUFFER + && it.c == '\n') + it_overshoot_count = 1; + if (it_overshoot_count > 0) + move_it_by_lines (&it, -it_overshoot_count); + + overshoot_handled = 1; + } if (XINT (lines) <= 0) { it.vpos = 0; /* Do this even if LINES is 0, so that we move back to the beginning of the current line as we ought. */ if (XINT (lines) == 0 || IT_CHARPOS (it) > 0) - move_it_by_lines (&it, XINT (lines), 0); + move_it_by_lines (&it, max (INT_MIN, XINT (lines))); + } + else if (overshoot_handled) + { + it.vpos = 0; + move_it_by_lines (&it, min (INT_MAX, XINT (lines))); } else { - if (IT_CHARPOS (it) > it_start) - { - /* IT may move too far if truncate-lines is on and PT - lies beyond the right margin. In that case, - backtrack unless the starting point is on an image, - stretch glyph, composition, or Lisp string. */ - if (!it_overshoot_expected - /* Also, backtrack if the Lisp string contains no - newline, but there is a newline right after it. - In this case, IT overshoots if there is an - after-string just before the newline. */ - || (it_overshoot_expected < 0 - && it.method == GET_FROM_BUFFER - && it.c == '\n')) - move_it_by_lines (&it, -1, 0); - it.vpos = 0; - move_it_by_lines (&it, XINT (lines), 0); - } - else + /* Otherwise, we are at the first row occupied by PT, which + might span multiple screen lines (e.g., if it's on a + multi-line display string). We want to start from the + last line that it occupies. */ + if (it_start < ZV) { - /* Otherwise, we are at the first row occupied by PT, - which might span multiple screen lines (e.g., if it's - on a multi-line display string). We want to start - from the last line that it occupies. */ - if (it_start < ZV) - { - while (IT_CHARPOS (it) <= it_start) - { - it.vpos = 0; - move_it_by_lines (&it, 1, 0); - } - if (XINT (lines) > 1) - move_it_by_lines (&it, XINT (lines) - 1, 0); - } - else + while (IT_CHARPOS (it) <= it_start) { it.vpos = 0; - move_it_by_lines (&it, XINT (lines), 0); + move_it_by_lines (&it, 1); } + if (XINT (lines) > 1) + move_it_by_lines (&it, min (INT_MAX, XINT (lines) - 1)); + } + else + { + it.vpos = 0; + move_it_by_lines (&it, min (INT_MAX, XINT (lines))); } } @@ -2144,10 +2131,14 @@ whether or not it is currently displayed in some window. */) } SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); + bidi_unshelve_cache (itdata, 0); } if (BUFFERP (old_buffer)) - w->buffer = old_buffer; + { + w->buffer = old_buffer; + set_marker_both (w->pointm, w->buffer, old_charpos, old_bytepos); + } RETURN_UNGCPRO (make_number (it.vpos)); } @@ -2159,7 +2150,7 @@ whether or not it is currently displayed in some window. */) void syms_of_indent (void) { - DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode, + DEFVAR_BOOL ("indent-tabs-mode", indent_tabs_mode, doc: /* *Indentation can insert tabs if this is non-nil. */); indent_tabs_mode = 1; @@ -2170,6 +2161,3 @@ syms_of_indent (void) defsubr (&Svertical_motion); defsubr (&Scompute_motion); } - -/* arch-tag: 9adfea44-71f7-4988-8ee3-96da15c502cc - (do not change this comment) */