1 /* Indentation functions.
   2    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1998, 2000, 2001,
   3                  2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
   4                  Free Software Foundation, Inc.
   5 
   6 This file is part of GNU Emacs.
   7 
   8 GNU Emacs is free software: you can redistribute it and/or modify
   9 it under the terms of the GNU General Public License as published by
  10 the Free Software Foundation, either version 3 of the License, or
  11 (at your option) any later version.
  12 
  13 GNU Emacs is distributed in the hope that it will be useful,
  14 but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 GNU General Public License for more details.
  17 
  18 You should have received a copy of the GNU General Public License
  19 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
  20 
  21 #include <config.h>
  22 #include <stdio.h>
  23 #include <setjmp.h>
  24 
  25 #include "lisp.h"
  26 #include "buffer.h"
  27 #include "character.h"
  28 #include "category.h"
  29 #include "composite.h"
  30 #include "indent.h"
  31 #include "keyboard.h"
  32 #include "frame.h"
  33 #include "window.h"
  34 #include "termchar.h"
  35 #include "termopts.h"
  36 #include "disptab.h"
  37 #include "intervals.h"
  38 #include "dispextern.h"
  39 #include "region-cache.h"
  40 
  41 /* Indentation can insert tabs if this is non-zero;
  42    otherwise always uses spaces.  */
  43 
  44 static int indent_tabs_mode;
  45 
  46 #define CR 015
  47 
  48 /* These three values memorize the current column to avoid recalculation.  */
  49 
  50 /* Last value returned by current_column.
  51    Some things in set last_known_column_point to -1
  52    to mark the memorized value as invalid.  */
  53 
  54 static double last_known_column;
  55 
  56 /* Value of point when current_column was called.  */
  57 
  58 EMACS_INT last_known_column_point;
  59 
  60 /* Value of MODIFF when current_column was called.  */
  61 
  62 static int last_known_column_modified;
  63 
  64 static double current_column_1 P_ ((void));
  65 static double position_indentation P_ ((int));
  66 
  67 /* Cache of beginning of line found by the last call of
  68    current_column. */
  69 
  70 static EMACS_INT current_column_bol_cache;
  71 
  72 /* Get the display table to use for the current buffer.  */
  73 
  74 struct Lisp_Char_Table *
  75 buffer_display_table ()
  76 {
  77   Lisp_Object thisbuf;
  78 
  79   thisbuf = current_buffer->display_table;
  80   if (DISP_TABLE_P (thisbuf))
  81     return XCHAR_TABLE (thisbuf);
  82   if (DISP_TABLE_P (Vstandard_display_table))
  83     return XCHAR_TABLE (Vstandard_display_table);
  84   return 0;
  85 }
  86 
  87 /* Width run cache considerations.  */
  88 
  89 /* Return the width of character C under display table DP.  */
  90 
  91 static int
  92 character_width (c, dp)
  93      int c;
  94      struct Lisp_Char_Table *dp;
  95 {
  96   Lisp_Object elt;
  97 
  98   /* These width computations were determined by examining the cases
  99      in display_text_line.  */
 100 
 101   /* Everything can be handled by the display table, if it's
 102      present and the element is right.  */
 103   if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
 104     return XVECTOR (elt)->size;
 105 
 106   /* Some characters are special.  */
 107   if (c == '\n' || c == '\t' || c == '\015')
 108     return 0;
 109 
 110   /* Printing characters have width 1.  */
 111   else if (c >= 040 && c < 0177)
 112     return 1;
 113 
 114   /* Everybody else (control characters, metacharacters) has other
 115      widths.  We could return their actual widths here, but they
 116      depend on things like ctl_arrow and crud like that, and they're
 117      not very common at all.  So we'll just claim we don't know their
 118      widths.  */
 119   else
 120     return 0;
 121 }
 122 
 123 /* Return true if the display table DISPTAB specifies the same widths
 124    for characters as WIDTHTAB.  We use this to decide when to
 125    invalidate the buffer's width_run_cache.  */
 126 
 127 int
 128 disptab_matches_widthtab (disptab, widthtab)
 129      struct Lisp_Char_Table *disptab;
 130      struct Lisp_Vector *widthtab;
 131 {
 132   int i;
 133 
 134   if (widthtab->size != 256)
 135     abort ();
 136 
 137   for (i = 0; i < 256; i++)
 138     if (character_width (i, disptab)
 139         != XFASTINT (widthtab->contents[i]))
 140       return 0;
 141 
 142   return 1;
 143 }
 144 
 145 /* Recompute BUF's width table, using the display table DISPTAB.  */
 146 
 147 void
 148 recompute_width_table (buf, disptab)
 149      struct buffer *buf;
 150      struct Lisp_Char_Table *disptab;
 151 {
 152   int i;
 153   struct Lisp_Vector *widthtab;
 154 
 155   if (!VECTORP (buf->width_table))
 156     buf->width_table = Fmake_vector (make_number (256), make_number (0));
 157   widthtab = XVECTOR (buf->width_table);
 158   if (widthtab->size != 256)
 159     abort ();
 160 
 161   for (i = 0; i < 256; i++)
 162     XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
 163 }
 164 
 165 /* Allocate or free the width run cache, as requested by the current
 166    state of current_buffer's cache_long_line_scans variable.  */
 167 
 168 static void
 169 width_run_cache_on_off ()
 170 {
 171   if (NILP (current_buffer->cache_long_line_scans)
 172       /* And, for the moment, this feature doesn't work on multibyte
 173          characters.  */
 174       || !NILP (current_buffer->enable_multibyte_characters))
 175     {
 176       /* It should be off.  */
 177       if (current_buffer->width_run_cache)
 178         {
 179           free_region_cache (current_buffer->width_run_cache);
 180           current_buffer->width_run_cache = 0;
 181           current_buffer->width_table = Qnil;
 182         }
 183     }
 184   else
 185     {
 186       /* It should be on.  */
 187       if (current_buffer->width_run_cache == 0)
 188         {
 189           current_buffer->width_run_cache = new_region_cache ();
 190           recompute_width_table (current_buffer, buffer_display_table ());
 191         }
 192     }
 193 }
 194 
 195 
 196 /* Skip some invisible characters starting from POS.
 197    This includes characters invisible because of text properties
 198    and characters invisible because of overlays.
 199 
 200    If position POS is followed by invisible characters,
 201    skip some of them and return the position after them.
 202    Otherwise return POS itself.
 203 
 204    Set *NEXT_BOUNDARY_P to the next position at which
 205    it will be necessary to call this function again.
 206 
 207    Don't scan past TO, and don't set *NEXT_BOUNDARY_P
 208    to a value greater than TO.
 209 
 210    If WINDOW is non-nil, and this buffer is displayed in WINDOW,
 211    take account of overlays that apply only in WINDOW.
 212 
 213    We don't necessarily skip all the invisible characters after POS
 214    because that could take a long time.  We skip a reasonable number
 215    which can be skipped quickly.  If there might be more invisible
 216    characters immediately following, then *NEXT_BOUNDARY_P
 217    will equal the return value.  */
 218 
 219 EMACS_INT
 220 skip_invisible (pos, next_boundary_p, to, window)
 221      EMACS_INT pos;
 222      EMACS_INT *next_boundary_p;
 223      EMACS_INT to;
 224      Lisp_Object window;
 225 {
 226   Lisp_Object prop, position, overlay_limit, proplimit;
 227   Lisp_Object buffer, tmp;
 228   EMACS_INT end;
 229   int inv_p;
 230 
 231   XSETFASTINT (position, pos);
 232   XSETBUFFER (buffer, current_buffer);
 233 
 234   /* Give faster response for overlay lookup near POS.  */
 235   recenter_overlay_lists (current_buffer, pos);
 236 
 237   /* We must not advance farther than the next overlay change.
 238      The overlay change might change the invisible property;
 239      or there might be overlay strings to be displayed there.  */
 240   overlay_limit = Fnext_overlay_change (position);
 241   /* As for text properties, this gives a lower bound
 242      for where the invisible text property could change.  */
 243   proplimit = Fnext_property_change (position, buffer, Qt);
 244   if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
 245     proplimit = overlay_limit;
 246   /* PROPLIMIT is now a lower bound for the next change
 247      in invisible status.  If that is plenty far away,
 248      use that lower bound.  */
 249   if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
 250     *next_boundary_p = XFASTINT (proplimit);
 251   /* Otherwise, scan for the next `invisible' property change.  */
 252   else
 253     {
 254       /* Don't scan terribly far.  */
 255       XSETFASTINT (proplimit, min (pos + 100, to));
 256       /* No matter what, don't go past next overlay change.  */
 257       if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
 258         proplimit = overlay_limit;
 259       tmp = Fnext_single_property_change (position, Qinvisible,
 260                                           buffer, proplimit);
 261       end = XFASTINT (tmp);
 262 #if 0
 263       /* Don't put the boundary in the middle of multibyte form if
 264          there is no actual property change.  */
 265       if (end == pos + 100
 266           && !NILP (current_buffer->enable_multibyte_characters)
 267           && end < ZV)
 268         while (pos < end && !CHAR_HEAD_P (POS_ADDR (end)))
 269           end--;
 270 #endif
 271       *next_boundary_p = end;
 272     }
 273   /* if the `invisible' property is set, we can skip to
 274      the next property change */
 275   prop = Fget_char_property (position, Qinvisible,
 276                              (!NILP (window)
 277                               && EQ (XWINDOW (window)->buffer, buffer))
 278                              ? window : buffer);
 279   inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
 280   /* When counting columns (window == nil), don't skip over ellipsis text.  */
 281   if (NILP (window) ? inv_p == 1 : inv_p)
 282     return *next_boundary_p;
 283   return pos;
 284 }
 285 
 286 /* Set variables WIDTH and BYTES for a multibyte sequence starting at P.
 287 
 288    DP is a display table or NULL.
 289 
 290    This macro is used in current_column_1, Fmove_to_column, and
 291    compute_motion.  */
 292 
 293 #define MULTIBYTE_BYTES_WIDTH(p, dp)                                    \
 294   do {                                                                  \
 295     int c;                                                              \
 296                                                                         \
 297     wide_column = 0;                                                    \
 298     c = STRING_CHAR_AND_LENGTH (p, bytes);                              \
 299     if (BYTES_BY_CHAR_HEAD (*p) != bytes)                               \
 300       width = bytes * 4;                                                \
 301     else                                                                \
 302       {                                                                 \
 303         if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))              \
 304           width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;             \
 305         else                                                            \
 306           width = CHAR_WIDTH (c);                                       \
 307         if (width > 1)                                                  \
 308           wide_column = width;                                          \
 309       }                                                                 \
 310   } while (0)
 311 
 312 
 313 DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
 314        doc: /* Return the horizontal position of point.  Beginning of line is column 0.
 315 This is calculated by adding together the widths of all the displayed
 316 representations of the character between the start of the previous line
 317 and point (eg. control characters will have a width of 2 or 4, tabs
 318 will have a variable width).
 319 Ignores finite width of frame, which means that this function may return
 320 values greater than (frame-width).
 321 Whether the line is visible (if `selective-display' is t) has no effect;
 322 however, ^M is treated as end of line when `selective-display' is t.
 323 Text that has an invisible property is considered as having width 0, unless
 324 `buffer-invisibility-spec' specifies that it is replaced by an ellipsis.  */)
 325      ()
 326 {
 327   Lisp_Object temp;
 328   XSETFASTINT (temp, (int) current_column ()); /* iftc */
 329   return temp;
 330 }
 331 
 332 /* Cancel any recorded value of the horizontal position.  */
 333 
 334 void
 335 invalidate_current_column ()
 336 {
 337   last_known_column_point = 0;
 338 }
 339 
 340 double
 341 current_column ()
 342 {
 343   register int col;
 344   register unsigned char *ptr, *stop;
 345   register int tab_seen;
 346   int post_tab;
 347   register int c;
 348   register int tab_width = XINT (current_buffer->tab_width);
 349   int ctl_arrow = !NILP (current_buffer->ctl_arrow);
 350   register struct Lisp_Char_Table *dp = buffer_display_table ();
 351 
 352   if (PT == last_known_column_point
 353       && MODIFF == last_known_column_modified)
 354     return last_known_column;
 355 
 356   /* If the buffer has overlays, text properties,
 357      or multibyte characters, use a more general algorithm.  */
 358   if (BUF_INTERVALS (current_buffer)
 359       || current_buffer->overlays_before
 360       || current_buffer->overlays_after
 361       || Z != Z_BYTE)
 362     return current_column_1 ();
 363 
 364   /* Scan backwards from point to the previous newline,
 365      counting width.  Tab characters are the only complicated case.  */
 366 
 367   /* Make a pointer for decrementing through the chars before point.  */
 368   ptr = BYTE_POS_ADDR (PT_BYTE - 1) + 1;
 369   /* Make a pointer to where consecutive chars leave off,
 370      going backwards from point.  */
 371   if (PT == BEGV)
 372     stop = ptr;
 373   else if (PT <= GPT || BEGV > GPT)
 374     stop = BEGV_ADDR;
 375   else
 376     stop = GAP_END_ADDR;
 377 
 378   if (tab_width <= 0 || tab_width > 1000)
 379     tab_width = 8;
 380 
 381   col = 0, tab_seen = 0, post_tab = 0;
 382 
 383   while (1)
 384     {
 385       EMACS_INT i, n;
 386       Lisp_Object charvec;
 387 
 388       if (ptr == stop)
 389         {
 390           /* We stopped either for the beginning of the buffer
 391              or for the gap.  */
 392           if (ptr == BEGV_ADDR)
 393             break;
 394 
 395           /* It was the gap.  Jump back over it.  */
 396           stop = BEGV_ADDR;
 397           ptr = GPT_ADDR;
 398 
 399           /* Check whether that brings us to beginning of buffer.  */
 400           if (BEGV >= GPT)
 401             break;
 402         }
 403 
 404       c = *--ptr;
 405 
 406       if (dp && VECTORP (DISP_CHAR_VECTOR (dp, c)))
 407         {
 408           charvec = DISP_CHAR_VECTOR (dp, c);
 409           n = ASIZE (charvec);
 410         }
 411       else
 412         {
 413           charvec = Qnil;
 414           n = 1;
 415         }
 416 
 417       for (i = n - 1; i >= 0; --i)
 418         {
 419           if (VECTORP (charvec))
 420             {
 421               /* This should be handled the same as
 422                  next_element_from_display_vector does it.  */
 423               Lisp_Object entry = AREF (charvec, i);
 424 
 425               if (GLYPH_CODE_P (entry)
 426                   && GLYPH_CODE_CHAR_VALID_P (entry))
 427                 c = GLYPH_CODE_CHAR (entry);
 428               else
 429                 c = ' ';
 430             }
 431 
 432           if (c >= 040 && c < 0177)
 433             col++;
 434           else if (c == '\n'
 435                    || (c == '\r'
 436                        && EQ (current_buffer->selective_display, Qt)))
 437             {
 438               ptr++;
 439               goto start_of_line_found;
 440             }
 441           else if (c == '\t')
 442             {
 443               if (tab_seen)
 444                 col = ((col + tab_width) / tab_width) * tab_width;
 445 
 446               post_tab += col;
 447               col = 0;
 448               tab_seen = 1;
 449             }
 450           else if (VECTORP (charvec))
 451             /* With a display table entry, C is displayed as is, and
 452                not displayed as \NNN or as ^N.  If C is a single-byte
 453                character, it takes one column.  If C is multi-byte in
 454                an unibyte buffer, it's translated to unibyte, so it
 455                also takes one column.  */
 456             ++col;
 457           else
 458             col += (ctl_arrow && c < 0200) ? 2 : 4;
 459         }
 460     }
 461 
 462  start_of_line_found:
 463 
 464   if (tab_seen)
 465     {
 466       col = ((col + tab_width) / tab_width) * tab_width;
 467       col += post_tab;
 468     }
 469 
 470   if (ptr == BEGV_ADDR)
 471     current_column_bol_cache = BEGV;
 472   else
 473     current_column_bol_cache = BYTE_TO_CHAR (PTR_BYTE_POS (ptr));
 474 
 475   last_known_column = col;
 476   last_known_column_point = PT;
 477   last_known_column_modified = MODIFF;
 478 
 479   return col;
 480 }
 481 
 482 extern Lisp_Object Qspace, QCwidth, QCalign_to;
 483 
 484 /* Check the presence of a display property and compute its width.
 485    If a property was found and its width was found as well, return
 486    its width (>= 0) and set the position of the end of the property
 487    in ENDPOS.
 488    Otherwise just return -1.  */
 489 static int
 490 check_display_width (EMACS_INT pos, EMACS_INT col, EMACS_INT *endpos)
 491 {
 492   Lisp_Object val, overlay;
 493 
 494   if (CONSP (val = get_char_property_and_overlay
 495              (make_number (pos), Qdisplay, Qnil, &overlay))
 496       && EQ (Qspace, XCAR (val)))
 497     { /* FIXME: Use calc_pixel_width_or_height, as in term.c.  */
 498       Lisp_Object plist = XCDR (val), prop;
 499       int width = -1;
 500 
 501       if ((prop = Fplist_get (plist, QCwidth), NATNUMP (prop)))
 502         width = XINT (prop);
 503       else if (FLOATP (prop))
 504         width = (int)(XFLOAT_DATA (prop) + 0.5);
 505       else if ((prop = Fplist_get (plist, QCalign_to), NATNUMP (prop)))
 506         width = XINT (prop) - col;
 507       else if (FLOATP (prop))
 508         width = (int)(XFLOAT_DATA (prop) + 0.5) - col;
 509             
 510       if (width >= 0)
 511         {
 512           EMACS_INT start;
 513           if (OVERLAYP (overlay))
 514             *endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
 515           else
 516             get_property_and_range (pos, Qdisplay, &val, &start, endpos, Qnil);
 517           return width;
 518         }
 519     }
 520   return -1;
 521 }
 522 
 523 /* Scanning from the beginning of the current line, stop at the buffer
 524    position ENDPOS or at the column GOALCOL or at the end of line, whichever
 525    comes first.
 526    Return the resulting buffer position and column in ENDPOS and GOALCOL.
 527    PREVCOL gets set to the column of the previous position (it's always
 528    strictly smaller than the goal column).  */
 529 static void
 530 scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol)
 531 {
 532   register EMACS_INT tab_width = XINT (current_buffer->tab_width);
 533   register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
 534   register struct Lisp_Char_Table *dp = buffer_display_table ();
 535   int multibyte = !NILP (current_buffer->enable_multibyte_characters);
 536   struct composition_it cmp_it;
 537   Lisp_Object window;
 538   struct window *w;
 539 
 540   /* Start the scan at the beginning of this line with column number 0.  */
 541   register EMACS_INT col = 0, prev_col = 0;
 542   EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
 543   EMACS_INT end = endpos ? *endpos : PT;
 544   EMACS_INT scan, scan_byte;
 545   EMACS_INT next_boundary;
 546   {
 547   EMACS_INT opoint = PT, opoint_byte = PT_BYTE;
 548   scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
 549   current_column_bol_cache = PT;
 550   scan = PT, scan_byte = PT_BYTE;
 551   SET_PT_BOTH (opoint, opoint_byte);
 552   next_boundary = scan;
 553   }
 554 
 555   window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
 556   w = ! NILP (window) ? XWINDOW (window) : NULL;
 557 
 558   if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
 559   bzero (&cmp_it, sizeof cmp_it);
 560   cmp_it.id = -1;
 561   composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil);
 562 
 563   /* Scan forward to the target position.  */
 564   while (scan < end)
 565     {
 566       int c;
 567 
 568       /* Occasionally we may need to skip invisible text.  */
 569       while (scan == next_boundary)
 570         {
 571           EMACS_INT old_scan = scan;
 572           /* This updates NEXT_BOUNDARY to the next place
 573              where we might need to skip more invisible text.  */
 574           scan = skip_invisible (scan, &next_boundary, end, Qnil);
 575           if (scan != old_scan)
 576             scan_byte = CHAR_TO_BYTE (scan);
 577           if (scan >= end)
 578             goto endloop;
 579         }
 580 
 581       /* Test reaching the goal column.  We do this after skipping
 582          invisible characters, so that we put point before the
 583          character on which the cursor will appear.  */
 584       if (col >= goal)
 585         break;
 586       prev_col = col;
 587 
 588       { /* Check display property.  */
 589         EMACS_INT end;
 590         int width = check_display_width (scan, col, &end);
 591         if (width >= 0)
 592           {
 593             col += width;
 594             if (end > scan) /* Avoid infinite loops with 0-width overlays.  */
 595               {
 596                 scan = end; scan_byte = charpos_to_bytepos (scan);
 597                 continue;
 598               }
 599           }
 600       }
 601 
 602       /* Check composition sequence.  */
 603       if (cmp_it.id >= 0
 604           || (scan == cmp_it.stop_pos
 605               && composition_reseat_it (&cmp_it, scan, scan_byte, end,
 606                                         w, NULL, Qnil)))
 607         composition_update_it (&cmp_it, scan, scan_byte, Qnil);
 608       if (cmp_it.id >= 0)
 609         {
 610           scan += cmp_it.nchars;
 611           scan_byte += cmp_it.nbytes;
 612           if (scan <= end)
 613             col += cmp_it.width;
 614           if (cmp_it.to == cmp_it.nglyphs)
 615             {
 616               cmp_it.id = -1;
 617               composition_compute_stop_pos (&cmp_it, scan, scan_byte, end,
 618                                             Qnil);
 619             }
 620           else
 621             cmp_it.from = cmp_it.to;
 622           continue;
 623         }
 624 
 625       c = FETCH_BYTE (scan_byte);
 626 
 627       /* See if there is a display table and it relates
 628          to this character.  */
 629 
 630       if (dp != 0
 631           && ! (multibyte && BASE_LEADING_CODE_P (c))
 632           && VECTORP (DISP_CHAR_VECTOR (dp, c)))
 633         {
 634           Lisp_Object charvec;
 635           EMACS_INT i, n;
 636 
 637           /* This character is displayed using a vector of glyphs.
 638              Update the column/position based on those glyphs.  */
 639 
 640           charvec = DISP_CHAR_VECTOR (dp, c);
 641           n = ASIZE (charvec);
 642 
 643           for (i = 0; i < n; i++)
 644             {
 645               /* This should be handled the same as
 646                  next_element_from_display_vector does it.  */
 647               Lisp_Object entry = AREF (charvec, i);
 648 
 649               if (GLYPH_CODE_P (entry)
 650                   && GLYPH_CODE_CHAR_VALID_P (entry))
 651                 c = GLYPH_CODE_CHAR (entry);
 652               else
 653                 c = ' ';
 654 
 655               if (c == '\n')
 656                 goto endloop;
 657               if (c == '\r' && EQ (current_buffer->selective_display, Qt))
 658                 goto endloop;
 659               if (c == '\t')
 660                 {
 661                   col += tab_width;
 662                   col = col / tab_width * tab_width;
 663                 }
 664               else
 665                 ++col;
 666             }
 667         }
 668       else
 669         {
 670           /* The display table doesn't affect this character;
 671              it displays as itself.  */
 672 
 673           if (c == '\n')
 674             goto endloop;
 675           if (c == '\r' && EQ (current_buffer->selective_display, Qt))
 676             goto endloop;
 677           if (c == '\t')
 678             {
 679               col += tab_width;
 680               col = col / tab_width * tab_width;
 681             }
 682           else if (multibyte && BASE_LEADING_CODE_P (c))
 683             {
 684               /* Start of multi-byte form.  */
 685               unsigned char *ptr;
 686               int bytes, width, wide_column;
 687 
 688               ptr = BYTE_POS_ADDR (scan_byte);
 689               MULTIBYTE_BYTES_WIDTH (ptr, dp);
 690               /* Subtract one to compensate for the increment
 691                  that is going to happen below.  */
 692               scan_byte += bytes - 1;
 693               col += width;
 694             }
 695           else if (ctl_arrow && (c < 040 || c == 0177))
 696             col += 2;
 697           else if (c < 040 || c >= 0177)
 698             col += 4;
 699           else
 700             col++;
 701         }
 702       scan++;
 703       scan_byte++;
 704 
 705     }
 706  endloop:
 707 
 708   last_known_column = col;
 709   last_known_column_point = PT;
 710   last_known_column_modified = MODIFF;
 711 
 712   if (goalcol)
 713     *goalcol = col;
 714   if (endpos)
 715     *endpos = scan;
 716   if (prevcol)
 717     *prevcol = prev_col;
 718 }
 719 
 720 /* Return the column number of position POS
 721    by scanning forward from the beginning of the line.
 722    This function handles characters that are invisible
 723    due to text properties or overlays.  */
 724 
 725 static double
 726 current_column_1 ()
 727 {
 728   EMACS_INT col = MOST_POSITIVE_FIXNUM;
 729   EMACS_INT opoint = PT;
 730 
 731   scan_for_column (&opoint, &col, NULL);
 732   return col;
 733 }
 734 
 735 
 736 #if 0 /* Not used.  */
 737 
 738 /* Return the width in columns of the part of STRING from BEG to END.
 739    If BEG is nil, that stands for the beginning of STRING.
 740    If END is nil, that stands for the end of STRING.  */
 741 
 742 static double
 743 string_display_width (string, beg, end)
 744      Lisp_Object string, beg, end;
 745 {
 746   register int col;
 747   register unsigned char *ptr, *stop;
 748   register int tab_seen;
 749   int post_tab;
 750   register int c;
 751   register int tab_width = XINT (current_buffer->tab_width);
 752   int ctl_arrow = !NILP (current_buffer->ctl_arrow);
 753   register struct Lisp_Char_Table *dp = buffer_display_table ();
 754   int b, e;
 755 
 756   if (NILP (end))
 757     e = SCHARS (string);
 758   else
 759     {
 760       CHECK_NUMBER (end);
 761       e = XINT (end);
 762     }
 763 
 764   if (NILP (beg))
 765     b = 0;
 766   else
 767     {
 768       CHECK_NUMBER (beg);
 769       b = XINT (beg);
 770     }
 771 
 772   /* Make a pointer for decrementing through the chars before point.  */
 773   ptr = SDATA (string) + e;
 774   /* Make a pointer to where consecutive chars leave off,
 775      going backwards from point.  */
 776   stop = SDATA (string) + b;
 777 
 778   if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
 779 
 780   col = 0, tab_seen = 0, post_tab = 0;
 781 
 782   while (1)
 783     {
 784       if (ptr == stop)
 785         break;
 786 
 787       c = *--ptr;
 788       if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
 789         col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
 790       else if (c >= 040 && c < 0177)
 791         col++;
 792       else if (c == '\n')
 793         break;
 794       else if (c == '\t')
 795         {
 796           if (tab_seen)
 797             col = ((col + tab_width) / tab_width) * tab_width;
 798 
 799           post_tab += col;
 800           col = 0;
 801           tab_seen = 1;
 802         }
 803       else
 804         col += (ctl_arrow && c < 0200) ? 2 : 4;
 805     }
 806 
 807   if (tab_seen)
 808     {
 809       col = ((col + tab_width) / tab_width) * tab_width;
 810       col += post_tab;
 811     }
 812 
 813   return col;
 814 }
 815 
 816 #endif /* 0 */
 817 
 818 
 819 DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
 820        doc: /* Indent from point with tabs and spaces until COLUMN is reached.
 821 Optional second argument MINIMUM says always do at least MINIMUM spaces
 822 even if that goes past COLUMN; by default, MINIMUM is zero.
 823 
 824 The return value is COLUMN.  */)
 825      (column, minimum)
 826      Lisp_Object column, minimum;
 827 {
 828   int mincol;
 829   register int fromcol;
 830   register int tab_width = XINT (current_buffer->tab_width);
 831 
 832   CHECK_NUMBER (column);
 833   if (NILP (minimum))
 834     XSETFASTINT (minimum, 0);
 835   CHECK_NUMBER (minimum);
 836 
 837   fromcol = current_column ();
 838   mincol = fromcol + XINT (minimum);
 839   if (mincol < XINT (column)) mincol = XINT (column);
 840 
 841   if (fromcol == mincol)
 842     return make_number (mincol);
 843 
 844   if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
 845 
 846   if (indent_tabs_mode)
 847     {
 848       Lisp_Object n;
 849       XSETFASTINT (n, mincol / tab_width - fromcol / tab_width);
 850       if (XFASTINT (n) != 0)
 851         {
 852           Finsert_char (make_number ('\t'), n, Qt);
 853 
 854           fromcol = (mincol / tab_width) * tab_width;
 855         }
 856     }
 857 
 858   XSETFASTINT (column, mincol - fromcol);
 859   Finsert_char (make_number (' '), column, Qt);
 860 
 861   last_known_column = mincol;
 862   last_known_column_point = PT;
 863   last_known_column_modified = MODIFF;
 864 
 865   XSETINT (column, mincol);
 866   return column;
 867 }
 868 
 869 
 870 static double position_indentation P_ ((int));
 871 
 872 DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
 873        0, 0, 0,
 874        doc: /* Return the indentation of the current line.
 875 This is the horizontal position of the character
 876 following any initial whitespace.  */)
 877      ()
 878 {
 879   Lisp_Object val;
 880   int opoint = PT, opoint_byte = PT_BYTE;
 881 
 882   scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
 883 
 884   XSETFASTINT (val, (int) position_indentation (PT_BYTE)); /* iftc */
 885   SET_PT_BOTH (opoint, opoint_byte);
 886   return val;
 887 }
 888 
 889 static double
 890 position_indentation (pos_byte)
 891      register int pos_byte;
 892 {
 893   register EMACS_INT column = 0;
 894   register EMACS_INT tab_width = XINT (current_buffer->tab_width);
 895   register unsigned char *p;
 896   register unsigned char *stop;
 897   unsigned char *start;
 898   EMACS_INT next_boundary_byte = pos_byte;
 899   EMACS_INT ceiling = next_boundary_byte;
 900 
 901   if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
 902 
 903   p = BYTE_POS_ADDR (pos_byte);
 904   /* STOP records the value of P at which we will need
 905      to think about the gap, or about invisible text,
 906      or about the end of the buffer.  */
 907   stop = p;
 908   /* START records the starting value of P.  */
 909   start = p;
 910   while (1)
 911     {
 912       while (p == stop)
 913         {
 914           EMACS_INT stop_pos_byte;
 915 
 916           /* If we have updated P, set POS_BYTE to match.
 917              The first time we enter the loop, POS_BYTE is already right.  */
 918           if (p != start)
 919             pos_byte = PTR_BYTE_POS (p);
 920           /* Consider the various reasons STOP might have been set here.  */
 921           if (pos_byte == ZV_BYTE)
 922             return column;
 923           if (pos_byte == next_boundary_byte)
 924             {
 925               EMACS_INT next_boundary;
 926               EMACS_INT pos = BYTE_TO_CHAR (pos_byte);
 927               pos = skip_invisible (pos, &next_boundary, ZV, Qnil);
 928               pos_byte = CHAR_TO_BYTE (pos);
 929               next_boundary_byte = CHAR_TO_BYTE (next_boundary);
 930             }
 931           if (pos_byte >= ceiling)
 932             ceiling = BUFFER_CEILING_OF (pos_byte) + 1;
 933           /* Compute the next place we need to stop and think,
 934              and set STOP accordingly.  */
 935           stop_pos_byte = min (ceiling, next_boundary_byte);
 936           /* The -1 and +1 arrange to point at the first byte of gap
 937              (if STOP_POS_BYTE is the position of the gap)
 938              rather than at the data after the gap.  */
 939 
 940           stop = BYTE_POS_ADDR (stop_pos_byte - 1) + 1;
 941           p = BYTE_POS_ADDR (pos_byte);
 942         }
 943       switch (*p++)
 944         {
 945         case 0240:
 946           if (! NILP (current_buffer->enable_multibyte_characters))
 947             return column;
 948         case ' ':
 949           column++;
 950           break;
 951         case '\t':
 952           column += tab_width - column % tab_width;
 953           break;
 954         default:
 955           if (ASCII_BYTE_P (p[-1])
 956               || NILP (current_buffer->enable_multibyte_characters))
 957             return column;
 958           {
 959             int c;
 960             pos_byte = PTR_BYTE_POS (p - 1);
 961             c = FETCH_MULTIBYTE_CHAR (pos_byte);
 962             if (CHAR_HAS_CATEGORY (c, ' '))
 963               {
 964                 column++;
 965                 INC_POS (pos_byte);
 966                 p = BYTE_POS_ADDR (pos_byte);
 967               }
 968             else
 969               return column;
 970           }
 971         }
 972     }
 973 }
 974 
 975 /* Test whether the line beginning at POS is indented beyond COLUMN.
 976    Blank lines are treated as if they had the same indentation as the
 977    preceding line.  */
 978 
 979 int
 980 indented_beyond_p (pos, pos_byte, column)
 981      int pos, pos_byte;
 982      double column;
 983 {
 984   double val;
 985   int opoint = PT, opoint_byte = PT_BYTE;
 986 
 987   SET_PT_BOTH (pos, pos_byte);
 988   while (PT > BEGV && FETCH_BYTE (PT_BYTE) == '\n')
 989     scan_newline (PT - 1, PT_BYTE - 1, BEGV, BEGV_BYTE, -1, 0);
 990 
 991   val = position_indentation (PT_BYTE);
 992   SET_PT_BOTH (opoint, opoint_byte);
 993   return val >= column;                 /* hmm, float comparison */
 994 }
 995 
 996 DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
 997        doc: /* Move point to column COLUMN in the current line.
 998 Interactively, COLUMN is the value of prefix numeric argument.
 999 The column of a character is calculated by adding together the widths
1000 as displayed of the previous characters in the line.
1001 This function ignores line-continuation;
1002 there is no upper limit on the column number a character can have
1003 and horizontal scrolling has no effect.
1004 
1005 If specified column is within a character, point goes after that character.
1006 If it's past end of line, point goes to end of line.
1007 
1008 Optional second argument FORCE non-nil means if COLUMN is in the
1009 middle of a tab character, change it to spaces.
1010 In addition, if FORCE is t, and the line is too short to reach
1011 COLUMN, add spaces/tabs to get there.
1012 
1013 The return value is the current column.  */)
1014      (column, force)
1015      Lisp_Object column, force;
1016 {
1017   EMACS_INT pos;
1018   EMACS_INT col, prev_col;
1019   EMACS_INT goal;
1020 
1021   CHECK_NATNUM (column);
1022   goal = XINT (column);
1023 
1024   col = goal;
1025   pos = ZV;
1026   scan_for_column (&pos, &col, &prev_col);
1027 
1028   SET_PT (pos);
1029 
1030   /* If a tab char made us overshoot, change it to spaces
1031      and scan through it again.  */
1032   if (!NILP (force) && col > goal)
1033     {
1034       int c;
1035       EMACS_INT pos_byte = PT_BYTE;
1036 
1037       DEC_POS (pos_byte);
1038       c = FETCH_CHAR (pos_byte);
1039       if (c == '\t' && prev_col < goal)
1040         {
1041           EMACS_INT goal_pt, goal_pt_byte;
1042 
1043           /* Insert spaces in front of the tab to reach GOAL.  Do this
1044              first so that a marker at the end of the tab gets
1045              adjusted.  */
1046           SET_PT_BOTH (PT - 1, PT_BYTE - 1);
1047           Finsert_char (make_number (' '), make_number (goal - prev_col), Qt);
1048 
1049           /* Now delete the tab, and indent to COL.  */
1050           del_range (PT, PT + 1);
1051           goal_pt = PT;
1052           goal_pt_byte = PT_BYTE;
1053           Findent_to (make_number (col), Qnil);
1054           SET_PT_BOTH (goal_pt, goal_pt_byte);
1055 
1056           /* Set the last_known... vars consistently.  */
1057           col = goal;
1058         }
1059     }
1060 
1061   /* If line ends prematurely, add space to the end.  */
1062   if (col < goal && EQ (force, Qt))
1063     Findent_to (make_number (col = goal), Qnil);
1064 
1065   last_known_column = col;
1066   last_known_column_point = PT;
1067   last_known_column_modified = MODIFF;
1068 
1069   return make_number (col);
1070 }
1071 
1072 /* compute_motion: compute buffer posn given screen posn and vice versa */
1073 
1074 struct position val_compute_motion;
1075 
1076 /* Scan the current buffer forward from offset FROM, pretending that
1077    this is at line FROMVPOS, column FROMHPOS, until reaching buffer
1078    offset TO or line TOVPOS, column TOHPOS (whichever comes first),
1079    and return the ending buffer position and screen location.  If we
1080    can't hit the requested column exactly (because of a tab or other
1081    multi-column character), overshoot.
1082 
1083    DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
1084    at FROM.  This is the case if FROMVPOS and FROMVPOS came from an
1085    earlier call to compute_motion.  The other common case is that FROMHPOS
1086    is zero and FROM is a position that "belongs" at column zero, but might
1087    be shifted by overlay strings; in this case DID_MOTION should be 0.
1088 
1089    WIDTH is the number of columns available to display text;
1090    compute_motion uses this to handle continuation lines and such.
1091    If WIDTH is -1, use width of window's text area adjusted for
1092    continuation glyph when needed.
1093 
1094    HSCROLL is the number of columns not being displayed at the left
1095    margin; this is usually taken from a window's hscroll member.
1096    TAB_OFFSET is the number of columns of the first tab that aren't
1097    being displayed, perhaps because of a continuation line or
1098    something.
1099 
1100    compute_motion returns a pointer to a struct position.  The bufpos
1101    member gives the buffer position at the end of the scan, and hpos
1102    and vpos give its cartesian location.  prevhpos is the column at
1103    which the character before bufpos started, and contin is non-zero
1104    if we reached the current line by continuing the previous.
1105 
1106    Note that FROMHPOS and TOHPOS should be expressed in real screen
1107    columns, taking HSCROLL and the truncation glyph at the left margin
1108    into account.  That is, beginning-of-line moves you to the hpos
1109    -HSCROLL + (HSCROLL > 0).
1110 
1111    For example, to find the buffer position of column COL of line LINE
1112    of a certain window, pass the window's starting location as FROM
1113    and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
1114    Pass the buffer's ZV as TO, to limit the scan to the end of the
1115    visible section of the buffer, and pass LINE and COL as TOVPOS and
1116    TOHPOS.
1117 
1118    When displaying in window w, a typical formula for WIDTH is:
1119 
1120         window_width - 1
1121          - (has_vertical_scroll_bars
1122             ? WINDOW_CONFIG_SCROLL_BAR_COLS (window)
1123             : (window_width + window_left != frame_cols))
1124 
1125         where
1126           window_width is XFASTINT (w->total_cols),
1127           window_left is XFASTINT (w->left_col),
1128           has_vertical_scroll_bars is
1129             WINDOW_HAS_VERTICAL_SCROLL_BAR (window)
1130           and frame_cols = FRAME_COLS (XFRAME (window->frame))
1131 
1132    Or you can let window_box_text_cols do this all for you, and write:
1133         window_box_text_cols (w) - 1
1134 
1135    The `-1' accounts for the continuation-line backslashes; the rest
1136    accounts for window borders if the window is split horizontally, and
1137    the scroll bars if they are turned on.  */
1138 
1139 struct position *
1140 compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, hscroll, tab_offset, win)
1141      EMACS_INT from, fromvpos, fromhpos, to, tovpos, tohpos;
1142      int did_motion;
1143      EMACS_INT width;
1144      EMACS_INT hscroll, tab_offset;
1145      struct window *win;
1146 {
1147   register EMACS_INT hpos = fromhpos;
1148   register EMACS_INT vpos = fromvpos;
1149 
1150   register EMACS_INT pos;
1151   EMACS_INT pos_byte;
1152   register int c = 0;
1153   register EMACS_INT tab_width = XFASTINT (current_buffer->tab_width);
1154   register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
1155   register struct Lisp_Char_Table *dp = window_display_table (win);
1156   int selective
1157     = (INTEGERP (current_buffer->selective_display)
1158        ? XINT (current_buffer->selective_display)
1159        : !NILP (current_buffer->selective_display) ? -1 : 0);
1160   int selective_rlen
1161     = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
1162        ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0);
1163   /* The next location where the `invisible' property changes, or an
1164      overlay starts or ends.  */
1165   EMACS_INT next_boundary = from;
1166 
1167   /* For computing runs of characters with similar widths.
1168      Invariant: width_run_width is zero, or all the characters
1169      from width_run_start to width_run_end have a fixed width of
1170      width_run_width.  */
1171   EMACS_INT width_run_start = from;
1172   EMACS_INT width_run_end   = from;
1173   EMACS_INT width_run_width = 0;
1174   Lisp_Object *width_table;
1175   Lisp_Object buffer;
1176 
1177   /* The next buffer pos where we should consult the width run cache. */
1178   EMACS_INT next_width_run = from;
1179   Lisp_Object window;
1180 
1181   int multibyte = !NILP (current_buffer->enable_multibyte_characters);
1182   /* If previous char scanned was a wide character,
1183      this is the column where it ended.  Otherwise, this is 0.  */
1184   EMACS_INT wide_column_end_hpos = 0;
1185   EMACS_INT prev_pos;           /* Previous buffer position.  */
1186   EMACS_INT prev_pos_byte;      /* Previous buffer position.  */
1187   EMACS_INT prev_hpos = 0;
1188   EMACS_INT prev_vpos = 0;
1189   EMACS_INT contin_hpos;        /* HPOS of last column of continued line.  */
1190   EMACS_INT prev_tab_offset;    /* Previous tab offset.  */
1191   EMACS_INT continuation_glyph_width;
1192 
1193   struct composition_it cmp_it;
1194 
1195   XSETBUFFER (buffer, current_buffer);
1196   XSETWINDOW (window, win);
1197 
1198   width_run_cache_on_off ();
1199   if (dp == buffer_display_table ())
1200     width_table = (VECTORP (current_buffer->width_table)
1201                    ? XVECTOR (current_buffer->width_table)->contents
1202                    : 0);
1203   else
1204     /* If the window has its own display table, we can't use the width
1205        run cache, because that's based on the buffer's display table.  */
1206     width_table = 0;
1207 
1208   if (tab_width <= 0 || tab_width > 1000)
1209     tab_width = 8;
1210 
1211   /* Negative width means use all available text columns.  */
1212   if (width < 0)
1213     {
1214       width = window_box_text_cols (win);
1215       /* We must make room for continuation marks if we don't have fringes.  */
1216 #ifdef HAVE_WINDOW_SYSTEM
1217       if (!FRAME_WINDOW_P (XFRAME (win->frame)))
1218 #endif
1219         width -= 1;
1220     }
1221 
1222   continuation_glyph_width = 1;
1223 #ifdef HAVE_WINDOW_SYSTEM
1224   if (FRAME_WINDOW_P (XFRAME (win->frame)))
1225     continuation_glyph_width = 0;  /* In the fringe.  */
1226 #endif
1227 
1228   immediate_quit = 1;
1229   QUIT;
1230 
1231   pos = prev_pos = from;
1232   pos_byte = prev_pos_byte = CHAR_TO_BYTE (from);
1233   contin_hpos = 0;
1234   prev_tab_offset = tab_offset;
1235   bzero (&cmp_it, sizeof cmp_it);
1236   cmp_it.id = -1;
1237   composition_compute_stop_pos (&cmp_it, pos, pos_byte, to, Qnil);
1238 
1239   while (1)
1240     {
1241       while (pos == next_boundary)
1242         {
1243           EMACS_INT pos_here = pos;
1244           EMACS_INT newpos;
1245 
1246           /* Don't skip invisible if we are already at the margin.  */
1247           if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
1248             {
1249               if (contin_hpos && prev_hpos == 0
1250                   && hpos > tohpos
1251                   && (contin_hpos == width || wide_column_end_hpos > width))
1252                 { /* Line breaks because we can't put the character at the
1253                      previous line any more.  It is not the multi-column
1254                      character continued in middle.  Go back to previous
1255                      buffer position, screen position, and set tab offset
1256                      to previous value.  It's the beginning of the
1257                      line.  */
1258                   pos = prev_pos;
1259                   pos_byte = prev_pos_byte;
1260                   hpos = prev_hpos;
1261                   vpos = prev_vpos;
1262                   tab_offset = prev_tab_offset;
1263                 }
1264               break;
1265             }
1266 
1267           /* If the caller says that the screen position came from an earlier
1268              call to compute_motion, then we've already accounted for the
1269              overlay strings at point.  This is only true the first time
1270              through, so clear the flag after testing it.  */
1271           if (!did_motion)
1272             /* We need to skip past the overlay strings.  Currently those
1273                strings must not contain TAB;
1274                if we want to relax that restriction, something will have
1275                to be changed here.  */
1276             {
1277               unsigned char *ovstr;
1278               int ovlen = overlay_strings (pos, win, &ovstr);
1279               hpos += ((multibyte && ovlen > 0)
1280                        ? strwidth (ovstr, ovlen) : ovlen);
1281             }
1282           did_motion = 0;
1283 
1284           if (pos >= to)
1285             break;
1286 
1287           /* Advance POS past invisible characters
1288              (but not necessarily all that there are here),
1289              and store in next_boundary the next position where
1290              we need to call skip_invisible.  */
1291           newpos = skip_invisible (pos, &next_boundary, to, window);
1292 
1293           if (newpos >= to)
1294             {
1295               pos = min (to, newpos);
1296               pos_byte = CHAR_TO_BYTE (pos);
1297               goto after_loop;
1298             }
1299 
1300           if (newpos != pos_here)
1301             {
1302               pos = newpos;
1303               pos_byte = CHAR_TO_BYTE (pos);
1304             }
1305         }
1306 
1307       /* Handle right margin.  */
1308       /* Note on a wide-column character.
1309 
1310          Characters are classified into the following three categories
1311          according to the width (columns occupied on screen).
1312 
1313          (1) single-column character: ex. `a'
1314          (2) multi-column character: ex. `^A', TAB, `\033'
1315          (3) wide-column character: ex. Japanese character, Chinese character
1316              (In the following example, `W_' stands for them.)
1317 
1318          Multi-column characters can be divided around the right margin,
1319          but wide-column characters cannot.
1320 
1321          NOTE:
1322 
1323          (*) The cursor is placed on the next character after the point.
1324 
1325              ----------
1326              abcdefghi\
1327              j        ^---- next after the point
1328              ^---  next char. after the point.
1329              ----------
1330                       In case of sigle-column character
1331 
1332              ----------
1333              abcdefgh\\
1334              033     ^----  next after the point, next char. after the point.
1335              ----------
1336                       In case of multi-column character
1337 
1338              ----------
1339              abcdefgh\\
1340              W_      ^---- next after the point
1341              ^----  next char. after the point.
1342              ----------
1343                       In case of wide-column character
1344 
1345          The problem here is continuation at a wide-column character.
1346          In this case, the line may shorter less than WIDTH.
1347          And we find the continuation AFTER it occurs.
1348 
1349        */
1350 
1351       if (hpos > width)
1352         {
1353           int total_width = width + continuation_glyph_width;
1354           int truncate = 0;
1355 
1356           if (!NILP (Vtruncate_partial_width_windows)
1357               && (total_width < FRAME_COLS (XFRAME (WINDOW_FRAME (win)))))
1358             {
1359               if (INTEGERP (Vtruncate_partial_width_windows))
1360                 truncate
1361                   = total_width < XFASTINT (Vtruncate_partial_width_windows);
1362               else
1363                 truncate = 1;
1364             }
1365 
1366           if (hscroll || truncate
1367               || !NILP (current_buffer->truncate_lines))
1368             {
1369               /* Truncating: skip to newline, unless we are already past
1370                  TO (we need to go back below).  */
1371               if (pos <= to)
1372                 {
1373                   pos = find_before_next_newline (pos, to, 1);
1374                   pos_byte = CHAR_TO_BYTE (pos);
1375                   hpos = width;
1376                   /* If we just skipped next_boundary,
1377                      loop around in the main while
1378                      and handle it.  */
1379                   if (pos >= next_boundary)
1380                     next_boundary = pos + 1;
1381                   prev_hpos = width;
1382                   prev_vpos = vpos;
1383                   prev_tab_offset = tab_offset;
1384                 }
1385             }
1386           else
1387             {
1388               /* Continuing.  */
1389               /* Remember the previous value.  */
1390               prev_tab_offset = tab_offset;
1391 
1392               if (wide_column_end_hpos > width)
1393                 {
1394                   hpos -= prev_hpos;
1395                   tab_offset += prev_hpos;
1396                 }
1397               else
1398                 {
1399                   tab_offset += width;
1400                   hpos -= width;
1401                 }
1402               vpos++;
1403               contin_hpos = prev_hpos;
1404               prev_hpos = 0;
1405               prev_vpos = vpos;
1406             }
1407         }
1408 
1409       /* Stop if past the target buffer position or screen position.  */
1410       if (pos > to)
1411         {
1412           /* Go back to the previous position.  */
1413           pos = prev_pos;
1414           pos_byte = prev_pos_byte;
1415           hpos = prev_hpos;
1416           vpos = prev_vpos;
1417           tab_offset = prev_tab_offset;
1418 
1419           /* NOTE on contin_hpos, hpos, and prev_hpos.
1420 
1421              ----------
1422              abcdefgh\\
1423              W_      ^----  contin_hpos
1424              | ^-----  hpos
1425              \---- prev_hpos
1426              ----------
1427            */
1428 
1429           if (contin_hpos && prev_hpos == 0
1430               && contin_hpos < width && !wide_column_end_hpos)
1431             {
1432               /* Line breaking occurs in the middle of multi-column
1433                  character.  Go back to previous line.  */
1434               hpos = contin_hpos;
1435               vpos = vpos - 1;
1436             }
1437           break;
1438         }
1439 
1440       if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
1441         {
1442           if (contin_hpos && prev_hpos == 0
1443               && hpos > tohpos
1444               && (contin_hpos == width || wide_column_end_hpos > width))
1445             { /* Line breaks because we can't put the character at the
1446                  previous line any more.  It is not the multi-column
1447                  character continued in middle.  Go back to previous
1448                  buffer position, screen position, and set tab offset
1449                  to previous value.  It's the beginning of the
1450                  line.  */
1451               pos = prev_pos;
1452               pos_byte = prev_pos_byte;
1453               hpos = prev_hpos;
1454               vpos = prev_vpos;
1455               tab_offset = prev_tab_offset;
1456             }
1457           break;
1458         }
1459       if (pos == ZV) /* We cannot go beyond ZV.  Stop here. */
1460         break;
1461 
1462       prev_hpos = hpos;
1463       prev_vpos = vpos;
1464       prev_pos = pos;
1465       prev_pos_byte = pos_byte;
1466       wide_column_end_hpos = 0;
1467 
1468       /* Consult the width run cache to see if we can avoid inspecting
1469          the text character-by-character.  */
1470       if (current_buffer->width_run_cache && pos >= next_width_run)
1471         {
1472           int run_end;
1473           int common_width
1474             = region_cache_forward (current_buffer,
1475                                     current_buffer->width_run_cache,
1476                                     pos, &run_end);
1477 
1478           /* A width of zero means the character's width varies (like
1479              a tab), is meaningless (like a newline), or we just don't
1480              want to skip over it for some other reason.  */
1481           if (common_width != 0)
1482             {
1483               int run_end_hpos;
1484 
1485               /* Don't go past the final buffer posn the user
1486                  requested.  */
1487               if (run_end > to)
1488                 run_end = to;
1489 
1490               run_end_hpos = hpos + (run_end - pos) * common_width;
1491 
1492               /* Don't go past the final horizontal position the user
1493                  requested.  */
1494               if (vpos == tovpos && run_end_hpos > tohpos)
1495                 {
1496                   run_end      = pos + (tohpos - hpos) / common_width;
1497                   run_end_hpos = hpos + (run_end - pos) * common_width;
1498                 }
1499 
1500               /* Don't go past the margin.  */
1501               if (run_end_hpos >= width)
1502                 {
1503                   run_end      = pos + (width  - hpos) / common_width;
1504                   run_end_hpos = hpos + (run_end - pos) * common_width;
1505                 }
1506 
1507               hpos = run_end_hpos;
1508               if (run_end > pos)
1509                 prev_hpos = hpos - common_width;
1510               if (pos != run_end)
1511                 {
1512                   pos = run_end;
1513                   pos_byte = CHAR_TO_BYTE (pos);
1514                 }
1515             }
1516 
1517           next_width_run = run_end + 1;
1518         }
1519 
1520       /* We have to scan the text character-by-character.  */
1521       else
1522         {
1523           EMACS_INT i, n;
1524           Lisp_Object charvec;
1525 
1526           /* Check composition sequence.  */
1527           if (cmp_it.id >= 0
1528               || (pos == cmp_it.stop_pos
1529                   && composition_reseat_it (&cmp_it, pos, pos_byte, to, win,
1530                                             NULL, Qnil)))
1531             composition_update_it (&cmp_it, pos, pos_byte, Qnil);
1532           if (cmp_it.id >= 0)
1533             {
1534               pos += cmp_it.nchars;
1535               pos_byte += cmp_it.nbytes;
1536               hpos += cmp_it.width;
1537               if (cmp_it.to == cmp_it.nglyphs)
1538                 {
1539                   cmp_it.id = -1;
1540                   composition_compute_stop_pos (&cmp_it, pos, pos_byte, to,
1541                                                 Qnil);
1542                 }
1543               else
1544                 cmp_it.from = cmp_it.to;
1545               continue;
1546             }
1547 
1548           c = FETCH_BYTE (pos_byte);
1549           pos++, pos_byte++;
1550 
1551           /* Perhaps add some info to the width_run_cache.  */
1552           if (current_buffer->width_run_cache)
1553             {
1554               /* Is this character part of the current run?  If so, extend
1555                  the run.  */
1556               if (pos - 1 == width_run_end
1557                   && XFASTINT (width_table[c]) == width_run_width)
1558                 width_run_end = pos;
1559 
1560               /* The previous run is over, since this is a character at a
1561                  different position, or a different width.  */
1562               else
1563                 {
1564                   /* Have we accumulated a run to put in the cache?
1565                      (Currently, we only cache runs of width == 1).  */
1566                   if (width_run_start < width_run_end
1567                       && width_run_width == 1)
1568                     know_region_cache (current_buffer,
1569                                        current_buffer->width_run_cache,
1570                                        width_run_start, width_run_end);
1571 
1572                   /* Start recording a new width run.  */
1573                   width_run_width = XFASTINT (width_table[c]);
1574                   width_run_start = pos - 1;
1575                   width_run_end = pos;
1576                 }
1577             }
1578 
1579           if (dp != 0
1580               && ! (multibyte && BASE_LEADING_CODE_P (c))
1581               && VECTORP (DISP_CHAR_VECTOR (dp, c)))
1582             {
1583               charvec = DISP_CHAR_VECTOR (dp, c);
1584               n = ASIZE (charvec);
1585             }
1586           else
1587             {
1588               charvec = Qnil;
1589               n = 1;
1590             }
1591 
1592           for (i = n - 1; i >= 0; --i)
1593             {
1594               if (VECTORP (charvec))
1595                 {
1596                   /* This should be handled the same as
1597                      next_element_from_display_vector does it.  */
1598                   Lisp_Object entry = AREF (charvec, i);
1599 
1600                   if (GLYPH_CODE_P (entry)
1601                       && GLYPH_CODE_CHAR_VALID_P (entry))
1602                     c = GLYPH_CODE_CHAR (entry);
1603                   else
1604                     c = ' ';
1605                 }
1606 
1607               if (c >= 040 && c < 0177)
1608                 hpos++;
1609               else if (c == '\t')
1610                 {
1611                   int tem = ((hpos + tab_offset + hscroll - (hscroll > 0))
1612                              % tab_width);
1613                   if (tem < 0)
1614                     tem += tab_width;
1615                   hpos += tab_width - tem;
1616                 }
1617               else if (c == '\n')
1618                 {
1619                   if (selective > 0
1620                       && indented_beyond_p (pos, pos_byte,
1621                                             (double) selective)) /* iftc */
1622                     {
1623                       /* If (pos == to), we don't have to take care of
1624                          selective display.  */
1625                       if (pos < to)
1626                         {
1627                           /* Skip any number of invisible lines all at once */
1628                           do
1629                             {
1630                               pos = find_before_next_newline (pos, to, 1);
1631                               if (pos < to)
1632                                 pos++;
1633                               pos_byte = CHAR_TO_BYTE (pos);
1634                             }
1635                           while (pos < to
1636                                  && indented_beyond_p (pos, pos_byte,
1637                                                        (double) selective)); /* iftc */
1638                           /* Allow for the " ..." that is displayed for them. */
1639                           if (selective_rlen)
1640                             {
1641                               hpos += selective_rlen;
1642                               if (hpos >= width)
1643                                 hpos = width;
1644                             }
1645                           DEC_BOTH (pos, pos_byte);
1646                           /* We have skipped the invis text, but not the
1647                              newline after.  */
1648                         }
1649                     }
1650                   else
1651                     {
1652                       /* A visible line.  */
1653                       vpos++;
1654                       hpos = 0;
1655                       hpos -= hscroll;
1656                       /* Count the truncation glyph on column 0 */
1657                       if (hscroll > 0)
1658                         hpos += continuation_glyph_width;
1659                       tab_offset = 0;
1660                     }
1661                   contin_hpos = 0;
1662                 }
1663               else if (c == CR && selective < 0)
1664                 {
1665                   /* In selective display mode,
1666                      everything from a ^M to the end of the line is invisible.
1667                      Stop *before* the real newline.  */
1668                   if (pos < to)
1669                     {
1670                       pos = find_before_next_newline (pos, to, 1);
1671                       pos_byte = CHAR_TO_BYTE (pos);
1672                     }
1673                   /* If we just skipped next_boundary,
1674                      loop around in the main while
1675                      and handle it.  */
1676                   if (pos > next_boundary)
1677                     next_boundary = pos;
1678                   /* Allow for the " ..." that is displayed for them. */
1679                   if (selective_rlen)
1680                     {
1681                       hpos += selective_rlen;
1682                       if (hpos >= width)
1683                         hpos = width;
1684                     }
1685                 }
1686               else if (multibyte && BASE_LEADING_CODE_P (c))
1687                 {
1688                   /* Start of multi-byte form.  */
1689                   unsigned char *ptr;
1690                   int bytes, width, wide_column;
1691 
1692                   pos_byte--;   /* rewind POS_BYTE */
1693                   ptr = BYTE_POS_ADDR (pos_byte);
1694                   MULTIBYTE_BYTES_WIDTH (ptr, dp);
1695                   pos_byte += bytes;
1696                   if (wide_column)
1697                     wide_column_end_hpos = hpos + wide_column;
1698                   hpos += width;
1699                 }
1700               else if (VECTORP (charvec))
1701                 ++hpos;
1702               else
1703                 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
1704             }
1705         }
1706     }
1707 
1708  after_loop:
1709 
1710   /* Remember any final width run in the cache.  */
1711   if (current_buffer->width_run_cache
1712       && width_run_width == 1
1713       && width_run_start < width_run_end)
1714     know_region_cache (current_buffer, current_buffer->width_run_cache,
1715                        width_run_start, width_run_end);
1716 
1717   val_compute_motion.bufpos = pos;
1718   val_compute_motion.bytepos = pos_byte;
1719   val_compute_motion.hpos = hpos;
1720   val_compute_motion.vpos = vpos;
1721   if (contin_hpos && prev_hpos == 0)
1722     val_compute_motion.prevhpos = contin_hpos;
1723   else
1724     val_compute_motion.prevhpos = prev_hpos;
1725   /* We alalways handle all of them here; none of them remain to do.  */
1726   val_compute_motion.ovstring_chars_done = 0;
1727 
1728   /* Nonzero if have just continued a line */
1729   val_compute_motion.contin = (contin_hpos && prev_hpos == 0);
1730 
1731   immediate_quit = 0;
1732   return &val_compute_motion;
1733 }
1734 
1735 
1736 DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
1737        doc: /* Scan through the current buffer, calculating screen position.
1738 Scan the current buffer forward from offset FROM,
1739 assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--
1740 to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--
1741 and return the ending buffer position and screen location.
1742 
1743 If TOPOS is nil, the actual width and height of the window's
1744 text area are used.
1745 
1746 There are three additional arguments:
1747 
1748 WIDTH is the number of columns available to display text;
1749 this affects handling of continuation lines.  A value of nil
1750 corresponds to the actual number of available text columns.
1751 
1752 OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).
1753 HSCROLL is the number of columns not being displayed at the left
1754 margin; this is usually taken from a window's hscroll member.
1755 TAB-OFFSET is the number of columns of the first tab that aren't
1756 being displayed, perhaps because the line was continued within it.
1757 If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.
1758 
1759 WINDOW is the window to operate on.  It is used to choose the display table;
1760 if it is showing the current buffer, it is used also for
1761 deciding which overlay properties apply.
1762 Note that `compute-motion' always operates on the current buffer.
1763 
1764 The value is a list of five elements:
1765   (POS HPOS VPOS PREVHPOS CONTIN)
1766 POS is the buffer position where the scan stopped.
1767 VPOS is the vertical position where the scan stopped.
1768 HPOS is the horizontal position where the scan stopped.
1769 
1770 PREVHPOS is the horizontal position one character back from POS.
1771 CONTIN is t if a line was continued after (or within) the previous character.
1772 
1773 For example, to find the buffer position of column COL of line LINE
1774 of a certain window, pass the window's starting location as FROM
1775 and the window's upper-left coordinates as FROMPOS.
1776 Pass the buffer's (point-max) as TO, to limit the scan to the end of the
1777 visible section of the buffer, and pass LINE and COL as TOPOS.  */)
1778      (from, frompos, to, topos, width, offsets, window)
1779      Lisp_Object from, frompos, to, topos;
1780      Lisp_Object width, offsets, window;
1781 {
1782   struct window *w;
1783   Lisp_Object bufpos, hpos, vpos, prevhpos;
1784   struct position *pos;
1785   int hscroll, tab_offset;
1786 
1787   CHECK_NUMBER_COERCE_MARKER (from);
1788   CHECK_CONS (frompos);
1789   CHECK_NUMBER_CAR (frompos);
1790   CHECK_NUMBER_CDR (frompos);
1791   CHECK_NUMBER_COERCE_MARKER (to);
1792   if (!NILP (topos))
1793     {
1794       CHECK_CONS (topos);
1795       CHECK_NUMBER_CAR (topos);
1796       CHECK_NUMBER_CDR (topos);
1797     }
1798   if (!NILP (width))
1799     CHECK_NUMBER (width);
1800 
1801   if (!NILP (offsets))
1802     {
1803       CHECK_CONS (offsets);
1804       CHECK_NUMBER_CAR (offsets);
1805       CHECK_NUMBER_CDR (offsets);
1806       hscroll = XINT (XCAR (offsets));
1807       tab_offset = XINT (XCDR (offsets));
1808     }
1809   else
1810     hscroll = tab_offset = 0;
1811 
1812   if (NILP (window))
1813     window = Fselected_window ();
1814   else
1815     CHECK_LIVE_WINDOW (window);
1816   w = XWINDOW (window);
1817 
1818   if (XINT (from) < BEGV || XINT (from) > ZV)
1819     args_out_of_range_3 (from, make_number (BEGV), make_number (ZV));
1820   if (XINT (to) < BEGV || XINT (to) > ZV)
1821     args_out_of_range_3 (to, make_number (BEGV), make_number (ZV));
1822 
1823   pos = compute_motion (XINT (from), XINT (XCDR (frompos)),
1824                         XINT (XCAR (frompos)), 0,
1825                         XINT (to),
1826                         (NILP (topos)
1827                          ? window_internal_height (w)
1828                          : XINT (XCDR (topos))),
1829                         (NILP (topos)
1830                          ? (window_box_text_cols (w)
1831                             - (
1832 #ifdef HAVE_WINDOW_SYSTEM
1833                                FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
1834 #endif
1835                                1))
1836                          : XINT (XCAR (topos))),
1837                         (NILP (width) ? -1 : XINT (width)),
1838                         hscroll, tab_offset,
1839                         XWINDOW (window));
1840 
1841   XSETFASTINT (bufpos, pos->bufpos);
1842   XSETINT (hpos, pos->hpos);
1843   XSETINT (vpos, pos->vpos);
1844   XSETINT (prevhpos, pos->prevhpos);
1845 
1846   return Fcons (bufpos,
1847                 Fcons (hpos,
1848                        Fcons (vpos,
1849                               Fcons (prevhpos,
1850                                      Fcons (pos->contin ? Qt : Qnil, Qnil)))));
1851 
1852 }
1853 
1854 /* Fvertical_motion and vmotion */
1855 
1856 struct position val_vmotion;
1857 
1858 struct position *
1859 vmotion (from, vtarget, w)
1860      register EMACS_INT from, vtarget;
1861      struct window *w;
1862 {
1863   EMACS_INT hscroll = XINT (w->hscroll);
1864   struct position pos;
1865   /* vpos is cumulative vertical position, changed as from is changed */
1866   register int vpos = 0;
1867   EMACS_INT prevline;
1868   register EMACS_INT first;
1869   EMACS_INT from_byte;
1870   EMACS_INT lmargin = hscroll > 0 ? 1 - hscroll : 0;
1871   int selective
1872     = (INTEGERP (current_buffer->selective_display)
1873        ? XINT (current_buffer->selective_display)
1874        : !NILP (current_buffer->selective_display) ? -1 : 0);
1875   Lisp_Object window;
1876   EMACS_INT start_hpos = 0;
1877   int did_motion;
1878   /* This is the object we use for fetching character properties.  */
1879   Lisp_Object text_prop_object;
1880 
1881   XSETWINDOW (window, w);
1882 
1883   /* If the window contains this buffer, use it for getting text properties.
1884      Otherwise use the current buffer as arg for doing that.  */
1885   if (EQ (w->buffer, Fcurrent_buffer ()))
1886     text_prop_object = window;
1887   else
1888     text_prop_object = Fcurrent_buffer ();
1889 
1890   if (vpos >= vtarget)
1891     {
1892       /* To move upward, go a line at a time until
1893          we have gone at least far enough.  */
1894 
1895       first = 1;
1896 
1897       while ((vpos > vtarget || first) && from > BEGV)
1898         {
1899           Lisp_Object propval;
1900 
1901           prevline = find_next_newline_no_quit (from - 1, -1);
1902           while (prevline > BEGV
1903                  && ((selective > 0
1904                       && indented_beyond_p (prevline,
1905                                             CHAR_TO_BYTE (prevline),
1906                                             (double) selective)) /* iftc */
1907                      /* Watch out for newlines with `invisible' property.
1908                         When moving upward, check the newline before.  */
1909                      || (propval = Fget_char_property (make_number (prevline - 1),
1910                                                        Qinvisible,
1911                                                        text_prop_object),
1912                          TEXT_PROP_MEANS_INVISIBLE (propval))))
1913             prevline = find_next_newline_no_quit (prevline - 1, -1);
1914           pos = *compute_motion (prevline, 0,
1915                                  lmargin + (prevline == BEG ? start_hpos : 0),
1916                                  0,
1917                                  from,
1918                                  /* Don't care for VPOS...  */
1919                                  1 << (BITS_PER_SHORT - 1),
1920                                  /* ... nor HPOS.  */
1921                                  1 << (BITS_PER_SHORT - 1),
1922                                  -1, hscroll,
1923                                  /* This compensates for start_hpos
1924                                     so that a tab as first character
1925                                     still occupies 8 columns.  */
1926                                  (prevline == BEG ? -start_hpos : 0),
1927                                  w);
1928           vpos -= pos.vpos;
1929           first = 0;
1930           from = prevline;
1931         }
1932 
1933       /* If we made exactly the desired vertical distance,
1934          or if we hit beginning of buffer,
1935          return point found */
1936       if (vpos >= vtarget)
1937         {
1938           val_vmotion.bufpos = from;
1939           val_vmotion.bytepos = CHAR_TO_BYTE (from);
1940           val_vmotion.vpos = vpos;
1941           val_vmotion.hpos = lmargin;
1942           val_vmotion.contin = 0;
1943           val_vmotion.prevhpos = 0;
1944           val_vmotion.ovstring_chars_done = 0;
1945           val_vmotion.tab_offset = 0; /* For accumulating tab offset.  */
1946           return &val_vmotion;
1947         }
1948 
1949       /* Otherwise find the correct spot by moving down */
1950     }
1951   /* Moving downward is simple, but must calculate from beg of line
1952      to determine hpos of starting point */
1953   from_byte = CHAR_TO_BYTE (from);
1954   if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n')
1955     {
1956       Lisp_Object propval;
1957 
1958       prevline = find_next_newline_no_quit (from, -1);
1959       while (prevline > BEGV
1960              && ((selective > 0
1961                   && indented_beyond_p (prevline,
1962                                         CHAR_TO_BYTE (prevline),
1963                                         (double) selective)) /* iftc */
1964                  /* Watch out for newlines with `invisible' property.
1965                     When moving downward, check the newline after.  */
1966                  || (propval = Fget_char_property (make_number (prevline),
1967                                                    Qinvisible,
1968                                                    text_prop_object),
1969                      TEXT_PROP_MEANS_INVISIBLE (propval))))
1970         prevline = find_next_newline_no_quit (prevline - 1, -1);
1971       pos = *compute_motion (prevline, 0,
1972                              lmargin + (prevline == BEG
1973                                         ? start_hpos : 0),
1974                              0,
1975                              from,
1976                              /* Don't care for VPOS...  */
1977                              1 << (BITS_PER_SHORT - 1),
1978                              /* ... nor HPOS.  */
1979                              1 << (BITS_PER_SHORT - 1),
1980                              -1, hscroll,
1981                              (prevline == BEG ? -start_hpos : 0),
1982                              w);
1983       did_motion = 1;
1984     }
1985   else
1986     {
1987       pos.hpos = lmargin + (from == BEG ? start_hpos : 0);
1988       pos.vpos = 0;
1989       pos.tab_offset = 0;
1990       did_motion = 0;
1991     }
1992   return compute_motion (from, vpos, pos.hpos, did_motion,
1993                          ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)),
1994                          -1, hscroll,
1995                          pos.tab_offset - (from == BEG ? start_hpos : 0),
1996                          w);
1997 }
1998 
1999 DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
2000        doc: /* Move point to start of the screen line LINES lines down.
2001 If LINES is negative, this means moving up.
2002 
2003 This function is an ordinary cursor motion function
2004 which calculates the new position based on how text would be displayed.
2005 The new position may be the start of a line,
2006 or just the start of a continuation line.
2007 The function returns number of screen lines moved over;
2008 that usually equals LINES, but may be closer to zero
2009 if beginning or end of buffer was reached.
2010 
2011 The optional second argument WINDOW specifies the window to use for
2012 parameters such as width, horizontal scrolling, and so on.
2013 The default is to use the selected window's parameters.
2014 
2015 LINES can optionally take the form (COLS . LINES), in which case
2016 the motion will not stop at the start of a screen line but on
2017 its column COLS (if such exists on that line, that is).
2018 
2019 `vertical-motion' always uses the current buffer,
2020 regardless of which buffer is displayed in WINDOW.
2021 This is consistent with other cursor motion functions
2022 and makes it possible to use `vertical-motion' in any buffer,
2023 whether or not it is currently displayed in some window.  */)
2024      (lines, window)
2025      Lisp_Object lines, window;
2026 {
2027   struct it it;
2028   struct text_pos pt;
2029   struct window *w;
2030   Lisp_Object old_buffer;
2031   struct gcpro gcpro1;
2032   Lisp_Object lcols = Qnil;
2033   double cols;
2034 
2035   /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES).  */
2036   if (CONSP (lines) && (NUMBERP (XCAR (lines))))
2037     {
2038       lcols = XCAR (lines);
2039       cols = INTEGERP (lcols) ? (double) XINT (lcols) : XFLOAT_DATA (lcols);
2040       lines = XCDR (lines);
2041     }
2042 
2043   CHECK_NUMBER (lines);
2044   if (! NILP (window))
2045     CHECK_WINDOW (window);
2046   else
2047     window = selected_window;
2048   w = XWINDOW (window);
2049 
2050   old_buffer = Qnil;
2051   GCPRO1 (old_buffer);
2052   if (XBUFFER (w->buffer) != current_buffer)
2053     {
2054       /* Set the window's buffer temporarily to the current buffer.  */
2055       old_buffer = w->buffer;
2056       XSETBUFFER (w->buffer, current_buffer);
2057     }
2058 
2059   if (noninteractive)
2060     {
2061       struct position pos;
2062       pos = *vmotion (PT, XINT (lines), w);
2063       SET_PT_BOTH (pos.bufpos, pos.bytepos);
2064     }
2065   else
2066     {
2067       int it_start, first_x, it_overshoot_expected;
2068 
2069       SET_TEXT_POS (pt, PT, PT_BYTE);
2070       start_display (&it, w, pt);
2071       first_x = it.first_visible_x;
2072       it_start = IT_CHARPOS (it);
2073 
2074       /* See comments below for why we calculate this.  */
2075       if (XINT (lines) > 0)
2076         {
2077           if (it.cmp_it.id >= 0)
2078             it_overshoot_expected = 1;
2079           else if (it.method == GET_FROM_STRING)
2080             {
2081               const char *s = SDATA (it.string);
2082               const char *e = s + SBYTES (it.string);
2083               while (s < e && *s != '\n')
2084                 ++s;
2085               it_overshoot_expected = (s == e) ? -1 : 0;
2086             }
2087           else
2088             it_overshoot_expected = (it.method == GET_FROM_IMAGE
2089                                      || it.method == GET_FROM_STRETCH);
2090         }
2091 
2092       /* Scan from the start of the line containing PT.  If we don't
2093          do this, we start moving with IT->current_x == 0, while PT is
2094          really at some x > 0.  */
2095       reseat_at_previous_visible_line_start (&it);
2096       it.current_x = it.hpos = 0;
2097       if (IT_CHARPOS (it) != PT)
2098         /* We used to temporarily disable selective display here; the
2099            comment said this is "so we don't move too far" (2005-01-19
2100            checkin by kfs).  But this does nothing useful that I can
2101            tell, and it causes Bug#2694 .  -- cyd */
2102         move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
2103 
2104       if (XINT (lines) <= 0)
2105         {
2106           it.vpos = 0;
2107           /* Do this even if LINES is 0, so that we move back to the
2108              beginning of the current line as we ought.  */
2109           if (XINT (lines) == 0 || IT_CHARPOS (it) > 0)
2110             move_it_by_lines (&it, XINT (lines), 0);
2111         }
2112       else
2113         {
2114           if (IT_CHARPOS (it) > it_start)
2115             {
2116               /* IT may move too far if truncate-lines is on and PT
2117                  lies beyond the right margin.  In that case,
2118                  backtrack unless the starting point is on an image,
2119                  stretch glyph, composition, or Lisp string.  */
2120               if (!it_overshoot_expected
2121                   /* Also, backtrack if the Lisp string contains no
2122                      newline, but there is a newline right after it.
2123                      In this case, IT overshoots if there is an
2124                      after-string just before the newline.  */
2125                   || (it_overshoot_expected < 0
2126                       && it.method == GET_FROM_BUFFER
2127                       && it.c == '\n'))
2128                 move_it_by_lines (&it, -1, 0);
2129               it.vpos = 0;
2130               move_it_by_lines (&it, XINT (lines), 0);
2131             }
2132           else
2133             {
2134               /* Otherwise, we are at the first row occupied by PT,
2135                  which might span multiple screen lines (e.g., if it's
2136                  on a multi-line display string).  We want to start
2137                  from the last line that it occupies.  */
2138               if (it_start < ZV)
2139                 {
2140                   while (IT_CHARPOS (it) <= it_start)
2141                     {
2142                       it.vpos = 0;
2143                       move_it_by_lines (&it, 1, 0);
2144                     }
2145                   if (XINT (lines) > 1)
2146                     move_it_by_lines (&it, XINT (lines) - 1, 0);
2147                 }
2148               else
2149                 {
2150                   it.vpos = 0;
2151                   move_it_by_lines (&it, XINT (lines), 0);
2152                 }
2153             }
2154         }
2155 
2156       /* Move to the goal column, if one was specified.  */
2157       if (!NILP (lcols))
2158         {
2159           /* If the window was originally hscrolled, move forward by
2160              the hscrolled amount first.  */
2161           if (first_x > 0)
2162             {
2163               move_it_in_display_line (&it, ZV, first_x, MOVE_TO_X);
2164               it.current_x = 0;
2165             }
2166           move_it_in_display_line
2167             (&it, ZV,
2168              (int)(cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5),
2169              MOVE_TO_X);
2170         }
2171 
2172       SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
2173     }
2174 
2175   if (BUFFERP (old_buffer))
2176     w->buffer = old_buffer;
2177 
2178   RETURN_UNGCPRO (make_number (it.vpos));
2179 }
2180 
2181 
2182 
2183 /* File's initialization.  */
2184 
2185 void
2186 syms_of_indent ()
2187 {
2188   DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
2189                doc: /* *Indentation can insert tabs if this is non-nil.  */);
2190   indent_tabs_mode = 1;
2191 
2192   defsubr (&Scurrent_indentation);
2193   defsubr (&Sindent_to);
2194   defsubr (&Scurrent_column);
2195   defsubr (&Smove_to_column);
2196   defsubr (&Svertical_motion);
2197   defsubr (&Scompute_motion);
2198 }
2199 
2200 /* arch-tag: 9adfea44-71f7-4988-8ee3-96da15c502cc
2201    (do not change this comment) */