[gnu.emacs] Improvement to line counting functions

worley@EDDIE.MIT.EDU (Dale Worley) (10/26/89)

The line-counting operations (goto-line and count-lines) don't work
correctly when selective-display is on, because they don't count ^M's
as end-of-line characters.  I've modified them to handle this
correctly.  In order to do this, I made a lisp-callable interface to
the search_buffer routine, called "search-buffer".  This routine gives
you the fullest power of Emacs' internal search routines.

Unfortunately, I haven't had time to fully test these routines, but
they're simple enough that there shouldn't be much trouble with them.

*** search.c.orig.2	Wed Oct 25 11:23:03 1989
--- search.c	Wed Oct 25 11:56:24 1989
***************
*** 942,947 ****
--- 942,1013 ----
    return search_command (string, bound, noerror, count, 1, 1);
  }
  
+ DEFUN ("search-buffer", Fsearch_buffer, Ssearch_buffer, 1, 5, 0,
+   "Arguments are STRING, POS, BOUND, N, RE.\n\
+ Search for the Nth occurrence of STRING in the current buffer,\n\
+ starting at position POS and stopping at position BOUND, treating\n\
+ STRING as a literal string if RE is false or as a regular expression\n\
+ if RE is true.\n\
+ If N is positive, searching is forward and BOUND must be greater than FROM.\n\
+ If N is negative, searching is backward and BOUND must be less than FROM.\n\
+ POS defaults to the point, BOUND defaults to the beginning/end of the buffer,\n\
+ N defaults to 1, and RE defaults to false.\n\
+ \n\
+ Returns -x if only N-x occurrences found (x > 0), or else the position\n\
+ at the beginning of the Nth occurrence (if searching backward) or the\n\
+ end (if searching forward).\n\
+ Does not move the point.")
+   (string, pos, bound, n, re)
+      Lisp_Object string, pos, bound, n, re;
+ {
+   int p, nn, lim, r;
+ 
+   /* string */
+   CHECK_STRING (string, 0);
+ 
+   /* pos defaults to point */
+   if (NULL (pos))
+     p = point;
+   else
+     {
+       CHECK_NUMBER_COERCE_MARKER (pos, 1);
+       p = XINT (pos);
+     }
+ 
+   /* n defaults to 1 */
+   if (NULL (n))
+     nn = 1;
+   else
+     {
+       CHECK_NUMBER (n, 3);
+       nn = XINT (n);
+     }
+ 
+   /* bound defaults to end of buffer */
+   if (NULL (bound))
+     lim = nn > 0 ? NumCharacters + 1 : FirstCharacter;
+   else
+     {
+       CHECK_NUMBER_COERCE_MARKER (bound, 2);
+       lim = XINT (bound);
+       if (nn > 0 ? lim < point : lim > point)
+ 	error ("Invalid search bound (wrong side of point)");
+       if (lim > NumCharacters + 1)
+ 	lim = NumCharacters + 1;
+       if (lim < FirstCharacter)
+ 	lim = FirstCharacter;
+     }
+   
+   /* re defaults to false */
+   r = !NULL (re);  
+ 
+   /* call search_buffer */
+   return make_number (search_buffer (string, p, lim, nn, r,
+ 		                     !NULL (bf_cur->case_fold_search) ? 
+ 				     downcase_table :
+ 				     0));
+ }
+ 
  DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 3, 0,
    "Replace text matched by last search with NEWTEXT.\n\
  If second arg FIXEDCASE is non-nil, do not alter case of replacement text.\n\
***************
*** 1291,1296 ****
--- 1357,1363 ----
    defsubr (&Sword_search_backward);
    defsubr (&Sre_search_forward);
    defsubr (&Sre_search_backward);
+   defsubr (&Ssearch_buffer);
    defsubr (&Sreplace_match);
    defsubr (&Smatch_beginning);
    defsubr (&Smatch_end);

*** simple.el.orig	Wed Oct 25 14:14:32 1989
--- simple.el	Wed Oct 25 14:17:33 1989
***************
*** 246,257 ****
  	       (1+ (count-lines 1 (point)))))))
  
  (defun count-lines (start end)
!   "Return number of newlines between START and END."
!   (save-excursion
!     (save-restriction
!       (narrow-to-region start end)
!       (goto-char (point-min))
!       (- (buffer-size) (forward-line (buffer-size))))))
  
  (defun what-cursor-position ()
    "Print info on cursor position (on screen and within buffer)."
--- 246,256 ----
  	       (1+ (count-lines 1 (point)))))))
  
  (defun count-lines (start end)
!   "Return number of newlines between START and END.
! If  selective-display  is non-nil, then ^M's count as newlines also."
!   (+ (point-max)
!      (search-buffer (if selective-display "[\n\C-m]" "\n")
! 		    start end (point-max) selective-display)))
  
  (defun what-cursor-position ()
    "Print info on cursor position (on screen and within buffer)."
***************
*** 354,365 ****
    (next-complex-command (- n)))
  
  (defun goto-line (arg)
!   "Goto line ARG, counting from line 1 at beginning of buffer."
    (interactive "NGoto line: ")
    (save-restriction
      (widen)
      (goto-char 1)
!     (forward-line (1- arg))))
  
  ;Put this on C-x u, so we can force that rather than C-_ into startup msg
  (fset 'advertised-undo 'undo)
--- 353,368 ----
    (next-complex-command (- n)))
  
  (defun goto-line (arg)
!   "Goto line ARG, counting from line 1 at beginning of buffer.
! If  selective-display  is non-nil, then ^M's count as newlines also."
    (interactive "NGoto line: ")
    (save-restriction
      (widen)
      (goto-char 1)
!     (re-search-forward (if selective-display "[\n\C-m]" "\n")
! 		       nil
! 		       'end
! 		       (1- arg))))
  
  ;Put this on C-x u, so we can force that rather than C-_ into startup msg
  (fset 'advertised-undo 'undo)

Dale Worley		Compass, Inc.			worley@compass.com
--
"We'd better wake up and smell the goats or it will be burlap soup for all
of us!"

"Burlap soup?"

"No thanks, I had lunch on the way over."