Mercurial > emacs
changeset 36846:89efd94a5832
(current_column, current_column_1, Fmove_to_column)
(compute_motion): Handle characters from display vectors
differently.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Fri, 16 Mar 2001 13:33:17 +0000 |
parents | 10226e5798e3 |
children | 581b627c7eb0 |
files | src/indent.c |
diffstat | 1 files changed, 308 insertions(+), 183 deletions(-) [+] |
line wrap: on
line diff
--- a/src/indent.c Fri Mar 16 12:56:13 2001 +0000 +++ b/src/indent.c Fri Mar 16 13:33:17 2001 +0000 @@ -1,5 +1,6 @@ /* Indentation functions. - Copyright (C) 1985,86,87,88,93,94,95,98 Free Software Foundation, Inc. + Copyright (C) 1985,86,87,88,93,94,95,98, 2000, 2001 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -18,7 +19,6 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - #include <config.h> #include "lisp.h" #include "buffer.h" @@ -35,7 +35,8 @@ #include "region-cache.h" /* Indentation can insert tabs if this is non-zero; - otherwise always uses spaces */ + otherwise always uses spaces. */ + int indent_tabs_mode; #define min(a, b) ((a) < (b) ? (a) : (b)) @@ -43,21 +44,28 @@ #define CR 015 -/* These three values memoize the current column to avoid recalculation */ -/* Some things in set last_known_column_point to -1 - to mark the memoized value as invalid */ -/* Last value returned by current_column */ +/* These three values memoize the current column to avoid recalculation. */ + +/* Last value returned by current_column. + Some things in set last_known_column_point to -1 + to mark the memoized value as invalid. */ + int last_known_column; -/* Value of point when current_column was called */ + +/* Value of point when current_column was called. */ + int last_known_column_point; -/* Value of MODIFF when current_column was called */ + +/* Value of MODIFF when current_column was called. */ + int last_known_column_modified; -static int current_column_1 (); -static int position_indentation (); +static int current_column_1 P_ ((void)); +static int position_indentation P_ ((int)); /* Cache of beginning of line found by the last call of current_column. */ + int current_column_bol_cache; /* Get the display table to use for the current buffer. */ @@ -114,6 +122,7 @@ /* Return true iff the display table DISPTAB specifies the same widths for characters as WIDTHTAB. We use this to decide when to invalidate the buffer's width_run_cache. */ + int disptab_matches_widthtab (disptab, widthtab) struct Lisp_Char_Table *disptab; @@ -133,6 +142,7 @@ } /* Recompute BUF's width table, using the display table DISPTAB. */ + void recompute_width_table (buf, disptab) struct buffer *buf; @@ -153,6 +163,7 @@ /* Allocate or free the width run cache, as requested by the current state of current_buffer's cache_long_line_scans variable. */ + static void width_run_cache_on_off () { @@ -382,49 +393,85 @@ else stop = GAP_END_ADDR; - if (tab_width <= 0 || tab_width > 1000) tab_width = 8; + if (tab_width <= 0 || tab_width > 1000) + tab_width = 8; col = 0, tab_seen = 0, post_tab = 0; while (1) { + EMACS_INT i, n; + Lisp_Object charvec; + if (ptr == stop) { /* We stopped either for the beginning of the buffer or for the gap. */ if (ptr == BEGV_ADDR) break; + /* It was the gap. Jump back over it. */ stop = BEGV_ADDR; ptr = GPT_ADDR; + /* Check whether that brings us to beginning of buffer. */ - if (BEGV >= GPT) break; + if (BEGV >= GPT) + break; } c = *--ptr; - if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) - col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; - else if (c >= 040 && c < 0177) - col++; - else if (c == '\n' - || (c == '\r' && EQ (current_buffer->selective_display, Qt))) + + if (dp && VECTORP (DISP_CHAR_VECTOR (dp, c))) { - ptr++; - break; - } - else if (c == '\t') - { - if (tab_seen) - col = ((col + tab_width) / tab_width) * tab_width; - - post_tab += col; - col = 0; - tab_seen = 1; + charvec = DISP_CHAR_VECTOR (dp, c); + n = ASIZE (charvec); } else - col += (ctl_arrow && c < 0200) ? 2 : 4; + { + charvec = Qnil; + n = 1; + } + + for (i = n - 1; i >= 0; --i) + { + if (VECTORP (charvec)) + { + /* This should be handled the same as + next_element_from_display_vector does it. */ + Lisp_Object entry = AREF (charvec, i); + + if (INTEGERP (entry) + && GLYPH_CHAR_VALID_P (XFASTINT (entry))) + c = FAST_GLYPH_CHAR (XFASTINT (entry)); + else + c = ' '; + } + + if (c >= 040 && c < 0177) + col++; + else if (c == '\n' + || (c == '\r' + && EQ (current_buffer->selective_display, Qt))) + { + ptr++; + goto start_of_line_found; + } + else if (c == '\t') + { + if (tab_seen) + col = ((col + tab_width) / tab_width) * tab_width; + + post_tab += col; + col = 0; + tab_seen = 1; + } + else + col += (ctl_arrow && c < 0200) ? 2 : 4; + } } + start_of_line_found: + if (tab_seen) { col = ((col + tab_width) / tab_width) * tab_width; @@ -475,6 +522,8 @@ while (scan < opoint) { int c; + EMACS_INT i, n; + Lisp_Object charvec; /* Occasionally we may need to skip invisible text. */ while (scan == next_boundary) @@ -506,44 +555,65 @@ } c = FETCH_BYTE (scan_byte); + if (dp != 0 && ! (multibyte && BASE_LEADING_CODE_P (c)) && VECTORP (DISP_CHAR_VECTOR (dp, c))) { - col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; + charvec = DISP_CHAR_VECTOR (dp, c); + n = ASIZE (charvec); + } + else + { + charvec = Qnil; + n = 1; + } + + for (i = n - 1; i >= 0; --i) + { + if (VECTORP (charvec)) + { + /* This should be handled the same as + next_element_from_display_vector does it. */ + Lisp_Object entry = AREF (charvec, i); + + if (INTEGERP (entry) + && GLYPH_CHAR_VALID_P (XFASTINT (entry))) + c = FAST_GLYPH_CHAR (XFASTINT (entry)); + else + c = ' '; + } + + if (c == '\n') + goto endloop; + if (c == '\r' && EQ (current_buffer->selective_display, Qt)) + goto endloop; scan++; scan_byte++; - continue; - } - if (c == '\n') - break; - if (c == '\r' && EQ (current_buffer->selective_display, Qt)) - break; - scan++; - scan_byte++; - if (c == '\t') - { - int prev_col = col; - col += tab_width; - col = col / tab_width * tab_width; + if (c == '\t') + { + int prev_col = col; + col += tab_width; + col = col / tab_width * tab_width; + } + else if (multibyte && BASE_LEADING_CODE_P (c)) + { + unsigned char *ptr; + int bytes, width, wide_column; + + scan_byte--; + ptr = BYTE_POS_ADDR (scan_byte); + MULTIBYTE_BYTES_WIDTH (ptr, dp); + scan_byte += bytes; + col += width; + } + else if (ctl_arrow && (c < 040 || c == 0177)) + col += 2; + else if (c < 040 || c >= 0177) + col += 4; + else + col++; } - else if (multibyte && BASE_LEADING_CODE_P (c)) - { - unsigned char *ptr; - int bytes, width, wide_column; - - scan_byte--; - ptr = BYTE_POS_ADDR (scan_byte); - MULTIBYTE_BYTES_WIDTH (ptr, dp); - scan_byte += bytes; - col += width; - } - else if (ctl_arrow && (c < 040 || c == 0177)) - col += 2; - else if (c < 040 || c >= 0177) - col += 4; - else - col++; } endloop: @@ -864,6 +934,9 @@ while (pos < end) { + Lisp_Object charvec; + EMACS_INT i, n; + while (pos == next_boundary) { int prev = pos; @@ -895,47 +968,69 @@ } c = FETCH_BYTE (pos_byte); + if (dp != 0 && ! (multibyte && BASE_LEADING_CODE_P (c)) && VECTORP (DISP_CHAR_VECTOR (dp, c))) { - col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; - pos_byte++; - pos++; - continue; - } - if (c == '\n') - break; - if (c == '\r' && EQ (current_buffer->selective_display, Qt)) - break; - pos++; - pos_byte++; - if (c == '\t') - { - prev_col = col; - col += tab_width; - col = col / tab_width * tab_width; - } - else if (ctl_arrow && (c < 040 || c == 0177)) - col += 2; - else if (c < 040 || c == 0177) - col += 4; - else if (c < 0177) - col++; - else if (multibyte && BASE_LEADING_CODE_P (c)) - { - /* Start of multi-byte form. */ - unsigned char *ptr; - int bytes, width, wide_column; - - pos_byte--; - ptr = BYTE_POS_ADDR (pos_byte); - MULTIBYTE_BYTES_WIDTH (ptr, dp); - pos_byte += bytes; - col += width; + charvec = DISP_CHAR_VECTOR (dp, c); + n = ASIZE (charvec); } else - col += 4; + { + charvec = Qnil; + n = 1; + } + + for (i = n - 1; i >= 0; --i) + { + if (VECTORP (charvec)) + { + /* This should be handled the same as + next_element_from_display_vector does it. */ + Lisp_Object entry = AREF (charvec, i); + + if (INTEGERP (entry) + && GLYPH_CHAR_VALID_P (XFASTINT (entry))) + c = FAST_GLYPH_CHAR (XFASTINT (entry)); + else + c = ' '; + } + + + if (c == '\n') + goto endloop; + if (c == '\r' && EQ (current_buffer->selective_display, Qt)) + goto endloop; + pos++; + pos_byte++; + if (c == '\t') + { + prev_col = col; + col += tab_width; + col = col / tab_width * tab_width; + } + else if (ctl_arrow && (c < 040 || c == 0177)) + col += 2; + else if (c < 040 || c == 0177) + col += 4; + else if (c < 0177) + col++; + else if (multibyte && BASE_LEADING_CODE_P (c)) + { + /* Start of multi-byte form. */ + unsigned char *ptr; + int bytes, width, wide_column; + + pos_byte--; + ptr = BYTE_POS_ADDR (pos_byte); + MULTIBYTE_BYTES_WIDTH (ptr, dp); + pos_byte += bytes; + col += width; + } + else + col += 4; + } } endloop: @@ -1386,6 +1481,9 @@ /* We have to scan the text character-by-character. */ else { + EMACS_INT i, n; + Lisp_Object charvec; + c = FETCH_BYTE (pos_byte); /* Check composition sequence. */ @@ -1434,99 +1532,125 @@ if (dp != 0 && ! (multibyte && BASE_LEADING_CODE_P (c)) && VECTORP (DISP_CHAR_VECTOR (dp, c))) - hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; - else if (c >= 040 && c < 0177) - hpos++; - else if (c == '\t') + { + charvec = DISP_CHAR_VECTOR (dp, c); + n = ASIZE (charvec); + } + else + { + charvec = Qnil; + n = 1; + } + + for (i = n - 1; i >= 0; --i) { - int tem = (hpos + tab_offset + hscroll - (hscroll > 0)) % tab_width; - if (tem < 0) - tem += tab_width; - hpos += tab_width - tem; - } - else if (c == '\n') - { - if (selective > 0 - && indented_beyond_p (pos, pos_byte, selective)) + if (VECTORP (charvec)) + { + /* This should be handled the same as + next_element_from_display_vector does it. */ + Lisp_Object entry = AREF (charvec, i); + + if (INTEGERP (entry) + && GLYPH_CHAR_VALID_P (XFASTINT (entry))) + c = FAST_GLYPH_CHAR (XFASTINT (entry)); + else + c = ' '; + } + + if (c >= 040 && c < 0177) + hpos++; + else if (c == '\t') + { + int tem = ((hpos + tab_offset + hscroll - (hscroll > 0)) + % tab_width); + if (tem < 0) + tem += tab_width; + hpos += tab_width - tem; + } + else if (c == '\n') { - /* If (pos == to), we don't have to take care of - selective display. */ + if (selective > 0 + && indented_beyond_p (pos, pos_byte, selective)) + { + /* If (pos == to), we don't have to take care of + selective display. */ + if (pos < to) + { + /* Skip any number of invisible lines all at once */ + do + { + pos = find_before_next_newline (pos, to, 1); + if (pos < to) + pos++; + pos_byte = CHAR_TO_BYTE (pos); + } + while (pos < to + && indented_beyond_p (pos, pos_byte, selective)); + /* Allow for the " ..." that is displayed for them. */ + if (selective_rlen) + { + hpos += selective_rlen; + if (hpos >= width) + hpos = width; + } + DEC_BOTH (pos, pos_byte); + /* We have skipped the invis text, but not the + newline after. */ + } + } + else + { + /* A visible line. */ + vpos++; + hpos = 0; + hpos -= hscroll; + /* Count the truncation glyph on column 0 */ + if (hscroll > 0) + hpos++; + tab_offset = 0; + } + contin_hpos = 0; + } + else if (c == CR && selective < 0) + { + /* In selective display mode, + everything from a ^M to the end of the line is invisible. + Stop *before* the real newline. */ if (pos < to) { - /* Skip any number of invisible lines all at once */ - do - { - pos = find_before_next_newline (pos, to, 1); - if (pos < to) - pos++; - pos_byte = CHAR_TO_BYTE (pos); - } - while (pos < to - && indented_beyond_p (pos, pos_byte, selective)); - /* Allow for the " ..." that is displayed for them. */ - if (selective_rlen) - { - hpos += selective_rlen; - if (hpos >= width) - hpos = width; - } - DEC_BOTH (pos, pos_byte); - /* We have skipped the invis text, but not the - newline after. */ + pos = find_before_next_newline (pos, to, 1); + pos_byte = CHAR_TO_BYTE (pos); + } + /* If we just skipped next_boundary, + loop around in the main while + and handle it. */ + if (pos > next_boundary) + next_boundary = pos; + /* Allow for the " ..." that is displayed for them. */ + if (selective_rlen) + { + hpos += selective_rlen; + if (hpos >= width) + hpos = width; } } + else if (multibyte && BASE_LEADING_CODE_P (c)) + { + /* Start of multi-byte form. */ + unsigned char *ptr; + int bytes, width, wide_column; + + 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; + } else - { - /* A visible line. */ - vpos++; - hpos = 0; - hpos -= hscroll; - /* Count the truncation glyph on column 0 */ - if (hscroll > 0) - hpos++; - tab_offset = 0; - } - contin_hpos = 0; + hpos += (ctl_arrow && c < 0200) ? 2 : 4; } - else if (c == CR && selective < 0) - { - /* In selective display mode, - everything from a ^M to the end of the line is invisible. - Stop *before* the real newline. */ - if (pos < to) - { - pos = find_before_next_newline (pos, to, 1); - pos_byte = CHAR_TO_BYTE (pos); - } - /* If we just skipped next_boundary, - loop around in the main while - and handle it. */ - if (pos > next_boundary) - next_boundary = pos; - /* Allow for the " ..." that is displayed for them. */ - if (selective_rlen) - { - hpos += selective_rlen; - if (hpos >= width) - hpos = width; - } - } - else if (multibyte && BASE_LEADING_CODE_P (c)) - { - /* Start of multi-byte form. */ - unsigned char *ptr; - int bytes, width, wide_column; - - 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; - } - else - hpos += (ctl_arrow && c < 0200) ? 2 : 4; } } @@ -1664,6 +1788,7 @@ } /* Fvertical_motion and vmotion */ + struct position val_vmotion; struct position * @@ -1870,7 +1995,7 @@ -/* file's initialization. */ +/* File's initialization. */ void syms_of_indent ()