/* Indentation functions.
- Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2012
- Free Software Foundation, Inc.
+ Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2014 Free Software
+ Foundation, Inc.
This file is part of GNU Emacs.
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 ptrdiff_t current_column_bol_cache;
-
/* Get the display table to use for the current buffer. */
struct Lisp_Char_Table *
struct Lisp_Vector *widthtab;
if (!VECTORP (BVAR (buf, width_table)))
- bset_width_table (buf, Fmake_vector (make_number (256), make_number (0)));
+ bset_width_table (buf, make_uninit_vector (256));
widthtab = XVECTOR (BVAR (buf, width_table));
eassert (widthtab->header.size == 256);
XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
}
-/* Allocate or free the width run cache, as requested by the current
- state of current_buffer's cache_long_line_scans variable. */
+/* Allocate or free the width run cache, as requested by the
+ current state of current_buffer's cache_long_scans variable. */
-static void
+static struct region_cache *
width_run_cache_on_off (void)
{
- if (NILP (BVAR (current_buffer, cache_long_line_scans))
+ struct buffer *cache_buffer = current_buffer;
+ bool indirect_p = false;
+
+ if (cache_buffer->base_buffer)
+ {
+ cache_buffer = cache_buffer->base_buffer;
+ indirect_p = true;
+ }
+
+ if (NILP (BVAR (current_buffer, cache_long_scans))
/* And, for the moment, this feature doesn't work on 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;
- bset_width_table (current_buffer, Qnil);
+ if (!indirect_p
+ || NILP (BVAR (cache_buffer, cache_long_scans))
+ || !NILP (BVAR (cache_buffer, enable_multibyte_characters)))
+ {
+ /* It should be off. */
+ if (cache_buffer->width_run_cache)
+ {
+ free_region_cache (cache_buffer->width_run_cache);
+ cache_buffer->width_run_cache = 0;
+ bset_width_table (current_buffer, Qnil);
+ }
}
+ return NULL;
}
else
{
- /* It should be on. */
- if (current_buffer->width_run_cache == 0)
- {
- current_buffer->width_run_cache = new_region_cache ();
- recompute_width_table (current_buffer, buffer_display_table ());
- }
+ if (!indirect_p
+ || (!NILP (BVAR (cache_buffer, cache_long_scans))
+ && NILP (BVAR (cache_buffer, enable_multibyte_characters))))
+ {
+ /* It should be on. */
+ if (cache_buffer->width_run_cache == 0)
+ {
+ cache_buffer->width_run_cache = new_region_cache ();
+ recompute_width_table (current_buffer, buffer_display_table ());
+ }
+ }
+ return cache_buffer->width_run_cache;
}
}
the next property change */
prop = Fget_char_property (position, Qinvisible,
(!NILP (window)
- && EQ (XWINDOW (window)->buffer, buffer))
+ && EQ (XWINDOW (window)->contents, buffer))
? window : buffer);
inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
/* When counting columns (window == nil), don't skip over ellipsis text. */
doc: /* Return the horizontal position of point. Beginning of line is column 0.
This is calculated by adding together the widths of all the displayed
representations of the character between the start of the previous line
-and point (eg. control characters will have a width of 2 or 4, tabs
+and point (e.g., control characters will have a width of 2 or 4, tabs
will have a variable width).
Ignores finite width of frame, which means that this function may return
values greater than (frame-width).
col += post_tab;
}
- if (ptr == BEGV_ADDR)
- current_column_bol_cache = BEGV;
- else
- current_column_bol_cache = BYTE_TO_CHAR (PTR_BYTE_POS (ptr));
-
last_known_column = col;
last_known_column_point = PT;
last_known_column_modified = MODIFF;
register ptrdiff_t col = 0, prev_col = 0;
EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
ptrdiff_t end = endpos ? *endpos : PT;
- ptrdiff_t scan, scan_byte;
- ptrdiff_t next_boundary;
- {
- 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;
- SET_PT_BOTH (opoint, opoint_byte);
+ ptrdiff_t scan, scan_byte, next_boundary;
+
+ scan = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &scan_byte, 1);
next_boundary = scan;
- }
window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
w = ! NILP (window) ? XWINDOW (window) : NULL;
col += width;
if (endp > scan) /* Avoid infinite loops with 0-width overlays. */
{
- scan = endp; scan_byte = charpos_to_bytepos (scan);
+ scan = endp;
+ scan_byte = CHAR_TO_BYTE (scan);
continue;
}
}
*prevcol = prev_col;
}
-/* Return the column number of position POS
+/* Return the column number of point
by scanning forward from the beginning of the line.
This function handles characters that are invisible
due to text properties or overlays. */
following any initial whitespace. */)
(void)
{
- Lisp_Object val;
- ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
-
- scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
+ ptrdiff_t posbyte;
- XSETFASTINT (val, position_indentation (PT_BYTE));
- SET_PT_BOTH (opoint, opoint_byte);
- return val;
+ find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &posbyte, 1);
+ return make_number (position_indentation (posbyte));
}
static ptrdiff_t
column += tab_width - column % tab_width;
break;
default:
- if (ASCII_BYTE_P (p[-1])
+ if (ASCII_CHAR_P (p[-1])
|| NILP (BVAR (current_buffer, enable_multibyte_characters)))
return column;
{
bool
indented_beyond_p (ptrdiff_t pos, ptrdiff_t pos_byte, EMACS_INT column)
{
- 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')
- scan_newline (PT - 1, PT_BYTE - 1, BEGV, BEGV_BYTE, -1, 0);
-
- val = position_indentation (PT_BYTE);
- SET_PT_BOTH (opoint, opoint_byte);
- return val >= column;
+ while (pos > BEGV && FETCH_BYTE (pos_byte) == '\n')
+ {
+ DEC_BOTH (pos, pos_byte);
+ pos = find_newline (pos, pos_byte, BEGV, BEGV_BYTE,
+ -1, NULL, &pos_byte, 0);
+ }
+ return position_indentation (pos_byte) >= column;
}
\f
DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2,
: (window_width + window_left != frame_cols))
where
- window_width is XFASTINT (w->total_cols),
- window_left is XFASTINT (w->left_col),
+ window_width is w->total_cols,
+ window_left is w->left_col,
has_vertical_scroll_bars is
WINDOW_HAS_VERTICAL_SCROLL_BAR (window)
and frame_cols = FRAME_COLS (XFRAME (window->frame))
the scroll bars if they are turned on. */
struct position *
-compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos,
- bool did_motion, ptrdiff_t to,
+compute_motion (ptrdiff_t from, ptrdiff_t frombyte, 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)
{
EMACS_INT contin_hpos; /* HPOS of last column of continued line. */
int prev_tab_offset; /* Previous tab offset. */
int continuation_glyph_width;
+ struct buffer *cache_buffer = current_buffer;
+ struct region_cache *width_cache;
struct composition_it cmp_it;
XSETWINDOW (window, win);
- width_run_cache_on_off ();
+ if (cache_buffer->base_buffer)
+ cache_buffer = cache_buffer->base_buffer;
+ width_cache = width_run_cache_on_off ();
if (dp == buffer_display_table ())
width_table = (VECTORP (BVAR (current_buffer, width_table))
? XVECTOR (BVAR (current_buffer, width_table))->contents
/* Negative width means use all available text columns. */
if (width < 0)
{
- width = window_body_cols (win);
+ width = window_body_width (win, 0);
/* We must make room for continuation marks if we don't have fringes. */
#ifdef HAVE_WINDOW_SYSTEM
if (!FRAME_WINDOW_P (XFRAME (win->frame)))
immediate_quit = 1;
QUIT;
+ /* It's just impossible to be too paranoid here. */
+ eassert (from == BYTE_TO_CHAR (frombyte) && frombyte == CHAR_TO_BYTE (from));
+
pos = prev_pos = from;
- pos_byte = prev_pos_byte = CHAR_TO_BYTE (from);
+ pos_byte = prev_pos_byte = frombyte;
contin_hpos = 0;
prev_tab_offset = tab_offset;
memset (&cmp_it, 0, sizeof cmp_it);
TO (we need to go back below). */
if (pos <= to)
{
- pos = find_before_next_newline (pos, to, 1);
- pos_byte = CHAR_TO_BYTE (pos);
+ pos = find_before_next_newline (pos, to, 1, &pos_byte);
hpos = width;
/* If we just skipped next_boundary,
loop around in the main while
/* Consult the width run cache to see if we can avoid inspecting
the text character-by-character. */
- if (current_buffer->width_run_cache && pos >= next_width_run)
+ if (width_cache && pos >= next_width_run)
{
ptrdiff_t run_end;
int common_width
- = region_cache_forward (current_buffer,
- current_buffer->width_run_cache,
- pos, &run_end);
+ = region_cache_forward (cache_buffer, width_cache, pos, &run_end);
/* A width of zero means the character's width varies (like
a tab), is meaningless (like a newline), or we just don't
pos++, pos_byte++;
/* Perhaps add some info to the width_run_cache. */
- if (current_buffer->width_run_cache)
+ if (width_cache)
{
/* Is this character part of the current run? If so, extend
the run. */
(Currently, we only cache runs of width == 1). */
if (width_run_start < width_run_end
&& width_run_width == 1)
- know_region_cache (current_buffer,
- current_buffer->width_run_cache,
+ know_region_cache (cache_buffer, width_cache,
width_run_start, width_run_end);
/* Start recording a new width run. */
/* Skip any number of invisible lines all at once */
do
{
- pos = find_before_next_newline (pos, to, 1);
+ pos = find_before_next_newline (pos, to, 1, &pos_byte);
if (pos < to)
- pos++;
- pos_byte = CHAR_TO_BYTE (pos);
+ INC_BOTH (pos, pos_byte);
}
while (pos < to
&& indented_beyond_p (pos, pos_byte,
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);
- }
+ pos = find_before_next_newline (pos, to, 1, &pos_byte);
/* If we just skipped next_boundary,
loop around in the main while
and handle it. */
after_loop:
/* Remember any final width run in the cache. */
- if (current_buffer->width_run_cache
+ if (width_cache
&& width_run_width == 1
&& width_run_start < width_run_end)
- know_region_cache (current_buffer, current_buffer->width_run_cache,
+ know_region_cache (cache_buffer, width_cache,
width_run_start, width_run_end);
val_compute_motion.bufpos = pos;
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. */)
- (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos, Lisp_Object width, Lisp_Object offsets, Lisp_Object 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;
if (XINT (to) < BEGV || XINT (to) > ZV)
args_out_of_range_3 (to, make_number (BEGV), make_number (ZV));
- pos = compute_motion (XINT (from), XINT (XCDR (frompos)),
+ pos = compute_motion (XINT (from), CHAR_TO_BYTE (XINT (from)),
+ XINT (XCDR (frompos)),
XINT (XCAR (frompos)), 0,
XINT (to),
(NILP (topos)
? window_internal_height (w)
: XINT (XCDR (topos))),
(NILP (topos)
- ? (window_body_cols (w)
+ ? (window_body_width (w, 0)
- (
#ifdef HAVE_WINDOW_SYSTEM
FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
XSETINT (vpos, pos->vpos);
XSETINT (prevhpos, pos->prevhpos);
- return Fcons (bufpos,
- Fcons (hpos,
- Fcons (vpos,
- Fcons (prevhpos,
- Fcons (pos->contin ? Qt : Qnil, Qnil)))));
-
+ return list5 (bufpos, hpos, vpos, prevhpos, pos->contin ? Qt : Qnil);
}
-\f
-/* Fvertical_motion and vmotion */
+
+/* Fvertical_motion and vmotion. */
static struct position val_vmotion;
struct position *
-vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w)
+vmotion (register ptrdiff_t from, register ptrdiff_t from_byte,
+ register EMACS_INT vtarget, struct window *w)
{
ptrdiff_t hscroll = w->hscroll;
struct position pos;
- /* vpos is cumulative vertical position, changed as from is changed */
+ /* VPOS is cumulative vertical position, changed as from is changed. */
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))
/* If the window contains this buffer, use it for getting text properties.
Otherwise use the current buffer as arg for doing that. */
- if (EQ (w->buffer, Fcurrent_buffer ()))
+ if (EQ (w->contents, Fcurrent_buffer ()))
text_prop_object = window;
else
text_prop_object = Fcurrent_buffer ();
while ((vpos > vtarget || first) && from > BEGV)
{
+ ptrdiff_t bytepos = from_byte;
Lisp_Object propval;
- prevline = find_next_newline_no_quit (from - 1, -1);
+ prevline = from;
+ DEC_BOTH (prevline, bytepos);
+ prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
+
while (prevline > BEGV
&& ((selective > 0
- && indented_beyond_p (prevline,
- CHAR_TO_BYTE (prevline),
- selective))
+ && indented_beyond_p (prevline, bytepos, selective))
/* Watch out for newlines with `invisible' property.
When moving upward, check the newline before. */
|| (propval = Fget_char_property (make_number (prevline - 1),
Qinvisible,
text_prop_object),
TEXT_PROP_MEANS_INVISIBLE (propval))))
- prevline = find_next_newline_no_quit (prevline - 1, -1);
- pos = *compute_motion (prevline, 0,
- lmargin,
- 0,
- from,
+ {
+ DEC_BOTH (prevline, bytepos);
+ prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
+ }
+ pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from,
/* Don't care for VPOS... */
1 << (BITS_PER_SHORT - 1),
/* ... nor HPOS. */
1 << (BITS_PER_SHORT - 1),
- -1, hscroll,
- 0,
- w);
+ -1, hscroll, 0, w);
vpos -= pos.vpos;
first = 0;
from = prevline;
+ from_byte = bytepos;
}
- /* If we made exactly the desired vertical distance,
- or if we hit beginning of buffer,
- return point found */
+ /* If we made exactly the desired vertical distance, or
+ if we hit beginning of buffer, return point found. */
if (vpos >= vtarget)
{
val_vmotion.bufpos = from;
- val_vmotion.bytepos = CHAR_TO_BYTE (from);
+ val_vmotion.bytepos = from_byte;
val_vmotion.vpos = vpos;
val_vmotion.hpos = lmargin;
val_vmotion.contin = 0;
return &val_vmotion;
}
- /* Otherwise find the correct spot by moving down */
+ /* Otherwise find the correct spot by moving down. */
}
- /* Moving downward is simple, but must calculate from beg of line
- to determine hpos of starting point */
- from_byte = CHAR_TO_BYTE (from);
+
+ /* Moving downward is simple, but must calculate from
+ beg of line to determine hpos of starting point. */
+
if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n')
{
+ ptrdiff_t bytepos;
Lisp_Object propval;
- prevline = find_next_newline_no_quit (from, -1);
+ prevline = find_newline_no_quit (from, from_byte, -1, &bytepos);
while (prevline > BEGV
&& ((selective > 0
- && indented_beyond_p (prevline,
- CHAR_TO_BYTE (prevline),
- selective))
+ && indented_beyond_p (prevline, bytepos, selective))
/* Watch out for newlines with `invisible' property.
When moving downward, check the newline after. */
|| (propval = Fget_char_property (make_number (prevline),
Qinvisible,
text_prop_object),
TEXT_PROP_MEANS_INVISIBLE (propval))))
- prevline = find_next_newline_no_quit (prevline - 1, -1);
- pos = *compute_motion (prevline, 0,
- lmargin,
- 0,
- from,
+ {
+ DEC_BOTH (prevline, bytepos);
+ prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
+ }
+ pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from,
/* Don't care for VPOS... */
1 << (BITS_PER_SHORT - 1),
/* ... nor HPOS. */
1 << (BITS_PER_SHORT - 1),
- -1, hscroll,
- 0,
- w);
+ -1, hscroll, 0, w);
did_motion = 1;
}
else
pos.vpos = 0;
did_motion = 0;
}
- return compute_motion (from, vpos, pos.hpos, did_motion,
+ return compute_motion (from, from_byte, vpos, pos.hpos, did_motion,
ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)),
- -1, hscroll,
- 0,
- w);
+ -1, hscroll, 0, w);
}
DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
parameters such as width, horizontal scrolling, and so on.
The default is to use the selected window's parameters.
-LINES can optionally take the form (COLS . LINES), in which case
-the motion will not stop at the start of a screen line but on
-its column COLS (if such exists on that line, that is).
+LINES can optionally take the form (COLS . LINES), in which case the
+motion will not stop at the start of a screen line but COLS column
+from the visual start of the line (if such exists on that line, that
+is). If the line is scrolled horizontally, COLS is interpreted
+visually, i.e., as addition to the columns of text beyond the left
+edge of the window.
`vertical-motion' always uses the current buffer,
regardless of which buffer is displayed in WINDOW.
struct window *w;
Lisp_Object old_buffer;
EMACS_INT old_charpos IF_LINT (= 0), old_bytepos IF_LINT (= 0);
- struct gcpro gcpro1, gcpro2, gcpro3;
+ struct gcpro gcpro1;
Lisp_Object lcols = Qnil;
double cols IF_LINT (= 0);
void *itdata = NULL;
w = decode_live_window (window);
old_buffer = Qnil;
- GCPRO3 (old_buffer, old_charpos, old_bytepos);
- if (XBUFFER (w->buffer) != current_buffer)
+ GCPRO1 (old_buffer);
+ if (XBUFFER (w->contents) != 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;
+ old_buffer = w->contents;
+ old_charpos = marker_position (w->pointm);
+ old_bytepos = marker_byte_position (w->pointm);
wset_buffer (w, Fcurrent_buffer ());
- set_marker_both (w->pointm, w->buffer,
+ set_marker_both (w->pointm, w->contents,
BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer));
}
if (noninteractive)
{
struct position pos;
- pos = *vmotion (PT, XINT (lines), w);
+ pos = *vmotion (PT, PT_BYTE, XINT (lines), w);
SET_PT_BOTH (pos.bufpos, pos.bytepos);
}
else
const char *s = SSDATA (it.string);
const char *e = s + SBYTES (it.string);
+ disp_string_at_start_p =
/* If it.area is anything but TEXT_AREA, we need not bother
about the display string, as it doesn't affect cursor
positioning. */
- disp_string_at_start_p =
- it.string_from_display_prop_p && it.area == TEXT_AREA;
+ it.area == TEXT_AREA
+ && it.string_from_display_prop_p
+ /* A display string on anything but buffer text (e.g., on
+ an overlay string) doesn't affect cursor positioning. */
+ && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER);
while (s < e)
{
if (*s++ == '\n')
string, move_it_to will overshoot it, while vertical-motion
wants to put the cursor _before_ the display string. So in
that case, we move to buffer position before the display
- string, and avoid overshooting. */
- move_it_to (&it, disp_string_at_start_p ? PT - 1 : PT,
+ string, and avoid overshooting. But if the position before
+ the display string is a newline, we don't do this, because
+ otherwise we will end up in a screen line that is one too
+ far back. */
+ move_it_to (&it,
+ (!disp_string_at_start_p
+ || FETCH_BYTE (IT_BYTEPOS (it)) == '\n')
+ ? PT
+ : PT - 1,
-1, -1, -1, MOVE_TO_POS);
/* IT may move too far if truncate-lines is on and PT lies
}
}
- /* Move to the goal column, if one was specified. */
+ /* Move to the goal column, if one was specified. If the window
+ was originally hscrolled, the goal column is interpreted as
+ an addition to the hscroll amount. */
if (!NILP (lcols))
{
- /* If the window was originally hscrolled, move forward by
- the hscrolled amount first. */
- if (first_x > 0)
- {
- move_it_in_display_line (&it, ZV, first_x, MOVE_TO_X);
- it.current_x = 0;
- }
- move_it_in_display_line
- (&it, ZV,
- (int)(cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5),
- MOVE_TO_X);
+ int to_x = (int)(cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5);
+
+ move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X);
}
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
if (BUFFERP (old_buffer))
{
wset_buffer (w, old_buffer);
- set_marker_both (w->pointm, w->buffer,
+ set_marker_both (w->pointm, w->contents,
old_charpos, old_bytepos);
}
- RETURN_UNGCPRO (make_number (it.vpos));
+ return make_number (it.vpos);
}
void
syms_of_indent (void)
{
+#include "indent.x"
+
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 (&Sindent_to);
- defsubr (&Scurrent_column);
- defsubr (&Smove_to_column);
- defsubr (&Svertical_motion);
- defsubr (&Scompute_motion);
}