indent.c 62 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Indentation functions.
2
   Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2011
Glenn Morris's avatar
Glenn Morris committed
3
                 Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
4 5 6

This file is part of GNU Emacs.

7
GNU Emacs is free software: you can redistribute it and/or modify
Jim Blandy's avatar
Jim Blandy committed
8
it under the terms of the GNU General Public License as published by
9 10
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jim Blandy's avatar
Jim Blandy committed
11 12 13 14 15 16 17

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
18
along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
Jim Blandy's avatar
Jim Blandy committed
19

20
#include <config.h>
21
#include <stdio.h>
22
#include <setjmp.h>
23

Jim Blandy's avatar
Jim Blandy committed
24 25
#include "lisp.h"
#include "buffer.h"
26
#include "character.h"
27
#include "category.h"
28
#include "composite.h"
Jim Blandy's avatar
Jim Blandy committed
29
#include "indent.h"
30
#include "keyboard.h"
Jim Blandy's avatar
Jim Blandy committed
31
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
32 33 34 35
#include "window.h"
#include "termchar.h"
#include "termopts.h"
#include "disptab.h"
36
#include "intervals.h"
37
#include "dispextern.h"
38
#include "region-cache.h"
Jim Blandy's avatar
Jim Blandy committed
39 40 41

#define CR 015

Eli Zaretskii's avatar
Eli Zaretskii committed
42
/* These three values memorize the current column to avoid recalculation.  */
43 44 45

/* Last value returned by current_column.
   Some things in set last_known_column_point to -1
Eli Zaretskii's avatar
Eli Zaretskii committed
46
   to mark the memorized value as invalid.  */
47

48
static EMACS_INT last_known_column;
49 50 51

/* Value of point when current_column was called.  */

Stefan Monnier's avatar
Stefan Monnier committed
52
EMACS_INT last_known_column_point;
53 54 55

/* Value of MODIFF when current_column was called.  */

56
static int last_known_column_modified;
Jim Blandy's avatar
Jim Blandy committed
57

58 59
static EMACS_INT current_column_1 (void);
static EMACS_INT position_indentation (int);
60

61 62
/* Cache of beginning of line found by the last call of
   current_column. */
63

Stefan Monnier's avatar
Stefan Monnier committed
64
static EMACS_INT current_column_bol_cache;
65

Jim Blandy's avatar
Jim Blandy committed
66 67
/* Get the display table to use for the current buffer.  */

68
struct Lisp_Char_Table *
69
buffer_display_table (void)
Jim Blandy's avatar
Jim Blandy committed
70 71 72
{
  Lisp_Object thisbuf;

Tom Tromey's avatar
Tom Tromey committed
73
  thisbuf = BVAR (current_buffer, display_table);
74 75 76 77
  if (DISP_TABLE_P (thisbuf))
    return XCHAR_TABLE (thisbuf);
  if (DISP_TABLE_P (Vstandard_display_table))
    return XCHAR_TABLE (Vstandard_display_table);
Jim Blandy's avatar
Jim Blandy committed
78 79
  return 0;
}
80 81 82 83

/* Width run cache considerations.  */

/* Return the width of character C under display table DP.  */
84

85
static int
86
character_width (int c, struct Lisp_Char_Table *dp)
87 88 89 90 91 92
{
  Lisp_Object elt;

  /* These width computations were determined by examining the cases
     in display_text_line.  */

93
  /* Everything can be handled by the display table, if it's
94
     present and the element is right.  */
95
  if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
96
    return ASIZE (elt);
97

98 99 100 101 102
  /* Some characters are special.  */
  if (c == '\n' || c == '\t' || c == '\015')
    return 0;

  /* Printing characters have width 1.  */
103 104 105 106 107 108 109 110 111 112 113 114
  else if (c >= 040 && c < 0177)
    return 1;

  /* Everybody else (control characters, metacharacters) has other
     widths.  We could return their actual widths here, but they
     depend on things like ctl_arrow and crud like that, and they're
     not very common at all.  So we'll just claim we don't know their
     widths.  */
  else
    return 0;
}

Glenn Morris's avatar
Glenn Morris committed
115
/* Return true if the display table DISPTAB specifies the same widths
116 117
   for characters as WIDTHTAB.  We use this to decide when to
   invalidate the buffer's width_run_cache.  */
118

119
int
120
disptab_matches_widthtab (struct Lisp_Char_Table *disptab, struct Lisp_Vector *widthtab)
121 122 123
{
  int i;

124
  if (widthtab->header.size != 256)
125 126 127 128 129 130 131 132
    abort ();

  for (i = 0; i < 256; i++)
    if (character_width (i, disptab)
        != XFASTINT (widthtab->contents[i]))
      return 0;

  return 1;
133
}
134 135

/* Recompute BUF's width table, using the display table DISPTAB.  */
136

137
void
138
recompute_width_table (struct buffer *buf, struct Lisp_Char_Table *disptab)
139 140
{
  int i;
141
  struct Lisp_Vector *widthtab;
142

Tom Tromey's avatar
Tom Tromey committed
143 144 145
  if (!VECTORP (BVAR (buf, width_table)))
    BVAR (buf, width_table) = Fmake_vector (make_number (256), make_number (0));
  widthtab = XVECTOR (BVAR (buf, width_table));
146
  if (widthtab->header.size != 256)
147 148 149
    abort ();

  for (i = 0; i < 256; i++)
150
    XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
151 152 153 154
}

/* Allocate or free the width run cache, as requested by the current
   state of current_buffer's cache_long_line_scans variable.  */
155

156
static void
157
width_run_cache_on_off (void)
158
{
Tom Tromey's avatar
Tom Tromey committed
159
  if (NILP (BVAR (current_buffer, cache_long_line_scans))
160 161
      /* And, for the moment, this feature doesn't work on multibyte
         characters.  */
Tom Tromey's avatar
Tom Tromey committed
162
      || !NILP (BVAR (current_buffer, enable_multibyte_characters)))
163 164 165 166 167 168
    {
      /* It should be off.  */
      if (current_buffer->width_run_cache)
        {
          free_region_cache (current_buffer->width_run_cache);
          current_buffer->width_run_cache = 0;
Tom Tromey's avatar
Tom Tromey committed
169
          BVAR (current_buffer, width_table) = Qnil;
170 171 172 173 174 175
        }
    }
  else
    {
      /* It should be on.  */
      if (current_buffer->width_run_cache == 0)
176
        {
177 178 179 180 181 182
          current_buffer->width_run_cache = new_region_cache ();
          recompute_width_table (current_buffer, buffer_display_table ());
        }
    }
}

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206

/* Skip some invisible characters starting from POS.
   This includes characters invisible because of text properties
   and characters invisible because of overlays.

   If position POS is followed by invisible characters,
   skip some of them and return the position after them.
   Otherwise return POS itself.

   Set *NEXT_BOUNDARY_P to the next position at which
   it will be necessary to call this function again.

   Don't scan past TO, and don't set *NEXT_BOUNDARY_P
   to a value greater than TO.

   If WINDOW is non-nil, and this buffer is displayed in WINDOW,
   take account of overlays that apply only in WINDOW.

   We don't necessarily skip all the invisible characters after POS
   because that could take a long time.  We skip a reasonable number
   which can be skipped quickly.  If there might be more invisible
   characters immediately following, then *NEXT_BOUNDARY_P
   will equal the return value.  */

Stefan Monnier's avatar
Stefan Monnier committed
207
EMACS_INT
208
skip_invisible (EMACS_INT pos, EMACS_INT *next_boundary_p, EMACS_INT to, Lisp_Object window)
209
{
210
  Lisp_Object prop, position, overlay_limit, proplimit;
211
  Lisp_Object buffer, tmp;
Stefan Monnier's avatar
Stefan Monnier committed
212 213
  EMACS_INT end;
  int inv_p;
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

  XSETFASTINT (position, pos);
  XSETBUFFER (buffer, current_buffer);

  /* Give faster response for overlay lookup near POS.  */
  recenter_overlay_lists (current_buffer, pos);

  /* We must not advance farther than the next overlay change.
     The overlay change might change the invisible property;
     or there might be overlay strings to be displayed there.  */
  overlay_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 (overlay_limit) < XFASTINT (proplimit))
    proplimit = overlay_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 (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
    *next_boundary_p = XFASTINT (proplimit);
  /* Otherwise, scan for the next `invisible' property change.  */
  else
    {
      /* Don't scan terribly far.  */
      XSETFASTINT (proplimit, min (pos + 100, to));
240
      /* No matter what, don't go past next overlay change.  */
241 242
      if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
	proplimit = overlay_limit;
243 244 245
      tmp = Fnext_single_property_change (position, Qinvisible,
					  buffer, proplimit);
      end = XFASTINT (tmp);
246
#if 0
247 248 249 250 251 252 253
      /* Don't put the boundary in the middle of multibyte form if
         there is no actual property change.  */
      if (end == pos + 100
	  && !NILP (current_buffer->enable_multibyte_characters)
	  && end < ZV)
	while (pos < end && !CHAR_HEAD_P (POS_ADDR (end)))
	  end--;
254
#endif
255
      *next_boundary_p = end;
256 257 258
    }
  /* if the `invisible' property is set, we can skip to
     the next property change */
259 260 261 262 263 264 265
  prop = Fget_char_property (position, Qinvisible,
			     (!NILP (window)
			      && EQ (XWINDOW (window)->buffer, buffer))
			     ? window : buffer);
  inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
  /* When counting columns (window == nil), don't skip over ellipsis text.  */
  if (NILP (window) ? inv_p == 1 : inv_p)
266 267 268
    return *next_boundary_p;
  return pos;
}
Jim Blandy's avatar
Jim Blandy committed
269

270 271 272 273
/* Set variables WIDTH and BYTES for a multibyte sequence starting at P.

   DP is a display table or NULL.

274
   This macro is used in scan_for_column and in
275 276
   compute_motion.  */

277
#define MULTIBYTE_BYTES_WIDTH(p, dp, bytes, width)			\
278
  do {									\
279
    int ch;								\
280
    									\
281
    ch = STRING_CHAR_AND_LENGTH (p, bytes);				\
282 283 284 285
    if (BYTES_BY_CHAR_HEAD (*p) != bytes)				\
      width = bytes * 4;						\
    else								\
      {									\
286
	if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, ch)))		\
287
	  width = ASIZE (DISP_CHAR_VECTOR (dp, ch));			\
288
	else								\
289
	  width = CHAR_WIDTH (ch);					\
290
      }									\
291 292
  } while (0)

293

Jim Blandy's avatar
Jim Blandy committed
294
DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
295 296 297
       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
298 299
and point (eg. control characters will have a width of 2 or 4, tabs
will have a variable width).
300 301 302
Ignores finite width of frame, which means that this function may return
values greater than (frame-width).
Whether the line is visible (if `selective-display' is t) has no effect;
Stefan Monnier's avatar
Stefan Monnier committed
303 304 305
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.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
306
  (void)
Jim Blandy's avatar
Jim Blandy committed
307 308
{
  Lisp_Object temp;
309
  XSETFASTINT (temp, current_column ());
Jim Blandy's avatar
Jim Blandy committed
310 311 312
  return temp;
}

Jim Blandy's avatar
Jim Blandy committed
313 314
/* Cancel any recorded value of the horizontal position.  */

315
void
316
invalidate_current_column (void)
Jim Blandy's avatar
Jim Blandy committed
317 318 319 320
{
  last_known_column_point = 0;
}

321 322 323 324 325 326 327 328 329
/* Return a non-outlandish value for the tab width.  */

static int
sane_tab_width (void)
{
  EMACS_INT n = XFASTINT (BVAR (current_buffer, tab_width));
  return 0 < n && n <= 1000 ? n : 8;
}

330
EMACS_INT
331
current_column (void)
Jim Blandy's avatar
Jim Blandy committed
332
{
333
  register EMACS_INT col;
Jim Blandy's avatar
Jim Blandy committed
334 335
  register unsigned char *ptr, *stop;
  register int tab_seen;
336
  EMACS_INT post_tab;
Jim Blandy's avatar
Jim Blandy committed
337
  register int c;
338
  int tab_width = sane_tab_width ();
Tom Tromey's avatar
Tom Tromey committed
339
  int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
340
  register struct Lisp_Char_Table *dp = buffer_display_table ();
Jim Blandy's avatar
Jim Blandy committed
341

342
  if (PT == last_known_column_point
Jim Blandy's avatar
Jim Blandy committed
343 344 345
      && MODIFF == last_known_column_modified)
    return last_known_column;

346 347
  /* If the buffer has overlays, text properties,
     or multibyte characters, use a more general algorithm.  */
348
  if (BUF_INTERVALS (current_buffer)
349 350
      || current_buffer->overlays_before
      || current_buffer->overlays_after
351 352
      || Z != Z_BYTE)
    return current_column_1 ();
353 354 355 356

  /* Scan backwards from point to the previous newline,
     counting width.  Tab characters are the only complicated case.  */

Jim Blandy's avatar
Jim Blandy committed
357
  /* Make a pointer for decrementing through the chars before point.  */
358
  ptr = BYTE_POS_ADDR (PT_BYTE - 1) + 1;
Jim Blandy's avatar
Jim Blandy committed
359 360
  /* Make a pointer to where consecutive chars leave off,
     going backwards from point.  */
361
  if (PT == BEGV)
Jim Blandy's avatar
Jim Blandy committed
362
    stop = ptr;
363
  else if (PT <= GPT || BEGV > GPT)
Jim Blandy's avatar
Jim Blandy committed
364 365 366 367 368 369 370 371
    stop = BEGV_ADDR;
  else
    stop = GAP_END_ADDR;

  col = 0, tab_seen = 0, post_tab = 0;

  while (1)
    {
372 373
      EMACS_INT i, n;
      Lisp_Object charvec;
374

Jim Blandy's avatar
Jim Blandy committed
375 376 377 378 379 380
      if (ptr == stop)
	{
	  /* We stopped either for the beginning of the buffer
	     or for the gap.  */
	  if (ptr == BEGV_ADDR)
	    break;
381

Jim Blandy's avatar
Jim Blandy committed
382 383 384
	  /* It was the gap.  Jump back over it.  */
	  stop = BEGV_ADDR;
	  ptr = GPT_ADDR;
385

Jim Blandy's avatar
Jim Blandy committed
386
	  /* Check whether that brings us to beginning of buffer.  */
387 388
	  if (BEGV >= GPT)
	    break;
Jim Blandy's avatar
Jim Blandy committed
389 390 391
	}

      c = *--ptr;
392

393
      if (dp && VECTORP (DISP_CHAR_VECTOR (dp, c)))
394
	{
395 396
	  charvec = DISP_CHAR_VECTOR (dp, c);
	  n = ASIZE (charvec);
397
	}
398
      else
Jim Blandy's avatar
Jim Blandy committed
399
	{
400 401 402
	  charvec = Qnil;
	  n = 1;
	}
403

404 405 406 407 408 409 410
      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);
411

412 413 414
	      if (GLYPH_CODE_P (entry)
		  && GLYPH_CODE_CHAR_VALID_P (entry))
		c = GLYPH_CODE_CHAR (entry);
415 416 417
	      else
		c = ' ';
	    }
418

419 420 421 422
	  if (c >= 040 && c < 0177)
	    col++;
	  else if (c == '\n'
		   || (c == '\r'
Tom Tromey's avatar
Tom Tromey committed
423
		       && EQ (BVAR (current_buffer, selective_display), Qt)))
424 425 426 427 428 429 430 431
	    {
	      ptr++;
	      goto start_of_line_found;
	    }
	  else if (c == '\t')
	    {
	      if (tab_seen)
		col = ((col + tab_width) / tab_width) * tab_width;
432

433 434 435 436
	      post_tab += col;
	      col = 0;
	      tab_seen = 1;
	    }
437 438 439 440 441 442 443
	  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;
444 445
	  else
	    col += (ctl_arrow && c < 0200) ? 2 : 4;
Jim Blandy's avatar
Jim Blandy committed
446 447 448
	}
    }

449 450
 start_of_line_found:

Jim Blandy's avatar
Jim Blandy committed
451 452 453 454 455 456
  if (tab_seen)
    {
      col = ((col + tab_width) / tab_width) * tab_width;
      col += post_tab;
    }

457 458 459
  if (ptr == BEGV_ADDR)
    current_column_bol_cache = BEGV;
  else
460 461
    current_column_bol_cache = BYTE_TO_CHAR (PTR_BYTE_POS (ptr));

Jim Blandy's avatar
Jim Blandy committed
462
  last_known_column = col;
463
  last_known_column_point = PT;
Jim Blandy's avatar
Jim Blandy committed
464 465 466 467 468
  last_known_column_modified = MODIFF;

  return col;
}

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494

/* Check the presence of a display property and compute its width.
   If a property was found and its width was found as well, return
   its width (>= 0) and set the position of the end of the property
   in ENDPOS.
   Otherwise just return -1.  */
static int
check_display_width (EMACS_INT pos, EMACS_INT col, EMACS_INT *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.  */
      Lisp_Object plist = XCDR (val), prop;
      int width = -1;

      if ((prop = Fplist_get (plist, QCwidth), NATNUMP (prop)))
	width = XINT (prop);
      else if (FLOATP (prop))
	width = (int)(XFLOAT_DATA (prop) + 0.5);
      else if ((prop = Fplist_get (plist, QCalign_to), NATNUMP (prop)))
	width = XINT (prop) - col;
      else if (FLOATP (prop))
	width = (int)(XFLOAT_DATA (prop) + 0.5) - col;
495

496 497 498 499 500 501 502 503 504 505 506 507 508
      if (width >= 0)
	{
	  EMACS_INT start;
	  if (OVERLAYP (overlay))
	    *endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
	  else
	    get_property_and_range (pos, Qdisplay, &val, &start, endpos, Qnil);
	  return width;
	}
    }
  return -1;
}

509 510 511 512 513 514 515 516
/* Scanning from the beginning of the current line, stop at the buffer
   position ENDPOS or at the column GOALCOL or at the end of line, whichever
   comes first.
   Return the resulting buffer position and column in ENDPOS and GOALCOL.
   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)
517
{
518
  int tab_width = sane_tab_width ();
Tom Tromey's avatar
Tom Tromey committed
519
  register int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
520
  register struct Lisp_Char_Table *dp = buffer_display_table ();
Tom Tromey's avatar
Tom Tromey committed
521
  int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
522
  struct composition_it cmp_it;
523 524
  Lisp_Object window;
  struct window *w;
525 526

  /* Start the scan at the beginning of this line with column number 0.  */
527 528 529
  register EMACS_INT col = 0, prev_col = 0;
  EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
  EMACS_INT end = endpos ? *endpos : PT;
Stefan Monnier's avatar
Stefan Monnier committed
530 531
  EMACS_INT scan, scan_byte;
  EMACS_INT next_boundary;
532
  {
Stefan Monnier's avatar
Stefan Monnier committed
533
  EMACS_INT opoint = PT, opoint_byte = PT_BYTE;
534
  scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
535 536 537 538
  current_column_bol_cache = PT;
  scan = PT, scan_byte = PT_BYTE;
  SET_PT_BOTH (opoint, opoint_byte);
  next_boundary = scan;
539
  }
540

541 542 543
  window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
  w = ! NILP (window) ? XWINDOW (window) : NULL;

544
  memset (&cmp_it, 0, sizeof cmp_it);
545 546
  cmp_it.id = -1;
  composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil);
547 548

  /* Scan forward to the target position.  */
549
  while (scan < end)
550 551 552 553 554 555
    {
      int c;

      /* Occasionally we may need to skip invisible text.  */
      while (scan == next_boundary)
	{
556
	  EMACS_INT old_scan = scan;
557 558
	  /* This updates NEXT_BOUNDARY to the next place
	     where we might need to skip more invisible text.  */
559
	  scan = skip_invisible (scan, &next_boundary, end, Qnil);
560 561
	  if (scan != old_scan)
	    scan_byte = CHAR_TO_BYTE (scan);
562 563
	  if (scan >= end)
	    goto endloop;
564 565
	}

566 567 568 569 570 571 572
      /* Test reaching the goal column.  We do this after skipping
	 invisible characters, so that we put point before the
	 character on which the cursor will appear.  */
      if (col >= goal)
	break;
      prev_col = col;

573
      { /* Check display property.  */
574 575
	EMACS_INT endp;
	int width = check_display_width (scan, col, &endp);
576 577 578
	if (width >= 0)
	  {
	    col += width;
579
	    if (endp > scan) /* Avoid infinite loops with 0-width overlays.  */
580
	      {
581
		scan = endp; scan_byte = charpos_to_bytepos (scan);
582 583 584 585 586
		continue;
	      }
	  }
      }

587 588 589 590
      /* Check composition sequence.  */
      if (cmp_it.id >= 0
	  || (scan == cmp_it.stop_pos
	      && composition_reseat_it (&cmp_it, scan, scan_byte, end,
591
					w, NULL, Qnil)))
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
	composition_update_it (&cmp_it, scan, scan_byte, Qnil);
      if (cmp_it.id >= 0)
	{
	  scan += cmp_it.nchars;
	  scan_byte += cmp_it.nbytes;
	  if (scan <= end)
	    col += cmp_it.width;
	  if (cmp_it.to == cmp_it.nglyphs)
	    {
	      cmp_it.id = -1;
	      composition_compute_stop_pos (&cmp_it, scan, scan_byte, end,
					    Qnil);
	    }
	  else
	    cmp_it.from = cmp_it.to;
	  continue;
	}

610
      c = FETCH_BYTE (scan_byte);
611

612 613 614
      /* See if there is a display table and it relates
	 to this character.  */

615
      if (dp != 0
616
	  && ! (multibyte && LEADING_CODE_P (c))
617
	  && VECTORP (DISP_CHAR_VECTOR (dp, c)))
618
	{
619 620 621 622
	  Lisp_Object charvec;
	  EMACS_INT i, n;

	  /* This character is displayed using a vector of glyphs.
623
	     Update the column/position based on those glyphs.  */
624

625 626 627
	  charvec = DISP_CHAR_VECTOR (dp, c);
	  n = ASIZE (charvec);

628
	  for (i = 0; i < n; i++)
629 630 631
	    {
	      /* This should be handled the same as
		 next_element_from_display_vector does it.  */
632
	      Lisp_Object entry = AREF (charvec, i);
633

634 635 636
	      if (GLYPH_CODE_P (entry)
		  && GLYPH_CODE_CHAR_VALID_P (entry))
		c = GLYPH_CODE_CHAR (entry);
637 638
	      else
		c = ' ';
639 640 641

	      if (c == '\n')
		goto endloop;
Tom Tromey's avatar
Tom Tromey committed
642
	      if (c == '\r' && EQ (BVAR (current_buffer, selective_display), Qt))
643 644 645 646 647 648 649 650
		goto endloop;
	      if (c == '\t')
		{
		  col += tab_width;
		  col = col / tab_width * tab_width;
		}
	      else
		++col;
651
	    }
652 653 654
	}
      else
	{
655 656
	  /* The display table doesn't affect this character;
	     it displays as itself.  */
657

658 659
	  if (c == '\n')
	    goto endloop;
Tom Tromey's avatar
Tom Tromey committed
660
	  if (c == '\r' && EQ (BVAR (current_buffer, selective_display), Qt))
661 662 663 664 665 666
	    goto endloop;
	  if (c == '\t')
	    {
	      col += tab_width;
	      col = col / tab_width * tab_width;
	    }
667
	  else if (multibyte && LEADING_CODE_P (c))
668
	    {
669
	      /* Start of multi-byte form.  */
670
	      unsigned char *ptr;
671
	      int bytes, width;
672

673
	      ptr = BYTE_POS_ADDR (scan_byte);
674
	      MULTIBYTE_BYTES_WIDTH (ptr, dp, bytes, width);
675 676
	      /* Subtract one to compensate for the increment
		 that is going to happen below.  */
677
	      scan_byte += bytes - 1;
678 679 680 681 682 683 684 685
	      col += width;
	    }
	  else if (ctl_arrow && (c < 040 || c == 0177))
	    col += 2;
	  else if (c < 040 || c >= 0177)
	    col += 4;
	  else
	    col++;
686
	}
687 688 689
      scan++;
      scan_byte++;

690 691 692 693
    }
 endloop:

  last_known_column = col;
694
  last_known_column_point = PT;
695 696
  last_known_column_modified = MODIFF;

697 698 699 700 701 702 703 704 705 706 707 708 709
  if (goalcol)
    *goalcol = col;
  if (endpos)
    *endpos = scan;
  if (prevcol)
    *prevcol = prev_col;
}

/* 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.  */

710
static EMACS_INT
711
current_column_1 (void)
712 713 714 715 716
{
  EMACS_INT col = MOST_POSITIVE_FIXNUM;
  EMACS_INT opoint = PT;

  scan_for_column (&opoint, &col, NULL);
717 718 719
  return col;
}

720 721 722

#if 0 /* Not used.  */

723 724 725 726
/* 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.  */

727
static double
728
string_display_width (string, beg, end)
729 730 731 732 733 734 735
     Lisp_Object string, beg, end;
{
  register int col;
  register unsigned char *ptr, *stop;
  register int tab_seen;
  int post_tab;
  register int c;
736
  int tab_width = sane_tab_width ();
737
  int ctl_arrow = !NILP (current_buffer->ctl_arrow);
738
  register struct Lisp_Char_Table *dp = buffer_display_table ();
739 740 741
  int b, e;

  if (NILP (end))
742
    e = SCHARS (string);
743 744
  else
    {
745
      CHECK_NUMBER (end);
746 747 748 749 750 751 752
      e = XINT (end);
    }

  if (NILP (beg))
    b = 0;
  else
    {
753
      CHECK_NUMBER (beg);
754 755 756 757
      b = XINT (beg);
    }

  /* Make a pointer for decrementing through the chars before point.  */
758
  ptr = SDATA (string) + e;
759 760
  /* Make a pointer to where consecutive chars leave off,
     going backwards from point.  */
761
  stop = SDATA (string) + b;
762 763 764 765 766 767 768 769 770 771

  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)))
772
	col += ASIZE (DISP_CHAR_VECTOR (dp, c));
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
      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;
}
798 799 800

#endif /* 0 */

801

Paul Eggert's avatar
Paul Eggert committed
802
DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
803
       doc: /* Indent from point with tabs and spaces until COLUMN is reached.
804
Optional second argument MINIMUM says always do at least MINIMUM spaces
Eli Zaretskii's avatar
Eli Zaretskii committed
805 806 807
even if that goes past COLUMN; by default, MINIMUM is zero.

The return value is COLUMN.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
808
  (Lisp_Object column, Lisp_Object minimum)
Jim Blandy's avatar
Jim Blandy committed
809
{
810 811
  EMACS_INT mincol;
  register EMACS_INT fromcol;
812
  int tab_width = sane_tab_width ();
Jim Blandy's avatar
Jim Blandy committed
813

814
  CHECK_NUMBER (column);
Jim Blandy's avatar
Jim Blandy committed
815
  if (NILP (minimum))
816
    XSETFASTINT (minimum, 0);
817
  CHECK_NUMBER (minimum);
Jim Blandy's avatar
Jim Blandy committed
818 819 820

  fromcol = current_column ();
  mincol = fromcol + XINT (minimum);
821
  if (mincol < XINT (column)) mincol = XINT (column);
Jim Blandy's avatar
Jim Blandy committed
822 823 824 825 826 827 828

  if (fromcol == mincol)
    return make_number (mincol);

  if (indent_tabs_mode)
    {
      Lisp_Object n;
829
      XSETFASTINT (n, mincol / tab_width - fromcol / tab_width);
Jim Blandy's avatar
Jim Blandy committed
830 831
      if (XFASTINT (n) != 0)
	{
832
	  Finsert_char (make_number ('\t'), n, Qt);
Jim Blandy's avatar
Jim Blandy committed
833 834 835 836 837

	  fromcol = (mincol / tab_width) * tab_width;
	}
    }

838 839
  XSETFASTINT (column, mincol - fromcol);
  Finsert_char (make_number (' '), column, Qt);
Jim Blandy's avatar
Jim Blandy committed
840 841

  last_known_column = mincol;
842
  last_known_column_point = PT;
Jim Blandy's avatar
Jim Blandy committed
843 844
  last_known_column_modified = MODIFF;

845 846
  XSETINT (column, mincol);
  return column;
Jim Blandy's avatar
Jim Blandy committed
847
}
848

Jim Blandy's avatar
Jim Blandy committed
849 850

DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
851 852 853 854
       0, 0, 0,
       doc: /* Return the indentation of the current line.
This is the horizontal position of the character
following any initial whitespace.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
855
  (void)
Jim Blandy's avatar
Jim Blandy committed
856 857
{
  Lisp_Object val;
858
  EMACS_INT opoint = PT, opoint_byte = PT_BYTE;
859 860

  scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
Jim Blandy's avatar
Jim Blandy committed
861

862
  XSETFASTINT (val, position_indentation (PT_BYTE));
863
  SET_PT_BOTH (opoint, opoint_byte);
Jim Blandy's avatar
Jim Blandy committed
864 865 866
  return val;
}

867
static EMACS_INT
868
position_indentation (register int pos_byte)
Jim Blandy's avatar
Jim Blandy committed
869
{
Stefan Monnier's avatar
Stefan Monnier committed
870
  register EMACS_INT column = 0;
871
  int tab_width = sane_tab_width ();
Jim Blandy's avatar
Jim Blandy committed
872 873
  register unsigned char *p;
  register unsigned char *stop;
874
  unsigned char *start;
Stefan Monnier's avatar
Stefan Monnier committed
875 876
  EMACS_INT next_boundary_byte = pos_byte;
  EMACS_INT ceiling = next_boundary_byte;
877

878
  p = BYTE_POS_ADDR (pos_byte);
879 880 881 882 883 884
  /* STOP records the value of P at which we will need
     to think about the gap, or about invisible text,
     or about the end of the buffer.  */
  stop = p;
  /* START records the starting value of P.  */
  start = p;
Jim Blandy's avatar
Jim Blandy committed
885 886 887 888
  while (1)
    {
      while (p == stop)
	{
Stefan Monnier's avatar
Stefan Monnier committed
889
	  EMACS_INT stop_pos_byte;
890

891 892
	  /* If we have updated P, set POS_BYTE to match.
	     The first time we enter the loop, POS_BYTE is already right.  */
893
	  if (p != start)
894
	    pos_byte = PTR_BYTE_POS (p);
895
	  /* Consider the various reasons STOP might have been set here.  */
896
	  if (pos_byte == ZV_BYTE)
Jim Blandy's avatar
Jim Blandy committed
897
	    return column;
898 899
	  if (pos_byte == next_boundary_byte)
	    {
Stefan Monnier's avatar
Stefan Monnier committed
900 901
	      EMACS_INT next_boundary;
	      EMACS_INT pos = BYTE_TO_CHAR (pos_byte);
902 903 904 905 906 907
	      pos = skip_invisible (pos, &next_boundary, ZV, Qnil);
	      pos_byte = CHAR_TO_BYTE (pos);
	      next_boundary_byte = CHAR_TO_BYTE (next_boundary);
	    }
	  if (pos_byte >= ceiling)
	    ceiling = BUFFER_CEILING_OF (pos_byte) + 1;
908 909
	  /* Compute the next place we need to stop and think,
	     and set STOP accordingly.  */
910
	  stop_pos_byte = min (ceiling, next_boundary_byte);
911
	  /* The -1 and +1 arrange to point at the first byte of gap
912
	     (if STOP_POS_BYTE is the position of the gap)
913
	     rather than at the data after the gap.  */
914

915 916
	  stop = BYTE_POS_ADDR (stop_pos_byte - 1) + 1;
	  p = BYTE_POS_ADDR (pos_byte);
Jim Blandy's avatar
Jim Blandy committed
917 918 919
	}
      switch (*p++)
	{
920
	case 0240:
Tom Tromey's avatar
Tom Tromey committed
921
	  if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
922
	    return column;
Jim Blandy's avatar
Jim Blandy committed
923 924 925 926 927 928 929
	case ' ':
	  column++;
	  break;
	case '\t':
	  column += tab_width - column % tab_width;
	  break;
	default:
930
	  if (ASCII_BYTE_P (p[-1])
Tom Tromey's avatar
Tom Tromey committed
931
	      || NILP (BVAR (current_buffer, enable_multibyte_characters)))