diff options
Diffstat (limited to 'src/indent.c')
-rw-r--r-- | src/indent.c | 358 |
1 files changed, 144 insertions, 214 deletions
diff --git a/src/indent.c b/src/indent.c index 9561927167d..641805c2eaa 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1,5 +1,5 @@ /* Indentation functions. - Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -22,11 +22,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "lisp.h" #include "buffer.h" #include "indent.h" -#include "screen.h" #include "window.h" #include "termchar.h" #include "termopts.h" -#include "disptab.h" + +#define CR '\015' /* Indentation can insert tabs if this is non-zero; otherwise always uses spaces */ @@ -35,8 +35,6 @@ int indent_tabs_mode; #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) -#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 */ @@ -48,23 +46,6 @@ int last_known_column_point; int last_known_column_modified; extern int minibuf_prompt_width; - -/* Get the display table to use for the current buffer. */ - -struct Lisp_Vector * -buffer_display_table () -{ - Lisp_Object thisbuf; - - thisbuf = current_buffer->display_table; - if (XTYPE (thisbuf) == Lisp_Vector - && XVECTOR (thisbuf)->size == DISP_TABLE_SIZE) - return XVECTOR (thisbuf); - if (XTYPE (Vstandard_display_table) == Lisp_Vector - && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE) - return XVECTOR (Vstandard_display_table); - return 0; -} DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0, "Return the horizontal position of point. Beginning of line is column 0.\n\ @@ -74,8 +55,7 @@ and point. (eg control characters will have a width of 2 or 4, tabs\n\ will have a variable width)\n\ Ignores finite width of screen, which means that this function may return\n\ values greater than (screen-width).\n\ -Whether the line is visible (if `selective-display' is t) has no effect;\n\ -however, ^M is treated as end of line when `selective-display' is t.") +Whether the line is visible (if `selective-display' is t) has no effect.") () { Lisp_Object temp; @@ -83,18 +63,22 @@ however, ^M is treated as end of line when `selective-display' is t.") return temp; } +/* Cancel any recorded value of the horizontal position. */ + +invalidate_current_column () +{ + last_known_column_point = 0; +} + int current_column () { register int col; - register unsigned char *ptr, *stop; + register unsigned char *ptr, *stop, c; register int tab_seen; - int post_tab; - register int c; + register int post_tab; register int tab_width = XINT (current_buffer->tab_width); int ctl_arrow = !NULL (current_buffer->ctl_arrow); - register struct Lisp_Vector *dp = buffer_display_table (); - int stopchar; if (point == last_known_column_point && MODIFF == last_known_column_modified) @@ -131,8 +115,7 @@ current_column () } c = *--ptr; - if (c >= 040 && c < 0177 - && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String)) + if (c >= 040 && c < 0177) { col++; } @@ -149,8 +132,6 @@ current_column () col = 0; tab_seen = 1; } - else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String) - col += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH); else col += (ctl_arrow && c < 0200) ? 2 : 4; } @@ -168,11 +149,45 @@ current_column () return col; } +ToCol (col) + int col; +{ + register int fromcol = current_column (); + register int n; + register int tab_width = XINT (current_buffer->tab_width); + + if (fromcol > col) + return; + + if (tab_width <= 0 || tab_width > 20) tab_width = 8; + + if (indent_tabs_mode) + { + n = col / tab_width - fromcol / tab_width; + if (n) + { + while (n-- > 0) + insert ("\t", 1); + + fromcol = (col / tab_width) * tab_width; + } + } + + while (fromcol < col) + { + insert (" ", min (8, col - fromcol)); + fromcol += min (8, col - fromcol); + } + + last_known_column = col; + last_known_column_point = point; + last_known_column_modified = MODIFF; +} DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ", "Indent from point with tabs and spaces until COLUMN is reached.\n\ -Optional second argument MIN says always do at least MIN spaces\n\ -even if that goes past COLUMN; by default, MIN is zero.") +Always do at least MIN spaces even if that goes past COLUMN;\n\ +by default, MIN is zero.") (col, minimum) Lisp_Object col, minimum; { @@ -190,7 +205,7 @@ even if that goes past COLUMN; by default, MIN is zero.") if (mincol < XINT (col)) mincol = XINT (col); if (fromcol == mincol) - return make_number (mincol); + return make_number (fromcol); if (tab_width <= 0 || tab_width > 20) tab_width = 8; @@ -237,10 +252,10 @@ position_indentation (pos) register int tab_width = XINT (current_buffer->tab_width); register unsigned char *p; register unsigned char *stop; - + if (tab_width <= 0 || tab_width > 20) tab_width = 8; - - stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1; + + stop = &FETCH_CHAR (BufferSafeCeiling (pos)) + 1; p = &FETCH_CHAR (pos); while (1) { @@ -250,7 +265,7 @@ position_indentation (pos) return column; pos += p - &FETCH_CHAR (pos); p = &FETCH_CHAR (pos); - stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1; + stop = &FETCH_CHAR (BufferSafeCeiling (pos)) + 1; } switch (*p++) { @@ -266,43 +281,29 @@ position_indentation (pos) } } -DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, 0, +DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 1, 0, "Move point to column COLUMN in the current line.\n\ -The column of a character is calculated by adding together the widths\n\ -as displayed of the previous characters in the line.\n\ -This function ignores line-continuation;\n\ -there is no upper limit on the column number a character can have\n\ -and horizontal scrolling has no effect.\n\n\ -If specified column is within a character, point goes after that character.\n\ -If it's past end of line, point goes to end of line.\n\n\ -A non-nil second (optional) argument FORCE means, if the line\n\ -is too short to reach column COLUMN then add spaces/tabs to get there,\n\ -and if COLUMN is in the middle of a tab character, change it to spaces.") - (column, force) - Lisp_Object column, force; +COLUMN is calculated by adding together the widths of all the displayed\n\ +representations of the character between the start of the previous line\n\ +and point. (eg control characters will have a width of 2 or 4, tabs\n\ +will have a variable width)\n\ +Ignores finite width of screen, which means that this function may be\n\ +passed values greater than (screen-width)") + (column) + Lisp_Object column; { - register int pos; + register int pos = point; register int col = current_column (); register int goal; - register int end; + register int end = ZV; register int tab_width = XINT (current_buffer->tab_width); register int ctl_arrow = !NULL (current_buffer->ctl_arrow); - register struct Lisp_Vector *dp = buffer_display_table (); Lisp_Object val; - int prev_col; - int c; if (tab_width <= 0 || tab_width > 20) tab_width = 8; - CHECK_NATNUM (column, 0); + CHECK_NUMBER (column, 0); goal = XINT (column); - - retry: - pos = point; - end = ZV; - - /* If we're starting past the desired column, - back up to beginning of line and scan from there. */ if (col > goal) { pos = find_next_newline (pos, -1); @@ -311,44 +312,26 @@ and if COLUMN is in the middle of a tab character, change it to spaces.") while (col < goal && pos < end) { - c = FETCH_CHAR (pos); + int c = FETCH_CHAR (pos); if (c == '\n') break; if (c == '\r' && EQ (current_buffer->selective_display, Qt)) break; pos++; + col++; if (c == '\t') { - prev_col = col; - col += tab_width; + col += tab_width - 1; col = col / tab_width * tab_width; } - else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String) - col += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH); else if (ctl_arrow && (c < 040 || c == 0177)) col++; else if (c < 040 || c >= 0177) col += 3; - else - col++; } SET_PT (pos); - /* If a tab char made us overshoot, change it to spaces - and scan through it again. */ - if (!NULL (force) && col > goal && c == '\t' && prev_col < goal) - { - del_range (point - 1, point); - Findent_to (make_number (col - 1)); - insert_char (' '); - goto retry; - } - - /* If line ends prematurely, add space to the end. */ - if (col < goal && !NULL (force)) - Findent_to (make_number (col = goal)); - last_known_column = col; last_known_column_point = point; last_known_column_modified = MODIFF; @@ -359,102 +342,47 @@ and if COLUMN is in the middle of a tab character, change it to spaces.") 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 - offset TO or line TOVPOS, column TOHPOS (whichever comes first), - and return the ending buffer position and screen location. - - WIDTH is the number of columns available to display text; - compute_motion uses this to handle continuation lines and such. - HSCROLL is the number of columns not being displayed at the left - margin; this is usually taken from a window's hscroll member. - TAB_OFFSET is a mysterious value, perhaps the number of columns of - the first tab that aren't being displayed, perhaps because of a - continuation line or something. - - compute_motion returns a pointer to a struct position. The bufpos - member gives the buffer position at the end of the scan, and hpos - and vpos give its cartesian location. I'm not clear on what the - other members are. - - For example, to find the buffer position of column COL of line LINE - of a certain window, pass the window's starting location as FROM - and the window's upper-left coordinates as FROMVPOS and FROMHPOS. - Pass the buffer's ZV as TO, to limit the scan to the end of the - visible section of the buffer, and pass LINE and COL as TOVPOS and - TOHPOS. - - When displaying in window w, a typical formula for WIDTH is: - - window_width - 1 - - (window_width + window_left != screen_width) - - where - window_width is XFASTINT (w->width), - window_left is XFASTINT (w->left), - and screen_width = SCREEN_WIDTH (XSCREEN (window->screen)) - - This accounts for the continuation-line backslashes, and the window - borders if the window is split vertically. */ - struct position * compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, tab_offset) int from, fromvpos, fromhpos, to, tovpos, tohpos; register int width; int hscroll, tab_offset; { -/* Note that `cpos' is CURRENT_VPOS << SHORTBITS + CURRENT_HPOS, - and that CURRENT_HPOS may be negative. Use these macros - to extract the hpos or the vpos from cpos or anything like it. - */ -#ifndef SHORT_CAST_BUG -#define HPOS(VAR) (short) (VAR) -#else -#define HPOS(VAR) (((VAR) & (1 << (SHORTBITS - 1)) \ - ? ~((1 << SHORTBITS) - 1) : 0) \ - | (VAR) & ((1 << SHORTBITS) - 1)) -/* #define HPOS(VAR) (((VAR) & 0x8000 ? 0xffff0000 : 0) | ((VAR) & 0xffff)) */ -#endif /* SHORT_CAST_BUG */ - -#define VPOS(VAR) (((VAR) >> SHORTBITS) + (HPOS (VAR) < 0)) - - -#ifndef TAHOE_REGISTER_BUG - register -#endif /* TAHOE_REGISTER_BUG */ - int cpos = fromhpos + (fromvpos << SHORTBITS); - register int target = tohpos + (tovpos << SHORTBITS); + register int hpos = fromhpos; + register int vpos = fromvpos; + register int pos; register int c; register int tab_width = XFASTINT (current_buffer->tab_width); register int ctl_arrow = !NULL (current_buffer->ctl_arrow); - register struct Lisp_Vector *dp = buffer_display_table (); int selective = XTYPE (current_buffer->selective_display) == Lisp_Int ? XINT (current_buffer->selective_display) : !NULL (current_buffer->selective_display) ? -1 : 0; - int prevpos; - int selective_rlen - = (selective && dp && XTYPE (DISP_INVIS_ROPE (dp)) == Lisp_String - ? XSTRING (DISP_INVIS_ROPE (dp))->size / sizeof (GLYPH) : 0); + int prev_vpos, prev_hpos; if (tab_width <= 0 || tab_width > 20) tab_width = 8; - for (pos = from; pos < to && cpos < target; pos++) + for (pos = from; pos < to; pos++) { - prevpos = cpos; + /* Stop if past the target screen position. */ + if (vpos > tovpos + || (vpos == tovpos && hpos >= tohpos)) + break; + + prev_vpos = vpos; + prev_hpos = hpos; + c = FETCH_CHAR (pos); - if (c >= 040 && c < 0177 - && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String)) - cpos++; + if (c >= 040 && c < 0177) + hpos++; else if (c == '\t') { - cpos += tab_width - - HPOS (cpos + tab_offset + hscroll - (hscroll > 0) - /* Add tab_width here to make sure positive. - cpos can be negative after continuation - but can't be less than -tab_width. */ - + tab_width) - % tab_width; + hpos += tab_width - ((hpos + tab_offset + hscroll - (hscroll > 0) + /* Add tab_width here to make sure positive. + hpos can be negative after continuation + but can't be less than -tab_width. */ + + tab_width) + % tab_width); } else if (c == '\n') { @@ -463,61 +391,72 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta /* Skip any number of invisible lines all at once */ do { - while (++pos < to && FETCH_CHAR(pos) != '\n'); + while (++pos < to && FETCH_CHAR (pos) != '\n'); } - while (selective > 0 && position_indentation (pos + 1) >= selective); + while (pos < to && position_indentation (pos + 1) >= selective); pos--; /* Allow for the " ..." that is displayed for them. */ - if (selective_rlen) + if (!NULL (current_buffer->selective_display_ellipses)) { - cpos += selective_rlen; - if (HPOS (cpos) >= width) - cpos -= HPOS (cpos) - width; + hpos += 4; + if (hpos >= width) + hpos = width; } + /* We have skipped the invis text, but not the newline after. */ } else - cpos += (1 << SHORTBITS) - HPOS (cpos); - cpos -= hscroll; - if (hscroll > 0) cpos++; /* Count the ! on column 0 */ - tab_offset = 0; + { + /* A visible line follows. + Skip this newline and advance to next line. */ + vpos++; + hpos = 0; + hpos -= hscroll; + if (hscroll > 0) hpos++; /* Count the ! on column 0 */ + tab_offset = 0; + } } else if (c == CR && selective < 0) { /* In selective display mode, everything from a ^M to the end of the line is invisible */ - while (pos < to && FETCH_CHAR(pos) != '\n') pos++; + while (pos < to && FETCH_CHAR (pos) != '\n') pos++; + /* Stop *before* the real newline. */ pos--; /* Allow for the " ..." that is displayed for them. */ - if (selective_rlen) + if (!NULL (current_buffer->selective_display_ellipses)) { - cpos += selective_rlen; - if (HPOS (cpos) >= width) - cpos -= HPOS (cpos) - width; + hpos += 4; + if (hpos >= width) + hpos = width; } } - else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String) - cpos += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH); else - cpos += (ctl_arrow && c < 0200) ? 2 : 4; + hpos += (ctl_arrow && c < 0200) ? 2 : 4; - if (HPOS (cpos) >= width - && (HPOS (cpos) > width - || (pos < (ZV - 1) + /* Handle right margin. */ + if (hpos >= width + && (hpos > width + || (pos < ZV - 1 && FETCH_CHAR (pos + 1) != '\n'))) { - if (cpos >= target) + if (vpos > tovpos + || (vpos == tovpos && hpos >= tohpos)) break; if (hscroll || (truncate_partial_width_windows - && width + 1 < SCREEN_WIDTH (selected_screen)) + && width + 1 < screen_width) || !NULL (current_buffer->truncate_lines)) { - while (pos < to && FETCH_CHAR(pos) != '\n') pos++; + /* Truncating: skip to newline. */ + while (pos < to && FETCH_CHAR (pos) != '\n') pos++; pos--; + hpos = width; } else { - cpos += (1 << SHORTBITS) - width; + /* Continuing. */ + vpos++; + hpos -= width; tab_offset += width; } @@ -525,44 +464,35 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta } val_compute_motion.bufpos = pos; - val_compute_motion.hpos = HPOS (cpos); - val_compute_motion.vpos = VPOS (cpos); - val_compute_motion.prevhpos = HPOS (prevpos); + val_compute_motion.hpos = hpos; + val_compute_motion.vpos = vpos; + val_compute_motion.prevhpos = prev_hpos; /* Nonzero if have just continued a line */ val_compute_motion.contin - = pos != from - && (val_compute_motion.vpos != VPOS (prevpos)) - && c != '\n'; + = (pos != from + && (val_compute_motion.vpos != prev_vpos) + && c != '\n'); return &val_compute_motion; } -#undef HPOS -#undef VPOS - -/* Return the column of position POS in window W's buffer, - rounded down to a multiple of the internal width of W. - This is the amount of indentation of position POS - that is not visible in its horizontal position in the window. */ - -int pos_tab_offset (w, pos) struct window *w; register int pos; { int opoint = point; int col; - int width = XFASTINT (w->width) - 1 - - (XFASTINT (w->width) + XFASTINT (w->left) - != SCREEN_WIDTH (XSCREEN (w->screen))); if (pos == BEGV || FETCH_CHAR (pos - 1) == '\n') return 0; SET_PT (pos); col = current_column (); SET_PT (opoint); - return col - (col % width); + return (col + - (col % (XFASTINT (w->width) - 1 + - (XFASTINT (w->width) + XFASTINT (w->left) + != screen_width)))); } /* start_hpos is the hpos of the first character of the buffer: @@ -603,7 +533,7 @@ vmotion (from, vtarget, width, hscroll, window) prevline = find_next_newline (prevline - 1, -1); pos = *compute_motion (prevline, 0, lmargin + (prevline == 1 ? start_hpos : 0), - from, 10000, 10000, + from, 1 << (INTBITS - 2), 0, width, hscroll, 0); } else @@ -612,7 +542,7 @@ vmotion (from, vtarget, width, hscroll, window) pos.vpos = 0; } return compute_motion (from, vpos, pos.hpos, - ZV, vtarget, - (1 << (SHORTBITS - 1)), + ZV, vtarget, - (1 << (INTBITS - 2)), width, hscroll, pos.vpos * width); } @@ -634,7 +564,7 @@ vmotion (from, vtarget, width, hscroll, window) } pos = *compute_motion (prevline, 0, lmargin + (prevline == 1 ? start_hpos : 0), - from, 10000, 10000, + from, 1 << (INTBITS - 2), 0, width, hscroll, 0); vpos -= pos.vpos; first = 0; @@ -670,13 +600,13 @@ Returns number of lines moved; may be closer to zero than LINES\n\ { struct position pos; register struct window *w = XWINDOW (selected_window); - int width = XFASTINT (w->width) - 1 - - (XFASTINT (w->width) + XFASTINT (w->left) - != SCREEN_WIDTH (XSCREEN (w->screen))); CHECK_NUMBER (lines, 0); - pos = *vmotion (point, XINT (lines), width, + pos = *vmotion (point, XINT (lines), + XFASTINT (w->width) - 1 + - (XFASTINT (w->width) + XFASTINT (w->left) + != XFASTINT (XWINDOW (minibuf_window)->width)), /* Not XFASTINT since perhaps could be negative */ XINT (w->hscroll), selected_window); |