/* 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.
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
#include <config.h>
#include "lisp.h"
#include "buffer.h"
#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))
#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. */
/* 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;
}
/* Recompute BUF's width table, using the display table DISPTAB. */
+
void
recompute_width_table (buf, disptab)
struct buffer *buf;
/* 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 ()
{
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;
+ charvec = DISP_CHAR_VECTOR (dp, c);
+ n = ASIZE (charvec);
}
- else if (c == '\t')
+ else
{
- if (tab_seen)
- col = ((col + tab_width) / tab_width) * tab_width;
-
- post_tab += col;
- col = 0;
- tab_seen = 1;
+ 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;
}
- else
- col += (ctl_arrow && c < 0200) ? 2 : 4;
}
+ start_of_line_found:
+
if (tab_seen)
{
col = ((col + tab_width) / tab_width) * tab_width;
while (scan < opoint)
{
int c;
+ EMACS_INT i, n;
+ Lisp_Object charvec;
/* Occasionally we may need to skip invisible text. */
while (scan == next_boundary)
}
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;
- scan++;
- scan_byte++;
- continue;
+ charvec = DISP_CHAR_VECTOR (dp, c);
+ n = ASIZE (charvec);
}
- if (c == '\n')
- break;
- if (c == '\r' && EQ (current_buffer->selective_display, Qt))
- break;
- scan++;
- scan_byte++;
- if (c == '\t')
+ else
{
- int prev_col = col;
- col += tab_width;
- col = col / tab_width * tab_width;
+ charvec = Qnil;
+ n = 1;
}
- else if (multibyte && BASE_LEADING_CODE_P (c))
+
+ for (i = n - 1; i >= 0; --i)
{
- 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;
+ 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++;
+ 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 (ctl_arrow && (c < 040 || c == 0177))
- col += 2;
- else if (c < 040 || c >= 0177)
- col += 4;
- else
- col++;
}
endloop:
while (pos < end)
{
+ Lisp_Object charvec;
+ EMACS_INT i, n;
+
while (pos == next_boundary)
{
int prev = pos;
}
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;
+ charvec = DISP_CHAR_VECTOR (dp, c);
+ n = ASIZE (charvec);
}
- if (c == '\n')
- break;
- if (c == '\r' && EQ (current_buffer->selective_display, Qt))
- break;
- pos++;
- pos_byte++;
- if (c == '\t')
+ else
{
- prev_col = col;
- col += tab_width;
- col = col / tab_width * tab_width;
+ charvec = Qnil;
+ n = 1;
}
- 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))
+
+ for (i = n - 1; i >= 0; --i)
{
- /* 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;
+ 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;
}
- else
- col += 4;
}
endloop:
/* 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. */
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')
{
- int tem = (hpos + tab_offset + hscroll - (hscroll > 0)) % tab_width;
- if (tem < 0)
- tem += tab_width;
- hpos += tab_width - tem;
+ charvec = DISP_CHAR_VECTOR (dp, c);
+ n = ASIZE (charvec);
}
- else if (c == '\n')
+ else
{
- if (selective > 0
- && indented_beyond_p (pos, pos_byte, selective))
+ charvec = Qnil;
+ n = 1;
+ }
+
+ for (i = n - 1; i >= 0; --i)
+ {
+ if (VECTORP (charvec))
{
- /* If (pos == to), we don't have to take care of
- selective display. */
- if (pos < to)
+ /* 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 (selective > 0
+ && indented_beyond_p (pos, pos_byte, selective))
{
- /* Skip any number of invisible lines all at once */
- do
+ /* If (pos == to), we don't have to take care of
+ selective display. */
+ if (pos < to)
{
- pos = find_before_next_newline (pos, to, 1);
- if (pos < to)
- pos++;
- pos_byte = CHAR_TO_BYTE (pos);
+ /* 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. */
}
- 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
- {
- /* 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)
+ else if (c == CR && selective < 0)
{
- pos = find_before_next_newline (pos, to, 1);
- pos_byte = CHAR_TO_BYTE (pos);
+ /* 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;
+ }
}
- /* 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)
+ else if (multibyte && BASE_LEADING_CODE_P (c))
{
- hpos += selective_rlen;
- if (hpos >= width)
- hpos = width;
+ /* 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;
}
- 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;
}
}
}
\f
/* Fvertical_motion and vmotion */
+
struct position val_vmotion;
struct position *
\f
-/* file's initialization. */
+/* File's initialization. */
void
syms_of_indent ()