diff src/indent.c @ 272:c5d627a313b1 r21-0b34

Import from CVS: tag r21-0b34
author cvs
date Mon, 13 Aug 2007 10:28:48 +0200
parents 3d6bfa290dbd
children 6330739388db
line wrap: on
line diff
--- a/src/indent.c	Mon Aug 13 10:27:41 2007 +0200
+++ b/src/indent.c	Mon Aug 13 10:28:48 2007 +0200
@@ -529,16 +529,39 @@
 
 #endif /* 0 */
 
+/* Helper for vmotion_1 - compute vertical pixel motion between
+   START and END in the line start cache CACHE.  This just sums
+   the line heights, including both the starting and ending lines.
+*/
+static int
+vpix_motion (line_start_cache_dynarr *cache, int start, int end)
+{
+  int i, vpix;
+
+  assert (start <= end);
+  assert (start >= 0);
+  assert (end < Dynarr_length (cache));
+  
+  vpix = 0;
+  for (i = start; i <= end; i++)
+    vpix += Dynarr_atp (cache, i)->height;
+
+  return vpix;
+}
+
 /*****************************************************************************
- vmotion
+ vmotion_1
 
  Given a starting position ORIG, move point VTARGET lines in WINDOW.
  Returns the new value for point.  If the arg ret_vpos is not nil, it is
  taken to be a pointer to an int and the number of lines actually moved is
- returned in it.
+ returned in it.  If the arg ret_vpix is not nil, it is taken to be a
+ pointer to an int and the vertical pixel height of the motion which
+ took place is returned in it.
  ****************************************************************************/
-Bufpos
-vmotion (struct window *w, Bufpos orig, int vtarget, int *ret_vpos)
+static Bufpos
+vmotion_1 (struct window *w, Bufpos orig, int vtarget,
+           int *ret_vpos, int *ret_vpix)
 {
   struct buffer *b = XBUFFER (w->buffer);
   int elt;
@@ -576,6 +599,8 @@
 	}
 
       if (ret_vpos) *ret_vpos = cur_line;
+      if (ret_vpix)
+        *ret_vpix = vpix_motion (w->line_start_cache, elt, cur_line + elt);
       return ret_pt;
     }
   else if (vtarget < 0)
@@ -583,12 +608,16 @@
       if (elt < -vtarget)
 	{
 	  if (ret_vpos) *ret_vpos = -elt;
+          if (ret_vpix)
+            *ret_vpix = vpix_motion (w->line_start_cache, 0, elt);
 	  /* #### This should be BUF_BEGV (b), right? */
 	  return Dynarr_atp (w->line_start_cache, 0)->start;
 	}
       else
 	{
 	  if (ret_vpos) *ret_vpos = vtarget;
+          if (ret_vpix)
+            *ret_vpix = vpix_motion (w->line_start_cache, elt + vtarget, elt);
 	  return Dynarr_atp (w->line_start_cache, elt + vtarget)->start;
 	}
     }
@@ -597,6 +626,8 @@
       /* No vertical motion requested so we just return the position
          of the beginning of the current line. */
       if (ret_vpos) *ret_vpos = 0;
+      if (ret_vpix)
+        *ret_vpix = vpix_motion (w->line_start_cache, elt, elt);
 
       return Dynarr_atp (w->line_start_cache, elt)->start;
     }
@@ -604,6 +635,20 @@
   RETURN_NOT_REACHED(0)	/* shut up compiler */
 }
 
+/*****************************************************************************
+ vmotion
+
+ Given a starting position ORIG, move point VTARGET lines in WINDOW.
+ Returns the new value for point.  If the arg ret_vpos is not nil, it is
+ taken to be a pointer to an int and the number of lines actually moved is
+ returned in it.
+ ****************************************************************************/
+Bufpos
+vmotion (struct window *w, Bufpos orig, int vtarget, int *ret_vpos)
+{
+  return vmotion_1 (w, orig, vtarget, ret_vpos, NULL);
+}
+
 DEFUN ("vertical-motion", Fvertical_motion, 1, 2, 0, /*
 Move to start of frame line LINES lines down.
 If LINES is negative, this is moving up.
@@ -643,6 +688,43 @@
   }
 }
 
+DEFUN ("vertical-motion-pixels", Fvertical_motion_pixels, 1, 2, 0, /*
+Move to start of frame line LINES lines down.
+If LINES is negative, this is moving up.
+
+This function is identical in behavior to `vertical-motion'
+except that the vertical pixel height of the motion which
+took place is returned instead of the actual number of lines
+moved.  A motion of zero lines returns the height of the
+current line.
+
+The optional second argument WINDOW specifies the window to use 
+for parameters such as width, horizontal scrolling, and so on.  
+The default is the selected window.  Note that this function
+sets WINDOW's buffer's point, not WINDOW's point.
+*/
+       (lines, window))
+{
+  if (NILP (window))
+    window = Fselected_window (Qnil);
+  CHECK_WINDOW (window);
+  {
+    Bufpos bufpos;
+    int vpix;
+    struct window *w  = XWINDOW (window);
+
+    CHECK_INT (lines);
+
+    bufpos = vmotion_1 (XWINDOW (window), BUF_PT (XBUFFER (w->buffer)),
+		      XINT (lines), NULL, &vpix);
+
+    /* Note that the buffer's point is set, not the window's point. */
+    BUF_SET_PT (XBUFFER (w->buffer), bufpos);
+
+    return make_int (vpix);
+  }
+}
+
 
 void
 syms_of_indent (void)
@@ -655,6 +737,7 @@
   DEFSUBR (Fcompute_motion);
 #endif
   DEFSUBR (Fvertical_motion);
+  DEFSUBR (Fvertical_motion_pixels);
 }
 
 void