#include "charset.h"
#include "category.h"
#include "indent.h"
+#include "keyboard.h"
#include "frame.h"
#include "window.h"
#include "termchar.h"
characters immediately following, then *NEXT_BOUNDARY_P
will equal the return value. */
-static int
+int
skip_invisible (pos, next_boundary_p, to, window)
int pos;
int *next_boundary_p;
return pos;
}
\f
-/* Set variables WIDTH and BYTES for a multibyte sequence starting at P.
+/* If a composition starts at POS/POS_BYTE and it doesn't stride over
+ POINT, set *LEN / *LEN_BYTE to the character and byte lengths, *WIDTH
+ to the width, and return 1. Otherwise, return 0. */
+
+static int
+check_composition (pos, pos_byte, point, len, len_byte, width)
+ int pos, pos_byte, point;
+ int *len, *len_byte, *width;
+{
+ Lisp_Object prop;
+ int start, end;
+ int id;
- C is *P which should satisfy `BASE_LEADING_CODE_P (c)'.
+ if (! find_composition (pos, -1, &start, &end, &prop, Qnil)
+ || pos != start || point < end
+ || !COMPOSITION_VALID_P (start, end, prop))
+ return 0;
+ if ((id = get_composition_id (pos, pos_byte, end - pos, prop, Qnil)) < 0)
+ return 0;
+
+ *len = COMPOSITION_LENGTH (prop);
+ *len_byte = CHAR_TO_BYTE (end) - pos_byte;
+ *width = composition_table[id]->width;
+ return 1;
+}
+\f
+/* Set variables WIDTH and BYTES for a multibyte sequence starting at P.
DP is a display table or NULL.
This macro is used in current_column_1, Fmove_to_column, and
compute_motion. */
-#define MULTIBYTE_BYTES_WIDTH(p, c, dp) \
+#define MULTIBYTE_BYTES_WIDTH(p, dp) \
do { \
- unsigned char *pend = p + 1; \
+ int c; \
\
wide_column = 0; \
- while (! CHAR_HEAD_P (*pend)) pend++; \
- \
- if (c == LEADING_CODE_COMPOSITION) \
- { \
- int id = str_cmpchar_id (p, pend - p); \
- int ch = MAKE_COMPOSITE_CHAR (id); \
- \
- if (id >= 0) \
- { \
- bytes = cmpchar_table[id]->len; \
- if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, ch))) \
- width = XVECTOR (DISP_CHAR_VECTOR (dp, ch))->size; \
- else \
- width = cmpchar_table[id]->width; \
- if (width > 1) \
- wide_column = width; \
- } \
- else \
- { \
- bytes = 1; \
- width = 4; \
- } \
- } \
+ c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, bytes); \
+ if (BYTES_BY_CHAR_HEAD (*p) != bytes) \
+ width = bytes * 4; \
else \
{ \
- bytes = BYTES_BY_CHAR_HEAD (c); \
- if (bytes >= 2 && bytes <= pend - p) \
- { \
- int ch; \
- \
- if (dp && (ch = STRING_CHAR (p, bytes), \
- VECTORP (DISP_CHAR_VECTOR (dp, ch)))) \
- width = XVECTOR (DISP_CHAR_VECTOR (dp, ch))->size; \
- else \
- width = WIDTH_BY_CHAR_HEAD (c); \
- if (width > 1) \
- wide_column = width; \
- } \
+ if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \
+ width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \
else \
- { \
- bytes = 1; \
- width = 4; \
- } \
- } \
- if (p + bytes < pend) \
- { \
- width += 4 * (pend - (p + bytes)); \
- bytes = pend - p; \
+ width = WIDTH_BY_CHAR_HEAD (*p); \
+ if (width > 1) \
+ wide_column = width; \
} \
} while (0)
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 stopchar;
if (PT == last_known_column_point
&& MODIFF == last_known_column_modified)
next_boundary_byte = CHAR_TO_BYTE (next_boundary);
}
+ /* Check composition sequence. */
+ {
+ int len, len_byte, width;
+
+ if (check_composition (scan, scan_byte, opoint,
+ &len, &len_byte, &width))
+ {
+ scan += len;
+ scan_byte += len_byte;
+ if (scan <= opoint)
+ col += width;
+ continue;
+ }
+ }
+
c = FETCH_BYTE (scan_byte);
if (dp != 0
&& ! (multibyte && BASE_LEADING_CODE_P (c))
scan_byte--;
ptr = BYTE_POS_ADDR (scan_byte);
- MULTIBYTE_BYTES_WIDTH (ptr, c, dp);
+ MULTIBYTE_BYTES_WIDTH (ptr, dp);
scan_byte += bytes;
col += width;
}
val = position_indentation (PT_BYTE);
SET_PT_BOTH (opoint, opoint_byte);
- return val;
+ return val >= column;
}
\f
DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
\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.\n\
+A non-nil second (optional) argument FORCE means,\n\
+if COLUMN is in the middle of a tab character, change it to spaces.\n\
+In addition, if FORCE is t, and the line is too short\n\
+to reach column COLUMN, add spaces/tabs to get there.\n\
\n\
The return value is the current column.")
(column, force)
register int multibyte = !NILP (current_buffer->enable_multibyte_characters);
Lisp_Object val;
- int prev_col;
- int c;
+ int prev_col = 0;
+ int c = 0;
int next_boundary;
int pos_byte, end_byte, next_boundary_byte;
if (col >= goal)
break;
+ /* Check composition sequence. */
+ {
+ int len, len_byte, width;
+
+ if (check_composition (pos, pos_byte, Z, &len, &len_byte, &width))
+ {
+ pos += len;
+ pos_byte += len_byte;
+ col += width;
+ continue;
+ }
+ }
+
c = FETCH_BYTE (pos_byte);
if (dp != 0
&& ! (multibyte && BASE_LEADING_CODE_P (c))
pos_byte--;
ptr = BYTE_POS_ADDR (pos_byte);
- MULTIBYTE_BYTES_WIDTH (ptr, c, dp);
+ MULTIBYTE_BYTES_WIDTH (ptr, dp);
pos_byte += bytes;
col += width;
}
and scan through it again. */
if (!NILP (force) && col > goal && c == '\t' && prev_col < goal)
{
- int old_point, old_point_byte;
-
- del_range (PT - 1, PT);
- Findent_to (make_number (goal), Qnil);
- old_point = PT;
- old_point_byte = PT_BYTE;
+ int 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
+ adjusted. */
+ SET_PT_BOTH (PT - 1, PT_BYTE - 1);
+ Finsert_char (make_number (' '), make_number (goal - prev_col), Qt);
+
+ /* Now delete the tab, and indent to COL. */
+ del_range (PT, PT + 1);
+ goal_pt = PT;
+ goal_pt_byte = PT_BYTE;
Findent_to (make_number (col), Qnil);
- SET_PT_BOTH (old_point, old_point_byte);
+ SET_PT_BOTH (goal_pt, goal_pt_byte);
+
/* Set the last_known... vars consistently. */
col = goal;
}
/* If line ends prematurely, add space to the end. */
- if (col < goal && !NILP (force))
+ if (col < goal && EQ (force, Qt))
Findent_to (make_number (col = goal), Qnil);
last_known_column = col;
register int pos;
int pos_byte;
- register int c;
+ register int c = 0;
register 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);
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;
+ if (tab_width <= 0 || tab_width > 1000)
+ tab_width = 8;
+
+ immediate_quit = 1;
+ QUIT;
pos = prev_pos = from;
pos_byte = prev_pos_byte = CHAR_TO_BYTE (from);
int pos_here = pos;
int newpos;
+ /* Don't skip invisible if we are already at the margin. */
+ if (vpos > tovpos || vpos == tovpos && hpos >= tohpos)
+ {
+ if (contin_hpos && prev_hpos == 0
+ && hpos > tohpos
+ && (contin_hpos == width || wide_column_end_hpos > width))
+ { /* Line breaks because we can't put the character at the
+ previous line any more. It is not the multi-column
+ character continued in middle. Go back to previous
+ buffer position, screen position, and set tab offset
+ to previous value. It's the beginning of the
+ line. */
+ pos = prev_pos;
+ pos_byte = prev_pos_byte;
+ hpos = prev_hpos;
+ tab_offset = prev_tab_offset;
+ }
+ break;
+ }
+
/* If the caller says that the screen position came from an earlier
call to compute_motion, then we've already accounted for the
overlay strings at point. This is only true the first time
if (newpos >= to)
{
pos = min (to, newpos);
+ pos_byte = CHAR_TO_BYTE (pos);
goto after_loop;
}
if (vpos > tovpos || vpos == tovpos && hpos >= tohpos)
{
if (contin_hpos && prev_hpos == 0
- && wide_column_end_hpos > width)
+ && hpos > tohpos
+ && (contin_hpos == width || wide_column_end_hpos > width))
{ /* Line breaks because we can't put the character at the
previous line any more. It is not the multi-column
character continued in middle. Go back to previous
else
{
c = FETCH_BYTE (pos_byte);
+
+ /* Check composition sequence. */
+ {
+ int len, len_byte, width;
+
+ if (check_composition (pos, pos_byte, to, &len, &len_byte, &width))
+ {
+ pos += len;
+ pos_byte += len_byte;
+ hpos += width;
+ continue;
+ }
+ }
+
pos++, pos_byte++;
/* Perhaps add some info to the width_run_cache. */
/* Skip any number of invisible lines all at once */
do
{
- pos = find_before_next_newline (pos, to, 1) + 1;
+ pos = find_before_next_newline (pos, to, 1);
+ if (pos < to)
+ pos++;
pos_byte = CHAR_TO_BYTE (pos);
}
while (pos < to
pos_byte--; /* rewind POS_BYTE */
ptr = BYTE_POS_ADDR (pos_byte);
- MULTIBYTE_BYTES_WIDTH (ptr, c, dp);
+ MULTIBYTE_BYTES_WIDTH (ptr, dp);
pos_byte += bytes;
if (wide_column)
wide_column_end_hpos = hpos + wide_column;
/* Nonzero if have just continued a line */
val_compute_motion.contin = (contin_hpos && prev_hpos == 0);
+ immediate_quit = 0;
return &val_compute_motion;
}
+
#if 0 /* The doc string is too long for some compilers,
but make-docfile can find it in this comment. */
DEFUN ("compute-motion", Ffoo, Sfoo, 7, 7, 0,
Lisp_Object from, frompos, to, topos;
Lisp_Object width, offsets, window;
{
- Lisp_Object bufpos, hpos, vpos, prevhpos, contin;
+ Lisp_Object bufpos, hpos, vpos, prevhpos;
struct position *pos;
int hscroll, tab_offset;
CHECK_NUMBER_COERCE_MARKER (from, 0);
CHECK_CONS (frompos, 0);
- CHECK_NUMBER (XCONS (frompos)->car, 0);
- CHECK_NUMBER (XCONS (frompos)->cdr, 0);
+ CHECK_NUMBER (XCAR (frompos), 0);
+ CHECK_NUMBER (XCDR (frompos), 0);
CHECK_NUMBER_COERCE_MARKER (to, 0);
CHECK_CONS (topos, 0);
- CHECK_NUMBER (XCONS (topos)->car, 0);
- CHECK_NUMBER (XCONS (topos)->cdr, 0);
+ CHECK_NUMBER (XCAR (topos), 0);
+ CHECK_NUMBER (XCDR (topos), 0);
CHECK_NUMBER (width, 0);
if (!NILP (offsets))
{
CHECK_CONS (offsets, 0);
- CHECK_NUMBER (XCONS (offsets)->car, 0);
- CHECK_NUMBER (XCONS (offsets)->cdr, 0);
- hscroll = XINT (XCONS (offsets)->car);
- tab_offset = XINT (XCONS (offsets)->cdr);
+ CHECK_NUMBER (XCAR (offsets), 0);
+ CHECK_NUMBER (XCDR (offsets), 0);
+ hscroll = XINT (XCAR (offsets));
+ tab_offset = XINT (XCDR (offsets));
}
else
hscroll = tab_offset = 0;
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 (XCONS (frompos)->cdr),
- XINT (XCONS (frompos)->car), 0,
- XINT (to), XINT (XCONS (topos)->cdr),
- XINT (XCONS (topos)->car),
+ pos = compute_motion (XINT (from), XINT (XCDR (frompos)),
+ XINT (XCAR (frompos)), 0,
+ XINT (to), XINT (XCDR (topos)),
+ XINT (XCAR (topos)),
XINT (width), hscroll, tab_offset,
XWINDOW (window));
Lisp_Object window;
int start_hpos = 0;
int did_motion;
+ /* This is the object we use for fetching character properties. */
+ Lisp_Object text_prop_object;
XSETWINDOW (window, w);
- /* The omission of the clause
- && marker_position (w->start) == BEG
- here is deliberate; I think we want to measure from the prompt
- position even if the minibuffer window has scrolled. */
- if (EQ (window, minibuf_window))
- {
- if (minibuf_prompt_width == 0 && STRINGP (minibuf_prompt))
- minibuf_prompt_width
- = string_display_width (minibuf_prompt, Qnil, Qnil);
-
- start_hpos = minibuf_prompt_width;
- }
+ /* 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 ()))
+ text_prop_object = window;
+ else
+ text_prop_object = Fcurrent_buffer ();
if (vpos >= vtarget)
{
&& indented_beyond_p (XFASTINT (prevline),
CHAR_TO_BYTE (XFASTINT (prevline)),
selective))
-#ifdef USE_TEXT_PROPERTIES
/* watch out for newlines with `invisible' property */
|| (propval = Fget_char_property (prevline,
Qinvisible,
- window),
- TEXT_PROP_MEANS_INVISIBLE (propval))
-#endif
- ))
+ text_prop_object),
+ TEXT_PROP_MEANS_INVISIBLE (propval))))
XSETFASTINT (prevline,
find_next_newline_no_quit (XFASTINT (prevline) - 1,
-1));
&& indented_beyond_p (XFASTINT (prevline),
CHAR_TO_BYTE (XFASTINT (prevline)),
selective))
-#ifdef USE_TEXT_PROPERTIES
/* watch out for newlines with `invisible' property */
|| (propval = Fget_char_property (prevline, Qinvisible,
- window),
- TEXT_PROP_MEANS_INVISIBLE (propval))
-#endif
- ))
+ text_prop_object),
+ TEXT_PROP_MEANS_INVISIBLE (propval))))
XSETFASTINT (prevline,
find_next_newline_no_quit (XFASTINT (prevline) - 1,
-1));
(lines, window)
Lisp_Object lines, window;
{
- struct position pos;
+ struct it it;
+ struct text_pos pt;
+ struct window *w;
+ Lisp_Object old_buffer;
+ struct gcpro gcpro1;
CHECK_NUMBER (lines, 0);
if (! NILP (window))
CHECK_WINDOW (window, 0);
else
window = selected_window;
+ w = XWINDOW (window);
- pos = *vmotion (PT, (int) XINT (lines), XWINDOW (window));
-
- SET_PT (pos.bufpos);
- return make_number (pos.vpos);
+ old_buffer = Qnil;
+ GCPRO1 (old_buffer);
+ 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);
+ }
+
+ SET_TEXT_POS (pt, PT, PT_BYTE);
+ start_display (&it, w, pt);
+ move_it_by_lines (&it, XINT (lines), 0);
+ SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
+
+ if (BUFFERP (old_buffer))
+ w->buffer = old_buffer;
+
+ RETURN_UNGCPRO (make_number (it.vpos));
}
+
+
\f
/* file's initialization. */