+ else
+ {
+ 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 if (VECTORP (charvec))
+ /* With a display table entry, C is displayed as is, and
+ not displayed as \NNN or as ^N. If C is a single-byte
+ character, it takes one column. If C is multi-byte in
+ an unibyte buffer, it's translated to unibyte, so it
+ also takes one column. */
+ ++col;
+ else
+ col += (ctl_arrow && c < 0200) ? 2 : 4;
+ }
+ }
+
+ start_of_line_found:
+
+ if (tab_seen)
+ {
+ col = ((col + tab_width) / tab_width) * tab_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;
+
+ return col;
+}
+\f
+/* Return the column number of position POS
+ by scanning forward from the beginning of the line.
+ This function handles characters that are invisible
+ due to text properties or overlays. */
+
+static int
+current_column_1 ()
+{
+ register 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);
+
+ /* Start the scan at the beginning of this line with column number 0. */
+ register int col = 0;
+ int scan, scan_byte;
+ int next_boundary, next_boundary_byte;
+ int 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);
+ next_boundary = scan;
+ next_boundary_byte = scan_byte;
+
+ if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
+
+ /* Scan forward to the target position. */
+ while (scan < opoint)
+ {
+ int c;
+
+ /* Occasionally we may need to skip invisible text. */
+ while (scan == next_boundary)
+ {
+ int 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, opoint, Qnil);
+ if (scan >= opoint)
+ goto endloop;
+ if (scan != old_scan)
+ scan_byte = CHAR_TO_BYTE (scan);
+ 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))
+ && VECTORP (DISP_CHAR_VECTOR (dp, c)))
+ {
+ Lisp_Object charvec;
+ EMACS_INT i, n;
+
+ /* This character is displayed using a vector of glyphs.
+ Update the column based on those glyphs. */
+
+ charvec = DISP_CHAR_VECTOR (dp, c);
+ n = ASIZE (charvec);
+
+ for (i = 0; i < n; i++)
+ {
+ /* This should be handled the same as
+ next_element_from_display_vector does it. */
+ Lisp_Object entry;
+ 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;
+ if (c == '\t')
+ {
+ col += tab_width;
+ col = col / tab_width * tab_width;
+ }
+ else
+ ++col;
+ }
+ }
+ else
+ {
+ /* The display table says nothing for this character.
+ Display it as itself. */
+
+ if (c == '\n')
+ goto endloop;
+ if (c == '\r' && EQ (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))
+ {
+ unsigned char *ptr;
+ int bytes, width, wide_column;
+
+ ptr = BYTE_POS_ADDR (scan_byte);
+ MULTIBYTE_BYTES_WIDTH (ptr, dp);
+ scan_byte += bytes;
+ /* Subtract one to compensate for the increment
+ that is going to happen below. */
+ scan_byte--;
+ col += width;
+ }
+ else if (ctl_arrow && (c < 040 || c == 0177))
+ col += 2;
+ else if (c < 040 || c >= 0177)
+ col += 4;
+ else
+ col++;
+ }
+ scan++;
+ scan_byte++;
+
+ }
+ endloop:
+
+ last_known_column = col;
+ last_known_column_point = PT;
+ last_known_column_modified = MODIFF;
+
+ return col;
+}
+\f
+
+#if 0 /* Not used. */
+
+/* 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_display_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_Char_Table *dp = buffer_display_table ();
+ int b, e;
+
+ if (NILP (end))
+ e = XSTRING (string)->size;
+ else
+ {
+ CHECK_NUMBER (end);
+ e = XINT (end);
+ }
+
+ if (NILP (beg))
+ b = 0;
+ else
+ {
+ CHECK_NUMBER (beg);
+ 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)