/* Indentation functions.
- Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1998, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+ Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2012
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
-#include "buffer.h"
#include "character.h"
+#include "buffer.h"
#include "category.h"
#include "composite.h"
#include "indent.h"
#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. */
Some things in set last_known_column_point to -1
to mark the memorized value as invalid. */
-static double last_known_column;
+static ptrdiff_t last_known_column;
/* Value of point when current_column was called. */
-EMACS_INT last_known_column_point;
+ptrdiff_t last_known_column_point;
/* Value of MODIFF when current_column was called. */
-static int last_known_column_modified;
+static EMACS_INT last_known_column_modified;
-static double current_column_1 P_ ((void));
-static double position_indentation P_ ((int));
+static ptrdiff_t current_column_1 (void);
+static ptrdiff_t position_indentation (ptrdiff_t);
/* Cache of beginning of line found by the last call of
current_column. */
-static EMACS_INT current_column_bol_cache;
+static ptrdiff_t current_column_bol_cache;
/* Get the display table to use for the current buffer. */
struct Lisp_Char_Table *
-buffer_display_table ()
+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))
/* Return the width of character C under display table DP. */
static int
-character_width (c, dp)
- int c;
- struct Lisp_Char_Table *dp;
+character_width (int c, struct Lisp_Char_Table *dp)
{
Lisp_Object elt;
/* 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_SIZE (elt);
+ return ASIZE (elt);
/* Some characters are special. */
if (c == '\n' || c == '\t' || c == '\015')
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;
- struct Lisp_Vector *widthtab;
+bool
+disptab_matches_widthtab (struct Lisp_Char_Table *disptab, struct Lisp_Vector *widthtab)
{
int i;
if (widthtab->header.size != 256)
- abort ();
+ emacs_abort ();
for (i = 0; i < 256; i++)
if (character_width (i, disptab)
/* Recompute BUF's width table, using the display table DISPTAB. */
void
-recompute_width_table (buf, disptab)
- struct buffer *buf;
- struct Lisp_Char_Table *disptab;
+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 (!VECTORP (BVAR (buf, width_table)))
+ bset_width_table (buf, Fmake_vector (make_number (256), make_number (0)));
+ widthtab = XVECTOR (BVAR (buf, width_table));
if (widthtab->header.size != 256)
- abort ();
+ emacs_abort ();
for (i = 0; i < 256; i++)
XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
state of current_buffer's cache_long_line_scans variable. */
static void
-width_run_cache_on_off ()
+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;
+ bset_width_table (current_buffer, Qnil);
}
}
else
characters immediately following, then *NEXT_BOUNDARY_P
will equal the return value. */
-EMACS_INT
-skip_invisible (pos, next_boundary_p, to, window)
- EMACS_INT pos;
- EMACS_INT *next_boundary_p;
- EMACS_INT to;
- Lisp_Object window;
+ptrdiff_t
+skip_invisible (ptrdiff_t pos, ptrdiff_t *next_boundary_p, ptrdiff_t to, Lisp_Object window)
{
Lisp_Object prop, position, overlay_limit, proplimit;
Lisp_Object buffer, tmp;
- EMACS_INT end;
+ ptrdiff_t end;
int inv_p;
XSETFASTINT (position, pos);
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_SIZE (DISP_CHAR_VECTOR (dp, c)); \
+ 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)
however, ^M is treated as end of line when `selective-display' is t.
Text that has an invisible property is considered as having width 0, unless
`buffer-invisibility-spec' specifies that it is replaced by an ellipsis. */)
- ()
+ (void)
{
Lisp_Object temp;
- XSETFASTINT (temp, (int) current_column ()); /* iftc */
+ XSETFASTINT (temp, current_column ());
return temp;
}
/* Cancel any recorded value of the horizontal position. */
void
-invalidate_current_column ()
+invalidate_current_column (void)
{
last_known_column_point = 0;
}
-double
-current_column ()
+ptrdiff_t
+current_column (void)
{
- 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 ctl_arrow = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = buffer_display_table ();
+ ptrdiff_t col;
+ unsigned char *ptr, *stop;
+ bool tab_seen;
+ ptrdiff_t post_tab;
+ int c;
+ int tab_width = SANE_TAB_WIDTH (current_buffer);
+ bool ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
+ struct Lisp_Char_Table *dp = buffer_display_table ();
if (PT == last_known_column_point
&& MODIFF == last_known_column_modified)
/* If the buffer has overlays, text properties,
or multibyte characters, use a more general algorithm. */
- if (BUF_INTERVALS (current_buffer)
- || current_buffer->overlays_before
- || current_buffer->overlays_after
+ if (buffer_intervals (current_buffer)
+ || buffer_has_overlays ()
|| Z != Z_BYTE)
return current_column_1 ();
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)
{
- EMACS_INT i, n;
+ ptrdiff_t i, n;
Lisp_Object charvec;
if (ptr == stop)
next_element_from_display_vector does it. */
Lisp_Object entry = AREF (charvec, i);
- if (GLYPH_CODE_P (entry)
- && GLYPH_CODE_CHAR_VALID_P (entry))
+ if (GLYPH_CODE_P (entry))
c = GLYPH_CODE_CHAR (entry);
else
c = ' ';
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;
return col;
}
\f
-extern Lisp_Object Qspace, QCwidth, QCalign_to;
/* Check the presence of a display property and compute its width.
If a property was found and its width was found as well, return
in ENDPOS.
Otherwise just return -1. */
static int
-check_display_width (EMACS_INT pos, EMACS_INT col, EMACS_INT *endpos)
+check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
{
Lisp_Object val, overlay;
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;
+ EMACS_INT align_to_max =
+ (col < MOST_POSITIVE_FIXNUM - INT_MAX
+ ? (EMACS_INT) INT_MAX + col
+ : MOST_POSITIVE_FIXNUM);
- if ((prop = Fplist_get (plist, QCwidth), NATNUMP (prop)))
+ if ((prop = Fplist_get (plist, QCwidth),
+ RANGED_INTEGERP (0, prop, INT_MAX)))
width = XINT (prop);
- else if (FLOATP (prop))
+ else if (FLOATP (prop) && 0 <= XFLOAT_DATA (prop)
+ && XFLOAT_DATA (prop) <= INT_MAX)
width = (int)(XFLOAT_DATA (prop) + 0.5);
- else if ((prop = Fplist_get (plist, QCalign_to), NATNUMP (prop)))
+ else if ((prop = Fplist_get (plist, QCalign_to),
+ RANGED_INTEGERP (col, prop, align_to_max)))
width = XINT (prop) - col;
- else if (FLOATP (prop))
+ else if (FLOATP (prop) && col <= XFLOAT_DATA (prop)
+ && (XFLOAT_DATA (prop) <= align_to_max))
width = (int)(XFLOAT_DATA (prop) + 0.5) - col;
-
+
if (width >= 0)
{
- EMACS_INT start;
+ ptrdiff_t start;
if (OVERLAYP (overlay))
*endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
else
PREVCOL gets set to the column of the previous position (it's always
strictly smaller than the goal column). */
static void
-scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol)
+scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, ptrdiff_t *prevcol)
{
- register EMACS_INT tab_width = XINT (current_buffer->tab_width);
- register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = buffer_display_table ();
- int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+ int tab_width = SANE_TAB_WIDTH (current_buffer);
+ bool ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
+ struct Lisp_Char_Table *dp = buffer_display_table ();
+ bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
struct composition_it cmp_it;
Lisp_Object window;
struct window *w;
/* Start the scan at the beginning of this line with column number 0. */
- register EMACS_INT col = 0, prev_col = 0;
+ register ptrdiff_t col = 0, prev_col = 0;
EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
- EMACS_INT end = endpos ? *endpos : PT;
- EMACS_INT scan, scan_byte;
- EMACS_INT next_boundary;
+ ptrdiff_t end = endpos ? *endpos : PT;
+ ptrdiff_t scan, scan_byte;
+ ptrdiff_t next_boundary;
{
- EMACS_INT opoint = PT, opoint_byte = PT_BYTE;
+ ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
current_column_bol_cache = PT;
scan = PT, scan_byte = PT_BYTE;
window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
w = ! NILP (window) ? XWINDOW (window) : NULL;
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
- bzero (&cmp_it, sizeof cmp_it);
+ memset (&cmp_it, 0, sizeof cmp_it);
cmp_it.id = -1;
composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil);
/* Occasionally we may need to skip invisible text. */
while (scan == next_boundary)
{
- EMACS_INT old_scan = scan;
+ ptrdiff_t old_scan = scan;
/* This updates NEXT_BOUNDARY to the next place
where we might need to skip more invisible text. */
scan = skip_invisible (scan, &next_boundary, end, Qnil);
prev_col = col;
{ /* Check display property. */
- EMACS_INT end;
- int width = check_display_width (scan, col, &end);
+ ptrdiff_t 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;
}
}
to this character. */
if (dp != 0
- && ! (multibyte && BASE_LEADING_CODE_P (c))
+ && ! (multibyte && LEADING_CODE_P (c))
&& VECTORP (DISP_CHAR_VECTOR (dp, c)))
{
Lisp_Object charvec;
- EMACS_INT i, n;
+ ptrdiff_t i, n;
/* This character is displayed using a vector of glyphs.
Update the column/position based on those glyphs. */
next_element_from_display_vector does it. */
Lisp_Object entry = AREF (charvec, i);
- if (GLYPH_CODE_P (entry)
- && GLYPH_CODE_CHAR_VALID_P (entry))
+ if (GLYPH_CODE_P (entry))
c = GLYPH_CODE_CHAR (entry);
else
c = ' ';
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')
{
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')
{
col += tab_width;
col = col / tab_width * tab_width;
}
- else if (multibyte && BASE_LEADING_CODE_P (c))
+ else if (multibyte && LEADING_CODE_P (c))
{
/* 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;
This function handles characters that are invisible
due to text properties or overlays. */
-static double
-current_column_1 ()
+static ptrdiff_t
+current_column_1 (void)
{
EMACS_INT col = MOST_POSITIVE_FIXNUM;
- EMACS_INT opoint = PT;
+ ptrdiff_t opoint = PT;
scan_for_column (&opoint, &col, NULL);
return col;
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 col;
+ unsigned char *ptr, *stop;
+ bool tab_seen;
int post_tab;
- register int c;
- register int tab_width = XINT (current_buffer->tab_width);
- int ctl_arrow = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = buffer_display_table ();
+ int c;
+ int tab_width = SANE_TAB_WIDTH (current_buffer);
+ bool ctl_arrow = !NILP (current_buffer->ctl_arrow);
+ struct Lisp_Char_Table *dp = buffer_display_table ();
int b, e;
if (NILP (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)
c = *--ptr;
if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- col += XVECTOR_SIZE (DISP_CHAR_VECTOR (dp, c));
+ col += ASIZE (DISP_CHAR_VECTOR (dp, c));
else if (c >= 040 && c < 0177)
col++;
else if (c == '\n')
even if that goes past COLUMN; by default, MINIMUM is zero.
The return value is COLUMN. */)
- (column, minimum)
- Lisp_Object column, minimum;
+ (Lisp_Object column, Lisp_Object minimum)
{
- int mincol;
- register int fromcol;
- register int tab_width = XINT (current_buffer->tab_width);
+ EMACS_INT mincol;
+ register ptrdiff_t fromcol;
+ int tab_width = SANE_TAB_WIDTH (current_buffer);
CHECK_NUMBER (column);
if (NILP (minimum))
if (fromcol == mincol)
return make_number (mincol);
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
if (indent_tabs_mode)
{
Lisp_Object n;
}
\f
-static double position_indentation P_ ((int));
-
DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
0, 0, 0,
doc: /* Return the indentation of the current line.
This is the horizontal position of the character
following any initial whitespace. */)
- ()
+ (void)
{
Lisp_Object val;
- int opoint = PT, opoint_byte = PT_BYTE;
+ ptrdiff_t 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 (pos_byte)
- register int pos_byte;
+static ptrdiff_t
+position_indentation (ptrdiff_t pos_byte)
{
- register EMACS_INT column = 0;
- register EMACS_INT tab_width = XINT (current_buffer->tab_width);
+ register ptrdiff_t column = 0;
+ 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;
+ ptrdiff_t next_boundary_byte = pos_byte;
+ ptrdiff_t ceiling = next_boundary_byte;
p = BYTE_POS_ADDR (pos_byte);
/* STOP records the value of P at which we will need
{
while (p == stop)
{
- EMACS_INT stop_pos_byte;
+ ptrdiff_t stop_pos_byte;
/* If we have updated P, set POS_BYTE to match.
The first time we enter the loop, POS_BYTE is already right. */
return column;
if (pos_byte == next_boundary_byte)
{
- EMACS_INT next_boundary;
- EMACS_INT pos = BYTE_TO_CHAR (pos_byte);
+ ptrdiff_t next_boundary;
+ ptrdiff_t pos = BYTE_TO_CHAR (pos_byte);
pos = skip_invisible (pos, &next_boundary, ZV, Qnil);
pos_byte = CHAR_TO_BYTE (pos);
next_boundary_byte = CHAR_TO_BYTE (next_boundary);
switch (*p++)
{
case 0240:
- if (! NILP (current_buffer->enable_multibyte_characters))
+ if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
return column;
case ' ':
column++;
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;
Blank lines are treated as if they had the same indentation as the
preceding line. */
-int
-indented_beyond_p (pos, pos_byte, column)
- int pos, pos_byte;
- double column;
+bool
+indented_beyond_p (ptrdiff_t pos, ptrdiff_t pos_byte, EMACS_INT column)
{
- double val;
- int opoint = PT, opoint_byte = PT_BYTE;
+ ptrdiff_t val;
+ ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
SET_PT_BOTH (pos, pos_byte);
while (PT > BEGV && FETCH_BYTE (PT_BYTE) == '\n')
val = position_indentation (PT_BYTE);
SET_PT_BOTH (opoint, opoint_byte);
- return val >= column; /* hmm, float comparison */
+ return val >= column;
}
\f
-DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
+DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2,
+ "NMove to column: ",
doc: /* Move point to column COLUMN in the current line.
Interactively, COLUMN is the value of prefix numeric argument.
The column of a character is calculated by adding together the widths
COLUMN, add spaces/tabs to get there.
The return value is the current column. */)
- (column, force)
- Lisp_Object column, force;
+ (Lisp_Object column, Lisp_Object force)
{
- EMACS_INT pos;
- EMACS_INT col, prev_col;
+ ptrdiff_t pos, prev_col;
+ EMACS_INT col;
EMACS_INT goal;
CHECK_NATNUM (column);
if (!NILP (force) && col > goal)
{
int c;
- EMACS_INT pos_byte = PT_BYTE;
+ ptrdiff_t pos_byte = PT_BYTE;
DEC_POS (pos_byte);
c = FETCH_CHAR (pos_byte);
if (c == '\t' && prev_col < goal)
{
- EMACS_INT goal_pt, goal_pt_byte;
+ ptrdiff_t goal_pt, goal_pt_byte;
/* Insert spaces in front of the tab to reach GOAL. Do this
first so that a marker at the end of the tab gets
\f
/* 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
can't hit the requested column exactly (because of a tab or other
multi-column character), overshoot.
- DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
+ DID_MOTION is true if FROMHPOS has already accounted for overlay strings
at FROM. This is the case if FROMVPOS and FROMVPOS came from an
earlier call to compute_motion. The other common case is that FROMHPOS
is zero and FROM is a position that "belongs" at column zero, but might
- be shifted by overlay strings; in this case DID_MOTION should be 0.
+ be shifted by overlay strings; in this case DID_MOTION should be false.
WIDTH is the number of columns available to display text;
compute_motion uses this to handle continuation lines and such.
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
the scroll bars if they are turned on. */
struct position *
-compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, hscroll, tab_offset, win)
- EMACS_INT from, fromvpos, fromhpos, to, tovpos, tohpos;
- int did_motion;
- EMACS_INT width;
- EMACS_INT hscroll, tab_offset;
- struct window *win;
+compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos,
+ bool did_motion, ptrdiff_t to,
+ EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width,
+ ptrdiff_t hscroll, int tab_offset, struct window *win)
{
- register EMACS_INT hpos = fromhpos;
- register EMACS_INT vpos = fromvpos;
-
- 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);
- 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);
- int selective_rlen
+ EMACS_INT hpos = fromhpos;
+ EMACS_INT vpos = fromvpos;
+
+ ptrdiff_t pos;
+ ptrdiff_t pos_byte;
+ int c = 0;
+ int tab_width = SANE_TAB_WIDTH (current_buffer);
+ bool ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
+ struct Lisp_Char_Table *dp = window_display_table (win);
+ EMACS_INT selective
+ = (INTEGERP (BVAR (current_buffer, selective_display))
+ ? XINT (BVAR (current_buffer, selective_display))
+ : !NILP (BVAR (current_buffer, selective_display)) ? -1 : 0);
+ ptrdiff_t selective_rlen
= (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
- ? XVECTOR_SIZE (DISP_INVIS_VECTOR (dp)) : 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;
+ ptrdiff_t next_boundary = from;
/* For computing runs of characters with similar widths.
Invariant: width_run_width is zero, or all the characters
from width_run_start to width_run_end have a fixed width of
width_run_width. */
- EMACS_INT width_run_start = from;
- EMACS_INT width_run_end = from;
- EMACS_INT width_run_width = 0;
+ ptrdiff_t width_run_start = from;
+ ptrdiff_t width_run_end = from;
+ ptrdiff_t width_run_width = 0;
Lisp_Object *width_table;
- Lisp_Object buffer;
/* The next buffer pos where we should consult the width run cache. */
- EMACS_INT next_width_run = from;
+ ptrdiff_t next_width_run = from;
Lisp_Object window;
- int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+ bool 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;
- EMACS_INT prev_pos; /* Previous buffer position. */
- EMACS_INT prev_pos_byte; /* Previous buffer position. */
+ ptrdiff_t prev_pos; /* Previous buffer position. */
+ ptrdiff_t prev_pos_byte; /* Previous buffer position. */
EMACS_INT prev_hpos = 0;
EMACS_INT prev_vpos = 0;
EMACS_INT contin_hpos; /* HPOS of last column of continued line. */
- EMACS_INT prev_tab_offset; /* Previous tab offset. */
- EMACS_INT continuation_glyph_width;
+ int prev_tab_offset; /* Previous tab offset. */
+ int continuation_glyph_width;
struct composition_it cmp_it;
- XSETBUFFER (buffer, current_buffer);
XSETWINDOW (window, win);
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)))
pos_byte = prev_pos_byte = CHAR_TO_BYTE (from);
contin_hpos = 0;
prev_tab_offset = tab_offset;
- bzero (&cmp_it, sizeof cmp_it);
+ memset (&cmp_it, 0, sizeof cmp_it);
cmp_it.id = -1;
composition_compute_stop_pos (&cmp_it, pos, pos_byte, to, Qnil);
{
while (pos == next_boundary)
{
- EMACS_INT pos_here = pos;
- EMACS_INT newpos;
+ ptrdiff_t pos_here = pos;
+ ptrdiff_t newpos;
/* Don't skip invisible if we are already at the margin. */
if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
to be changed here. */
{
unsigned char *ovstr;
- int ovlen = overlay_strings (pos, win, &ovstr);
+ ptrdiff_t ovlen = overlay_strings (pos, win, &ovstr);
hpos += ((multibyte && ovlen > 0)
- ? strwidth (ovstr, ovlen) : ovlen);
+ ? strwidth ((char *) ovstr, ovlen) : ovlen);
}
did_motion = 0;
if (hpos > width)
{
- int total_width = width + continuation_glyph_width;
- int truncate = 0;
+ EMACS_INT total_width = width + continuation_glyph_width;
+ bool truncate = 0;
if (!NILP (Vtruncate_partial_width_windows)
&& (total_width < FRAME_COLS (XFRAME (WINDOW_FRAME (win)))))
}
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). */
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,
want to skip over it for some other reason. */
if (common_width != 0)
{
- int run_end_hpos;
+ ptrdiff_t run_end_hpos;
/* Don't go past the final buffer posn the user
requested. */
/* We have to scan the text character-by-character. */
else
{
- EMACS_INT i, n;
+ ptrdiff_t i, n;
Lisp_Object charvec;
/* Check composition sequence. */
}
if (dp != 0
- && ! (multibyte && BASE_LEADING_CODE_P (c))
+ && ! (multibyte && LEADING_CODE_P (c))
&& VECTORP (DISP_CHAR_VECTOR (dp, c)))
{
charvec = DISP_CHAR_VECTOR (dp, c);
n = 1;
}
- for (i = n - 1; i >= 0; --i)
+ for (i = 0; i < n; ++i)
{
if (VECTORP (charvec))
{
next_element_from_display_vector does it. */
Lisp_Object entry = AREF (charvec, i);
- if (GLYPH_CODE_P (entry)
- && GLYPH_CODE_CHAR_VALID_P (entry))
+ if (GLYPH_CODE_P (entry))
c = GLYPH_CODE_CHAR (entry);
else
c = ' ';
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. */
}
while (pos < to
&& indented_beyond_p (pos, pos_byte,
- (double) selective)); /* iftc */
+ selective));
/* Allow for the " ..." that is displayed for them. */
if (selective_rlen)
{
hpos = width;
}
}
- else if (multibyte && BASE_LEADING_CODE_P (c))
+ else if (multibyte && LEADING_CODE_P (c))
{
/* 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;
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. */
- val_compute_motion.ovstring_chars_done = 0;
/* Nonzero if have just continued a line */
val_compute_motion.contin = (contin_hpos && prev_hpos == 0);
and the window's upper-left coordinates as FROMPOS.
Pass the buffer's (point-max) as TO, to limit the scan to the end of the
visible section of the buffer, and pass LINE and COL as TOPOS. */)
- (from, frompos, to, topos, width, offsets, window)
- Lisp_Object from, frompos, to, topos;
- Lisp_Object width, offsets, window;
+ (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos, Lisp_Object width, Lisp_Object offsets, Lisp_Object window)
{
struct window *w;
Lisp_Object bufpos, hpos, vpos, prevhpos;
struct position *pos;
- int hscroll, tab_offset;
+ ptrdiff_t hscroll;
+ int tab_offset;
CHECK_NUMBER_COERCE_MARKER (from);
CHECK_CONS (frompos);
CHECK_CONS (offsets);
CHECK_NUMBER_CAR (offsets);
CHECK_NUMBER_CDR (offsets);
+ if (! (0 <= XINT (XCAR (offsets)) && XINT (XCAR (offsets)) <= PTRDIFF_MAX
+ && 0 <= XINT (XCDR (offsets)) && XINT (XCDR (offsets)) <= INT_MAX))
+ args_out_of_range (XCAR (offsets), XCDR (offsets));
hscroll = XINT (XCAR (offsets));
tab_offset = XINT (XCDR (offsets));
}
? 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 :
\f
/* Fvertical_motion and vmotion */
-struct position val_vmotion;
+static struct position val_vmotion;
struct position *
-vmotion (from, vtarget, w)
- register EMACS_INT from, vtarget;
- struct window *w;
+vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w)
{
- EMACS_INT hscroll = XINT (w->hscroll);
+ ptrdiff_t hscroll = w->hscroll;
struct position pos;
/* vpos is cumulative vertical position, changed as from is changed */
- register int vpos = 0;
- EMACS_INT prevline;
- 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);
+ register EMACS_INT vpos = 0;
+ ptrdiff_t prevline;
+ register ptrdiff_t first;
+ ptrdiff_t from_byte;
+ ptrdiff_t lmargin = hscroll > 0 ? 1 - hscroll : 0;
+ ptrdiff_t selective
+ = (INTEGERP (BVAR (current_buffer, selective_display))
+ ? clip_to_bounds (-1, XINT (BVAR (current_buffer, selective_display)),
+ PTRDIFF_MAX)
+ : !NILP (BVAR (current_buffer, selective_display)) ? -1 : 0);
Lisp_Object window;
- EMACS_INT start_hpos = 0;
- int did_motion;
+ bool did_motion;
/* This is the object we use for fetching character properties. */
Lisp_Object text_prop_object;
&& ((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),
TEXT_PROP_MEANS_INVISIBLE (propval))))
prevline = find_next_newline_no_quit (prevline - 1, -1);
pos = *compute_motion (prevline, 0,
- lmargin + (prevline == BEG ? start_hpos : 0),
+ lmargin,
0,
from,
/* Don't care for VPOS... */
/* ... nor HPOS. */
1 << (BITS_PER_SHORT - 1),
-1, hscroll,
- /* This compensates for start_hpos
- so that a tab as first character
- still occupies 8 columns. */
- (prevline == BEG ? -start_hpos : 0),
+ 0,
w);
vpos -= pos.vpos;
first = 0;
val_vmotion.hpos = lmargin;
val_vmotion.contin = 0;
val_vmotion.prevhpos = 0;
- val_vmotion.ovstring_chars_done = 0;
- val_vmotion.tab_offset = 0; /* For accumulating tab offset. */
return &val_vmotion;
}
&& ((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),
TEXT_PROP_MEANS_INVISIBLE (propval))))
prevline = find_next_newline_no_quit (prevline - 1, -1);
pos = *compute_motion (prevline, 0,
- lmargin + (prevline == BEG
- ? start_hpos : 0),
+ lmargin,
0,
from,
/* Don't care for VPOS... */
/* ... nor HPOS. */
1 << (BITS_PER_SHORT - 1),
-1, hscroll,
- (prevline == BEG ? -start_hpos : 0),
+ 0,
w);
did_motion = 1;
}
else
{
- pos.hpos = lmargin + (from == BEG ? start_hpos : 0);
+ pos.hpos = lmargin;
pos.vpos = 0;
- pos.tab_offset = 0;
did_motion = 0;
}
return compute_motion (from, vpos, pos.hpos, did_motion,
ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)),
-1, hscroll,
- pos.tab_offset - (from == BEG ? start_hpos : 0),
+ 0,
w);
}
This is consistent with other cursor motion functions
and makes it possible to use `vertical-motion' in any buffer,
whether or not it is currently displayed in some window. */)
- (lines, window)
- Lisp_Object lines, window;
+ (Lisp_Object lines, Lisp_Object window)
{
struct it it;
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))))
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;
- XSETBUFFER (w->buffer, current_buffer);
+ old_charpos = XMARKER (w->pointm)->charpos;
+ old_bytepos = XMARKER (w->pointm)->bytepos;
+ wset_buffer (w, Fcurrent_buffer ());
+ set_marker_both (w->pointm, w->buffer,
+ BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer));
}
if (noninteractive)
}
else
{
- int it_start, first_x, it_overshoot_expected;
+ ptrdiff_t it_start, it_overshoot_count = 0;
+ int first_x;
+ bool overshoot_handled = 0;
+ bool disp_string_at_start_p = 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);
+
+ disp_string_at_start_p = it.string_from_display_prop_p;
+ 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
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, or spans several screen lines. 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;
+ else if (disp_string_at_start_p && it.vpos > 0)
+ {
+ /* This is the case of a display string that spans
+ several screen lines. In that case, we end up at the
+ end of the string, and it.vpos tells us how many
+ screen lines we need to backtrack. */
+ it_overshoot_count = it.vpos;
+ }
+ 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 (PTRDIFF_MIN, XINT (lines)));
+ }
+ else if (overshoot_handled)
+ {
+ it.vpos = 0;
+ move_it_by_lines (&it, min (PTRDIFF_MAX, XINT (lines)));
}
else
{
- if (IT_CHARPOS (it) > it_start)
+ /* 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)
{
- /* 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)
- {
- 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 (PTRDIFF_MAX, XINT (lines) - 1));
+ }
+ else
+ {
+ it.vpos = 0;
+ move_it_by_lines (&it, min (PTRDIFF_MAX, XINT (lines)));
}
}
}
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
+ bidi_unshelve_cache (itdata, 0);
}
if (BUFFERP (old_buffer))
- w->buffer = old_buffer;
+ {
+ wset_buffer (w, old_buffer);
+ set_marker_both (w->pointm, w->buffer,
+ old_charpos, old_bytepos);
+ }
RETURN_UNGCPRO (make_number (it.vpos));
}
/* File's initialization. */
void
-syms_of_indent ()
+syms_of_indent (void)
{
- DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
- doc: /* *Indentation can insert tabs if this is non-nil. */);
+ DEFVAR_BOOL ("indent-tabs-mode", indent_tabs_mode,
+ doc: /* Indentation can insert tabs if this is non-nil. */);
indent_tabs_mode = 1;
defsubr (&Scurrent_indentation);
defsubr (&Svertical_motion);
defsubr (&Scompute_motion);
}
-
-/* arch-tag: 9adfea44-71f7-4988-8ee3-96da15c502cc
- (do not change this comment) */