]> code.delx.au - gnu-emacs/blobdiff - src/indent.c
Merge from emacs--devo--0
[gnu-emacs] / src / indent.c
index 6ca15c67345ea5a405c717d1a128c8befbe04c39..c4ed2b94854a6c621fc6cece58622531c9aac6f9 100644 (file)
@@ -1,12 +1,12 @@
 /* Indentation functions.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1998, 2000, 2001,
-                 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -337,8 +337,8 @@ DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
        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)
+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;
@@ -736,8 +736,10 @@ string_display_width (string, beg, end)
 \f
 DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
        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.  */)
+Optional second argument MINIMUM says always do at least MINIMUM spaces
+even if that goes past COLUMN; by default, MINIMUM is zero.
+
+The return value is COLUMN.  */)
      (column, minimum)
      Lisp_Object column, minimum;
 {
@@ -911,6 +913,7 @@ indented_beyond_p (pos, pos_byte, column)
 \f
 DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
        doc: /* Move point to column COLUMN in the current line.
+Interactively, COLUMN is the value of prefix numeric argument.
 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;
@@ -920,10 +923,10 @@ 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.
+Optional second argument FORCE non-nil 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, add spaces/tabs to get there.
 
 The return value is the current column.  */)
      (column, force)
@@ -950,7 +953,6 @@ The return value is the current column.  */)
   pos = PT;
   pos_byte = PT_BYTE;
   end = ZV;
-  next_boundary = pos;
 
   /* If we're starting past the desired column,
      back up to beginning of line and scan from there.  */
@@ -962,6 +964,8 @@ The return value is the current column.  */)
       col = 0;
     }
 
+  next_boundary = pos;
+
   while (pos < end)
     {
       while (pos == next_boundary)
@@ -2076,7 +2080,7 @@ whether or not it is currently displayed in some window.  */)
     {
       int it_start;
       int oselective;
-      int start_on_image_or_stretch_p;
+      int it_overshoot_expected;
 
       SET_TEXT_POS (pt, PT, PT_BYTE);
       start_display (&it, w, pt);
@@ -2088,8 +2092,31 @@ whether or not it is currently displayed in some window.  */)
         while the end position is really at some X > 0, the same X that
         PT had.  */
       it_start = IT_CHARPOS (it);
-      start_on_image_or_stretch_p = (it.method == GET_FROM_IMAGE
-                                    || it.method == GET_FROM_STRETCH);
+
+      /* We expect the call to move_it_to, further down, to overshoot
+        if the starting point is on an image, stretch glyph,
+        composition, or Lisp string.  We won't need to backtrack in
+        this situation, except for one corner case: when the Lisp
+        string contains a newline.  */
+      if (it.method == GET_FROM_STRING)
+       {
+         const char *s = SDATA (it.string);
+         const char *e = s + SBYTES (it.string);
+
+         while (s < e && *s != '\n')
+           ++s;
+
+         /* If there is no newline in the string, we need to check
+            whether there is a newline immediately after the string
+            in move_it_to below.  This may happen if there is an
+            overlay with an after-string just before the newline.  */
+         it_overshoot_expected = (s == e) ? -1 : 0;
+       }
+      else
+       it_overshoot_expected = (it.method == GET_FROM_IMAGE
+                                || it.method == GET_FROM_STRETCH
+                                || it.method == GET_FROM_COMPOSITION);
+
       reseat_at_previous_visible_line_start (&it);
       it.current_x = it.hpos = 0;
       /* Temporarily disable selective display so we don't move too far */
@@ -2100,16 +2127,19 @@ whether or not it is currently displayed in some window.  */)
 
       /* Move back if we got too far.  This may happen if
         truncate-lines is on and PT is beyond right margin.
-        It may also happen if it_start is on an image or a stretch
-        glyph -- in that case, don't go back.  */
+        Don't go back if the overshoot is expected (see above).  */
       if (IT_CHARPOS (it) > it_start && XINT (lines) > 0
-         && !start_on_image_or_stretch_p)
+         && (!it_overshoot_expected
+             || (it_overshoot_expected < 0
+                 && it.method == GET_FROM_BUFFER
+                 && it.c == '\n')))
        move_it_by_lines (&it, -1, 0);
 
       it.vpos = 0;
       /* Do this even if LINES is 0, so that we move back
         to the beginning of the current line as we ought.  */
-      move_it_by_lines (&it, XINT (lines), 0);
+      if (XINT (lines) >= 0 || IT_CHARPOS (it) > 0)
+       move_it_by_lines (&it, XINT (lines), 0);
 
       SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
     }