Commits

Anonymous committed ac39682

Created

Comments (0)

Files changed (11)

+1998-01-12  SL Baur  <steve@altair.xemacs.org>
+
+	* Makefile: Update to newer package interface.
+
+1998-01-03  SL Baur  <steve@altair.xemacs.org>
+
+	* Makefile: Update to newer package interface.
+
+1997-12-14  Hrvoje Niksic  <hniksic@srce.hr>
+
+	* texnfo-upd.el: Synched with FSF 20.2.
+
+	* texinfo.el: Synched with FSF 20.2.
+
+	* texinfo.el (texinfo-mode-syntax-table): `@' is a
+	symbol-constituent, not an escape.
+
+1997-12-30  SL Baur  <steve@altair.xemacs.org>
+
+	* Makefile (ELCS): Add informat.el.
+
+1997-12-24  SL Baur  <steve@altair.xemacs.org>
+
+	* Makefile: Created.
+# Makefile for TeXinfo support lisp code
+
+# This file is part of XEmacs.
+
+# XEmacs 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) any
+# later version.
+
+# XEmacs is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with XEmacs; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+VERSION = 1.04
+PACKAGE = texinfo
+PKG_TYPE = regular
+REQUIRES = xemacs-base
+CATEGORY = wp
+
+ELCS = detexinfo.elc informat.elc makeinfo.elc tex-mode.elc texinfmt.elc \
+	texinfo.elc texnfo-tex.elc texnfo-upd.elc
+
+include ../../XEmacs.rules
+
+all:: $(ELCS) auto-autoloads.elc custom-load.elc
+
+srckit: srckit-std
+	if [ ! -d $(STAGING) ]; then mkdir -p $(STAGING); fi
+	(cd ../..; \
+	rm -rf $(STAGING)/$(PACKAGE)-$(VERSION)-src.tar*; \
+	tar cf $(STAGING)/$(PACKAGE)-$(VERSION)-src.tar wp/$(PACKAGE))
+	gzip -v9 $(STAGING)/$(PACKAGE)-$(VERSION)-src.tar
+
+binkit: binkit-sourceonly
+;;; detexinfo.el --- remove Texinfo commands from a Texinfo source file
+ 
+;; Copyright (C) 1992-1993 Free Software Foundation, Inc.
+
+;; Keywords: tex, docs
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the 
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Synched up with: Not in FSF.
+
+;;; Here is a handy keybinding: 
+
+(global-set-key "\C-x\\" 'detexinfo)
+
+;;;;;;;;;;;;;;;; detexinfo.el ;;;;;;;;;;;;;;;;
+;;;
+;;; Remove Texinfo commands from a Texinfo source file.
+;;;
+;;; Copyright (C) 1991, 1992 Free Software Foundation
+;;; Robert J. Chassell
+;;; bugs to bug-texinfo@prep.ai.mit.edu
+;;;
+;;; ==> test version <==
+;;; Fails if Texinfo source file contains formatting errors.
+;;; 
+;;; Version 0.05 -  3 Jun 1992
+;;; Add to list of removed commands.  Improve messages.
+;;;
+;;; Version 0.04 - 27 Jan 1992
+;;; Rewrite to insert detexinfo'd text into a temporary buffer.
+;;; 
+;;; Version 0.03 - 27 Dec 1991
+;;; Improved messages.
+;;;
+;;; Version 0.02 - 13 Nov 1991
+;;; detexinfo-remove-inline-cmd, detexinfo-syntax-table: Handle 
+;;;          nested commands.  
+;;; detexinfo: Handle nested @'s, eg @samp{@}} and @samp{@@};
+;;;          replace @TeX{} with TeX.
+;;; 
+;;; Version 0.01 - 13 Nov 1991
+;;;
+;;; Based on detex.el, by Bengt Martensson, 4 Oct 1987
+;;;
+;;;;;;;;;;;;;;;;
+
+(defvar detexinfo-buffer-name "*detexinfo*"
+  "*Name of the temporary buffer used by \\[detexinfo].")
+
+(defvar detexinfo-syntax-table nil)
+
+(if detexinfo-syntax-table
+    nil
+  (setq detexinfo-syntax-table (make-syntax-table))
+  (modify-syntax-entry ?\[ "." detexinfo-syntax-table)
+  (modify-syntax-entry ?\] "." detexinfo-syntax-table)
+  (modify-syntax-entry ?\" "." detexinfo-syntax-table)
+  (modify-syntax-entry ?\\ "." detexinfo-syntax-table)
+  (modify-syntax-entry ?\( "." detexinfo-syntax-table)
+  (modify-syntax-entry ?\) "." detexinfo-syntax-table)
+  (modify-syntax-entry ?{ "(}" detexinfo-syntax-table)
+  (modify-syntax-entry ?} "){" detexinfo-syntax-table))
+
+(defun detexinfo ()
+  "Remove Texinfo commands from current buffer, copying result to new buffer.
+BUG: Fails if Texinfo source file contains formatting errors."
+  (interactive)
+  (let ((input-buffer (current-buffer)))
+    ;; Find a buffer to use.
+    (switch-to-buffer (get-buffer-create detexinfo-buffer-name))
+    (setq major-mode 'detexinfo-mode)
+    (set-syntax-table detexinfo-syntax-table)
+    (erase-buffer)
+    (insert-buffer-substring input-buffer)
+    
+    ;; Replace @{ and @} with %#* and *#% temporarily, so @samp{@{} works.
+    ;; What is a better way of doing this??
+    (goto-char (point-min))
+    (while (search-forward "@{" nil t)  ; e.g., @samp{@{}
+      (replace-match "%#*"))
+    (goto-char (point-min))
+    (while (search-forward "@}" nil t)
+      (forward-char -3)                 ; e.g.,  @samp{@@}
+      (if (looking-at "@")              ; Two @@ in a row
+          (progn
+            (delete-char 2)
+            (insert "%&%#"))
+        (forward-char 1)
+        (delete-char 2)
+        (insert "*#%")))
+    
+    (goto-char (point-min))
+    ;; Remove @refill, the only inline command without braces.
+    (while (search-forward "@refill" nil t)
+      (replace-match ""))
+    ;; Replace @TeX{} with TeX
+    (goto-char (point-min))
+    (while (search-forward "@TeX{}" nil t) (replace-match "TeX" t t))
+    
+    (detexinfo-remove-line-cmds-without-arg)
+    (detexinfo-remove-inline-cmds-without-arg)
+    (detexinfo-remove-inline-cmds-keep-arg)
+    (detexinfo-remove-line-cmds-deletable-arg)
+    (detexinfo-remove-line-cmds-maybe-delete-arg)
+    (detexinfo-remove-line-cmds-keep-arg)
+    
+    ;; Now replace %#*, *#%, and %&%#  with {,  }, and @@.
+    (goto-char (point-min))
+    (while (search-forward "%#*" nil t)
+      (replace-match "{"))
+    (goto-char (point-min))
+    (while (search-forward "*#%" nil t)
+      (replace-match "}"))
+    (goto-char (point-min))
+    (while (search-forward "%&%#" nil t)
+      (replace-match "@@"))
+    
+    ;; Scan for remaining two character @-commands
+    (goto-char (point-min))
+    (while (search-forward "@" nil t)
+      (cond ((looking-at "[*:]")
+             (delete-region (1- (point)) (1+ (point))))
+            ((looking-at "[{}^@.'`]\"?!")
+             (delete-region (1- (point)) (point)))))
+    
+    (goto-char (point-min))
+    (message "Done...removed Texinfo commands from buffer. You may save it.")))
+
+(defun detexinfo-remove-whole-line (cmd)
+  "Delete Texinfo line command CMD at beginning of line and rest of line."
+  (goto-char (point-min))
+  (while
+      (re-search-forward
+       (concat "^@" cmd "[ \n]+") (point-max) t)
+    (goto-char (match-beginning 0))
+    (delete-region
+     (point) (save-excursion (end-of-line) (1+ (point))))))
+
+(defun detexinfo-remove-inline-cmd (cmd)
+  "Delete Texinfo inline command CMD, eg. @point, @code."
+  (goto-char (point-min))
+  (while
+      (re-search-forward (concat "@" cmd "{") (point-max) t)
+    (save-excursion
+      (forward-char -1)
+      (forward-sexp 1)
+      (delete-char -1))                 ; delete right brace
+    (delete-region (point) (match-beginning 0)))) 
+
+;;;;;;;;;;;;;;;; 
+
+;;; 1. @setfilename and other line commands with args to delete
+
+(defvar detexinfo-line-cmds-deletable-arg
+  '("enumerate" "ftable" "vtable" "itemize" "table"
+    "setfilename" "settitle" "setchapternewpage" 
+    "footnotestyle" "paragraphindent"
+    "include" "need" "sp" 
+    "clear" "ifclear" "ifset"  "set"
+    "defcodeindex" "defindex" "syncodeindex" "synindex")
+  "List of Texinfo commands whose arguments should be deleted.")
+
+(defun detexinfo-remove-line-cmds-deletable-arg ()
+  "Delete Texinfo line commands together with their args, eg @setfilename."
+  (message "Removing commands such as @enumerate...with their arguments...")
+  (mapcar 'detexinfo-remove-whole-line
+          detexinfo-line-cmds-deletable-arg))
+
+;;; 2. @cindex and other cmds with args that may be deleted
+;;;    This list is here just to make it easier to revise the
+;;;    categories.  In particular, you might want to keep the index entries.
+
+(defvar detexinfo-line-cmds-maybe-delete-arg
+   '("cindex" "findex" "kindex" "pindex" "tindex" "vindex" "node"
+     "c" "comment" "end" "headings"  "printindex" "vskip" 
+     "evenfooting"  "evenheading" "everyfooting" "everyheading" 
+     "oddfooting" "oddheading")
+  "List of Texinfo commands whose arguments may possibly be deleted.")
+
+(defun detexinfo-remove-line-cmds-maybe-delete-arg ()
+  "Delete Texinfo line commands together with their arguments, eg, @cindex."
+  (message "Removing commands such as @cindex...with their arguments...")
+  (mapcar 'detexinfo-remove-whole-line
+          detexinfo-line-cmds-maybe-delete-arg))
+
+;;; 3. @chapter and other line cmds with args to keep.
+
+(defvar detexinfo-line-cmds-keep-arg
+   '("top" "chapter" "section" "subsection" "subsubsection" 
+     "unnumbered" "unnumberedsec" "unnumberedsubsec" "unnumberedsubsubsec" 
+     "majorheading" "chapheading" "heading" "subheading" "subsubheading" 
+      "appendix" "appendixsec" "appendixsubsec" "appendixsubsubsec" 
+     "item" "itemx"
+     "title" "subtitle" "center" "author" "exdent"  
+     "defcv" "deffn" "defivar" "defmac" "defmethod" "defop" "defopt" 
+     "defspec" "deftp" "deftypefn" "deftypefun" "deftypvr"
+     "deftypevar" "defun" "defvar" "defvr")
+  "List of Texinfo line commands whose arguments should be kept.")
+
+(defun detexinfo-remove-line-cmds-keep-arg ()
+  "Delete Texinfo line commands but keep their arguments, eg @chapter."
+  (message "Removing commands such as @chapter...but not their arguments...")
+  (mapcar 'detexinfo-remove-line-cmd-keep-arg
+          detexinfo-line-cmds-keep-arg))
+
+(defun detexinfo-remove-line-cmd-keep-arg (cmd)
+  "Delete Texinfo line command CMD but keep its argument, eg @chapter."
+  (goto-char (point-min))
+  (while
+      (re-search-forward
+       (concat "^@" cmd "[ \n]+") (point-max) t)
+    (delete-region (match-beginning 0) (match-end 0))))
+
+;;; 4. @bye and other line commands without args.
+
+(defvar detexinfo-line-cmds-without-arg
+  '("bye" "contents" "display" "example" "finalout" 
+    "flushleft" "flushright" "format" "group" "ifhtml" "ifinfo" "iftex" 
+    "ignore" "lisp" "menu" "noindent" "page" "quotation"  
+    "shortcontents" "smallbook" "smallexample" "smalllisp" 
+    "summarycontents" "tex" "thischapter" "thischaptername" 
+    "thisfile" "thispage" "thissection" "thistitle" "titlepage")
+  "List of Texinfo commands without arguments that should be deleted.")
+
+(defun detexinfo-remove-line-cmds-without-arg ()
+  "Delete line Texinfo commands that lack args, eg. @example."
+  (message "Removing commands such as @example...that lack arguments...")
+  (mapcar 'detexinfo-remove-whole-line
+          detexinfo-line-cmds-without-arg))
+
+;;; 5. @equiv and other inline cmds without args.
+
+(defvar detexinfo-inline-cmds-without-arg
+  '("equiv" "error" "expansion" "point" "print" "result"
+    "asis"  "br" "bullet" "dots" "minus" "today")
+  "List of Texinfo inline commands without arguments that should be deleted.")
+
+(defun detexinfo-remove-inline-cmds-without-arg ()
+  "Delete Texinfo inline commands in that lack arguments."
+  (message "Removing within line commands such as @result...")
+  (mapcar 'detexinfo-remove-inline-cmd
+          detexinfo-inline-cmds-without-arg))
+
+;;; 6. @code and other inline cmds with args to keep
+
+(defvar detexinfo-inline-cmds-keep-arg
+  '("b" "cartouche" "cite" "code" "copyright" "ctrl" "dfn" "dmn"
+    "emph" "file" "footnote" "i" "inforef"
+    "kbd" "key" "pxref" "r" "ref" "samp" "sc" "titlefont" 
+    "strong" "t" "var" "w" "xref")
+  "List of Texinfo inline commands with arguments that should be kept.")
+
+(defun detexinfo-remove-inline-cmds-keep-arg ()
+  "Delete Texinfo inline commands but keep its arg, eg. @code."
+  (message
+   "Removing within line commands such as @code...but not their arguments...")
+  (mapcar 'detexinfo-remove-inline-cmd
+          detexinfo-inline-cmds-keep-arg))
+
+;;;;;;;;;;;;;;;; end detexinfo.el ;;;;;;;;;;;;;;;;
+;;; informat.el --- info support functions package for Emacs
+
+;; Copyright (C) 1986 Free Software Foundation, Inc.
+
+;; Maintainer: FSF
+;; Keywords: help
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+;; 02111-1307, USA.
+
+;;; Synched up with: FSF 19.34.
+
+;;; Code:
+
+(require 'info)
+
+;;;###autoload
+(defun Info-tagify ()
+  "Create or update Info-file tag table in current buffer."
+  (interactive)
+  ;; Save and restore point and restrictions.
+  ;; save-restrictions would not work
+  ;; because it records the old max relative to the end.
+  ;; We record it relative to the beginning.
+  (message "Tagifying %s ..." (file-name-nondirectory (buffer-file-name)))
+  (let ((omin (point-min))
+	(omax (point-max))
+	(nomax (= (point-max) (1+ (buffer-size))))
+	(opoint (point)))
+    (unwind-protect
+	(progn
+	  (widen)
+	  (goto-char (point-min))
+	  (if (search-forward "\^_\nIndirect:\n" nil t)
+	      (message "Cannot tagify split info file")
+	    (let ((regexp "Node:[ \t]*\\([^,\n\t]*\\)[,\t\n]")
+		  (case-fold-search t)
+		  list)
+	      (while (search-forward "\n\^_" nil t)
+		;; We want the 0-origin character position of the ^_.
+		;; That is the same as the Emacs (1-origin) position
+		;; of the newline before it.
+		(let ((beg (match-beginning 0)))
+		  (forward-line 2)
+		  (if (re-search-backward regexp beg t)
+		      (setq list
+			    (cons (list (buffer-substring-no-properties
+					  (match-beginning 1)
+					  (match-end 1))
+					beg)
+				  list)))))
+	      (goto-char (point-max))
+	      (forward-line -8)
+	      (let ((buffer-read-only nil))
+		(if (search-forward "\^_\nEnd tag table\n" nil t)
+		    (let ((end (point)))
+		      (search-backward "\nTag table:\n")
+		      (beginning-of-line)
+		      (delete-region (point) end)))
+		(goto-char (point-max))
+		(insert "\^_\f\nTag table:\n")
+		(move-marker Info-tag-table-marker (point))
+		(setq list (nreverse list))
+		(while list
+		  (insert "Node: " (car (car list)) ?\177)
+		  (princ (car (cdr (car list))) (current-buffer))
+		  (insert ?\n)
+		  (setq list (cdr list)))
+		(insert "\^_\nEnd tag table\n")))))
+      (goto-char opoint)
+      (narrow-to-region omin (if nomax (1+ (buffer-size))
+			       (min omax (point-max))))))
+  (message "Tagifying %s ... done" (file-name-nondirectory (buffer-file-name))))
+
+;;;###autoload
+(defun Info-split ()
+  "Split an info file into an indirect file plus bounded-size subfiles.
+Each subfile will be up to 50,000 characters plus one node.
+
+To use this command, first visit a large Info file that has a tag
+table.  The buffer is modified into a (small) indirect info file which
+should be saved in place of the original visited file.
+
+The subfiles are written in the same directory the original file is
+in, with names generated by appending `-' and a number to the original
+file name.  The indirect file still functions as an Info file, but it
+contains just the tag table and a directory of subfiles."
+
+  (interactive)
+  (if (< (buffer-size) 70000)
+      (error "This is too small to be worth splitting"))
+  (goto-char (point-min))
+  (search-forward "\^_")
+  (forward-char -1)
+  (let ((start (point))
+	(chars-deleted 0)
+	subfiles
+	(subfile-number 1)
+	(case-fold-search t)
+	(filename (file-name-sans-versions buffer-file-name)))
+    (goto-char (point-max))
+    (forward-line -8)
+    (setq buffer-read-only nil)
+    (or (search-forward "\^_\nEnd tag table\n" nil t)
+	(error "Tag table required; use M-x Info-tagify"))
+    (search-backward "\nTag table:\n")
+    (if (looking-at "\nTag table:\n\^_")
+	(error "Tag table is just a skeleton; use M-x Info-tagify"))
+    (beginning-of-line)
+    (forward-char 1)
+    (save-restriction
+      (narrow-to-region (point-min) (point))
+      (goto-char (point-min))
+      (while (< (1+ (point)) (point-max))
+	(goto-char (min (+ (point) 50000) (point-max)))
+	(search-forward "\^_" nil 'move)
+	(setq subfiles
+	      (cons (list (+ start chars-deleted)
+			  (concat (file-name-nondirectory filename)
+				  (format "-%d" subfile-number)))
+		    subfiles))
+	;; Put a newline at end of split file, to make Unix happier.
+	(insert "\n")
+	(write-region (point-min) (point)
+		      (concat filename (format "-%d" subfile-number)))
+	(delete-region (1- (point)) (point))
+	;; Back up over the final ^_.
+	(forward-char -1)
+	(setq chars-deleted (+ chars-deleted (- (point) start)))
+	(delete-region start (point))
+	(setq subfile-number (1+ subfile-number))))
+    (while subfiles
+      (goto-char start)
+      (insert (nth 1 (car subfiles))
+	      (format ": %d" (1- (car (car subfiles))))
+	      "\n")
+      (setq subfiles (cdr subfiles)))
+    (goto-char start)
+    (insert "\^_\nIndirect:\n")
+    (search-forward "\nTag Table:\n")
+    (insert "(Indirect)\n")))
+
+;;;###autoload
+(defun Info-validate ()
+  "Check current buffer for validity as an Info file.
+Check that every node pointer points to an existing node."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (widen)
+      (goto-char (point-min))
+      (if (search-forward "\nTag table:\n(Indirect)\n" nil t)
+	  (error "Don't yet know how to validate indirect info files: \"%s\""
+		 (buffer-name (current-buffer))))
+      (goto-char (point-min))
+      (let ((allnodes '(("*")))
+	    (regexp "Node:[ \t]*\\([^,\n\t]*\\)[,\t\n]")
+	    (case-fold-search t)
+	    (tags-losing nil)
+	    (lossages ()))
+	(while (search-forward "\n\^_" nil t)
+	  (forward-line 1)
+	  (let ((beg (point)))
+	    (forward-line 1)
+	    (if (re-search-backward regexp beg t)
+		(let ((name (downcase
+			      (buffer-substring-no-properties
+			        (match-beginning 1)
+				(progn
+				  (goto-char (match-end 1))
+				  (skip-chars-backward " \t")
+				  (point))))))
+		  (if (assoc name allnodes)
+		      (setq lossages
+			    (cons (list name "Duplicate node-name" nil)
+				  lossages))
+		      (setq allnodes
+			    (cons (list name
+					(progn
+					  (end-of-line)
+					  (and (re-search-backward
+						"prev[ious]*:" beg t)
+					       (progn
+						 (goto-char (match-end 0))
+						 (downcase
+						   (Info-following-node-name)))))
+					beg)
+				  allnodes)))))))
+	(goto-char (point-min))
+	(while (search-forward "\n\^_" nil t)
+	  (forward-line 1)
+	  (let ((beg (point))
+		thisnode next)
+	    (forward-line 1)
+	    (if (re-search-backward regexp beg t)
+		(save-restriction
+		  (search-forward "\n\^_" nil 'move)
+		  (narrow-to-region beg (point))
+		  (setq thisnode (downcase
+				   (buffer-substring-no-properties
+				     (match-beginning 1)
+				     (progn
+				       (goto-char (match-end 1))
+				       (skip-chars-backward " \t")
+				       (point)))))
+		  (end-of-line)
+		  (and (search-backward "next:" nil t)
+		       (setq next (Info-validate-node-name "invalid Next"))
+		       (assoc next allnodes)
+		       (if (equal (car (cdr (assoc next allnodes)))
+				  thisnode)
+			   ;; allow multiple `next' pointers to one node
+			   (let ((tem lossages))
+			     (while tem
+			       (if (and (equal (car (cdr (car tem)))
+					       "should have Previous")
+					(equal (car (car tem))
+					       next))
+				   (setq lossages (delq (car tem) lossages)))
+			       (setq tem (cdr tem))))
+			 (setq lossages
+			       (cons (list next
+					   "should have Previous"
+					   thisnode)
+				     lossages))))
+		  (end-of-line)
+		  (if (re-search-backward "prev[ious]*:" nil t)
+		      (Info-validate-node-name "invalid Previous"))
+		  (end-of-line)
+		  (if (search-backward "up:" nil t)
+		      (Info-validate-node-name "invalid Up"))
+		  (if (re-search-forward "\n* Menu:" nil t)
+		      (while (re-search-forward "\n\\* " nil t)
+			(Info-validate-node-name
+			  (concat "invalid menu item "
+				  (buffer-substring (point)
+						    (save-excursion
+						      (skip-chars-forward "^:")
+						      (point))))
+			  (Info-extract-menu-node-name))))
+		  (goto-char (point-min))
+		  (while (re-search-forward "\\*note[ \n]*[^:\t]*:" nil t)
+		    (goto-char (+ (match-beginning 0) 5))
+		    (skip-chars-forward " \n")
+		    (Info-validate-node-name
+		     (concat "invalid reference "
+			     (buffer-substring (point)
+					       (save-excursion
+						 (skip-chars-forward "^:")
+						 (point))))
+		     (Info-extract-menu-node-name "Bad format cross-reference")))))))
+	(setq tags-losing (not (Info-validate-tags-table)))
+	(if (or lossages tags-losing)
+	    (with-output-to-temp-buffer " *problems in info file*"
+	      (while lossages
+		(princ "In node \"")
+		(princ (car (car lossages)))
+		(princ "\", ")
+		(let ((tem (nth 1 (car lossages))))
+		  (cond ((string-match "\n" tem)
+			 (princ (substring tem 0 (match-beginning 0)))
+			 (princ "..."))
+			(t
+			 (princ tem))))
+		(if (nth 2 (car lossages))
+		    (progn
+		      (princ ": ")
+		      (let ((tem (nth 2 (car lossages))))
+			(cond ((string-match "\n" tem)
+			       (princ (substring tem 0 (match-beginning 0)))
+			       (princ "..."))
+			      (t
+			       (princ tem))))))
+		(terpri)
+		(setq lossages (cdr lossages)))
+	      (if tags-losing (princ "\nTags table must be recomputed\n")))
+	  ;; Here if info file is valid.
+	  ;; If we already made a list of problems, clear it out.
+	  (save-excursion
+	    (if (get-buffer " *problems in info file*")
+		(progn
+		  (set-buffer " *problems in info file*")
+		  (kill-buffer (current-buffer)))))
+	  (message "File appears valid"))))))
+
+(defun Info-validate-node-name (kind &optional name)
+  (if name
+      nil
+    (goto-char (match-end 0))
+    (skip-chars-forward " \t")
+    (if (= (following-char) ?\()
+	nil
+      (setq name
+	    (buffer-substring-no-properties
+	     (point)
+	     (progn
+	      (skip-chars-forward "^,\t\n")
+	      (skip-chars-backward " ")
+	      (point))))))
+  (if (null name)
+      nil
+    (setq name (downcase name))
+    (or (and (> (length name) 0) (= (aref name 0) ?\())
+	(assoc name allnodes)
+	(setq lossages
+	      (cons (list thisnode kind name) lossages))))
+  name)
+
+(defun Info-validate-tags-table ()
+  (goto-char (point-min))
+  (if (not (search-forward "\^_\nEnd tag table\n" nil t))
+      t
+    (not (catch 'losing
+	   (let* ((end (match-beginning 0))
+		  (start (progn (search-backward "\nTag table:\n")
+				(1- (match-end 0))))
+		  tem)
+	     (setq tem allnodes)
+	     (while tem
+	       (goto-char start)
+	       (or (equal (car (car tem)) "*")
+		   (search-forward (concat "Node: "
+					   (car (car tem))
+					   "\177")
+				   end t)
+		   (throw 'losing 'x))
+	       (setq tem (cdr tem)))
+	     (goto-char (1+ start))
+	     (while (looking-at ".*Node: \\(.*\\)\177\\([0-9]+\\)$")
+	       (setq tem (downcase (buffer-substring-no-properties
+				     (match-beginning 1)
+				     (match-end 1))))
+	       (setq tem (assoc tem allnodes))
+	       (if (or (not tem)
+		       (< 1000 (progn
+				 (goto-char (match-beginning 2))
+				 (setq tem (- (car (cdr (cdr tem)))
+					      (read (current-buffer))))
+				 (if (> tem 0) tem (- tem)))))
+		   (throw 'losing 'y))
+	       (forward-line 1)))
+	   (if (looking-at "\^_\n")
+	       (forward-line 1))
+	   (or (looking-at "End tag table\n")
+	       (throw 'losing 'z))
+	   nil))))
+
+;;;###autoload
+(defun batch-info-validate ()
+  "Runs `Info-validate' on the files remaining on the command line.
+Must be used only with -batch, and kills Emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke \"emacs -batch -f batch-info-validate $info/ ~/*.info\""
+  (if (not noninteractive)
+      (error "batch-info-validate may only be used -batch."))
+  (let ((version-control t)
+	(auto-save-default nil)
+	(find-file-run-dired nil)
+	(kept-old-versions 259259)
+	(kept-new-versions 259259))
+    (let ((error 0)
+	  file
+	  (files ()))
+      (while command-line-args-left
+	(setq file (expand-file-name (car command-line-args-left)))
+	(cond ((not (file-exists-p file))
+	       (message ">> %s does not exist!" file)
+	       (setq error 1
+		     command-line-args-left (cdr command-line-args-left))) 
+	      ((file-directory-p file)
+	       (setq command-line-args-left (nconc (directory-files file)
+					      (cdr command-line-args-left))))
+	      (t
+	       (setq files (cons file files)
+		     command-line-args-left (cdr command-line-args-left)))))
+      (while files
+	(setq file (car files)
+	      files (cdr files))
+	(let ((lose nil))
+	  (condition-case err
+	      (progn
+		(if buffer-file-name (kill-buffer (current-buffer)))
+		(find-file file)
+		(buffer-disable-undo (current-buffer))
+		(set-buffer-modified-p nil)
+		(fundamental-mode)
+		(let ((case-fold-search nil))
+		  (goto-char (point-max))
+		  (cond ((search-backward "\n\^_\^L\nTag table:\n" nil t)
+			 (message "%s already tagified" file))
+			((< (point-max) 30000)
+			 (message "%s too small to bother tagifying" file))
+			(t
+			 (Info-tagify))))
+		(let ((loss-name " *problems in info file*"))
+		  (message "Checking validity of info file %s..." file)
+		  (if (get-buffer loss-name)
+		      (kill-buffer loss-name))
+		  (Info-validate)
+		  (if (not (get-buffer loss-name))
+		      nil ;(message "Checking validity of info file %s... OK" file)
+		    (message "----------------------------------------------------------------------")
+		    (message ">> PROBLEMS IN INFO FILE %s" file)
+		    (save-excursion
+		      (set-buffer loss-name)
+		      (princ (buffer-substring-no-properties
+			      (point-min) (point-max))))
+		    (message "----------------------------------------------------------------------")
+		    (setq error 1 lose t)))
+		(if (and (buffer-modified-p)
+			 (not lose))
+		    (progn (message "Saving modified %s" file)
+			   (save-buffer))))
+	    (error (message ">> Error: %s" (prin1-to-string err))))))
+      (kill-emacs error))))
+
+;;; informat.el ends here
+;;; makeinfo.el --- run makeinfo conveniently
+
+;; Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+;; Author: Robert J. Chassell      
+;; Maintainer: FSF
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Synched up with: FSF 19.34.
+
+;;; Commentary:
+
+;;; The Texinfo mode `makeinfo' related commands are:
+
+;; makeinfo-region      to run makeinfo on the current region.
+;; makeinfo-buffer      to run makeinfo on the current buffer, or
+;;                        with optional prefix arg, on current region
+;; kill-compilation     to kill currently running makeinfo job
+;; makeinfo-recenter-makeinfo-buffer  to redisplay *compilation* buffer
+
+;;; Keybindings (defined in `texinfo.el')
+
+;; makeinfo bindings
+; (define-key texinfo-mode-map "\C-c\C-m\C-r" 'makeinfo-region)
+; (define-key texinfo-mode-map "\C-c\C-m\C-b" 'makeinfo-buffer)
+; (define-key texinfo-mode-map "\C-c\C-m\C-k" 'kill-compilation)
+; (define-key texinfo-mode-map "\C-c\C-m\C-l"
+;   'makeinfo-recenter-compilation-buffer)
+
+;;; Code:
+
+;;; Variables used by `makeinfo'
+
+(require 'compile)
+
+(defgroup makeinfo nil
+  "Run makeinfo conveniently."
+  :group 'docs)
+
+
+(defcustom makeinfo-run-command "makeinfo"
+  "*Command used to run `makeinfo' subjob.
+The name of the file is appended to this string, separated by a space."
+  :type 'string
+  :group 'makeinfo)
+
+(defcustom makeinfo-options "--fill-column=70"
+  "*String containing options for running `makeinfo'.  
+Do not include `--footnote-style' or `--paragraph-indent';
+the proper way to specify those is with the Texinfo commands
+`@footnotestyle` and `@paragraphindent'."
+  :type 'string
+  :group 'makeinfo)
+
+(require 'texinfo)
+
+(defvar makeinfo-compilation-process nil
+  "Process that runs `makeinfo'.  Should start out nil.")
+
+(defvar makeinfo-temp-file nil
+  "Temporary file name used for text being sent as input to `makeinfo'.")
+
+(defvar makeinfo-output-file-name nil
+  "Info file name used for text output by `makeinfo'.")
+
+
+;;; The `makeinfo' function definitions
+
+(defun makeinfo-region (region-beginning region-end)
+  "Make Info file from region of current Texinfo file, and switch to it.
+
+This command does not offer the `next-error' feature since it would
+apply to a temporary file, not the original; use the `makeinfo-buffer'
+command to gain use of `next-error'."
+  
+  (interactive "r")
+  (let (filename-or-header
+        filename-or-header-beginning
+        filename-or-header-end)
+    ;; Cannot use `let' for makeinfo-temp-file or
+    ;; makeinfo-output-file-name since `makeinfo-compilation-sentinel'
+    ;; needs them.
+
+    (setq makeinfo-temp-file
+          (concat
+           (make-temp-name
+            (substring (buffer-file-name)
+                       0 
+                       (or (string-match "\\.tex" (buffer-file-name)) 
+                           (length (buffer-file-name)))))
+           ".texinfo"))
+    
+    (save-excursion
+      (save-restriction
+        (widen)
+        (goto-char (point-min))
+        (let ((search-end (save-excursion (forward-line 100) (point))))
+          ;; Find and record the Info filename,
+          ;; or else explain that a filename is needed.
+          (if (re-search-forward 
+               "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
+               search-end t)
+              (setq makeinfo-output-file-name 
+                    (buffer-substring (match-beginning 1) (match-end 1)))
+            (error
+             "The texinfo file needs a line saying: @setfilename <name>"))
+
+          ;; Find header and specify its beginning and end.
+          (goto-char (point-min))
+          (if (and 
+               (prog1 
+                   (search-forward tex-start-of-header search-end t)
+                 (beginning-of-line)
+                 ;; Mark beginning of header.
+                 (setq filename-or-header-beginning (point)))
+               (prog1 
+                   (search-forward tex-end-of-header nil t)
+                 (beginning-of-line)
+                 ;; Mark end of header
+                 (setq filename-or-header-end (point))))
+              
+              ;; Insert the header into the temporary file.
+              (write-region
+               (min filename-or-header-beginning region-beginning)
+               filename-or-header-end
+               makeinfo-temp-file nil nil)
+            
+            ;; Else no header; insert @filename line into temporary file.
+            (goto-char (point-min))
+            (search-forward "@setfilename" search-end t)
+            (beginning-of-line)
+            (setq filename-or-header-beginning (point))
+            (forward-line 1)
+            (setq filename-or-header-end (point))
+            (write-region
+             (min filename-or-header-beginning region-beginning)
+             filename-or-header-end
+             makeinfo-temp-file nil nil))
+          
+          ;; Insert the region into the file.
+          (write-region
+           (max region-beginning filename-or-header-end)
+           region-end
+           makeinfo-temp-file t nil)
+
+          ;; Run the `makeinfo-compile' command in the *compilation* buffer
+          (save-excursion
+            (makeinfo-compile
+             (concat makeinfo-run-command
+                     " "
+                     makeinfo-options
+                     " " 
+                     makeinfo-temp-file)
+             "Use `makeinfo-buffer' to gain use of the `next-error' command"
+	     nil)))))))
+
+;;; Actually run makeinfo.  COMMAND is the command to run.
+;;; ERROR-MESSAGE is what to say when next-error can't find another error.
+;;; If PARSE-ERRORS is non-nil, do try to parse error messages.
+(defun makeinfo-compile (command error-message parse-errors)
+  (let ((buffer
+	 (compile-internal command error-message nil
+			   (and (not parse-errors)
+				;; If we do want to parse errors, pass nil.
+				;; Otherwise, use this function, which won't
+				;; ever find any errors.
+				'(lambda (&rest ignore)
+				   (setq compilation-error-list nil))))))
+    (set-process-sentinel (get-buffer-process buffer)
+			  'makeinfo-compilation-sentinel)))
+
+;; Delete makeinfo-temp-file after processing is finished,
+;; and visit Info file.
+;; This function is called when the compilation process changes state.
+;; Based on `compilation-sentinel' in compile.el
+(defun makeinfo-compilation-sentinel (proc msg)
+  (compilation-sentinel proc msg)
+  (if (and makeinfo-temp-file (file-exists-p makeinfo-temp-file))
+      (delete-file makeinfo-temp-file))
+  ;; Always use the version on disk.
+  (if (get-file-buffer makeinfo-output-file-name)
+      (progn (set-buffer makeinfo-output-file-name)
+	     (revert-buffer t t))
+    (find-file makeinfo-output-file-name))
+  (goto-char (point-min)))
+
+(defun makeinfo-buffer ()
+  "Make Info file from current buffer.
+
+Use the \\[next-error] command to move to the next error 
+\(if there are errors\)."
+ 
+  (interactive)
+  (cond ((null buffer-file-name)
+         (error "Buffer not visiting any file"))
+        ((buffer-modified-p)
+         (if (y-or-n-p "Buffer modified; do you want to save it? ")
+             (save-buffer))))
+  
+  ;; Find and record the Info filename,
+  ;; or else explain that a filename is needed.
+  (save-excursion
+    (goto-char (point-min))
+    (let ((search-end (save-excursion (forward-line 100) (point))))
+      (if (re-search-forward 
+           "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
+           search-end t)
+          (setq makeinfo-output-file-name 
+                (buffer-substring (match-beginning 1) (match-end 1)))
+        (error
+         "The texinfo file needs a line saying: @setfilename <name>"))))
+  
+  (save-excursion
+    (makeinfo-compile
+     (concat makeinfo-run-command " " makeinfo-options
+             " " buffer-file-name)
+     "No more errors."
+     t)))
+
+(defun makeinfo-recenter-compilation-buffer (linenum)
+  "Redisplay `*compilation*' buffer so most recent output can be seen.
+The last line of the buffer is displayed on
+line LINE of the window, or centered if LINE is nil."
+  (interactive "P")
+  (let ((makeinfo-buffer (get-buffer "*compilation*"))
+	(old-buffer (current-buffer)))
+    (if (null makeinfo-buffer)
+	(message "No *compilation* buffer")
+      (pop-to-buffer makeinfo-buffer)
+      (bury-buffer makeinfo-buffer)
+      (goto-char (point-max))
+      (recenter (if linenum
+		    (prefix-numeric-value linenum)
+		  (/ (window-height) 2)))
+      (pop-to-buffer old-buffer)
+      )))
+
+;;; Place `provide' at end of file.
+(provide 'makeinfo)
+
+;;; makeinfo.el ends here
+
+(texinfo
+  (version VERSION
+   description "XEmacs TeXinfo support."
+   filename FILENAME
+   md5sum MD5SUM
+   size SIZE
+   provides (makeinfo tex-mode texinfmt texinfo texnfo-tex texnfo-upd)
+   requires (REQUIRES)
+   type regular
+))
+;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands.
+
+;; Copyright (C) 1985-1992 Free Software Foundation, Inc.
+;; Contributions over the years by William F. Schelter, Dick King,
+;; Stephen Gildea, Michael Prange, and Edward M. Reingold.
+
+;; Latest revision (1992) by Edward M. Reingold <reingold@cs.uiuc.edu>.
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the 
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(require 'comint)
+
+(defvar tex-shell-file-name nil
+  "*If non-nil, is file name to use for the subshell in which TeX is run.")
+
+(defvar tex-directory "."
+  "*Directory in which temporary files are left.
+You can make this /tmp if your TEXINPUTS has no relative directories in it
+and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
+\\input commands with relative directories.")
+
+(defvar tex-offer-save t
+  "*If non-nil, ask about saving modified buffers before \\[tex-file] is run.")
+
+(defvar tex-run-command "tex"
+  "*Command used to run TeX subjob.
+If this string contains an asterisk (*), it will be replaced by the
+filename; if not, the name of the file, preceded by blank, will be added to
+this string.")
+
+(defvar latex-run-command "latex"
+  "*Command used to run LaTeX subjob.
+If this string contains an asterisk (*), it will be replaced by the
+filename; if not, the name of the file, preceded by blank, will be added to
+this string.")
+
+(defvar standard-latex-block-names
+      '("abstract"         "array"            "center"       "description"
+        "displaymath"      "document"         "enumerate"    "eqnarray"
+        "eqnarray*"        "equation"         "figure"       "figure*"
+        "flushleft"        "flushright"       "itemize"      "letter"
+        "list"             "minipage"         "picture"      "quotation"
+        "quote"            "slide"            "sloppypar"     "tabbing"
+        "table"            "table*"           "tabular"       "tabular*"
+        "thebibliography"  "theindex*"        "titlepage"     "trivlist"
+        "verbatim"         "verbatim*"        "verse")
+  "Standard LaTeX block names.")
+
+(defvar latex-block-names nil
+  "*User defined LaTeX block names.
+Combined with `standard-latex-block-names' for minibuffer completion.")
+
+(defvar tex-latex-document-regex "documentstyle\\|documentclass"
+  "matches the first command of a LaTeX document")
+
+(defvar slitex-run-command "slitex"
+  "*Command used to run SliTeX subjob.
+If this string contains an asterisk (*), it will be replaced by the
+filename; if not, the name of the file, preceded by blank, will be added to
+this string.")
+
+(defvar tex-slitex-document-regex "documentstyle{slides}"
+  "Matches the first command of a slitex document")
+  
+(defvar tex-bibtex-command "bibtex"
+  "*Command used by `tex-bibtex-file' to gather bibliographic data.
+If this string contains an asterisk (*), it will be replaced by the
+filename; if not, the name of the file, preceded by blank, will be added to
+this string.")
+
+(defvar tex-dvi-print-command "lpr -d"
+  "*Command used by \\[tex-print] to print a .dvi file.
+If this string contains an asterisk (*), it will be replaced by the
+filename; if not, the name of the file, preceded by blank, will be added to
+this string.")
+
+(defvar tex-alt-dvi-print-command "lpr -d"
+  "*Command used by \\[tex-print] with a prefix arg to print a .dvi file.
+If this string contains an asterisk (*), it will be replaced by the
+filename; if not, the name of the file, preceded by blank, will be added to
+this string.
+
+If two printers are not enough of a choice, you can define the value
+of tex-alt-dvi-print-command to be an expression that asks what you want;
+for example,
+
+    (setq tex-alt-dvi-print-command
+         '(format \"lpr -P%s\" (read-string \"Use printer: \")))
+
+would tell \\[tex-print] with a prefix argument to ask you which printer to
+use.")
+
+(defvar tex-dvi-view-command nil
+  "*Command used by \\[tex-view] to display a .dvi file.
+If this string contains an asterisk (*), it will be replaced by the
+filename; if not, the name of the file, preceded by blank, will be added to
+this string.
+
+This can be set conditionally so that the previewer used is suitable for the
+window system being used.  For example,
+
+    (setq tex-dvi-view-command
+          (if (eq window-system 'x) \"xdvi\" \"dvi2tty * | cat -s\"))
+
+would tell \\[tex-view] use xdvi under X windows and to use dvi2tty
+otherwise.")
+
+(defvar tex-show-queue-command "lpq"
+  "*Command used by \\[tex-show-print-queue] to show the print queue.
+Should show the queue(s) that \\[tex-print] puts jobs on.")
+
+(defvar tex-default-mode 'plain-tex-mode
+  "*Mode to enter for a new file that might be either TeX or LaTeX.
+This variable is used when it can't be determined whether the file
+is plain TeX or LaTeX or what because the file contains no commands.
+Normally set to either 'plain-tex-mode or 'latex-mode.")
+
+(defvar tex-open-quote "``"
+  "*String inserted by typing \\[tex-insert-quote] to open a quotation.")
+
+(defvar tex-close-quote "''"
+  "*String inserted by typing \\[tex-insert-quote] to close a quotation.")
+
+(defvar tex-last-temp-file nil
+  "Latest temporary file generated by \\[tex-region] and \\[tex-buffer].
+Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the
+tex-shell goes away.")
+
+(defvar tex-command nil
+  "Command to run TeX.
+The name of the file, preceded by a blank, will be added to this string.")
+
+(defvar tex-trailer nil
+  "String appended after the end of a region sent to TeX by \\[tex-region].")
+
+(defvar tex-start-of-header nil
+  "String used by \\[tex-region] to delimit the start of the file's header.")
+
+(defvar tex-end-of-header nil
+  "String used by \\[tex-region] to delimit the end of the file's header.")
+
+(defvar tex-shell-cd-command "cd"
+  "Command to give to shell running TeX to change directory.
+The value of tex-directory will be appended to this, separated by a space.")
+
+(defvar tex-zap-file nil
+  "Temporary file name used for text being sent as input to TeX.
+Should be a simple file name with no extension or directory specification.")
+
+(defvar tex-last-buffer-texed nil
+  "Buffer which was last TeXed.")
+
+(defvar tex-print-file nil
+  "File name that \\[tex-print] prints.
+Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
+
+(defvar tex-mode-syntax-table nil
+  "Syntax table used while in TeX mode.")
+
+(defun tex-define-common-keys (keymap)
+  "Define the keys that we want defined both in TeX mode and in the tex-shell."
+  (define-key keymap "\C-c\C-k" 'tex-kill-job)
+  (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer)
+  (define-key keymap "\C-c\C-q" 'tex-show-print-queue)
+  (define-key keymap "\C-c\C-p" 'tex-print)
+  (define-key keymap "\C-c\C-v" 'tex-view)
+  )
+
+(defvar tex-mode-map nil "Keymap for TeX mode.")
+
+(if tex-mode-map 
+    nil
+  (setq tex-mode-map (make-sparse-keymap))
+  (tex-define-common-keys tex-mode-map)
+  (define-key tex-mode-map "\"" 'tex-insert-quote)
+  (define-key tex-mode-map "\n" 'tex-terminate-paragraph)
+  (define-key tex-mode-map "\C-c}" 'up-list)
+  (define-key tex-mode-map "\C-c{" 'tex-insert-braces)
+  (define-key tex-mode-map "\C-c\C-r" 'tex-region)
+  (define-key tex-mode-map "\C-c\C-b" 'tex-buffer)
+  (define-key tex-mode-map "\C-c\C-f" 'tex-file)
+  (define-key tex-mode-map "\C-c\C-i" 'tex-bibtex-file)
+  (define-key tex-mode-map "\C-c\C-o" 'tex-latex-block)
+  (define-key tex-mode-map "\C-c\C-e" 'tex-close-latex-block))
+
+(defvar tex-shell-map nil
+  "Keymap for the tex-shell.  A comint-mode-map with a few additions.")
+
+;;; This would be a lot simpler if we just used a regexp search,
+;;; but then it would be too slow.
+;;;###autoload
+(defun tex-mode ()
+  "Major mode for editing files of input for TeX, LaTeX, or SliTeX.
+Tries to determine (by looking at the beginning of the file) whether
+this file is for plain TeX, LaTeX, or SliTeX and calls plain-tex-mode,
+latex-mode, or slitex-mode, respectively.  If it cannot be determined,
+such as if there are no commands in the file, the value of tex-default-mode
+is used."
+  (interactive)
+  (let (mode slash comment)
+    (save-excursion
+      (goto-char (point-min))
+      (while (and (setq slash (search-forward "\\" nil t))
+		  (setq comment (let ((search-end (point)))
+				  (save-excursion
+				    (beginning-of-line)
+				    (search-forward "%" search-end t))))))
+      (if (and slash (not comment))
+	  (setq mode (if (looking-at tex-latex-document-regex)
+                         (if (looking-at tex-slitex-document-regex)
+                             'slitex-mode
+                           'latex-mode)
+		       'plain-tex-mode))))
+    (if mode (funcall mode)
+      (funcall tex-default-mode))))
+;;;###autoload
+(fset 'TeX-mode 'tex-mode)
+;;;###autoload
+(fset 'LaTeX-mode 'latex-mode)
+
+;;;###autoload
+(defun plain-tex-mode ()
+  "Major mode for editing files of input for plain TeX.
+Makes $ and } display the characters they match.
+Makes \" insert `` when it seems to be the beginning of a quotation,
+and '' when it appears to be the end; it inserts \" only after a \\.
+
+Use \\[tex-region] to run TeX on the current region, plus a \"header\"
+copied from the top of the file (containing macro definitions, etc.),
+running TeX under a special subshell.  \\[tex-buffer] does the whole buffer.
+\\[tex-file] saves the buffer and then processes the file.
+\\[tex-print] prints the .dvi file made by any of these.
+\\[tex-view] previews the .dvi file made by any of these.
+\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
+
+Use \\[validate-tex-buffer] to check buffer for paragraphs containing
+mismatched $'s or braces.
+
+Special commands:
+\\{tex-mode-map}
+
+Mode variables:
+tex-run-command
+	Command string used by \\[tex-region] or \\[tex-buffer].
+tex-directory
+	Directory in which to create temporary files for TeX jobs
+	run by \\[tex-region] or \\[tex-buffer].
+tex-dvi-print-command
+	Command string used by \\[tex-print] to print a .dvi file.
+tex-alt-dvi-print-command
+	Alternative command string used by \\[tex-print] (when given a prefix
+	argument) to print a .dvi file.
+tex-dvi-view-command
+	Command string used by \\[tex-view] to preview a .dvi file.
+tex-show-queue-command
+	Command string used by \\[tex-show-print-queue] to show the print
+	queue that \\[tex-print] put your job on.
+
+Entering Plain-tex mode calls the value of text-mode-hook, then the value of
+tex-mode-hook, and then the value of plain-tex-mode-hook.  When the special
+subshell is initiated, the value of tex-shell-hook is called."
+  (interactive)
+  (tex-common-initialization)
+  (setq mode-name "TeX")
+  (setq major-mode 'plain-tex-mode)
+  (setq tex-command tex-run-command)
+  (setq tex-start-of-header "%**start of header")
+  (setq tex-end-of-header "%**end of header")
+  (setq tex-trailer "\\bye\n")
+  (run-hooks 'text-mode-hook 'tex-mode-hook 'plain-tex-mode-hook))
+;;;###autoload
+(fset 'plain-TeX-mode 'plain-tex-mode)
+
+;;;###autoload
+(defun latex-mode ()
+  "Major mode for editing files of input for LaTeX.
+Makes $ and } display the characters they match.
+Makes \" insert `` when it seems to be the beginning of a quotation,
+and '' when it appears to be the end; it inserts \" only after a \\.
+
+Use \\[tex-region] to run LaTeX on the current region, plus the preamble
+copied from the top of the file (containing \\documentstyle, etc.),
+running LaTeX under a special subshell.  \\[tex-buffer] does the whole buffer.
+\\[tex-file] saves the buffer and then processes the file.
+\\[tex-print] prints the .dvi file made by any of these.
+\\[tex-view] previews the .dvi file made by any of these.
+\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
+
+Use \\[validate-tex-buffer] to check buffer for paragraphs containing
+mismatched $'s or braces.
+
+Special commands:
+\\{tex-mode-map}
+
+Mode variables:
+latex-run-command
+	Command string used by \\[tex-region] or \\[tex-buffer].
+tex-directory
+	Directory in which to create temporary files for LaTeX jobs
+	run by \\[tex-region] or \\[tex-buffer].
+tex-dvi-print-command
+	Command string used by \\[tex-print] to print a .dvi file.
+tex-alt-dvi-print-command
+	Alternative command string used by \\[tex-print] (when given a prefix
+	argument) to print a .dvi file.
+tex-dvi-view-command
+	Command string used by \\[tex-view] to preview a .dvi file.
+tex-show-queue-command
+	Command string used by \\[tex-show-print-queue] to show the print
+	queue that \\[tex-print] put your job on.
+
+Entering Latex mode calls the value of text-mode-hook, then the value of
+tex-mode-hook, and then the value of latex-mode-hook.  When the special
+subshell is initiated, the value of tex-shell-hook is called."
+  (interactive)
+  (tex-common-initialization)
+  (setq mode-name "LaTeX")
+  (setq major-mode 'latex-mode)
+  (setq tex-command latex-run-command)
+  (setq tex-start-of-header "\\documentstyle")
+  (setq tex-end-of-header "\\begin{document}")
+  (setq tex-trailer "\\end{document}\n")
+  (run-hooks 'text-mode-hook 'tex-mode-hook 'latex-mode-hook))
+
+(defun slitex-mode ()
+  "Major mode for editing files of input for SliTeX.
+Makes $ and } display the characters they match.
+Makes \" insert `` when it seems to be the beginning of a quotation,
+and '' when it appears to be the end; it inserts \" only after a \\.
+
+Use \\[tex-region] to run SliTeX on the current region, plus the preamble
+copied from the top of the file (containing \\documentstyle, etc.),
+running SliTeX under a special subshell.  \\[tex-buffer] does the whole buffer.
+\\[tex-file] saves the buffer and then processes the file.
+\\[tex-print] prints the .dvi file made by any of these.
+\\[tex-view] previews the .dvi file made by any of these.
+\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
+
+Use \\[validate-tex-buffer] to check buffer for paragraphs containing
+mismatched $'s or braces.
+
+Special commands:
+\\{tex-mode-map}
+
+Mode variables:
+slitex-run-command
+	Command string used by \\[tex-region] or \\[tex-buffer].
+tex-directory
+	Directory in which to create temporary files for SliTeX jobs
+	run by \\[tex-region] or \\[tex-buffer].
+tex-dvi-print-command
+	Command string used by \\[tex-print] to print a .dvi file.
+tex-alt-dvi-print-command
+	Alternative command string used by \\[tex-print] (when given a prefix
+	argument) to print a .dvi file.
+tex-dvi-view-command
+	Command string used by \\[tex-view] to preview a .dvi file.
+tex-show-queue-command
+	Command string used by \\[tex-show-print-queue] to show the print
+	queue that \\[tex-print] put your job on.
+
+Entering SliTeX mode calls the value of text-mode-hook, then the value of
+tex-mode-hook, then the value of latex-mode-hook, and then the value of
+slitex-mode-hook.  When the special subshell is initiated, the value of
+tex-shell-hook is called."
+  (interactive)
+  (tex-common-initialization)
+  (setq mode-name "SliTeX")
+  (setq major-mode 'slitex-mode)
+  (setq tex-command slitex-run-command)
+  (setq tex-start-of-header "\\documentstyle{slides}")
+  (setq tex-end-of-header "\\begin{document}")
+  (setq tex-trailer "\\end{document}\n")
+  (run-hooks
+   'text-mode-hook 'tex-mode-hook 'latex-mode-hook 'slitex-mode-hook))
+
+(defun tex-common-initialization ()
+  (kill-all-local-variables)
+  (use-local-map tex-mode-map)
+  (setq local-abbrev-table text-mode-abbrev-table)
+  (if (null tex-mode-syntax-table)
+      (let ((char 0))
+	(setq tex-mode-syntax-table (make-syntax-table))
+	(set-syntax-table tex-mode-syntax-table)
+	(while (< char ? )
+	  (modify-syntax-entry char ".")
+	  (setq char (1+ char)))
+	(modify-syntax-entry ?\C-@ "w")
+	(modify-syntax-entry ?\t " ")
+	(modify-syntax-entry ?\n ">")
+	(modify-syntax-entry ?\f ">")
+	(modify-syntax-entry ?$ "$$")
+	(modify-syntax-entry ?% "<")
+	(modify-syntax-entry ?\\ "/")
+	(modify-syntax-entry ?\" ".")
+	(modify-syntax-entry ?& ".")
+	(modify-syntax-entry ?_ ".")
+	(modify-syntax-entry ?@ "_")
+	(modify-syntax-entry ?~ " ")
+	(modify-syntax-entry ?' "w"))
+    (set-syntax-table tex-mode-syntax-table))
+  (make-local-variable 'paragraph-start)
+  (setq paragraph-start "^[ \t]*$\\|^[\f\\\\%]")
+  (make-local-variable 'paragraph-separate)
+  (setq paragraph-separate paragraph-start)
+  (make-local-variable 'comment-start)
+  (setq comment-start "%")
+  (make-local-variable 'comment-start-skip)
+  (setq comment-start-skip "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
+  (make-local-variable 'comment-indent-function)
+  (setq comment-indent-function 'tex-comment-indent)
+  (make-local-variable 'compare-windows-whitespace)
+  (setq compare-windows-whitespace 'tex-categorize-whitespace)
+  (make-local-variable 'tex-command)
+  (make-local-variable 'tex-start-of-header)
+  (make-local-variable 'tex-end-of-header)
+  (make-local-variable 'tex-trailer))
+
+(defun tex-comment-indent ()
+  (if (looking-at "%%%")
+      (current-column)
+    (skip-chars-backward " \t")
+    (max (if (bolp) 0 (1+ (current-column)))
+	 comment-column)))
+
+(defun tex-categorize-whitespace (backward-limit)
+  ;; compare-windows-whitespace is set to this.
+  ;; This is basically a finite-state machine.
+  ;; Returns a symbol telling how TeX would treat
+  ;; the whitespace we are looking at: null, space, or par.
+  (let ((category 'null)
+	(not-finished t))
+    (skip-chars-backward " \t\n\f" backward-limit)
+    (while not-finished
+      (cond ((looking-at "[ \t]+")
+	     (goto-char (match-end 0))
+	     (if (eql category 'null)
+		 (setq category 'space)))
+	    ((looking-at "\n")
+	     (cond ((eql category 'newline)
+		    (setq category 'par)
+		    (setq not-finished nil))
+		   (t
+		    (setq category 'newline) ;a strictly internal state
+		    (goto-char (match-end 0)))))
+	    ((looking-at "\f+")
+	     (setq category 'par)
+	     (setq not-finished nil))
+	    (t
+	     (setq not-finished nil))))
+    (skip-chars-forward " \t\n\f")
+    (if (eql category 'newline)
+	'space				;TeX doesn't distinguish
+      category)))
+
+(defun tex-insert-quote (arg)
+  "Insert the appropriate quote marks for TeX.
+Inserts the value of tex-open-quote (normally ``) or tex-close-quote
+(normally '') depending on the context.  With prefix argument, always
+inserts \" characters."
+  (interactive "*P")
+  (if arg
+      (self-insert-command (prefix-numeric-value arg))
+    (insert
+     (cond ((or (bobp)
+		(save-excursion
+		  (forward-char -1)
+		  (looking-at "\\s(\\|\\s \\|\\s>")))
+	    tex-open-quote)
+	   ((= (preceding-char) ?\\)
+	    ?\")
+	   (t
+	    tex-close-quote)))))
+
+(defun validate-tex-buffer ()
+  "Check current buffer for paragraphs containing mismatched $'s.
+As each such paragraph is found, a mark is pushed at its beginning,
+and the location is displayed for a few seconds."
+  (interactive)
+  (let ((opoint (point)))
+    (goto-char (point-max))
+    ;; Does not use save-excursion
+    ;; because we do not want to save the mark.
+    (unwind-protect
+	(while (and (not (input-pending-p)) (not (bobp)))
+	  (let ((end (point)))
+	    (search-backward "\n\n" nil 'move)
+	    (or (tex-validate-region (point) end)
+		(progn
+		  (push-mark (point))
+		  (message "Mismatch found in pararaph starting here")
+		  (sit-for 4)))))
+      (goto-char opoint))))
+
+(defun tex-validate-region (start end)
+  "Check for mismatched braces or $'s in region.
+Returns t if no mismatches.  Returns nil and moves point to suspect
+area if a mismatch is found."
+  (interactive "r")
+  (let ((failure-point nil) (max-possible-sexps (- end start)))
+    (save-excursion
+      (condition-case ()
+	  (save-restriction
+	    (narrow-to-region start end)
+	    (goto-char start)
+	    (while (< 0 (setq max-possible-sexps (1- max-possible-sexps)))
+	      (forward-sexp 1)))
+	(error
+	  (setq failure-point (point)))))
+    (if failure-point
+	(progn
+	  (goto-char failure-point)
+	  nil)
+      t)))
+
+(defun tex-terminate-paragraph (inhibit-validation)
+  "Insert two newlines, breaking a paragraph for TeX.
+Check for mismatched braces/$'s in paragraph being terminated.
+A prefix arg inhibits the checking."
+  (interactive "*P")
+  (or inhibit-validation
+      (save-excursion
+	(tex-validate-region
+	  (save-excursion
+	    (search-backward "\n\n" nil 'move)
+	    (point))
+	  (point)))
+      (message "Paragraph being closed appears to contain a mismatch"))
+  (insert "\n\n"))
+
+(defun tex-insert-braces ()
+  "Make a pair of braces and be poised to type inside of them."
+  (interactive "*")
+  (insert ?\{)
+  (save-excursion
+    (insert ?})))
+
+;;; Like tex-insert-braces, but for LaTeX.
+(defun tex-latex-block (name)
+  "Creates a matching pair of lines \\begin{NAME} and \\end{NAME} at point.
+Puts point on a blank line between them."
+  (interactive
+   (prog2
+      (barf-if-buffer-read-only)
+      (list
+       (completing-read "LaTeX block name: "
+			(mapcar 'list
+                                (append standard-latex-block-names
+                                        latex-block-names))))))
+  (let ((col (current-column)))
+    (insert (format "\\begin{%s}\n" name))
+    (indent-to col)
+    (save-excursion
+      (insert ?\n)
+      (indent-to col)
+      (insert (format "\\end{%s}" name))
+      (if (eobp) (insert ?\n)))))
+
+(defun tex-last-unended-begin ()
+  "Leave point at the beginning of the last \\begin{...} that is unended."
+  (while (and (re-search-backward "\\(\\\\begin\\s *{\\)\\|\\(\\\\end\\s *{\\)")
+              (looking-at "\\\\end{"))
+    (tex-last-unended-begin)))
+
+(defun tex-close-latex-block ()
+  "Creates an \\end{...} to match the last unclosed \\begin{...}."
+  (interactive "*")
+  (let ((new-line-needed (bolp))
+	text indentation)
+    (save-excursion
+      (condition-case nil
+          (tex-last-unended-begin)
+        (error (error "Couldn't find unended \\begin")))
+      (setq indentation (current-column))
+      (re-search-forward "\\\\begin\\(\\s *{[^}\n]*}\\)")
+      (setq text (buffer-substring (match-beginning 1) (match-end 1))))
+    (indent-to indentation)
+    (insert "\\end" text)
+    (if new-line-needed (insert ?\n))))
+
+;;; Invoking TeX in an inferior shell.
+
+;;; Why use a shell instead of running TeX directly?  Because if TeX
+;;; gets stuck, the user can switch to the shell window and type at it.
+
+;;; The utility functions:
+
+(defun tex-start-shell ()
+  (save-excursion
+    (set-buffer
+     (make-comint
+      "tex-shell"
+      (or tex-shell-file-name (getenv "ESHELL") (getenv "SHELL") "/bin/sh")
+      nil "-v"))
+    (let ((proc (get-process "tex-shell")))
+      (set-process-sentinel proc 'tex-shell-sentinel)
+      (process-kill-without-query proc)
+      (setq tex-shell-map (copy-keymap comint-mode-map))
+      (tex-define-common-keys tex-shell-map)
+      (use-local-map tex-shell-map)
+      (run-hooks 'tex-shell-hook)
+      (while (zerop (buffer-size))
+          (sleep-for 1)))))
+
+(defun tex-shell-sentinel (proc msg)
+  (cond ((null (buffer-name (process-buffer proc)))
+	 ;; buffer killed
+	 (set-process-buffer proc nil)
+         (tex-delete-last-temp-files))
+	((memq (process-status proc) '(signal exit))
+         (tex-delete-last-temp-files))))
+
+(defun tex-set-buffer-directory (buffer directory)
+  "Set BUFFER's default directory to be DIRECTORY."
+  (setq directory (file-name-as-directory (expand-file-name directory)))
+  (if (not (file-directory-p directory))
+      (error "%s is not a directory" directory)
+    (save-excursion
+      (set-buffer buffer)
+      (setq default-directory directory))))
+
+(defun tex-send-command (command &optional file background)
+  "Send COMMAND to tex-shell, substituting optional FILE for *; in background
+if optional BACKGROUND is t.   If COMMAND has no *, FILE will be appended,
+preceded by a blank, to COMMAND.  If FILE is nil, no substitution will be made
+in COMMAND.  COMMAND can be any expression that evaluates to a command string."
+  (save-excursion
+    (let* ((cmd (eval command))
+           (star (string-match "\\*" cmd)))
+      (comint-proc-query (get-process "tex-shell")
+                         (concat (substring cmd 0 star)
+                                 (if file (concat " " file) "")
+                                 (if star (substring cmd (1+ star) nil) "")
+                                 (if background "&\n" "\n"))))))
+
+(defun tex-delete-last-temp-files ()
+  "Delete any junk files from last temp file."
+  (if tex-last-temp-file
+      (let* ((dir (file-name-directory tex-last-temp-file))
+             (list (file-name-all-completions
+                    (file-name-nondirectory tex-last-temp-file) dir)))
+        (while list
+          (delete-file (concat dir (car list)))
+          (setq list (cdr list))))))
+
+(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
+
+;;; The commands:
+
+(defun tex-region (beg end)
+  "Run TeX on the current region, via a temporary file.
+The file's name comes from the variable `tex-zap-file' and the
+variable `tex-directory' says where to put it.
+
+If the buffer has a header, the header is given to TeX before the
+region itself.  The buffer's header is all lines between the strings
+defined by `tex-start-of-header' and `tex-end-of-header' inclusive.
+The header must start in the first 100 lines of the buffer.
+
+The value of `tex-trailer' is given to TeX as input after the region.
+
+The value of `tex-command' specifies the command to use to run TeX."
+  (interactive "r")
+  (if (tex-shell-running)
+      (tex-kill-job)
+    (tex-start-shell))
+  (or tex-zap-file
+      (setq tex-zap-file (tex-generate-zap-file-name)))
+  (let* ((temp-buffer (get-buffer-create " TeX-Output-Buffer"))
+         ; Temp file will be written and TeX will be run in zap-directory.
+         ; If the TEXINPUTS file has relative directories or if the region has
+         ; \input of files, this must be the same directory as the file for
+         ; TeX to access the correct inputs.  That's why it's safest if
+         ; tex-directory is ".".
+         (zap-directory
+          (file-name-as-directory (expand-file-name tex-directory)))
+         (tex-out-file (concat zap-directory tex-zap-file)))
+    (tex-delete-last-temp-files)
+    ;; Write the new temp file.
+    (save-excursion
+      (save-restriction
+	(widen)
+	(goto-char (point-min))
+	(forward-line 100)
+	(let ((search-end (point))
+	      (hbeg (point-min)) (hend (point-min))
+	      (default-directory zap-directory))
+	  (goto-char (point-min))
+	  ;; Initialize the temp file with either the header or nothing
+	  (if (search-forward tex-start-of-header search-end t)
+	      (progn
+		(beginning-of-line)
+		(setq hbeg (point))	;mark beginning of header
+		(if (search-forward tex-end-of-header nil t)
+		    (progn (forward-line 1)
+			   (setq hend (point)))	;mark end of header
+		  (setq hbeg (point-min))))) ;no header
+	  (write-region (min hbeg beg) hend
+                        (concat tex-out-file ".tex") nil nil)
+	  (write-region (max beg hend) end (concat tex-out-file ".tex") t nil))
+	(let ((local-tex-trailer tex-trailer))
+	  (set-buffer temp-buffer)
+	  (erase-buffer)
+	  ;; make sure trailer isn't hidden by a comment
+	  (insert ?\n)
+	  (if local-tex-trailer (insert local-tex-trailer))
+	  (tex-set-buffer-directory temp-buffer zap-directory)
+	  (write-region (point-min) (point-max)
+                        (concat tex-out-file ".tex") t nil))))
+    ;; Record the file name to be deleted afterward.
+    (setq tex-last-temp-file tex-out-file)
+    (tex-send-command tex-shell-cd-command zap-directory)
+    (tex-send-command tex-command tex-out-file)
+    (setq tex-print-file tex-out-file)
+    (setq tex-last-buffer-texed (current-buffer))))
+
+(defun tex-buffer ()
+  "Run TeX on current buffer.  See \\[tex-region] for more information.
+Does not save the buffer, so it's useful for trying experimental versions.
+See \\[tex-file] for an alternative."
+  (interactive)
+  (tex-region (point-min) (point-max)))
+
+(defun tex-file ()
+  "Prompt to save all buffers and run TeX (or LaTeX) on current buffer's file.
+This function is more useful than \\[tex-buffer] when you need the
+`.aux' file of LaTeX to have the correct name."
+  (interactive)
+  (let ((tex-out-file
+         (if (buffer-file-name)
+             (file-name-nondirectory (buffer-file-name))
+           (error "Buffer does not seem to be associated with any file")))
+	(file-dir (file-name-directory (buffer-file-name))))
+    (save-some-buffers)
+    (if (tex-shell-running)
+        (tex-kill-job)
+      (tex-start-shell))
+    (tex-send-command tex-shell-cd-command file-dir)
+    (tex-send-command tex-command tex-out-file))
+  (setq tex-last-buffer-texed (current-buffer))
+  (setq tex-print-file (buffer-file-name)))
+
+(defun tex-generate-zap-file-name ()
+  "Generate a unique name suitable for use as a file name."
+  ;; Include the shell process number and host name
+  ;; in case there are multiple shells (for same or different user).
+  (format "#tz%d%s"
+          (process-id (get-buffer-process "*tex-shell*"))
+	  (tex-strip-dots (system-name))))
+
+(defun tex-strip-dots (s)
+  (setq s (copy-sequence s))
+  (while (string-match "\\." s)
+    (aset s (match-beginning 0) ?-))
+  s)
+
+;; This will perhaps be useful for modifying TEXINPUTS.
+;; Expand each file name, separated by colons, in the string S.
+(defun tex-expand-files (s)
+  (let (elts (start 0))
+    (while (string-match ":" s start)
+      (setq elts (cons (substring s start (match-beginning 0)) elts))
+      (setq start (match-end 0)))
+    (or (= start 0)
+	(setq elts (cons (substring s start) elts)))
+    (mapconcat 'expand-file-name (nreverse elts) ":")))
+
+(defun tex-shell-running ()
+  (and (get-process "tex-shell")
+       (eq (process-status (get-process "tex-shell")) 'run)))
+
+(defun tex-kill-job ()
+  "Kill the currently running TeX job."
+  (interactive)
+  (quit-process (get-process "tex-shell") t))
+
+(defun tex-recenter-output-buffer (linenum)
+  "Redisplay buffer of TeX job output so that most recent output can be seen.
+The last line of the buffer is displayed on
+line LINE of the window, or centered if LINE is nil."
+  (interactive "P")
+  (let ((tex-shell (get-buffer "*tex-shell*"))
+	(old-buffer (current-buffer)))
+    (if (null tex-shell)
+	(message "No TeX output buffer")
+      (pop-to-buffer tex-shell)
+      (bury-buffer tex-shell)
+      (goto-char (point-max))
+      (recenter (if linenum
+		    (prefix-numeric-value linenum)
+		  (/ (window-height) 2)))
+      (pop-to-buffer old-buffer))))
+
+(defun tex-print (&optional alt)
+  "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
+Runs the shell command defined by tex-dvi-print-command.  If prefix argument
+is provided, use the alternative command, tex-alt-dvi-print-command."
+  (interactive "P")
+  (let ((print-file-name-dvi (tex-append tex-print-file ".dvi"))
+	test-name)
+    (if (and (not (equal (current-buffer) tex-last-buffer-texed))
+	     (file-newer-than-file-p
+	      (setq test-name (tex-append (buffer-file-name) ".dvi"))
+	      print-file-name-dvi))
+	(setq print-file-name-dvi test-name))
+    (if (not (file-exists-p print-file-name-dvi))
+        (error "No appropriate `.dvi' file could be found")
+      (tex-send-command
+        (if alt tex-alt-dvi-print-command tex-dvi-print-command)
+        print-file-name-dvi t))))
+
+(defun tex-view ()
+  "Preview the last `.dvi' file made by running TeX under Emacs.
+This means, made using \\[tex-region], \\[tex-buffer] or \\[tex-file].
+The variable `tex-dvi-view-command' specifies the shell command for preview."
+  (interactive)
+  (let ((tex-dvi-print-command tex-dvi-view-command))
+    (tex-print)))
+
+(defun tex-append (file-name suffix)
+  "Append to FILENAME the suffix SUFFIX, using same algorithm TeX uses.
+Scans for the first (not last) period.
+No period is retained immediately before SUFFIX,
+so normally SUFFIX starts with one."
+  (if (stringp file-name)
+      (let ((file (file-name-nondirectory file-name)))
+	(concat (file-name-directory file-name)
+		(substring file 0
+			   (string-match "\\." file))
+		suffix))
+    " "))
+
+(defun tex-show-print-queue ()
+  "Show the print queue that \\[tex-print] put your job on.
+Runs the shell command defined by tex-show-queue-command."
+  (interactive)
+  (if (tex-shell-running)
+      (tex-kill-job)
+    (tex-start-shell))
+  (tex-send-command tex-show-queue-command))
+
+(defun tex-bibtex-file ()
+  "Run BibTeX on the current buffer's file."
+  (interactive)
+  (if (tex-shell-running)
+      (tex-kill-job)
+    (tex-start-shell))
+  (let ((tex-out-file
+         (tex-append (file-name-nondirectory (buffer-file-name)) ""))
+	(file-dir (file-name-directory (buffer-file-name))))
+    (tex-send-command tex-shell-cd-command file-dir)
+    (tex-send-command bibtex-command tex-out-file)))
+
+(run-hooks 'tex-mode-load-hook)
+
+(provide 'tex-mode)
+;;; texinfmt.el --- format Texinfo files into Info files.
+
+;; Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993 Free Software
+;; Foundation, Inc.
+
+;; Maintainer: Robert J. Chassell <bug-texinfo@prep.ai.mit.edu>
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+;; 02111-1307, USA.
+
+;;; Synched up with: FSF 19.34.
+
+;;; Code:
+
+;;; Emacs lisp functions to convert Texinfo files to Info files.
+
+(defvar texinfmt-version "2.34 of 7 June 1995")
+
+;;; Variable definitions
+
+(require 'texinfo)          ; So `texinfo-footnote-style' is defined.
+(require 'texnfo-upd)       ; So `texinfo-section-types-regexp' is defined.
+
+(defvar texinfo-format-syntax-table nil)
+
+(defvar texinfo-vindex)
+(defvar texinfo-findex)
+(defvar texinfo-cindex)
+(defvar texinfo-pindex)
+(defvar texinfo-tindex)
+(defvar texinfo-kindex)
+(defvar texinfo-last-node)
+(defvar texinfo-node-names)
+(defvar texinfo-enclosure-list)
+(defvar texinfo-alias-list)
+
+(defvar texinfo-command-start)
+(defvar texinfo-command-end)
+(defvar texinfo-command-name)
+(defvar texinfo-defun-type)
+(defvar texinfo-last-node-pos)
+(defvar texinfo-stack)
+(defvar texinfo-short-index-cmds-alist)
+(defvar texinfo-short-index-format-cmds-alist)
+(defvar texinfo-format-filename)
+(defvar texinfo-footnote-number)
+(defvar texinfo-start-of-header)
+(defvar texinfo-end-of-header)
+(defvar texinfo-raisesections-alist)
+(defvar texinfo-lowersections-alist)
+
+;;; Syntax table
+
+(if texinfo-format-syntax-table
+    nil
+  (setq texinfo-format-syntax-table (make-syntax-table))
+  (modify-syntax-entry ?\" " " texinfo-format-syntax-table)
+  (modify-syntax-entry ?\\ " " texinfo-format-syntax-table)
+  (modify-syntax-entry ?@ "\\" texinfo-format-syntax-table)
+  (modify-syntax-entry ?\^q "\\" texinfo-format-syntax-table)
+  (modify-syntax-entry ?\[ "." texinfo-format-syntax-table)
+  (modify-syntax-entry ?\] "." texinfo-format-syntax-table)
+  (modify-syntax-entry ?\( "." texinfo-format-syntax-table)
+  (modify-syntax-entry ?\) "." texinfo-format-syntax-table)
+  (modify-syntax-entry ?{ "(}" texinfo-format-syntax-table)
+  (modify-syntax-entry ?} "){" texinfo-format-syntax-table)
+  (modify-syntax-entry ?\' "." texinfo-format-syntax-table))
+
+
+;;; Top level buffer and region formatting functions
+
+;;;###autoload
+(defun texinfo-format-buffer (&optional notagify)
+  "Process the current buffer as texinfo code, into an Info file.
+The Info file output is generated in a buffer visiting the Info file
+names specified in the @setfilename command.
+
+Non-nil argument (prefix, if interactive) means don't make tag table
+and don't split the file if large.  You can use Info-tagify and
+Info-split to do these manually."
+  (interactive "P")
+  (let ((lastmessage "Formatting Info file..."))
+    (message lastmessage)
+    (texinfo-format-buffer-1)
+    (if notagify
+        nil
+      (if (> (buffer-size) 30000)
+          (progn
+            (message (setq lastmessage "Making tags table for Info file..."))
+            (Info-tagify)))
+      (if (> (buffer-size) 100000)
+          (progn
+            (message (setq lastmessage "Splitting Info file..."))
+            (Info-split))))
+    (message (concat lastmessage
+                     (if (interactive-p) "done.  Now save it." "done.")))))
+
+(defvar texinfo-region-buffer-name "*Info Region*"
+  "*Name of the temporary buffer used by \\[texinfo-format-region].")
+
+;;;###autoload
+(defun texinfo-format-region (region-beginning region-end)
+  "Convert the current region of the Texinfo file to Info format.
+This lets you see what that part of the file will look like in Info.
+The command is bound to \\[texinfo-format-region].  The text that is
+converted to Info is stored in a temporary buffer."
+  (interactive "r")
+  (message "Converting region to Info format...")
+  (let (texinfo-command-start
+        texinfo-command-end
+        texinfo-command-name
+        texinfo-vindex
+        texinfo-findex
+        texinfo-cindex
+        texinfo-pindex
+        texinfo-tindex
+        texinfo-kindex
+        texinfo-stack
+        (texinfo-format-filename "")
+        texinfo-example-start
+        texinfo-last-node-pos
+        texinfo-last-node
+        texinfo-node-names
+        (texinfo-footnote-number 0)
+        last-input-buffer
+        (fill-column-for-info fill-column)
+        (input-buffer (current-buffer))
+        (input-directory default-directory)
+        (header-text "")
+        (header-beginning 1)
+        (header-end 1))
+    
+;;; Copy lines between beginning and end of header lines, 
+;;;    if any, or else copy the `@setfilename' line, if any.
+    (save-excursion
+        (save-restriction
+          (widen)
+          (goto-char (point-min))
+          (let ((search-end (save-excursion (forward-line 100) (point))))
+            (if (or
+                 ;; Either copy header text.
+                 (and 
+                  (prog1 
+                      (search-forward tex-start-of-header search-end t)
+                    (forward-line 1)
+                    ;; Mark beginning of header.
+                    (setq header-beginning (point)))
+                  (prog1 
+                      (search-forward tex-end-of-header nil t)
+                    (beginning-of-line)
+                    ;; Mark end of header
+                    (setq header-end (point))))
+                 ;; Or copy @filename line.
+                 (prog2
+                  (goto-char (point-min))
+                  (search-forward "@setfilename" search-end t)
+                  (beginning-of-line)
+                  (setq header-beginning (point))
+                  (forward-line 1)
+                  (setq header-end (point))))
+                
+                ;; Copy header  
+                (setq header-text
+                      (buffer-substring
+                       (min header-beginning region-beginning)
+                       header-end))))))
+
+;;; Find a buffer to use.
+    (switch-to-buffer (get-buffer-create texinfo-region-buffer-name))
+    (erase-buffer)
+    ;; Insert the header into the buffer.
+    (insert header-text)
+    ;; Insert the region into the buffer.
+    (insert-buffer-substring
+     input-buffer
+     (max region-beginning header-end)
+     region-end)
+    ;; Make sure region ends in a newline.
+    (or (= (preceding-char) ?\n)
+        (insert "\n"))
+    
+    (goto-char (point-min))
+    (texinfo-mode)
+    (message "Converting region to Info format...")
+    (setq fill-column fill-column-for-info)
+    ;; Install a syntax table useful for scanning command operands.
+    (set-syntax-table texinfo-format-syntax-table)
+
+    ;; Insert @include files so `texinfo-raise-lower-sections' can
+    ;; work on them without losing track of multiple
+    ;; @raise/@lowersections commands. 
+    (while (re-search-forward "^@include" nil t)
+      (setq texinfo-command-end (point))
+      (let ((filename (concat input-directory
+                              (texinfo-parse-line-arg))))
+        (re-search-backward "^@include")
+        (delete-region (point) (save-excursion (forward-line 1) (point)))
+        (message "Reading included file: %s" filename)
+        (save-excursion
+          (save-restriction
+            (narrow-to-region
+             (point)
+             (+ (point) (car (cdr (insert-file-contents filename)))))
+            (goto-char (point-min))
+            ;; Remove `@setfilename' line from included file, if any,
+            ;; so @setfilename command not duplicated.
+            (if (re-search-forward 
+                 "^@setfilename" (save-excursion (forward-line 100) (point)) t)
+                (progn
+                  (beginning-of-line)
+                  (delete-region
+                   (point) (save-excursion (forward-line 1) (point)))))))))
+
+    ;; Raise or lower level of each section, if necessary.
+    (goto-char (point-min))
+    (texinfo-raise-lower-sections)
+    ;; Append @refill to appropriate paragraphs for filling.
+    (goto-char (point-min))
+    (texinfo-append-refill)
+    ;; If the region includes the effective end of the data,
+    ;; discard everything after that.
+    (goto-char (point-max))
+    (if (re-search-backward "^@bye" nil t)
+        (delete-region (point) (point-max)))
+    ;; Make sure buffer ends in a newline.
+    (or (= (preceding-char) ?\n)
+        (insert "\n"))
+    ;; Don't use a previous value of texinfo-enclosure-list.
+    (setq texinfo-enclosure-list nil)
+    (setq texinfo-alias-list nil)
+
+    (goto-char (point-min))
+    (if (looking-at "\\\\input[ \t]+texinfo")
+        (delete-region (point) (save-excursion (forward-line 1) (point))))
+
+    ;; Insert Info region title text.
+    (goto-char (point-min))
+    (if (search-forward 
+         "@setfilename" (save-excursion (forward-line 100) (point)) t)
+        (progn
+          (setq texinfo-command-end (point))
+          (beginning-of-line)
+          (setq texinfo-command-start (point))
+          (let ((arg (texinfo-parse-arg-discard)))
+            (insert " "
+              texinfo-region-buffer-name
+              " buffer for:  `") 
+            (insert (file-name-nondirectory (expand-file-name arg)))
+            (insert "',        -*-Text-*-\n")))
+      ;; Else no `@setfilename' line
+      (insert " "
+              texinfo-region-buffer-name
+              " buffer                       -*-Text-*-\n"))
+    (insert "produced by `texinfo-format-region'\n"
+            "from a region in: "
+            (if (buffer-file-name input-buffer)
+                  (concat "`"
+                          (file-name-sans-versions
+                           (file-name-nondirectory
+                            (buffer-file-name input-buffer)))
+                          "'")
+                (concat "buffer `" (buffer-name input-buffer) "'"))
+              "\nusing `texinfmt.el' version "
+              texinfmt-version
+              ".\n\n")
+
+    ;; Now convert for real.
+    (goto-char (point-min))
+    (texinfo-format-scan)
+    (goto-char (point-min))
+    
+    (message "Done.")))
+
+
+;;; Primary internal formatting function for the whole buffer.
+
+(defun texinfo-format-buffer-1 ()