]> code.delx.au - gnu-emacs/blobdiff - src/indent.c
Initial revision.
[gnu-emacs] / src / indent.c
index 49768ea52064928e5f01922a127fa68ed0906def..402456e168518cbb9a786c25b537850d7f62b44e 100644 (file)
@@ -39,16 +39,13 @@ Boston, MA 02111-1307, USA.  */
 
 int indent_tabs_mode;
 
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
 #define CR 015
 
-/* These three values memoize the current column to avoid recalculation.  */
+/* These three values memorize the current column to avoid recalculation.  */
 
 /* Last value returned by current_column.
    Some things in set last_known_column_point to -1
-   to mark the memoized value as invalid.  */
+   to mark the memorized value as invalid.  */
 
 int last_known_column;
 
@@ -273,7 +270,7 @@ skip_invisible (pos, next_boundary_p, to, window)
     prop = Fget_char_property (position, Qinvisible, window);
   else
     prop = Fget_char_property (position, Qinvisible, buffer);
-  if (TEXT_PROP_MEANS_INVISIBLE (prop))
+  if (TEXT_PROP_MEANS_INVISIBLE (prop) > NILP (window))
     return *next_boundary_p;
   return pos;
 }
@@ -331,16 +328,16 @@ check_composition (pos, pos_byte, point, len, len_byte, width)
   } while (0)
 
 DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
-  "Return the horizontal position of point.  Beginning of line is column 0.\n\
-This is calculated by adding together the widths of all the displayed\n\
-representations of the character between the start of the previous line\n\
-and point.  (eg control characters will have a width of 2 or 4, tabs\n\
-will have a variable width)\n\
-Ignores finite width of frame, which means that this function may return\n\
-values greater than (frame-width).\n\
-Whether the line is visible (if `selective-display' is t) has no effect;\n\
-however, ^M is treated as end of line when `selective-display' is t.")
-  ()
+       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
+and point.  (eg control characters will have a width of 2 or 4, tabs
+will have a variable width)
+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;
+however, ^M is treated as end of line when `selective-display' is t.  */)
+     ()
 {
   Lisp_Object temp;
   XSETFASTINT (temp, current_column ());
@@ -465,6 +462,13 @@ current_column ()
              col = 0;
              tab_seen = 1;
            }
+         else if (VECTORP (charvec))
+           /* With a display table entry, C is displayed as is, and
+              not displayed as \NNN or as ^N.  If C is a single-byte
+              character, it takes one column.  If C is multi-byte in
+              an unibyte buffer, it's translated to unibyte, so it
+              also takes one column.  */
+           ++col;
          else
            col += (ctl_arrow && c < 0200) ? 2 : 4;
        }
@@ -522,8 +526,6 @@ current_column_1 ()
   while (scan < opoint)
     {
       int c;
-      EMACS_INT i, n;
-      Lisp_Object charvec;
 
       /* Occasionally we may need to skip invisible text.  */
       while (scan == next_boundary)
@@ -560,39 +562,52 @@ current_column_1 ()
          && ! (multibyte && BASE_LEADING_CODE_P (c))
          && VECTORP (DISP_CHAR_VECTOR (dp, c)))
        {
+         Lisp_Object charvec;
+         EMACS_INT i, n;
+
+         /* This character is displayed using a vector of glyphs.
+            Update the column based on those glyphs.  */
+
          charvec = DISP_CHAR_VECTOR (dp, c);
          n = ASIZE (charvec);
-       }
-      else
-       {
-         charvec = Qnil;
-         n = 1;
-       }
 
-      for (i = n - 1; i >= 0; --i)
-       {
-         if (VECTORP (charvec))
+         for (i = 0; i < n; i++)
            {
              /* This should be handled the same as
                 next_element_from_display_vector does it.  */
-             Lisp_Object entry = AREF (charvec, i);
-             
+             Lisp_Object entry;
+             entry = AREF (charvec, i);
+
              if (INTEGERP (entry)
                  && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
                c = FAST_GLYPH_CHAR (XFASTINT (entry));
              else
                c = ' ';
+
+             if (c == '\n')
+               goto endloop;
+             if (c == '\r' && EQ (current_buffer->selective_display, Qt))
+               goto endloop;
+             if (c == '\t')
+               {
+                 col += tab_width;
+                 col = col / tab_width * tab_width;
+               }
+             else
+               ++col;
            }
-      
+       }
+      else
+       {
+         /* The display table says nothing for this character.
+            Display it as itself.  */
+
          if (c == '\n')
            goto endloop;
          if (c == '\r' && EQ (current_buffer->selective_display, Qt))
            goto endloop;
-         scan++;
-         scan_byte++;
          if (c == '\t')
            {
-             int prev_col = col;
              col += tab_width;
              col = col / tab_width * tab_width;
            }
@@ -601,10 +616,12 @@ current_column_1 ()
              unsigned char *ptr;
              int bytes, width, wide_column;
              
-             scan_byte--;
              ptr = BYTE_POS_ADDR (scan_byte);
              MULTIBYTE_BYTES_WIDTH (ptr, dp);
              scan_byte += bytes;
+             /* Subtract one to compensate for the increment
+                that is going to happen below.  */
+             scan_byte--;
              col += width;
            }
          else if (ctl_arrow && (c < 040 || c == 0177))
@@ -614,6 +631,9 @@ current_column_1 ()
          else
            col++;
        }
+      scan++;
+      scan_byte++;
+
     }
  endloop:
 
@@ -649,7 +669,7 @@ string_display_width (string, beg, end)
     e = XSTRING (string)->size;
   else
     {
-      CHECK_NUMBER (end, 0);
+      CHECK_NUMBER (end);
       e = XINT (end);
     }
 
@@ -657,7 +677,7 @@ string_display_width (string, beg, end)
     b = 0;
   else
     {
-      CHECK_NUMBER (beg, 0);
+      CHECK_NUMBER (beg);
       b = XINT (beg);
     }
 
@@ -709,20 +729,20 @@ string_display_width (string, beg, end)
 
 \f
 DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
-  "Indent from point with tabs and spaces until COLUMN is reached.\n\
-Optional second argument MININUM says always do at least MININUM spaces\n\
-even if that goes past COLUMN; by default, MININUM is zero.")
-  (column, minimum)
+       doc: /* Indent from point with tabs and spaces until COLUMN is reached.
+Optional second argument MININUM says always do at least MININUM spaces
+even if that goes past COLUMN; by default, MININUM is zero.  */)
+     (column, minimum)
      Lisp_Object column, minimum;
 {
   int mincol;
   register int fromcol;
   register int tab_width = XINT (current_buffer->tab_width);
 
-  CHECK_NUMBER (column, 0);
+  CHECK_NUMBER (column);
   if (NILP (minimum))
     XSETFASTINT (minimum, 0);
-  CHECK_NUMBER (minimum, 1);
+  CHECK_NUMBER (minimum);
 
   fromcol = current_column ();
   mincol = fromcol + XINT (minimum);
@@ -760,11 +780,11 @@ even if that goes past COLUMN; by default, MININUM is zero.")
 static int position_indentation P_ ((int));
 
 DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
-  0, 0, 0,
-  "Return the indentation of the current line.\n\
-This is the horizontal position of the character\n\
-following any initial whitespace.")
-  ()
+       0, 0, 0,
+       doc: /* Return the indentation of the current line.
+This is the horizontal position of the character
+following any initial whitespace.  */)
+     ()
 {
   Lisp_Object val;
   int opoint = PT, opoint_byte = PT_BYTE;
@@ -883,22 +903,23 @@ indented_beyond_p (pos, pos_byte, column)
 }
 \f
 DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
-  "Move point to column COLUMN in the current line.\n\
-The column of a character is calculated by adding together the widths\n\
-as displayed of the previous characters in the line.\n\
-This function ignores line-continuation;\n\
-there is no upper limit on the column number a character can have\n\
-and horizontal scrolling has no effect.\n\
-\n\
-If specified column is within a character, point goes after that character.\n\
-If it's past end of line, point goes to end of line.\n\n\
-A non-nil second (optional) argument FORCE means,\n\
-if COLUMN is in the middle of a tab character, change it to spaces.\n\
-In addition, if FORCE is t, and the line is too short\n\
-to reach column COLUMN, add spaces/tabs to get there.\n\
-\n\
-The return value is the current column.")
-  (column, force)
+       doc: /* Move point to column COLUMN in the current line.
+The column of a character is calculated by adding together the widths
+as displayed of the previous characters in the line.
+This function ignores line-continuation;
+there is no upper limit on the column number a character can have
+and horizontal scrolling has no effect.
+
+If specified column is within a character, point goes after that character.
+If it's past end of line, point goes to end of line.
+
+A non-nil second (optional) argument FORCE means,
+if COLUMN is in the middle of a tab character, change it to spaces.
+In addition, if FORCE is t, and the line is too short
+to reach column COLUMN, add spaces/tabs to get there.
+
+The return value is the current column.  */)
+     (column, force)
      Lisp_Object column, force;
 {
   register int pos;
@@ -918,7 +939,7 @@ The return value is the current column.")
   int pos_byte, end_byte, next_boundary_byte;
 
   if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-  CHECK_NATNUM (column, 0);
+  CHECK_NATNUM (column);
   goal = XINT (column);
 
   pos = PT;
@@ -940,9 +961,6 @@ The return value is the current column.")
 
   while (pos < end)
     {
-      Lisp_Object charvec;
-      EMACS_INT i, n;
-      
       while (pos == next_boundary)
        {
          int prev = pos;
@@ -975,41 +993,59 @@ The return value is the current column.")
 
       c = FETCH_BYTE (pos_byte);
 
+      /* See if there is a display table and it relates
+        to this character.  */
+
       if (dp != 0
          && ! (multibyte && BASE_LEADING_CODE_P (c))
          && VECTORP (DISP_CHAR_VECTOR (dp, c)))
        {
+         Lisp_Object charvec;
+         EMACS_INT i, n;
+
+         /* This character is displayed using a vector of glyphs.
+            Update the position based on those glyphs.  */
+
          charvec = DISP_CHAR_VECTOR (dp, c);
          n = ASIZE (charvec);
-       }
-      else
-       {
-         charvec = Qnil;
-         n = 1;
-       }
 
-      for (i = n - 1; i >= 0; --i)
-       {
-         if (VECTORP (charvec))
+         for (i = 0; i < n; i++)
            {
              /* This should be handled the same as
                 next_element_from_display_vector does it.  */
-             Lisp_Object entry = AREF (charvec, i);
-             
+
+             Lisp_Object entry;
+             entry = AREF (charvec, i);
+
              if (INTEGERP (entry)
                  && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
                c = FAST_GLYPH_CHAR (XFASTINT (entry));
              else
                c = ' ';
+
+             if (c == '\n')
+               goto endloop;
+             if (c == '\r' && EQ (current_buffer->selective_display, Qt))
+               goto endloop;
+             if (c == '\t')
+               {
+                 prev_col = col;
+                 col += tab_width;
+                 col = col / tab_width * tab_width;
+               }
+             else
+               ++col;
            }
+       }
+      else
+       {
+         /* The display table doesn't affect this character;
+            it displays as itself.  */
 
-      
          if (c == '\n')
            goto endloop;
          if (c == '\r' && EQ (current_buffer->selective_display, Qt))
            goto endloop;
-         pos++;
-         pos_byte++;
          if (c == '\t')
            {
              prev_col = col;
@@ -1028,15 +1064,17 @@ The return value is the current column.")
              unsigned char *ptr;
              int bytes, width, wide_column;
 
-             pos_byte--;
              ptr = BYTE_POS_ADDR (pos_byte);
              MULTIBYTE_BYTES_WIDTH (ptr, dp);
-             pos_byte += bytes;
+             pos_byte += bytes - 1;
              col += width;
            }
          else
            col += 4;
        }
+
+      pos++;
+      pos_byte++;
     }
  endloop:
 
@@ -1224,7 +1262,7 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width,
          int newpos;
 
          /* Don't skip invisible if we are already at the margin.  */
-         if (vpos > tovpos || vpos == tovpos && hpos >= tohpos)
+         if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
            {
              if (contin_hpos && prev_hpos == 0
                  && hpos > tohpos
@@ -1406,7 +1444,7 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width,
          break;
        }
 
-      if (vpos > tovpos || vpos == tovpos && hpos >= tohpos)
+      if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
        {
          if (contin_hpos && prev_hpos == 0
              && hpos > tohpos
@@ -1654,6 +1692,8 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width,
                    wide_column_end_hpos = hpos + wide_column;
                  hpos += width;
                }
+             else if (VECTORP (charvec))
+               ++hpos;
              else
                hpos += (ctl_arrow && c < 0200) ? 2 : 4;
            }
@@ -1688,54 +1728,47 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width,
 }
 
 
-#if 0 /* The doc string is too long for some compilers,
-        but make-docfile can find it in this comment.  */
-DEFUN ("compute-motion", Ffoo, Sfoo, 7, 7, 0,
-  "Scan through the current buffer, calculating screen position.\n\
-Scan the current buffer forward from offset FROM,\n\
-assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--\n\
-to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--\n\
-and return the ending buffer position and screen location.\n\
-\n\
-There are three additional arguments:\n\
-\n\
-WIDTH is the number of columns available to display text;\n\
-this affects handling of continuation lines.\n\
-This is usually the value returned by `window-width', less one (to allow\n\
-for the continuation glyph).\n\
-\n\
-OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).\n\
-HSCROLL is the number of columns not being displayed at the left\n\
-margin; this is usually taken from a window's hscroll member.\n\
-TAB-OFFSET is the number of columns of the first tab that aren't\n\
-being displayed, perhaps because the line was continued within it.\n\
-If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.\n\
-\n\
-WINDOW is the window to operate on.  It is used to choose the display table;\n\
-if it is showing the current buffer, it is used also for\n\
-deciding which overlay properties apply.\n\
-Note that `compute-motion' always operates on the current buffer.\n\
-\n\
-The value is a list of five elements:\n\
-  (POS HPOS VPOS PREVHPOS CONTIN)\n\
-POS is the buffer position where the scan stopped.\n\
-VPOS is the vertical position where the scan stopped.\n\
-HPOS is the horizontal position where the scan stopped.\n\
-\n\
-PREVHPOS is the horizontal position one character back from POS.\n\
-CONTIN is t if a line was continued after (or within) the previous character.\n\
-\n\
-For example, to find the buffer position of column COL of line LINE\n\
-of a certain window, pass the window's starting location as FROM\n\
-and the window's upper-left coordinates as FROMPOS.\n\
-Pass the buffer's (point-max) as TO, to limit the scan to the end of the\n\
-visible section of the buffer, and pass LINE and COL as TOPOS.")
-  (from, frompos, to, topos, width, offsets, window)
-#endif
-
 DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
-  0)
-  (from, frompos, to, topos, width, offsets, window)
+       doc: /* Scan through the current buffer, calculating screen position.
+Scan the current buffer forward from offset FROM,
+assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--
+to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--
+and return the ending buffer position and screen location.
+
+There are three additional arguments:
+
+WIDTH is the number of columns available to display text;
+this affects handling of continuation lines.
+This is usually the value returned by `window-width', less one (to allow
+for the continuation glyph).
+
+OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).
+HSCROLL is the number of columns not being displayed at the left
+margin; this is usually taken from a window's hscroll member.
+TAB-OFFSET is the number of columns of the first tab that aren't
+being displayed, perhaps because the line was continued within it.
+If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.
+
+WINDOW is the window to operate on.  It is used to choose the display table;
+if it is showing the current buffer, it is used also for
+deciding which overlay properties apply.
+Note that `compute-motion' always operates on the current buffer.
+
+The value is a list of five elements:
+  (POS HPOS VPOS PREVHPOS CONTIN)
+POS is the buffer position where the scan stopped.
+VPOS is the vertical position where the scan stopped.
+HPOS is the horizontal position where the scan stopped.
+
+PREVHPOS is the horizontal position one character back from POS.
+CONTIN is t if a line was continued after (or within) the previous character.
+
+For example, to find the buffer position of column COL of line LINE
+of a certain window, pass the window's starting location as FROM
+and the window's upper-left coordinates as FROMPOS.
+Pass the buffer's (point-max) as TO, to limit the scan to the end of the
+visible section of the buffer, and pass LINE and COL as TOPOS.  */)
+     (from, frompos, to, topos, width, offsets, window)
      Lisp_Object from, frompos, to, topos;
      Lisp_Object width, offsets, window;
 {
@@ -1743,20 +1776,20 @@ DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
   struct position *pos;
   int hscroll, tab_offset;
 
-  CHECK_NUMBER_COERCE_MARKER (from, 0);
-  CHECK_CONS (frompos, 0);
-  CHECK_NUMBER (XCAR (frompos), 0);
-  CHECK_NUMBER (XCDR (frompos), 0);
-  CHECK_NUMBER_COERCE_MARKER (to, 0);
-  CHECK_CONS (topos, 0);
-  CHECK_NUMBER (XCAR (topos), 0);
-  CHECK_NUMBER (XCDR (topos), 0);
-  CHECK_NUMBER (width, 0);
+  CHECK_NUMBER_COERCE_MARKER (from);
+  CHECK_CONS (frompos);
+  CHECK_NUMBER_CAR (frompos);
+  CHECK_NUMBER_CDR (frompos);
+  CHECK_NUMBER_COERCE_MARKER (to);
+  CHECK_CONS (topos);
+  CHECK_NUMBER_CAR (topos);
+  CHECK_NUMBER_CDR (topos);
+  CHECK_NUMBER (width);
   if (!NILP (offsets))
     {
-      CHECK_CONS (offsets, 0);
-      CHECK_NUMBER (XCAR (offsets), 0);
-      CHECK_NUMBER (XCDR (offsets), 0);
+      CHECK_CONS (offsets);
+      CHECK_NUMBER_CAR (offsets);
+      CHECK_NUMBER_CDR (offsets);
       hscroll = XINT (XCAR (offsets));
       tab_offset = XINT (XCDR (offsets));
     }
@@ -1766,7 +1799,7 @@ DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
   if (NILP (window))
     window = Fselected_window ();
   else
-    CHECK_LIVE_WINDOW (window, 0);
+    CHECK_LIVE_WINDOW (window);
 
   if (XINT (from) < BEGV || XINT (from) > ZV)
     args_out_of_range_3 (from, make_number (BEGV), make_number (ZV));
@@ -1943,27 +1976,27 @@ vmotion (from, vtarget, w)
 }
 
 DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
-  "Move point to start of the screen line LINES lines down.\n\
-If LINES is negative, this means moving up.\n\
-\n\
-This function is an ordinary cursor motion function\n\
-which calculates the new position based on how text would be displayed.\n\
-The new position may be the start of a line,\n\
-or just the start of a continuation line.\n\
-The function returns number of screen lines moved over;\n\
-that usually equals LINES, but may be closer to zero\n\
-if beginning or end of buffer was reached.\n\
-\n\
-The optional second argument WINDOW specifies the window to use for\n\
-parameters such as width, horizontal scrolling, and so on.\n\
-The default is to use the selected window's parameters.\n\
-\n\
-`vertical-motion' always uses the current buffer,\n\
-regardless of which buffer is displayed in WINDOW.\n\
-This is consistent with other cursor motion functions\n\
-and makes it possible to use `vertical-motion' in any buffer,\n\
-whether or not it is currently displayed in some window.")
-  (lines, window)
+       doc: /* Move point to start of the screen line LINES lines down.
+If LINES is negative, this means moving up.
+
+This function is an ordinary cursor motion function
+which calculates the new position based on how text would be displayed.
+The new position may be the start of a line,
+or just the start of a continuation line.
+The function returns number of screen lines moved over;
+that usually equals LINES, but may be closer to zero
+if beginning or end of buffer was reached.
+
+The optional second argument WINDOW specifies the window to use for
+parameters such as width, horizontal scrolling, and so on.
+The default is to use the selected window's parameters.
+
+`vertical-motion' always uses the current buffer,
+regardless of which buffer is displayed in WINDOW.
+This is consistent with other cursor motion functions
+and makes it possible to use `vertical-motion' in any buffer,
+whether or not it is currently displayed in some window.  */)
+     (lines, window)
      Lisp_Object lines, window;
 {
   struct it it;
@@ -1972,9 +2005,9 @@ whether or not it is currently displayed in some window.")
   Lisp_Object old_buffer;
   struct gcpro gcpro1;
 
-  CHECK_NUMBER (lines, 0);
+  CHECK_NUMBER (lines);
   if (! NILP (window))
-    CHECK_WINDOW (window, 0);
+    CHECK_WINDOW (window);
   else
     window = selected_window;
   w = XWINDOW (window);
@@ -2007,8 +2040,8 @@ void
 syms_of_indent ()
 {
   DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
-    "*Indentation can insert tabs if this is non-nil.\n\
-Setting this variable automatically makes it local to the current buffer.");
+              doc: /* *Indentation can insert tabs if this is non-nil.
+Setting this variable automatically makes it local to the current buffer.  */);
   indent_tabs_mode = 1;
 
   defsubr (&Scurrent_indentation);