use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / indent.c
index 47358e1..5b95bcf 100644 (file)
@@ -1,5 +1,5 @@
 /* Indentation functions.
 /* Indentation functions.
-   Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2013 Free Software
+   Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2014 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -141,33 +141,54 @@ recompute_width_table (struct buffer *buf, struct Lisp_Char_Table *disptab)
     XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
 }
 
     XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
 }
 
-/* Allocate or free the width run cache, as requested by the current
-   state of current_buffer's cache_long_line_scans variable.  */
+/* Allocate or free the width run cache, as requested by the
+   current state of current_buffer's cache_long_scans variable.  */
 
 
-static void
+static struct region_cache *
 width_run_cache_on_off (void)
 {
 width_run_cache_on_off (void)
 {
-  if (NILP (BVAR (current_buffer, cache_long_line_scans))
+  struct buffer *cache_buffer = current_buffer;
+  bool indirect_p = false;
+
+  if (cache_buffer->base_buffer)
+    {
+      cache_buffer = cache_buffer->base_buffer;
+      indirect_p = true;
+    }
+
+  if (NILP (BVAR (current_buffer, cache_long_scans))
       /* And, for the moment, this feature doesn't work on multibyte
          characters.  */
       || !NILP (BVAR (current_buffer, enable_multibyte_characters)))
     {
       /* And, for the moment, this feature doesn't work on multibyte
          characters.  */
       || !NILP (BVAR (current_buffer, enable_multibyte_characters)))
     {
-      /* It should be off.  */
-      if (current_buffer->width_run_cache)
-        {
-          free_region_cache (current_buffer->width_run_cache);
-          current_buffer->width_run_cache = 0;
-          bset_width_table (current_buffer, Qnil);
+      if (!indirect_p
+         || NILP (BVAR (cache_buffer, cache_long_scans))
+         || !NILP (BVAR (cache_buffer, enable_multibyte_characters)))
+       {
+         /* It should be off.  */
+         if (cache_buffer->width_run_cache)
+           {
+             free_region_cache (cache_buffer->width_run_cache);
+             cache_buffer->width_run_cache = 0;
+             bset_width_table (current_buffer, Qnil);
+           }
         }
         }
+      return NULL;
     }
   else
     {
     }
   else
     {
-      /* It should be on.  */
-      if (current_buffer->width_run_cache == 0)
-        {
-          current_buffer->width_run_cache = new_region_cache ();
-          recompute_width_table (current_buffer, buffer_display_table ());
-        }
+      if (!indirect_p
+         || (!NILP (BVAR (cache_buffer, cache_long_scans))
+             && NILP (BVAR (cache_buffer, enable_multibyte_characters))))
+       {
+         /* It should be on.  */
+         if (cache_buffer->width_run_cache == 0)
+           {
+             cache_buffer->width_run_cache = new_region_cache ();
+             recompute_width_table (current_buffer, buffer_display_table ());
+           }
+       }
+      return cache_buffer->width_run_cache;
     }
 }
 
     }
 }
 
@@ -510,15 +531,10 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, ptrdiff_t *prevcol)
   register ptrdiff_t col = 0, prev_col = 0;
   EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
   ptrdiff_t end = endpos ? *endpos : PT;
   register ptrdiff_t col = 0, prev_col = 0;
   EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
   ptrdiff_t end = endpos ? *endpos : PT;
-  ptrdiff_t scan, scan_byte;
-  ptrdiff_t next_boundary;
-  {
-  ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
-  scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
-  scan = PT, scan_byte = PT_BYTE;
-  SET_PT_BOTH (opoint, opoint_byte);
+  ptrdiff_t scan, scan_byte, next_boundary;
+
+  scan = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &scan_byte, 1);
   next_boundary = scan;
   next_boundary = scan;
-  }
 
   window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
   w = ! NILP (window) ? XWINDOW (window) : NULL;
 
   window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
   w = ! NILP (window) ? XWINDOW (window) : NULL;
@@ -684,7 +700,7 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, ptrdiff_t *prevcol)
     *prevcol = prev_col;
 }
 
     *prevcol = prev_col;
 }
 
-/* Return the column number of position POS
+/* Return the column number of point
    by scanning forward from the beginning of the line.
    This function handles characters that are invisible
    due to text properties or overlays.  */
    by scanning forward from the beginning of the line.
    This function handles characters that are invisible
    due to text properties or overlays.  */
@@ -835,14 +851,10 @@ This is the horizontal position of the character
 following any initial whitespace.  */)
   (void)
 {
 following any initial whitespace.  */)
   (void)
 {
-  Lisp_Object val;
-  ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
-
-  scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
+  ptrdiff_t posbyte;
 
 
-  XSETFASTINT (val, position_indentation (PT_BYTE));
-  SET_PT_BOTH (opoint, opoint_byte);
-  return val;
+  find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &posbyte, 1);
+  return make_number (position_indentation (posbyte));
 }
 
 static ptrdiff_t
 }
 
 static ptrdiff_t
@@ -908,7 +920,7 @@ position_indentation (ptrdiff_t pos_byte)
          column += tab_width - column % tab_width;
          break;
        default:
          column += tab_width - column % tab_width;
          break;
        default:
-         if (ASCII_BYTE_P (p[-1])
+         if (ASCII_CHAR_P (p[-1])
              || NILP (BVAR (current_buffer, enable_multibyte_characters)))
            return column;
          {
              || NILP (BVAR (current_buffer, enable_multibyte_characters)))
            return column;
          {
@@ -935,16 +947,13 @@ position_indentation (ptrdiff_t pos_byte)
 bool
 indented_beyond_p (ptrdiff_t pos, ptrdiff_t pos_byte, EMACS_INT column)
 {
 bool
 indented_beyond_p (ptrdiff_t pos, ptrdiff_t pos_byte, EMACS_INT column)
 {
-  ptrdiff_t val;
-  ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
-
-  SET_PT_BOTH (pos, pos_byte);
-  while (PT > BEGV && FETCH_BYTE (PT_BYTE) == '\n')
-    scan_newline (PT - 1, PT_BYTE - 1, BEGV, BEGV_BYTE, -1, 0);
-
-  val = position_indentation (PT_BYTE);
-  SET_PT_BOTH (opoint, opoint_byte);
-  return val >= column;
+  while (pos > BEGV && FETCH_BYTE (pos_byte) == '\n')
+    {
+      DEC_BOTH (pos, pos_byte);
+      pos = find_newline (pos, pos_byte, BEGV, BEGV_BYTE,
+                         -1, NULL, &pos_byte, 0);
+    }
+  return position_indentation (pos_byte) >= column;
 }
 \f
 DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2,
 }
 \f
 DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2,
@@ -1140,12 +1149,16 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
   EMACS_INT contin_hpos;       /* HPOS of last column of continued line.  */
   int prev_tab_offset;         /* Previous tab offset.  */
   int continuation_glyph_width;
   EMACS_INT contin_hpos;       /* HPOS of last column of continued line.  */
   int prev_tab_offset;         /* Previous tab offset.  */
   int continuation_glyph_width;
+  struct buffer *cache_buffer = current_buffer;
+  struct region_cache *width_cache;
 
   struct composition_it cmp_it;
 
   XSETWINDOW (window, win);
 
 
   struct composition_it cmp_it;
 
   XSETWINDOW (window, win);
 
-  width_run_cache_on_off ();
+  if (cache_buffer->base_buffer)
+    cache_buffer = cache_buffer->base_buffer;
+  width_cache = width_run_cache_on_off ();
   if (dp == buffer_display_table ())
     width_table = (VECTORP (BVAR (current_buffer, width_table))
                    ? XVECTOR (BVAR (current_buffer, width_table))->contents
   if (dp == buffer_display_table ())
     width_table = (VECTORP (BVAR (current_buffer, width_table))
                    ? XVECTOR (BVAR (current_buffer, width_table))->contents
@@ -1158,7 +1171,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
   /* Negative width means use all available text columns.  */
   if (width < 0)
     {
   /* Negative width means use all available text columns.  */
   if (width < 0)
     {
-      width = window_body_cols (win);
+      width = window_body_width (win, 0);
       /* We must make room for continuation marks if we don't have fringes.  */
 #ifdef HAVE_WINDOW_SYSTEM
       if (!FRAME_WINDOW_P (XFRAME (win->frame)))
       /* We must make room for continuation marks if we don't have fringes.  */
 #ifdef HAVE_WINDOW_SYSTEM
       if (!FRAME_WINDOW_P (XFRAME (win->frame)))
@@ -1416,13 +1429,11 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
 
       /* Consult the width run cache to see if we can avoid inspecting
          the text character-by-character.  */
 
       /* Consult the width run cache to see if we can avoid inspecting
          the text character-by-character.  */
-      if (current_buffer->width_run_cache && pos >= next_width_run)
+      if (width_cache && pos >= next_width_run)
         {
           ptrdiff_t run_end;
           int common_width
         {
           ptrdiff_t run_end;
           int common_width
-            = region_cache_forward (current_buffer,
-                                    current_buffer->width_run_cache,
-                                    pos, &run_end);
+            = region_cache_forward (cache_buffer, width_cache, pos, &run_end);
 
           /* A width of zero means the character's width varies (like
              a tab), is meaningless (like a newline), or we just don't
 
           /* A width of zero means the character's width varies (like
              a tab), is meaningless (like a newline), or we just don't
@@ -1498,7 +1509,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
          pos++, pos_byte++;
 
          /* Perhaps add some info to the width_run_cache.  */
          pos++, pos_byte++;
 
          /* Perhaps add some info to the width_run_cache.  */
-         if (current_buffer->width_run_cache)
+         if (width_cache)
            {
              /* Is this character part of the current run?  If so, extend
                 the run.  */
            {
              /* Is this character part of the current run?  If so, extend
                 the run.  */
@@ -1514,8 +1525,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
                     (Currently, we only cache runs of width == 1).  */
                  if (width_run_start < width_run_end
                      && width_run_width == 1)
                     (Currently, we only cache runs of width == 1).  */
                  if (width_run_start < width_run_end
                      && width_run_width == 1)
-                   know_region_cache (current_buffer,
-                                      current_buffer->width_run_cache,
+                   know_region_cache (cache_buffer, width_cache,
                                       width_run_start, width_run_end);
 
                  /* Start recording a new width run.  */
                                       width_run_start, width_run_end);
 
                  /* Start recording a new width run.  */
@@ -1651,10 +1661,10 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
  after_loop:
 
   /* Remember any final width run in the cache.  */
  after_loop:
 
   /* Remember any final width run in the cache.  */
-  if (current_buffer->width_run_cache
+  if (width_cache
       && width_run_width == 1
       && width_run_start < width_run_end)
       && width_run_width == 1
       && width_run_start < width_run_end)
-    know_region_cache (current_buffer, current_buffer->width_run_cache,
+    know_region_cache (cache_buffer, width_cache,
                        width_run_start, width_run_end);
 
   val_compute_motion.bufpos = pos;
                        width_run_start, width_run_end);
 
   val_compute_motion.bufpos = pos;
@@ -1768,7 +1778,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS.  */)
                         ? window_internal_height (w)
                         : XINT (XCDR (topos))),
                        (NILP (topos)
                         ? window_internal_height (w)
                         : XINT (XCDR (topos))),
                        (NILP (topos)
-                        ? (window_body_cols (w)
+                        ? (window_body_width (w, 0)
                            - (
 #ifdef HAVE_WINDOW_SYSTEM
                               FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
                            - (
 #ifdef HAVE_WINDOW_SYSTEM
                               FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
@@ -1934,9 +1944,12 @@ 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.
 
 parameters such as width, horizontal scrolling, and so on.
 The default is to use the selected window's parameters.
 
-LINES can optionally take the form (COLS . LINES), in which case
-the motion will not stop at the start of a screen line but on
-its column COLS (if such exists on that line, that is).
+LINES can optionally take the form (COLS . LINES), in which case the
+motion will not stop at the start of a screen line but COLS column
+from the visual start of the line (if such exists on that line, that
+is).  If the line is scrolled horizontally, COLS is interpreted
+visually, i.e., as addition to the columns of text beyond the left
+edge of the window.
 
 `vertical-motion' always uses the current buffer,
 regardless of which buffer is displayed in WINDOW.
 
 `vertical-motion' always uses the current buffer,
 regardless of which buffer is displayed in WINDOW.
@@ -2041,8 +2054,15 @@ whether or not it is currently displayed in some window.  */)
           string, move_it_to will overshoot it, while vertical-motion
           wants to put the cursor _before_ the display string.  So in
           that case, we move to buffer position before the display
           string, move_it_to will overshoot it, while vertical-motion
           wants to put the cursor _before_ the display string.  So in
           that case, we move to buffer position before the display
-          string, and avoid overshooting.  */
-       move_it_to (&it, disp_string_at_start_p ? PT - 1 : PT,
+          string, and avoid overshooting.  But if the position before
+          the display string is a newline, we don't do this, because
+          otherwise we will end up in a screen line that is one too
+          far back.  */
+       move_it_to (&it,
+                   (!disp_string_at_start_p
+                    || FETCH_BYTE (IT_BYTEPOS (it)) == '\n')
+                   ? PT
+                   : PT - 1,
                    -1, -1, -1, MOVE_TO_POS);
 
       /* IT may move too far if truncate-lines is on and PT lies
                    -1, -1, -1, MOVE_TO_POS);
 
       /* IT may move too far if truncate-lines is on and PT lies
@@ -2109,20 +2129,14 @@ whether or not it is currently displayed in some window.  */)
            }
        }
 
            }
        }
 
-      /* Move to the goal column, if one was specified.  */
+      /* Move to the goal column, if one was specified.  If the window
+        was originally hscrolled, the goal column is interpreted as
+        an addition to the hscroll amount.  */
       if (!NILP (lcols))
        {
       if (!NILP (lcols))
        {
-         /* If the window was originally hscrolled, move forward by
-            the hscrolled amount first.  */
-         if (first_x > 0)
-           {
-             move_it_in_display_line (&it, ZV, first_x, MOVE_TO_X);
-             it.current_x = 0;
-           }
-         move_it_in_display_line
-           (&it, ZV,
-            (int)(cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5),
-            MOVE_TO_X);
+         int to_x = (int)(cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5);
+
+         move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X);
        }
 
       SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
 
       SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
@@ -2136,7 +2150,7 @@ whether or not it is currently displayed in some window.  */)
                       old_charpos, old_bytepos);
     }
 
                       old_charpos, old_bytepos);
     }
 
-  RETURN_UNGCPRO (make_number (it.vpos));
+  return make_number (it.vpos);
 }
 
 
 }
 
 
@@ -2146,14 +2160,9 @@ whether or not it is currently displayed in some window.  */)
 void
 syms_of_indent (void)
 {
 void
 syms_of_indent (void)
 {
+#include "indent.x"
+
   DEFVAR_BOOL ("indent-tabs-mode", indent_tabs_mode,
               doc: /* Indentation can insert tabs if this is non-nil.  */);
   indent_tabs_mode = 1;
   DEFVAR_BOOL ("indent-tabs-mode", indent_tabs_mode,
               doc: /* Indentation can insert tabs if this is non-nil.  */);
   indent_tabs_mode = 1;
-
-  defsubr (&Scurrent_indentation);
-  defsubr (&Sindent_to);
-  defsubr (&Scurrent_column);
-  defsubr (&Smove_to_column);
-  defsubr (&Svertical_motion);
-  defsubr (&Scompute_motion);
 }
 }