/* Width run cache considerations. */
/* Return the width of character C under display table DP. */
+
static int
character_width (c, dp)
int c;
/* These width computations were determined by examining the cases
in display_text_line. */
- /* Some characters are never handled by the display table. */
- if (c == '\n' || c == '\t' || c == '\015')
- return 0;
-
- /* Everything else might be handled by the display table, if it's
+ /* Everything can be handled by the display table, if it's
present and the element is right. */
- else if (dp && (elt = DISP_CHAR_VECTOR (dp, c),
- VECTORP (elt)))
+ if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
return XVECTOR (elt)->size;
- /* In the absence of display table perversities, printing characters
- have width 1. */
+ /* Some characters are special. */
+ if (c == '\n' || c == '\t' || c == '\015')
+ return 0;
+
+ /* Printing characters have width 1. */
else if (c >= 040 && c < 0177)
return 1;
}
c = *--ptr;
- if (c >= 040 && c < 0177
- && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
- {
- col++;
- }
+ 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')
break;
else if (c == '\r' && EQ (current_buffer->selective_display, Qt))
col = 0;
tab_seen = 1;
}
- else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
else
col += (ctl_arrow && c < 0200) ? 2 : 4;
}
return col;
}
\f
+/* Return the width in columns of the part of STRING from BEG to END.
+ If BEG is nil, that stands for the beginning of STRING.
+ If END is nil, that stands for the end of STRING. */
+
+static int
+string_width (string, beg, end)
+ Lisp_Object string, beg, end;
+{
+ 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_Vector *dp = buffer_display_table ();
+ int b, e;
+
+ if (NILP (end))
+ e = XSTRING (string)->size;
+ else
+ {
+ CHECK_NUMBER (end, 0);
+ e = XINT (end);
+ }
+
+ if (NILP (beg))
+ b = 0;
+ else
+ {
+ CHECK_NUMBER (beg, 0);
+ b = XINT (beg);
+ }
+
+ /* Make a pointer for decrementing through the chars before point. */
+ ptr = XSTRING (string)->data + e;
+ /* Make a pointer to where consecutive chars leave off,
+ going backwards from point. */
+ stop = XSTRING (string)->data + b;
+
+ if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
+
+ col = 0, tab_seen = 0, post_tab = 0;
+
+ while (1)
+ {
+ if (ptr == stop)
+ 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')
+ break;
+ 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;
+ }
+
+ if (tab_seen)
+ {
+ col = ((col + tab_width) / tab_width) * tab_width;
+ col += post_tab;
+ }
+
+ return col;
+}
+\f
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\
while (col < goal && pos < end)
{
c = FETCH_CHAR (pos);
+ if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
+ {
+ col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
+ pos++;
+ break;
+ }
if (c == '\n')
break;
if (c == '\r' && EQ (current_buffer->selective_display, Qt))
col += tab_width;
col = col / tab_width * tab_width;
}
- else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
else if (ctl_arrow && (c < 040 || c == 0177))
col += 2;
else if (c < 040 || c >= 0177)
{
Lisp_Object end, limit, proplimit;
- /* Get a quit lower bound for how soon property might change. */
+ /* We must not advance farther than the next overlay change.
+ The overlay change might change the invisible property;
+ we have no way of telling. */
limit = Fnext_overlay_change (position);
+ /* As for text properties, this gives a lower bound
+ for where the invisible text property could change. */
proplimit = Fnext_property_change (position, buffer, Qt);
- if (XFASTINT (proplimit) < XFASTINT (limit))
- limit = proplimit;
- /* LIMIT is now a lower bound for the next change
+ if (XFASTINT (limit) < XFASTINT (proplimit))
+ proplimit = limit;
+ /* PROPLIMIT is now a lower bound for the next change
in invisible status. If that is plenty far away,
use that lower bound. */
- if (XFASTINT (limit) > pos + 100 || XFASTINT (limit) >= to)
- next_invisible = XINT (limit);
+ if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
+ next_invisible = XINT (proplimit);
/* Otherwise, scan for the next `invisible' property change. */
else
{
/* Don't scan terribly far. */
- XSETFASTINT (limit, min (pos + 100, to));
+ XSETFASTINT (proplimit, min (pos + 100, to));
+ /* No matter what. don't go past next overlay change. */
+ if (XFASTINT (limit) < XFASTINT (proplimit))
+ proplimit = limit;
end = Fnext_single_property_change (position, Qinvisible,
- buffer, limit);
+ buffer, proplimit);
if (INTEGERP (end) && XINT (end) < to)
next_invisible = XINT (end);
else
}
}
- if (c >= 040 && c < 0177
- && (dp == 0 || ! VECTORP (DISP_CHAR_VECTOR (dp, c))))
+ if (dp != 0 && 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')
{
hpos = width;
}
}
- else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
else
hpos += (ctl_arrow && c < 0200) ? 2 : 4;
}
&& marker_position (XWINDOW (window)->start) == BEG
here is deliberate; I think we want to measure from the prompt
position even if the minibuffer window has scrolled. */
- int start_hpos = (EQ (window, minibuf_window) ? minibuf_prompt_width : 0);
+ int start_hpos = 0;
+
+ if (EQ (window, minibuf_window))
+ {
+ if (minibuf_prompt_width == 0)
+ minibuf_prompt_width = string_width (minibuf_prompt, Qnil, Qnil);
+
+ start_hpos = minibuf_prompt_width;
+ }
retry:
if (vtarget > vpos)