changeset 4028:3831300d2ecb

Fix typo re `texinfo-sequential-node-update.' Ensure that no commands depend on the value of case-fold-search. Rewrite messages. Avoid using `mark-whole-buffer'. (texinfo-start-menu-description): New function to insert title as description in a menu. (texinfo-make-menu-list): Remove automatic title insertion. (texinfo-master-menu): Error message if file contains too few nodes for a master menu. Handle the case where no master menu was inserted. (texinfo-insert-master-menu-list): Only attempt to insert detailed master menu if there is one. Insert a master menu only after `Top' node and before next node. (texinfo-check-for-node-name): Offer section title as prompt. (texinfo-copy-next-section-title): Copy title correctly. Handle failure to find @node. (texinfo-copy-menu): Error message if menu empty. (texinfo-pointer-name): Find only those section commands that are accompanied by `@node' lines. (texinfo-section-types-regexp): Look for subh and subs, not just sub. (texinfo-make-one-menu): Copy node-name correctly for message. (texinfo-copy-menu-title): Copy title as it should rather than node line. (texinfo-find-higher-level-node): Stop search at limit. Special handling for `top' and `chapter' levels. (texinfo-copy-menu-title): Rewrite to handle outer include files. (texinfo-multi-file-update): Update all nodes properly (and sooner); rewrite doc string and interactive. Copy title properly. (texinfo-all-menus-update): Fixed typo that caused the function to create a master menu when it shouldn't. Update pre-existing master menu, if there is one. (texinfo-incorporate-descriptions): Use a regexp search to look for both kinds of menu item. (texinfo-menu-indent-description): Likewise. (texinfo-incorporate-menu-entry-names): New function. (texinfo-insert-menu): Handle both kinds of menu item. (texinfo-multi-files-insert-main-menu): Likewise. (texinfo-update-node): Pass t as second arg to push-mark. (texinfo-sequential-node-update): Likewise. (texinfo-insert-node-lines): Bind `title' at a higher level. Don't find previous @node if it's close. Take region to process as arguments. (texinfo-multiple-files-update): Handle prefix arg better within `interactive'. Canonicalize the blank lines.
author Richard M. Stallman <rms@gnu.org>
date Wed, 07 Jul 1993 22:15:20 +0000
parents afa1ecd408e1
children 8bf916902edc
files lisp/textmodes/texnfo-upd.el
diffstat 1 files changed, 757 insertions(+), 455 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/textmodes/texnfo-upd.el	Wed Jul 07 20:25:48 1993 +0000
+++ b/lisp/textmodes/texnfo-upd.el	Wed Jul 07 22:15:20 1993 +0000
@@ -1,9 +1,8 @@
-;;; texnfo-upd.el --- a utility for updating nodes and menus in Texinfo files.
+;;; Texinfo mode utilities for updating nodes and menus in Texinfo files.
+;;; Copyright 1989, 1990, 1991, 1992 Free Software Foundation
 
-;;;; Copyright 1989, 1990, 1992 Free Software Foundation
-
-;; Author: Bob Chassell <bob@gnu.ai.mit.edu>
-;; Version: 2.00
+;; Author: Robert J. Chassell      
+;; Maintainer: bug-texinfo@prep.ai.mit.edu
 ;; Keywords: maint, tex, docs
 
 ;; This file is part of GNU Emacs.
@@ -23,11 +22,10 @@
 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
 ;;; Commentary:
-
-;;;; Summary
 
-; (Much of the following commentary ought eventually be incorporated
-; into the Texinfo Manual.)
+;;; Known bug: update commands fail to ignore @ignore.
+
+;;; Summary: how to use the updating commands
 
 ; The node and menu updating functions automatically
 
@@ -35,13 +33,10 @@
 ;   * insert the `Next', `Previous' and `Up' pointers of a node,
 ;   * insert or update the menu for a section, 
 ;   * create a master menu for a Texinfo source file.
-
+;
 ; Passed an argument, the `texinfo-update-node' and
 ; `texinfo-make-menu' functions do their jobs in the region.
-
-; These functions replace doing these jobs by hand.
-; You may find them helpful.
-
+;
 ; In brief, the functions for creating or updating nodes and menus, are:
 ; 
 ;     texinfo-update-node (&optional region-p)            
@@ -81,8 +76,7 @@
 ; be the first node in the file.
 
 
-;;;; The updating functions in detail
-;    --------------------------------
+;;; The update node functions described in detail
 
 ; The `texinfo-update-node' function without an argument inserts
 ; the correct next, previous and up pointers for the node in which
@@ -98,10 +92,14 @@
 ; The `texinfo-every-node-update' function runs `texinfo-update-node'
 ; on the whole buffer.
 
-; The `texinfo-update-node' function inserts the immediately following
-; and preceding node into the `Next' or `Previous' pointers regardless
-; of their hierarchical level.  This is only useful for certain kinds
-; of text, like a novel, which you go through sequentially.  
+; The `texinfo-sequential-node-update' function inserts the
+; immediately following and preceding node into the `Next' or
+; `Previous' pointers regardless of their hierarchical level.  This is
+; only useful for certain kinds of text, like a novel, which you go
+; through sequentially.
+
+
+;;; The menu making functions described in detail
 
 ; The `texinfo-make-menu' function without an argument creates or
 ; updates a menu for the section encompassing the node that follows
@@ -146,9 +144,10 @@
 ; Since node names should be more concise than section or chapter
 ; titles, node names so inserted will need to be edited manually.
 
+ 
 ;;; Code:
- 
-;;;; Menu Making Functions
+
+;;; The menu making functions
 
 (defun texinfo-make-menu (&optional region-p)
   "Without any prefix argument, make or update a menu.
@@ -168,7 +167,7 @@
         (texinfo-make-one-menu level)
         (message "Done...updated the menu.  You may save the buffer."))
     ;; else
-    (message "Making or updating menus... ")
+    (message "Making or updating menus in %s... " (buffer-name))
     (let ((beginning (region-beginning))
 	  (region-end (region-end))
           (level (progn         ; find section type following point
@@ -207,40 +206,62 @@
        (first (texinfo-menu-first-node beginning end))
        (node-name (progn
                     (goto-char beginning)
+                    (beginning-of-line)
                     (texinfo-copy-node-name)))
        (new-menu-list (texinfo-make-menu-list beginning end level)))
     (if (texinfo-old-menu-p beginning first)
         (progn
           (texinfo-incorporate-descriptions new-menu-list)
+          (texinfo-incorporate-menu-entry-names new-menu-list)
           (texinfo-delete-old-menu beginning first)))
     (texinfo-insert-menu new-menu-list node-name)))
 
 (defun texinfo-all-menus-update (&optional update-all-nodes-p)
   "Update every regular menu in a Texinfo file.
-You must remove the detailed part of a pre-existing master menu before
-running this command, lest it be partly duplicated.
+Update pre-existing master menu, if there is one.
 
 If called with a non-nil argument, this function first updates all the
 nodes in the buffer before updating the menus."
   (interactive "P")
-  (save-excursion
-    (mark-whole-buffer)
-    (message "Checking for a master menu... ")
+  (let ((case-fold-search t)
+        master-menu-p)
     (save-excursion
-      (if (re-search-forward texinfo-master-menu-header nil t)
-          (error
-           "Please remove existing master menu, lest it be partly duplicated!")))
-
-  (if update-all-nodes-p
-      (progn
-        (message "First updating all nodes... ")
-        (sleep-for 2)
-        (mark-whole-buffer)
-        (texinfo-update-node t)))
-
-    (message "Updating all menus... ")
-    (sleep-for 2)
-    (texinfo-make-menu t)
+      (push-mark (point-max) t)
+      (goto-char (point-min))
+      (message "Checking for a master menu in %s ... "(buffer-name))
+      (save-excursion
+        (if (re-search-forward texinfo-master-menu-header nil t)
+            ;; Remove detailed master menu listing
+            (progn
+              (setq master-menu-p t)
+              (goto-char (match-beginning 0))
+              (let ((end-of-detailed-menu-descriptions
+                     (save-excursion     ; beginning of end menu line
+                       (goto-char (texinfo-menu-end))
+                       (beginning-of-line) (forward-char -1)
+                       (point))))
+                (delete-region (point) end-of-detailed-menu-descriptions)))))
+      
+      (if update-all-nodes-p
+          (progn
+            (message "Updating all nodes in %s ... " (buffer-name))
+            (sleep-for 2)
+            (push-mark (point-max) t)
+            (goto-char (point-min))
+            (texinfo-update-node t)))
+      
+      (message "Updating all menus in %s ... " (buffer-name))        
+      (sleep-for 2)
+      (push-mark (point-max) t)
+      (goto-char (point-min))
+      (texinfo-make-menu t)
+      
+      (if master-menu-p
+          (progn
+            (message "Updating the master menu in %s... " (buffer-name))
+            (sleep-for 2)
+            (texinfo-master-menu nil))))
+    
     (message "Done...updated all the menus.  You may save the buffer.")))
 
 (defun texinfo-find-lower-level-node (level region-end)
@@ -250,21 +271,21 @@
 
 Return t if the node is found, else nil.  Leave point at the beginning
 of the node if one is found; else do not move point."
-
-  (if (and (< (point) region-end)
-           (re-search-forward
-            (concat
-             "\\(^@node\\).*\n"         ; match node line
-             "\\(\\(\\(^@c\\).*\n\\)"   ; match comment line, if any
-             "\\|"                      ; or
-             "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
-             (eval (cdr (assoc level texinfo-update-menu-lower-regexps))))
-            ;; the next higher level node marks the end of this
-            ;; section, and no lower level node will be found beyond
-            ;; this position even if region-end is farther off
-            (texinfo-update-menu-region-end level) 
-            t))
-      (goto-char (match-beginning 1))))
+  (let ((case-fold-search t))
+    (if (and (< (point) region-end)
+             (re-search-forward
+              (concat
+               "\\(^@node\\).*\n"         ; match node line
+               "\\(\\(\\(^@c\\).*\n\\)"   ; match comment line, if any
+               "\\|"                      ; or
+               "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
+               (eval (cdr (assoc level texinfo-update-menu-lower-regexps))))
+              ;; the next higher level node marks the end of this
+              ;; section, and no lower level node will be found beyond
+              ;; this position even if region-end is farther off
+              (texinfo-update-menu-region-end level) 
+              t))
+        (goto-char (match-beginning 1)))))
 
 (defun texinfo-find-higher-level-node (level region-end)
   "Search forward from point for node at any higher level than argument LEVEL.
@@ -272,22 +293,24 @@
 
 Return t if the node is found, else nil.  Leave point at the beginning
 of the node if one is found; else do not move point."
-
-  (if (and (< (point) region-end)
-           (re-search-forward
-            (concat
-             "\\(^@node\\).*\n"         ; match node line
-             "\\(\\(\\(^@c\\).*\n\\)"   ; match comment line, if any
-             "\\|"                      ; or
-             "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
-             (eval                      ; (won't ever find a `top' node)
-              (cdr (assoc level texinfo-update-menu-higher-regexps))))
-            nil
-            t))
-      (goto-char (match-beginning 1))))
+  (let ((case-fold-search t))
+    (cond
+     ((or (string-equal "top" level) (string-equal "chapter" level))
+      (if (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" region-end t)
+          (progn (beginning-of-line) t)))
+     (t
+      (if (re-search-forward
+           (concat
+            "\\(^@node\\).*\n"              ; match node line
+            "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
+            "\\|"                           ; or
+            "\\(^@ifinfo[ ]*\n\\)\\)?"      ; ifinfo line, if any
+            (eval (cdr (assoc level texinfo-update-menu-higher-regexps))))
+           region-end t)
+          (progn (beginning-of-line) t))))))
 
 
-;;;; Making the list of new menu entries
+;;; Making the list of new menu entries
 
 (defun texinfo-make-menu-list (beginning end level)
   "Make a list of node names and their descriptions.
@@ -306,14 +329,16 @@
       (setq new-menu-list 
             (cons (cons 
                    (texinfo-copy-node-name)
-                   (texinfo-copy-section-title))
+                   (prog1 "" (forward-line 1)))
+                   ;; Use following to insert section titles automatically.
+                   ;; (texinfo-copy-section-title))
                   new-menu-list)))
     (reverse new-menu-list)))
 
 (defun texinfo-menu-locate-entry-p (level search-end)
   "Find a node that will be part of menu for this section.
 First argument is a string such as \"section\" specifying the general
-hierarchical level of the menu; second argument is a postion
+hierarchical level of the menu; second argument is a position
 specifying the end of the search.
 
 The function returns t if the node is found, else nil.  It searches
@@ -321,17 +346,18 @@
 
 The function finds entries of the same type.  Thus `subsections' and
 `unnumberedsubsecs' will appear in the same menu."
-  (if (re-search-forward
-       (concat
-        "\\(^@node\\).*\n"              ; match node line
-        "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
-        "\\|"                           ; or
-        "\\(^@ifinfo[ ]*\n\\)\\)?"      ; ifinfo line, if any
-        (eval
-         (cdr (assoc level texinfo-update-menu-same-level-regexps))))
-       search-end
-       t)
-      (goto-char (match-beginning 1))))
+  (let ((case-fold-search t))
+    (if (re-search-forward
+         (concat
+          "\\(^@node\\).*\n"              ; match node line
+          "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
+          "\\|"                           ; or
+          "\\(^@ifinfo[ ]*\n\\)\\)?"      ; ifinfo line, if any
+          (eval
+           (cdr (assoc level texinfo-update-menu-same-level-regexps))))
+         search-end
+         t)
+        (goto-char (match-beginning 1)))))
 
 (defun texinfo-copy-node-name ()
   "Return the node name as a string.
@@ -374,7 +400,7 @@
    (progn (end-of-line) (point))))
 
 
-;;;; Handling the old menu
+;;; Handling the old menu
 
 (defun texinfo-old-menu-p (beginning first)
   "Move point to the beginning of the menu for this section, if any.
@@ -397,24 +423,31 @@
 
 Point must be at beginning of old menu.
 
-If the node-name of the new menu entry cannot be found in the old
-menu, use the new section title for the description, but if the
-node-name of the new menu is found in the old menu, replace the
-section title with the old description, whatever it may be.
+If the node-name of the new menu is found in the old menu, insert the
+old description into the new entry.
 
 For this function, the new menu is a list made up of lists of dotted
 pairs in which the first element of the pair is the node name and the
-second element the description. The new menu is changed destructively.
+second element the description.  The new menu is changed destructively.
 The old menu is the menu as it appears in the texinfo file."
   
   (let ((new-menu-list-pointer new-menu-list)
         (end-of-menu (texinfo-menu-end)))
     (while new-menu-list
       (save-excursion                   ; keep point at beginning of menu 
-        (if (search-forward
-             (concat "\* "              ; so only menu entries are found
-                     (car (car new-menu-list))
-                     ":")               ; so only complete entries are found
+        (if (re-search-forward
+             ;; Existing nodes can have the form
+             ;;     * NODE NAME:: DESCRIPTION
+             ;; or
+             ;;     * MENU ITEM: NODE NAME.     DESCRIPTION.
+             ;; 
+             ;; Recognize both when looking for the description.
+             (concat "\\* \\("              ; so only menu entries are found
+                     (car (car new-menu-list)) "::"
+                     "\\|"
+                     ".*: " (car (car new-menu-list)) "[.,\t\n]"
+                     "\\)"
+                     )               ; so only complete entries are found
              end-of-menu
              t) 
             (setcdr (car new-menu-list) 
@@ -422,6 +455,47 @@
       (setq new-menu-list (cdr new-menu-list))) 
     (setq new-menu-list new-menu-list-pointer)))
 
+(defun texinfo-incorporate-menu-entry-names (new-menu-list)
+  "Copy any old menu entry names to the new menu.
+
+Point must be at beginning of old menu.
+
+If the node-name of the new menu entry cannot be found in the old
+menu, do nothing.
+
+For this function, the new menu is a list made up of lists of dotted
+pairs in which the first element of the pair is the node name and the
+second element is the description (or nil).
+
+If we find an existing menu entry name, we change the first element of
+the pair to be another dotted pair in which the car is the menu entry
+name and the cdr is the node name.
+
+NEW-MENU-LIST is changed destructively.  The old menu is the menu as it
+appears in the texinfo file."
+  
+  (let ((new-menu-list-pointer new-menu-list)
+        (end-of-menu (texinfo-menu-end)))
+    (while new-menu-list
+      (save-excursion                   ; keep point at beginning of menu 
+        (if (re-search-forward
+             ;; Existing nodes can have the form
+             ;;     * NODE NAME:: DESCRIPTION
+             ;; or
+             ;;     * MENU ITEM: NODE NAME.     DESCRIPTION.
+             ;; 
+             ;; We're interested in the second case.
+             (concat "\\* "              ; so only menu entries are found
+                     "\\(.*\\): " (car (car new-menu-list))  "[.,\t\n]")
+             end-of-menu
+             t)
+            (setcar
+              (car new-menu-list)  ; replace the node name
+              (cons (buffer-substring (match-beginning 1) (match-end 1))
+                    (car (car new-menu-list)))))
+      (setq new-menu-list (cdr new-menu-list))))
+    (setq new-menu-list new-menu-list-pointer)))
+
 (defun texinfo-menu-copy-old-description (end-of-menu)
   "Return description field of old menu line as string.
 Point must be located just after the node name.  Point left before description.
@@ -429,6 +503,7 @@
   (skip-chars-forward "[:.,\t\n ]+")
   ;; don't copy a carriage return at line beginning with asterisk!
   ;; do copy a description that begins with an `@'!
+  ;; !! Known bug: does not copy descriptions starting with ^|\{?* etc.
   (if (and (looking-at "\\(\\w+\\|@\\)")    
            (not (looking-at "\\(^\\* \\|^@end menu\\)")))  
       (buffer-substring
@@ -461,7 +536,7 @@
                    (point))))
 
 
-;;;; Inserting new menu
+;;; Inserting new menu
 
 ;; try 32, but perhaps 24 is better
 (defvar texinfo-column-for-description 32
@@ -475,30 +550,124 @@
 MENU-LIST has form:
 
     \(\(\"node-name1\" . \"description\"\) 
-    \(\"node-name\" . \"description\"\) ... \)
+    \(\"node-name2\" . \"description\"\) ... \)
+
+However, the description field might be nil.
 
-However, there does not need to be a description field."
+Also, the node-name field might itself be a dotted pair (call it P) of
+strings instead of just a string.  In that case, the car of P
+is the menu entry name, and the cdr of P is the node name."
   
   (insert "@menu\n")
   (while menu-list
-    (if (cdr (car menu-list))       ; menu-list has description entry
+    ;; Every menu entry starts with a star and a space.
+    (insert "* ")
+    
+    ;; Insert the node name (and menu entry name, if present).
+    (let ((node-part (car (car menu-list))))
+      (if (stringp node-part)
+          ;; "Double colon" entry line; menu entry and node name are the same,
+          (insert (format "%s::" node-part))  
+        ;; "Single colon" entry line; menu entry and node name are different.
+        (insert (format "%s: %s." (car node-part) (cdr node-part)))))
+    
+    ;; Insert the description, if present.
+    (if (cdr (car menu-list))
         (progn
-          (insert 
-           (format "* %s::" (car (car menu-list)))) ; node-name entry
-          (indent-to texinfo-column-for-description 2)
-          (insert 
-           (format "%s\n" (cdr (car menu-list)))))  ; description entry
-        ;; else menu-list lacks description entry
-      (insert
-       (format "* %s::\n" (car (car menu-list)))))  ; node-name entry
+          ;; Move to right place.
+          (indent-to texinfo-column-for-description 2) 
+          ;; Insert description.
+          (insert (format "%s" (cdr (car menu-list))))))  
+
+    (insert "\n") ; end this menu entry
     (setq menu-list (cdr menu-list)))
   (insert "@end menu")
-  (message
-   "Updated \"%s\" level menu following node: %s ... "
-   level node-name))
+  (message 
+   "Updated \"%s\" level menu following node: %s ... " level node-name))
 
 
-;;;; Handling description indentation
+;;; Starting menu descriptions by inserting titles
+
+(defun texinfo-start-menu-description ()
+  "In this menu entry, insert the node's section title as a description. 
+Position point at beginning of description ready for editing.
+Do not insert a title if the line contains an existing description.
+
+You will need to edit the inserted text since a useful description
+complements the node name rather than repeats it as a title does."
+  
+  (interactive)
+  (let (beginning end node-name title)
+    (save-excursion
+    (beginning-of-line)  
+      (if (search-forward "* " (save-excursion (end-of-line) (point)) t)
+          (progn (skip-chars-forward " \t")
+                 (setq beginning (point)))
+        (error "This is not a line in a menu!"))
+      
+      (cond
+        ;; "Double colon" entry line; menu entry and node name are the same,
+       ((search-forward "::" (save-excursion (end-of-line) (point)) t)
+        (if (looking-at "[ \t]*[^ \t\n]+")
+            (error "Descriptive text already exists."))
+        (skip-chars-backward ": \t")
+        (setq node-name (buffer-substring beginning (point))))
+       
+       ;; "Single colon" entry line; menu entry and node name are different.
+       ((search-forward ":" (save-excursion (end-of-line) (point)) t)
+        (skip-chars-forward " \t")
+        (setq beginning (point))
+        ;; Menu entry line ends in a period, comma, or tab. 
+        (if (re-search-forward "[.,\t]"
+                               (save-excursion (forward-line 1) (point)) t)
+            (progn
+              (if (looking-at "[ \t]*[^ \t\n]+")
+                  (error "Descriptive text already exists."))
+              (skip-chars-backward "., \t")
+              (setq node-name (buffer-substring beginning (point))))
+          ;; Menu entry line ends in a return.
+          (re-search-forward ".*\n"
+                           (save-excursion (forward-line 1) (point)) t)
+          (skip-chars-backward " \t\n")
+          (setq node-name (buffer-substring beginning (point)))
+          (if (= 0 (length node-name))
+              (error "No node name on this line.")
+            (insert "."))))
+       (t (error "No node name on this line.")))
+      ;; Search for node that matches node name, and copy the section title.
+      (if (re-search-forward
+           (concat 
+            "^@node[ \t]+"
+            node-name
+            ".*\n"                             ; match node line
+            "\\("
+            "\\(\\(^@c \\|^@comment\\).*\n\\)" ; match comment line, if any
+            "\\|"                              ; or
+            "\\(^@ifinfo[ ]*\n\\)"             ; ifinfo line, if any
+            "\\)?")
+           nil t)
+          (progn
+            (setq title
+                  (buffer-substring
+                   ;; skip over section type
+                   (progn (forward-word 1) 
+                          ;; and over spaces
+                          (skip-chars-forward " \t") 
+                          (point))
+                   (progn (end-of-line)
+                          (skip-chars-backward " \t")
+                          (point)))))
+        (error "Cannot find node to match node name in menu entry.")))
+    ;; Return point to the menu and insert the title.
+    (end-of-line)
+    (delete-region
+     (point)
+     (save-excursion (skip-chars-backward " \t") (point)))
+    (indent-to texinfo-column-for-description 2)
+    (save-excursion (insert title))))
+
+
+;;; Handling description indentation
 
 ; Since the make-menu functions indent descriptions, these functions
 ; are useful primarily for indenting a single menu specially.
@@ -540,7 +709,10 @@
                 (goto-char (texinfo-menu-end))
                 (beginning-of-line)
                 (point)))
-      (if (search-forward "::" (texinfo-menu-end) t)
+
+      (if (re-search-forward  "\\* \\(.*::\\|.*: [^.,\t\n]+[.,\t]\\)" 
+           (texinfo-menu-end) 
+           t)
           (progn
             (let ((beginning-white-space (point)))
               (skip-chars-forward " \t")  ; skip over spaces
@@ -554,7 +726,7 @@
       (setq beginning-of-next-line (point)))))
 
 
-;;;; Making the master menu
+;;; Making the master menu
 
 (defun texinfo-master-menu (update-all-nodes-menus-p)
   "Make a master menu for a whole Texinfo file.
@@ -570,7 +742,7 @@
 menus) before it constructs the master menu.
 
 The function removes the detailed part of an already existing master
-menu.  This action depends on the pre-existing master menu using the
+menu.  This action depends on the pre-exisitng master menu using the
 standard `texinfo-master-menu-header'.
 
 The master menu has the following format, which is adapted from the
@@ -588,66 +760,76 @@
 
 Each of the menus in the detailed node listing is introduced by the
 title of the section containing the menu."
-
+  
   (interactive "P")
-  (widen)
-  (goto-char (point-min))
-
-  ;; Move point to location after `top'.
-  (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
-      (error "This buffer needs a Top node!"))
-
-  (let ((first-chapter                  
-         (save-excursion (re-search-forward "^@node") (point))))
-    (if (re-search-forward texinfo-master-menu-header first-chapter t)
-        ;; Remove detailed master menu listing
-        (progn
-           (goto-char (match-beginning 0))
-          (let ((end-of-detailed-menu-descriptions
-                 (save-excursion     ; beginning of end menu line
-                   (goto-char (texinfo-menu-end))
-                   (beginning-of-line) (forward-char -1)
-                   (point))))
-            (delete-region (point) end-of-detailed-menu-descriptions)))))
-
-  (if update-all-nodes-menus-p
-      (progn
-        (message "Making a master menu...first updating all nodes... ")
-        (sleep-for 2)
-        (mark-whole-buffer)
-        (texinfo-update-node t)
-
-        (message "Updating all menus... ")        
-        (sleep-for 2)
-        (mark-whole-buffer)
-        (texinfo-make-menu t)))
-
-  (message "Now making the master menu... ")
-  (sleep-for 2)
-  (goto-char (point-min))
-  (texinfo-insert-master-menu-list
-   (texinfo-master-menu-list))
-
-  ;; Remove extra newlines that texinfo-insert-master-menu-list
-  ;; may have inserted.
-
-  (save-excursion
+  (let ((case-fold-search t))
+    (widen)
     (goto-char (point-min))
     
-    (re-search-forward texinfo-master-menu-header)
-    (goto-char (match-beginning 0))
-    (insert "\n")
-    (delete-blank-lines)
+    ;; Move point to location after `top'.
+    (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
+        (error "This buffer needs a Top node!"))
+    
+    (let ((first-chapter                  
+           (save-excursion
+             (or (re-search-forward "^@node" nil t)
+                 (error "Too few nodes for a master menu!"))
+             (point))))
+      (if (re-search-forward texinfo-master-menu-header first-chapter t)
+          ;; Remove detailed master menu listing
+          (progn
+            (goto-char (match-beginning 0))
+            (let ((end-of-detailed-menu-descriptions
+                   (save-excursion     ; beginning of end menu line
+                     (goto-char (texinfo-menu-end))
+                     (beginning-of-line) (forward-char -1)
+                     (point))))
+              (delete-region (point) end-of-detailed-menu-descriptions)))))
     
-    (re-search-backward "^@menu")
-    (forward-line -1)
-    (delete-blank-lines)
+    (if update-all-nodes-menus-p
+        (progn
+          (message "Making a master menu in %s ...first updating all nodes... "
+                   (buffer-name))
+          (sleep-for 2)
+          (push-mark (point-max) t)
+          (goto-char (point-min))
+          (texinfo-update-node t)
+          
+          (message "Updating all menus in %s ... " (buffer-name))        
+          (sleep-for 2)
+          (push-mark (point-max) t)
+          (goto-char (point-min))
+          (texinfo-make-menu t)))
+    
+    (message "Now making the master menu in %s... " (buffer-name))
+    (sleep-for 2)
+    (goto-char (point-min))
+    (texinfo-insert-master-menu-list
+     (texinfo-master-menu-list))
     
-    (re-search-forward "^@end menu")
-    (forward-line 1)
-    (delete-blank-lines))
+    ;; Remove extra newlines that texinfo-insert-master-menu-list
+    ;; may have inserted.
+    
+    (save-excursion
+      (goto-char (point-min))
+      
+      (if (re-search-forward texinfo-master-menu-header nil t)
+          (progn
+            (goto-char (match-beginning 0))
+            (insert "\n")
+            (delete-blank-lines)
+            (goto-char (point-min))))
 
-  (message "Done...completed making master menu.  You may save the buffer."))
+      (re-search-forward "^@menu")
+      (forward-line -1)
+      (delete-blank-lines)
+      
+      (re-search-forward "^@end menu")
+      (forward-line 1)
+      (delete-blank-lines))
+    
+    (message
+     "Done...completed making master menu.  You may save the buffer.")))
 
 (defun texinfo-master-menu-list ()
   "Return a list of menu entries and header lines for the master menu.
@@ -675,51 +857,60 @@
 (defun texinfo-insert-master-menu-list (master-menu-list)
   "Format and insert the master menu in the current buffer."
   (goto-char (point-min))
-  (re-search-forward "^@menu")
+  ;; Insert a master menu only after `Top' node and before next node
+  ;; \(or include file if there is no next node\).
+  (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
+      (error "This buffer needs a Top node!"))
+  (let ((first-chapter
+         (save-excursion (re-search-forward "^@node\\|^@include") (point))))
+    (if (not (re-search-forward "^@menu" first-chapter t))
+        (error
+         "Buffer lacks ordinary `Top' menu in which to insert master.")))
   (beginning-of-line)
-  (delete-region (point)        ; buffer must have ordinary top menu
-                 (save-excursion
-                   (re-search-forward "^@end menu")
-                   (point)))
-
-  (save-excursion                       ; leave point at beginning of menu
-  ;; Handle top of menu
-  (insert "\n@menu\n")
-  ;; Insert chapter menu entries
-  (setq this-very-menu-list (reverse (car (car master-menu-list))))
-  ;;; Tell user what is going on.
-  (message "Inserting chapter menu entry: %s ... " this-very-menu-list)
-  (while this-very-menu-list
-    (insert "* " (car this-very-menu-list) "\n")
-    (setq this-very-menu-list (cdr this-very-menu-list)))
+  (delete-region      ; buffer must have ordinary top menu
+   (point)   
+   (save-excursion (re-search-forward "^@end menu") (point)))
   
-  (setq master-menu-list (cdr master-menu-list))
-
-  (insert texinfo-master-menu-header)
-  
-  ;; Now, insert all the other menus
-
-  ;; The menu master-menu-list has a form like this:
-  ;; ((("beta"  "alpha") "title-A")
-  ;;  (("delta" "gamma") "title-B"))
-
-  (while master-menu-list
-
-    (message
-     "Inserting menu for %s .... " (car (cdr (car master-menu-list))))
-    ;; insert title of menu section
-    (insert "\n" (car (cdr (car master-menu-list))) "\n\n")
-
-    ;; insert each menu entry
+  (save-excursion                       ; leave point at beginning of menu
+    ;; Handle top of menu
+    (insert "\n@menu\n")
+    ;; Insert chapter menu entries
     (setq this-very-menu-list (reverse (car (car master-menu-list))))
+    ;; Tell user what is going on.
+    (message "Inserting chapter menu entry: %s ... " this-very-menu-list)
     (while this-very-menu-list
       (insert "* " (car this-very-menu-list) "\n")
       (setq this-very-menu-list (cdr this-very-menu-list)))
     
-    (setq master-menu-list (cdr master-menu-list)))
-  
-  ;; Finish menu
-  (insert "@end menu\n\n")))
+    (setq master-menu-list (cdr master-menu-list))
+    
+    ;; Only insert detailed master menu if there is one....
+    (if (car (car master-menu-list))
+        (insert texinfo-master-menu-header))
+    
+    ;; Now, insert all the other menus
+    
+    ;; The menu master-menu-list has a form like this:
+    ;; ((("beta"  "alpha") "title-A")
+    ;;  (("delta" "gamma") "title-B"))
+    
+    (while master-menu-list
+      
+      (message
+       "Inserting menu for %s .... " (car (cdr (car master-menu-list))))
+      ;; insert title of menu section
+      (insert "\n" (car (cdr (car master-menu-list))) "\n\n")
+      
+      ;; insert each menu entry
+      (setq this-very-menu-list (reverse (car (car master-menu-list))))
+      (while this-very-menu-list
+        (insert "* " (car this-very-menu-list) "\n")
+        (setq this-very-menu-list (cdr this-very-menu-list)))
+      
+      (setq master-menu-list (cdr master-menu-list)))
+    
+    ;; Finish menu
+    (insert "@end menu\n\n")))
 
 (defvar texinfo-master-menu-header
   "\n --- The Detailed Node Listing ---\n"
@@ -736,21 +927,24 @@
   "Return the title of the section preceding the menu as a string.
 If such a title cannot be found, return an empty string.  Do not move
 point."
-  (save-excursion
-    (if (re-search-backward
-         (concat
-          "\\(^@node\\).*\n"            ; match node line
-          "\\(\\(\\(^@c\\).*\n\\)"      ; match comment line, if any
-          "\\|"                         ; or
-          "\\(^@ifinfo[ ]*\n\\)\\)?"    ; ifinfo line, if any
-          (eval
-           (cdr
-            (assoc (texinfo-hierarchic-level)
-                   texinfo-update-menu-higher-regexps))))
-         nil
-         t)
-        (texinfo-copy-section-title)
-      " ")))
+  (let ((case-fold-search t))
+    (save-excursion
+      (if (re-search-backward
+           (concat
+            "\\(^@top"
+            "\\|"                         ; or
+            texinfo-section-types-regexp  ; all other section types
+            "\\)")
+           nil
+           t)
+          (progn
+            (beginning-of-line)
+            (forward-word 1)              ; skip over section type
+            (skip-chars-forward " \t")    ; and over spaces
+            (buffer-substring
+             (point)
+             (progn (end-of-line) (point))))
+        ""))))
 
 (defun texinfo-copy-menu ()
   "Return the entries of an existing menu as a list.
@@ -761,7 +955,9 @@
          (last-entry (save-excursion      ; position of beginning of
                                           ; last `* ' entry
                       (goto-char end-of-menu)
-                      (re-search-backward "^\* ") ; handle multi-line desc.
+                      ;; handle multi-line description
+                      (if (not (re-search-backward "^\* " nil t))
+                          (error "No entries in menu."))
                       (point))))
     (while (< (point) last-entry)
       (if (re-search-forward  "^\* " end-of-menu t)
@@ -778,7 +974,7 @@
     this-menu-list))
 
 
-;;;; Determining the hierarchical level in the texinfo file
+;;; Determining the hierarchical level in the texinfo file
 
 (defun texinfo-specific-section-type () 
   "Return the specific type of next section, as a string.
@@ -787,60 +983,67 @@
 Searches forward for a section.  Hence, point must be before the
 section whose type will be found.  Does not move point.  Signal an
 error if the node is not the top node and a section is not found."
-  (save-excursion
-    (cond
-     ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
-			 (save-excursion
-			   (end-of-line)
-			   (point))
-			 t)
-      "top")
-     ((re-search-forward texinfo-section-types-regexp nil t)
-      (buffer-substring (progn (beginning-of-line) ; copy its name
-                               (1+ (point)))
-                        (progn (forward-word 1)
-                               (point))))
-     (t
-      (error
-       "texinfo-specific-section-type: Chapter or section not found.")))))
+  (let ((case-fold-search t))
+    (save-excursion
+      (cond
+       ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
+;;; Following search limit by cph but causes a bug
+;;;			 (save-excursion
+;;;			   (end-of-line)
+;;;			   (point))
+                           nil
+                           t)
+        "top")
+       ((re-search-forward texinfo-section-types-regexp nil t)
+        (buffer-substring (progn (beginning-of-line) ; copy its name
+                                 (1+ (point)))
+                          (progn (forward-word 1)
+                                 (point))))
+       (t
+        (error
+         "texinfo-specific-section-type: Chapter or section not found."))))))
 
 (defun texinfo-hierarchic-level ()
   "Return the general hierarchal level of the next node in a texinfo file.
 Thus, a subheading or appendixsubsec is of type subsection."
-  (cdr (assoc
-        (texinfo-specific-section-type)
-        texinfo-section-to-generic-alist)))
+  (let ((case-fold-search t))
+    (cdr (assoc
+          (texinfo-specific-section-type)
+          texinfo-section-to-generic-alist))))
 
 
-;;;; Locating the major positions
+;;; Locating the major positions
 
 (defun texinfo-update-menu-region-beginning (level)  
   "Locate beginning of higher level section this section is within.
 Return position of the beginning of the node line; do not move point.
 Thus, if this level is subsection, searches backwards for section node.
 Only argument is a string of the general type of section."
-  
-  (cond
-   ((or (string-equal "top" level)
-	(string-equal "chapter" level))
-    (save-excursion
-      (goto-char (point-min))
-      (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)
-      (beginning-of-line)
-      (point)))
-   (t
-    (save-excursion
-      (re-search-backward
-       (concat
-        "\\(^@node\\).*\n"              ; match node line
-        "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
-        "\\|"                           ; or
-        "\\(^@ifinfo[ ]*\n\\)\\)?"      ; ifinfo line, if any
-        (eval
-         (cdr (assoc level texinfo-update-menu-higher-regexps))))
-       nil
-       'goto-beginning)
-      (point)))))
+  (let ((case-fold-search t))
+    ;; !! Known bug: if section immediately follows top node, this
+    ;; returns the beginning of the buffer as the beginning of the
+    ;; higher level section.
+    (cond
+     ((or (string-equal "top" level)
+          (string-equal "chapter" level))
+      (save-excursion
+        (goto-char (point-min))
+        (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)
+        (beginning-of-line)
+        (point)))
+     (t
+      (save-excursion
+        (re-search-backward
+         (concat
+          "\\(^@node\\).*\n"              ; match node line
+          "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
+          "\\|"                           ; or
+          "\\(^@ifinfo[ ]*\n\\)\\)?"      ; ifinfo line, if any
+          (eval
+           (cdr (assoc level texinfo-update-menu-higher-regexps))))
+         nil
+         'goto-beginning)
+        (point))))))
 
 (defun texinfo-update-menu-region-end (level)  
   "Locate end of higher level section this section is within.
@@ -848,20 +1051,21 @@
 subsection, find the node for the section this subsection is within.
 If level is top or chapter, returns end of file.  Only argument is a
 string of the general type of section."
-
-  (save-excursion
-    (if (re-search-forward
-         (concat
-          "\\(^@node\\).*\n"            ; match node line
-          "\\(\\(\\(^@c\\).*\n\\)"      ; match comment line, if any
-          "\\|"                         ; or
-          "\\(^@ifinfo[ ]*\n\\)\\)?"    ; ifinfo line, if any
-          (eval
-           (cdr (assoc level texinfo-update-menu-higher-regexps))))
-         nil
-         'goto-end)
-        (match-beginning 1)
-      (point-max))))
+  (let ((case-fold-search t))
+    (save-excursion
+      (if (re-search-forward
+           (concat
+            "\\(^@node\\).*\n"            ; match node line
+            "\\(\\(\\(^@c\\).*\n\\)"      ; match comment line, if any
+            "\\|"                         ; or
+            "\\(^@ifinfo[ ]*\n\\)\\)?"    ; ifinfo line, if any
+            (eval
+             ;; Never finds end of level above chapter so goes to end.
+             (cdr (assoc level texinfo-update-menu-higher-regexps))))
+           nil
+           'goto-end)
+          (match-beginning 1)
+        (point-max)))))
 
 (defun texinfo-menu-first-node (beginning end)
   "Locate first node of the section the menu will be placed in.  
@@ -880,7 +1084,7 @@
     (point)))
 
 
-;;;; Alists and regular expressions for defining hierarchical levels
+;;; Alists and regular expressions for defining hierarchical levels
 
 (defvar texinfo-section-to-generic-alist
   '(("top" . "top")
@@ -909,8 +1113,9 @@
 The keys are strings specifying specific types of section; the values
 are strings of their corresponding general types.")
 
+;; We used to look for just sub, but that found @subtitle.
 (defvar texinfo-section-types-regexp
-  "^@\\(chapter \\|sect\\|sub\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)"
+  "^@\\(chapter \\|sect\\|subs\\|subh\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)"
   "Regexp matching chapter, section, other headings (but not the top node).")
 
 (defvar texinfo-chapter-level-regexp 
@@ -1010,7 +1215,7 @@
 document; the values are regular expressions.")
 
 
-;;;; Updating a Node
+;;; Updating a node
 
 (defun texinfo-update-node (&optional region-p)
   "Without any prefix argument, update the node in which point is located.
@@ -1031,7 +1236,7 @@
     texinfo-indent-menu-description (column &optional region-p)
 
 The `texinfo-column-for-description' variable specifies the column to
-which menu descriptions are indented. Its default value is 24."
+which menu descriptions are indented. Its default value is 32."
   
   (interactive "P")
   (if (not region-p)
@@ -1049,7 +1254,7 @@
       (save-restriction
 	(narrow-to-region beginning end)
 	(goto-char beginning)
-        (push-mark)
+        (push-mark (point) t)
 	(while (re-search-forward "^@node" (point-max) t)
           (beginning-of-line)            
           (texinfo-update-the-node))
@@ -1059,7 +1264,8 @@
   "Update every node in a Texinfo file."
   (interactive)
   (save-excursion
-    (mark-whole-buffer)
+    (push-mark (point-max) t)
+    (goto-char (point-min))
     (texinfo-update-node t)
     (message "Done...updated every node.       You may save the buffer.")))
 
@@ -1111,12 +1317,17 @@
   "Determine whether the node has a node name.  Prompt for one if not.
 Point must be at beginning of node line.  Does not move point."
   (save-excursion
-    (forward-word 1)                    ; skip over node command
-    (skip-chars-forward " \t")          ; and over spaces
-    (if (not (looking-at "[^,\t\n ]+")) ; regexp based on what info looks for
-                                        ; alternatively, use "[a-zA-Z]+"
-        (let ((node-name (read-from-minibuffer "Node name: ")))
-          (insert " " node-name)))))
+    (let ((initial (texinfo-copy-next-section-title)))
+      ;; This is not clean.  Use `interactive' to read the arg.
+      (forward-word 1)                    ; skip over node command
+      (skip-chars-forward " \t")          ; and over spaces
+      (if (not (looking-at "[^,\t\n ]+")) ; regexp based on what Info looks for
+                                          ; alternatively, use "[a-zA-Z]+"
+        (let ((node-name
+               (read-from-minibuffer
+                "Node name (use no @, commas, colons, or apostrophes): "
+                initial)))
+          (insert " " node-name))))))
 
 (defun texinfo-delete-existing-pointers ()
   "Delete `Next', `Previous', and `Up' pointers.  
@@ -1144,42 +1355,71 @@
 will be at some level higher in the Texinfo file.  The fourth argument
 \(one of 'next, 'previous, or 'up\) specifies whether to find the
 `Next', `Previous', or `Up' pointer."
-
-  (cond ((eq direction 'next)
-         (forward-line 3)             ; skip over current node
-         (if (re-search-forward
-              (eval
-               (cdr (assoc level texinfo-update-menu-same-level-regexps)))
-              end
-              t)
-             'normal
-           'no-pointer))
-        ((eq direction 'previous)
-         (if (re-search-backward
-              (concat
-               "\\("
-               (eval
-                (cdr (assoc level texinfo-update-menu-same-level-regexps)))
-               "\\|"
-               (eval
-                (cdr (assoc level texinfo-update-menu-higher-regexps)))
-               "\\)")
-              beginning
-              t)
-             'normal
-           'no-pointer))
-        ((eq direction 'up)
-         (if (re-search-backward
-             (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
-              (save-excursion
-                (goto-char beginning)
-                (beginning-of-line)
-                (point))
-              t)
-             'normal
-           'no-pointer))
-        (t
-         (error "texinfo-find-pointer: lack proper arguments"))))
+  (let ((case-fold-search t))
+    (cond ((eq direction 'next)
+           (forward-line 3)             ; skip over current node
+           ;; Search for section commands accompanied by node lines;
+           ;; ignore section commands in the middle of nodes.
+           (if (re-search-forward
+                ;; A `Top' node is never a next pointer, so won't find it.
+                (concat
+                 ;; Match node line.
+                 "\\(^@node\\).*\n"         
+                 ;; Match comment or ifinfo line, if any
+                 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?" 
+                 (eval
+                  (cdr (assoc level texinfo-update-menu-same-level-regexps))))
+                end
+                t)
+               'normal
+             'no-pointer))
+          ((eq direction 'previous)
+           (if (re-search-backward
+                (concat
+                 "\\("
+                 ;; Match node line.
+                 "\\(^@node\\).*\n"         
+                 ;; Match comment or ifinfo line, if any
+                 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?" 
+                 (eval
+                  (cdr (assoc level texinfo-update-menu-same-level-regexps)))
+                 "\\|"
+                 ;; Match node line.
+                 "\\(^@node\\).*\n"         
+                 ;; Match comment or ifinfo line, if any
+                 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?" 
+                 (eval
+                  (cdr (assoc level texinfo-update-menu-higher-regexps)))
+                 "\\|"
+                 ;; Handle `Top' node specially.
+                 "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
+                 "\\)")
+                beginning
+                t)
+               'normal
+             'no-pointer))
+          ((eq direction 'up)
+           (if (re-search-backward
+                (concat
+                 "\\("
+                 ;; Match node line.
+                 "\\(^@node\\).*\n"         
+                 ;; Match comment or ifinfo line, if any
+                 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?" 
+                 (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
+                 "\\|"
+                 ;; Handle `Top' node specially.
+                 "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
+                 "\\)")
+                (save-excursion
+                  (goto-char beginning)
+                  (beginning-of-line)
+                  (point))
+                t)
+               'normal
+             'no-pointer))
+          (t
+           (error "texinfo-find-pointer: lack proper arguments")))))
 
 (defun texinfo-pointer-name (kind)
   "Return the node name preceding the section command.
@@ -1221,7 +1461,7 @@
   (delete-region (point) (save-excursion (end-of-line) (point))))
 
 
-;;;; Updating nodes sequentially
+;;; Updating nodes sequentially
 ; These sequential update functions insert `Next' or `Previous'
 ; pointers that point to the following or preceding nodes even if they
 ; are at higher or lower hierarchical levels.  This means that if a
@@ -1264,7 +1504,7 @@
       (save-restriction
         (narrow-to-region beginning end)
         (goto-char beginning)
-        (push-mark)
+        (push-mark (point) t)
         (while (re-search-forward "^@node" (point-max) t)
           (beginning-of-line)            
           (texinfo-sequentially-update-the-node))
@@ -1306,31 +1546,31 @@
 pointer, some level higher.  The second argument (one of 'next,
 'previous, or 'up) specifies whether to find the `Next', `Previous',
 or `Up' pointer."
-  
-  (cond ((eq direction 'next)
-         (forward-line 3)             ; skip over current node
-         (if (re-search-forward 
-              texinfo-section-types-regexp
-              (point-max)
-              t)
-             'normal
-           'no-pointer))
-        ((eq direction 'previous)
-         (if (re-search-backward 
-              texinfo-section-types-regexp
-              (point-min)
-              t)
-             'normal
-           'no-pointer))
-        ((eq direction 'up)
-         (if (re-search-backward
-              (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
-              beginning
-              t)
-             'normal
-           'no-pointer))
-        (t
-         (error "texinfo-sequential-find-pointer: lack proper arguments"))))
+  (let ((case-fold-search t))  
+    (cond ((eq direction 'next)
+           (forward-line 3)             ; skip over current node
+           (if (re-search-forward 
+                texinfo-section-types-regexp
+                (point-max)
+                t)
+               'normal
+             'no-pointer))
+          ((eq direction 'previous)
+           (if (re-search-backward 
+                texinfo-section-types-regexp
+                (point-min)
+                t)
+               'normal
+             'no-pointer))
+          ((eq direction 'up)
+           (if (re-search-backward
+                (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
+                beginning
+                t)
+               'normal
+             'no-pointer))
+          (t
+           (error "texinfo-sequential-find-pointer: lack proper arguments")))))
 
 (defun texinfo-sequentially-insert-pointer (level direction)
   "Insert the `Next', `Previous' or `Up' node name at point.
@@ -1348,67 +1588,82 @@
       (texinfo-sequentially-find-pointer level direction)))))
 
 
-;;;; Inserting `@node' lines
+;;; Inserting `@node' lines
 ; The `texinfo-insert-node-lines' function inserts `@node' lines as needed
 ; before the `@chapter', `@section', and such like lines of a region
 ; in a Texinfo file.
 
-(defun texinfo-insert-node-lines (&optional title-p)
+(defun texinfo-insert-node-lines (beginning end &optional title-p)
   "Insert missing `@node' lines in region of Texinfo file.
 Non-nil argument (prefix, if interactive) means also to insert the
 section titles as node names; and also to insert the section titles as
 node names in pre-existing @node lines that lack names."
-  (interactive "P")
-  (save-excursion
-    (let ((begin-region  (region-beginning))
-          (end-region (region-end)))
-      (goto-char begin-region)
-      (while (< (point) end-region)
-        (re-search-forward texinfo-section-types-regexp nil 'end)
-        ;; copy title, since most often, we will need it
-        (let ((title
-               (progn
-                 (beginning-of-line)
-                 (forward-word 1)
-                 (skip-chars-forward " \t")
-                 (buffer-substring
-                  (point)
-                  (save-excursion (end-of-line) (point))))))
-          ;; insert a node if necessary
-          (if (re-search-backward
-               "^@node"
-               (save-excursion
-                 (forward-line -3)
-                 (point))
-               t)
-              ;;  @node present, and point at beginning of that line
-              (forward-word 1)
-            ;; else @node missing, insert one
-            (progn
-              (beginning-of-line)       ; beginning of `@section' line
-              (insert "@node\n")
-              (backward-char 1)))       ; leave point just after `@node'
-          ;; insert a title if warranted
-          (if title-p
-              (progn
-                (skip-chars-forward " \t")
-                ;; use regexp based on what info looks for
-                ;; (alternatively, use "[a-zA-Z]+")
-                (if (not (looking-at "[^,\t\n ]+")) 
-                    (progn
-                      (beginning-of-line) 
-                      (forward-word 1)
-                      (insert " " title)
-                      (message "Inserted title %s ... " title)))))
-          ;; in any case, go forward beyond current section title
-          (forward-line 3)))))
-  (if title-p
+  (interactive "r\nP")
+
+  ;; Use marker; after inserting node lines, leave point at end of
+  ;; region and mark at beginning.
+
+  (let (beginning-marker end-marker title last-section-position)
+
+    ;; Save current position on mark ring and set mark to end.
+    (push-mark end t)                   
+    (setq end-marker (mark-marker))        
+
+    (goto-char beginning)
+    (while (re-search-forward
+            texinfo-section-types-regexp 
+            end-marker
+            'end)
+      ;; Copy title if desired.
+      (if title-p
+          (progn 
+            (beginning-of-line)
+            (forward-word 1)
+            (skip-chars-forward " \t")
+            (setq title (buffer-substring
+                         (point)
+                         (save-excursion (end-of-line) (point))))))
+      ;; Insert node line if necessary.
+      (if (re-search-backward
+           "^@node" 
+           ;; Avoid finding previous node line if node lines are close.
+           (or last-section-position    
+               (save-excursion (forward-line -2) (point))) t)
+          ;;  @node is present, and point at beginning of that line
+          (forward-word 1)          ; Leave point just after @node.
+        ;; Else @node missing; insert one.
+        (beginning-of-line)         ; Beginning of `@section' line.
+        (insert "@node\n")
+        (backward-char 1))          ; Leave point just after `@node'.
+      ;; Insert title if desired.
+      (if title-p
+          (progn
+            (skip-chars-forward " \t")
+            ;; Use regexp based on what info looks for
+            ;; (alternatively, use "[a-zA-Z]+");
+            ;; this means we only insert a title if none exists.
+            (if (not (looking-at "[^,\t\n ]+")) 
+                (progn
+                  (beginning-of-line) 
+                  (forward-word 1)
+                  (insert " " title)
+                  (message "Inserted title %s ... " title)))))
+      ;; Go forward beyond current section title.
+      (re-search-forward texinfo-section-types-regexp 
+                         (save-excursion (forward-line 3) (point)) t)
+      (setq last-section-position (point))
+      (forward-line 1))
+
+    ;; Leave point at end of region, mark at beginning.
+    (set-mark beginning)
+
+    (if title-p
       (message
        "Done inserting node lines and titles.  You may save the buffer.")
-    (message "Done inserting node lines.  You may save the buffer.")))
+    (message "Done inserting node lines.  You may save the buffer."))))
 
 
-;;;; Update and create menus for multi-file Texinfo sources
+;;; Update and create menus for multi-file Texinfo sources
 
 ;;  1. M-x texinfo-multiple-files-update 
 ;;
@@ -1437,7 +1692,7 @@
 ;;;     Hence, you may need a file for indices.
 
 
-;;;; Auxiliary functions for multiple file updating
+;;; Auxiliary functions for multiple file updating
 
 (defun texinfo-multi-file-included-list (outer-file)
   "Return a list of the included files in OUTER-FILE."
@@ -1465,25 +1720,27 @@
 
   (save-excursion
     (end-of-line)
-    (let ((section-end (or 
+    (let ((node-end (or 
                         (save-excursion
-                          (re-search-forward "\\(^@node\\)" nil t)
-                          (match-beginning 0))
+                          (if (re-search-forward "\\(^@node\\)" nil t)
+                              (match-beginning 0)))
                         (point-max))))
-      (if (re-search-forward texinfo-section-types-regexp section-end t)
-          ;; copy title
-          (let ((title
-                 (buffer-substring
-                  (progn (forward-word 1)           ; skip over section type
-                         (skip-chars-forward " \t") ; and over spaces
-                         (point))
-                  (progn (end-of-line) (point)))))
-            title)
+      (if (re-search-forward texinfo-section-types-regexp node-end t)
+          (progn
+            (beginning-of-line)
+            ;; copy title
+            (let ((title
+                   (buffer-substring
+                    (progn (forward-word 1)           ; skip over section type
+                           (skip-chars-forward " \t") ; and over spaces
+                           (point))
+                    (progn (end-of-line) (point)))))
+              title))
         ""))))
 
 (defun texinfo-multi-file-update (files &optional update-everything)
   "Update first node pointers in each file in FILES.
-Return a list of the node names and the title immediate following them.
+Return a list of the node names.
 
 The first file in the list is an outer file; the remaining are
 files included in the outer file with `@include' commands.
@@ -1502,16 +1759,20 @@
   * each highest hierarchical level node must be of the same type.
 
 Thus, normally, each included file contains one, and only one,
-chapter.
-
-The menu-list has the form:
+chapter."
 
-    \(\(\"node-name1\" . \"title1\"\) 
-      \(\"node-name2\" . \"title2\"\) ... \)
-
-However, there does not need to be a title field."
+; The menu-list has the form:
+; 
+;     \(\(\"node-name1\" . \"title1\"\) 
+;       \(\"node-name2\" . \"title2\"\) ... \)
+; 
+; However, there does not need to be a title field and this function
+; does not fill it; however a comment tells you how to do so.
+; You would use the title field if you wanted to insert titles in the
+; description slot of a menu as a description.
   
-  (let (menu-list)
+  (let ((case-fold-search t)
+        menu-list)
     
     ;; Find the name of the first node of the first included file.
     (switch-to-buffer (find-file-noselect (car (cdr files))))
@@ -1526,9 +1787,11 @@
     (setq menu-list
           (cons (cons 
                  next-node-name
-                 (texinfo-copy-next-section-title))
+                 (prog1 "" (forward-line 1)))
+                ;; Use following to insert section titles automatically.
+                ;; (texinfo-copy-next-section-title)
                 menu-list))
-    
+
     ;; Go to outer file
     (switch-to-buffer (find-file-noselect (car files)))
     (goto-char (point-min))
@@ -1560,7 +1823,9 @@
         (setq menu-list
               (cons (cons 
                      next-node-name
-                     (texinfo-copy-next-section-title))
+                     (prog1 "" (forward-line 1)))
+                    ;; Use following to insert section titles automatically.
+                    ;; (texinfo-copy-next-section-title)
                     menu-list)))
 
       ;; Go to node to be updated.
@@ -1569,6 +1834,11 @@
       (if (not (re-search-forward "^@node" nil t))
           (error "No `@node' line found in %s !" (buffer-name)))
       (beginning-of-line)
+      
+      ;; Update other menus and nodes if requested.
+      (if update-everything (texinfo-all-menus-update t))
+
+      (beginning-of-line)
       (texinfo-delete-existing-pointers)
       (end-of-line)
       (insert ", " next-node-name ", " previous-node-name ", " up-node-name)
@@ -1576,9 +1846,6 @@
       (beginning-of-line)
       (setq previous-node-name (texinfo-copy-node-name))
       
-      ;; Update other menus and nodes if requested.
-      (if update-everything (texinfo-all-menus-update t))
-      
       (setq files (cdr files)))
     (nreverse menu-list)))
 
@@ -1589,20 +1856,29 @@
 
   (insert "@menu\n")
   (while menu-list
-    (if (cdr (car menu-list))       ; menu-list has description entry
+    ;; Every menu entry starts with a star and a space.
+    (insert "* ")
+    
+    ;; Insert the node name (and menu entry name, if present).
+    (let ((node-part (car (car menu-list))))
+      (if (stringp node-part)
+          ;; "Double colon" entry line; menu entry and node name are the same,
+          (insert (format "%s::" node-part))  
+        ;; "Single colon" entry line; menu entry and node name are different.
+        (insert (format "%s: %s." (car node-part) (cdr node-part)))))
+    
+    ;; Insert the description, if present.
+    (if (cdr (car menu-list))
         (progn
-          (insert 
-           (format "* %s::" (car (car menu-list)))) ; node-name entry
-          (indent-to texinfo-column-for-description 2)
-          (insert 
-           (format "%s\n" (cdr (car menu-list)))))  ; description entry
-        ;; else menu-list lacks description entry
-      (insert
-       (format "* %s::\n" (car (car menu-list)))))  ; node-name entry
+          ;; Move to right place.
+          (indent-to texinfo-column-for-description 2) 
+          ;; Insert description.
+          (insert (format "%s" (cdr (car menu-list))))))  
+
+    (insert "\n") ; end this menu entry
     (setq menu-list (cdr menu-list)))
   (insert "@end menu"))
 
-
 (defun texinfo-multi-file-master-menu-list (files-list)
   "Return master menu list from files in FILES-LIST.
 Menu entries in each file collected using `texinfo-master-menu-list'.
@@ -1621,24 +1897,27 @@
       master-menu-list)))
 
 
-;;;; The multiple-file update function
+;;; The multiple-file update function
 
 (defun texinfo-multiple-files-update
   (outer-file &optional update-everything make-master-menu)
   "Update first node pointers in each file included in OUTER-FILE;
-create or update main menu in the outer file that refers to such nodes. 
-This does not create or update menus or pointers within the included files.
+create or update the `Top' level node pointers and the main menu in
+the outer file that refers to such nodes.  This does not create or
+update menus or pointers within the included files.
 
 With optional MAKE-MASTER-MENU argument (prefix arg, if interactive),
-insert a master menu in OUTER-FILE.  This does not create or update
-menus or pointers within the included files.
+insert a master menu in OUTER-FILE in addition to creating or updating
+pointers in the first @node line in each included file and creating or
+updating the `Top' level node pointers of the outer file.  This does
+not create or update other menus and pointers within the included
+files.
 
 With optional UPDATE-EVERYTHING argument (numeric prefix arg, if
 interactive), update all the menus and all the `Next', `Previous', and
 `Up' pointers of all the files included in OUTER-FILE before inserting
-a master menu in OUTER-FILE.
-
-The command also updates the `Top' level node pointers of OUTER-FILE.
+a master menu in OUTER-FILE.  Also, update the `Top' level node
+pointers of OUTER-FILE.
 
 Notes: 
 
@@ -1658,12 +1937,18 @@
 
 Thus, normally, each included file contains one, and only one,
 chapter."
-
-  (interactive "fName of outer `include' file: ")
-
-  (cond (current-prefix-arg
-         (setq make-master-menu (listp current-prefix-arg))
-         (setq update-everything (numberp current-prefix-arg))))
+  
+  (interactive (cons
+                (read-string
+                 "Name of outer `include' file: "
+                 (buffer-file-name))
+                (cond ((not current-prefix-arg)
+                       '(nil nil))
+                      ((listp current-prefix-arg)
+                       '(t nil))   ; make-master-menu 
+                      ((numberp current-prefix-arg)
+                       '(t t))     ; update-everything
+                      )))
 
   (let* ((included-file-list (texinfo-multi-file-included-list outer-file))
          (files included-file-list)
@@ -1720,10 +2005,27 @@
 
         ;; Create a master menu and insert it
         (texinfo-insert-master-menu-list 
-         (texinfo-multi-file-master-menu-list 
+         (texinfo-multi-file-master-menu-list
           included-file-list)))))
+
+  ;; Remove unwanted extra lines.
+  (save-excursion
+    (goto-char (point-min))
+      
+    (re-search-forward "^@menu")
+    (forward-line -1)
+    (insert  "\n") ; Ensure at least one blank line.
+    (delete-blank-lines)
+      
+    (re-search-forward "^@end menu")
+    (forward-line 1)
+    (insert  "\n") ; Ensure at least one blank line.
+    (delete-blank-lines))
+
   (message "Multiple files updated."))
 
+
+;;; Place `provide' at end of file.
 (provide 'texnfo-upd)
 
 ;;; texnfo-upd.el ends here