From xemacs-m  Sun Jun 22 16:31:36 1997
Received: from jagor.srce.hr (hniksic@jagor.srce.hr [161.53.2.130])
	by xemacs.org (8.8.5/8.8.5) with ESMTP id QAA19153
	for <xemacs-beta@xemacs.org>; Sun, 22 Jun 1997 16:31:32 -0500 (CDT)
Received: (from hniksic@localhost)
          by jagor.srce.hr (8.8.5/8.8.4)
	  id XAA26840; Sun, 22 Jun 1997 23:31:32 +0200 (MET DST)
To: XEmacs Developers <xemacs-beta@xemacs.org>
Subject: [PATCH] Info-next-reference fix
X-Attribution: Hrv
X-Face: Mie8:rOV<\c/~z{s.X4A{!?vY7{drJ([U]0O=W/<W*SMo/Mv:58:*_y~ki>xDi&N7XG
        KV^$k0m3Oe/)'e%3=$PCR&3ITUXH,cK>]bci&<qQ>Ff%x_>1`T(+M2Gg/fgndU%k*ft
        [(7._6e0n-V%|%'[c|q:;}td$#INd+;?!-V=c8Pqf}3J
From: Hrvoje Niksic <hniksic@srce.hr>
Date: 22 Jun 1997 23:31:32 +0200
Message-ID: <kign2oiqq8b.fsf@jagor.srce.hr>
Lines: 117
X-Mailer: Gnus v5.4.59/XEmacs 20.3(beta8) - "Copenhagen"

Has anyone noticed how insanely slow M-TAB is in large info buffers?
Well, the reason for that is the schizo code in `Info-next-reference'
which valiantly attempts to search backwards using `re-search-forward' 
a great number of times.  Extremely fast, as you can imagine.

Note that this function is quite untrivial to implement, if you wish
to do it correctly.  The existence of "* Menu:" false references and
the N argument complexify things visibly.  Still, I think it was worth
coding; the following patch ought to fix it.  M-TAB works as fast as
TAB now.

If you find any problems, please let me know.

1997-06-22  Hrvoje Niksic  <hniksic@srce.hr>

	* packages/info.el (Info-next-reference): Fix up for M-TAB to work 
	correctly.

--- lisp/packages/info.el.orig	Sun Jun 22 22:40:09 1997
+++ lisp/packages/info.el	Sun Jun 22 23:29:30 1997
@@ -292,6 +292,11 @@
 ;;
 ;; Modified Info-search to use with-caps-disable-folding
 
+;; Modified 6/21/97 by Hrvoje Niksic
+;;
+;; Fixed up Info-next-reference to work sanely when n < 0.
+;; Added S-tab binding.
+
 ;; Code:
 
 (defgroup info nil
@@ -1218,27 +1223,46 @@
   (let ((pat (format "\\*%s[ \n\t]*\\([^:]*\\):\\|^\\* .*:\\|<<.*>>"
 		     Info-footnote-tag))
 	(case-fold-search nil)
-	(old-pt (point)))
+	(old-pt (point))
+	wrapped found-nomenu)
     (while (< n 0)
-      (save-excursion
-	(goto-char (point-min))
-	(while (re-search-forward pat nil t)
-	  (setq n (1+ n)))
-	(goto-char (point-min))
-	(if (re-search-forward "^\\* Menu:" nil t)
-	    (setq n (1- n)))))
-    (while (>= (setq n (1- n)) 0)
+      (unless (re-search-backward pat nil t)
+	;; Don't wrap more than once in a buffer where only the
+	;; menu references are found.
+	(when (and wrapped (not found-nomenu))
+	  (goto-char old-pt)
+	  (error "No cross references in this node"))
+	(setq wrapped t)
+	(goto-char (point-max))
+	(unless (re-search-backward pat nil t)
+	  (goto-char old-pt)
+	  (error "No cross references in this node")))
+      (unless (save-excursion
+		(goto-char (match-beginning 0))
+		(when (looking-at "\\* Menu:")
+		  (decf n)))
+	(setq found-nomenu t))
+      (incf n))
+    (while (> n 0)
       (or (eobp) (forward-char 1))
-      (or (re-search-forward pat nil t)
-	  (progn
-	    (goto-char (point-min))
-	    (or (re-search-forward pat nil t)
-		(progn
-		  (goto-char old-pt)
-		  (error "No cross references in this node")))))
-      (goto-char (match-beginning 0))
-      (if (looking-at "\\* Menu:")
-	  (setq n (1+ n))))))
+      (unless (re-search-forward pat nil t)
+	(when (and wrapped (not found-nomenu))
+	  (goto-char old-pt)
+	  (error "No cross references in this node"))
+	(setq wrapped t)
+	(goto-char (point-min))
+	(unless (re-search-forward pat nil t)
+	  (goto-char old-pt)
+	  (error "No cross references in this node")))
+      (unless (save-excursion
+		(goto-char (match-beginning 0))
+		(when (looking-at "\\* Menu:")
+		  (incf n)))
+	(setq found-nomenu t))
+      (decf n))
+    (when (looking-at "\\* Menu:")
+      (error "No cross references in this node"))
+    (goto-char (match-beginning 0))))
 
 (defun Info-prev-reference (n)
   (interactive "p")
@@ -2074,8 +2098,9 @@
   (define-key Info-mode-map "@" 'Info-follow-nearest-node)
   (define-key Info-mode-map "," 'Info-index-next)
   (define-key Info-mode-map "*" 'Info-elisp-ref)
-  (define-key Info-mode-map "\t" 'Info-next-reference)
-  (define-key Info-mode-map "\e\t" 'Info-prev-reference)
+  (define-key Info-mode-map [tab] 'Info-next-reference)
+  (define-key Info-mode-map [(meta tab)] 'Info-prev-reference)
+  (define-key Info-mode-map [(shift tab)] 'Info-prev-reference)
   (define-key Info-mode-map "\r" 'Info-follow-nearest-node)
   ;; XEmacs addition
   (define-key Info-mode-map 'backspace 'Info-scroll-prev)


-- 
Hrvoje Niksic <hniksic@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------
* Vi is the God of editors.
* Emacs is the editor of Gods.

