Some fixes to follow coding conventions.
[bpt/emacs.git] / lisp / textmodes / texnfo-upd.el
index 377de8a..a474e4c 100644 (file)
@@ -1,14 +1,16 @@
-;;; texnfo-upd.el --- a utility for updating nodes and menus in Texinfo files.
+;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files
 
-;;;; Version 2.00   14 Dec 1990
+;; Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
 
-;;;; Copyright 1989, 1990 Free Software Foundation
+;; Author: Robert J. Chassell
+;; Maintainer: bug-texinfo@gnu.org
+;; Keywords: maint, tex, docs
 
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs 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 1, or (at your option)
+;; the Free Software Foundation; either version 2, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; 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.
 
-\f
-;;;; Summary
+;;; Commentary:
+
+;; Known bug: update commands fail to ignore @ignore.
+
+;; Summary: how to use the updating commands
+
+;; The node and menu updating functions automatically
+
+;;   * insert missing `@node' lines,
+;;   * 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.
+;;
+;; With a prefix argument, the `texinfo-update-node' and
+;; `texinfo-make-menu' functions do their jobs in the region.
+;;
+;; In brief, the functions for creating or updating nodes and menus, are:
+;;
+;;     texinfo-update-node (&optional beginning end)
+;;     texinfo-every-node-update ()
+;;     texinfo-sequential-node-update (&optional region-p)
+;;
+;;     texinfo-make-menu (&optional beginning end)
+;;     texinfo-all-menus-update ()
+;;     texinfo-master-menu ()
+;;
+;;     texinfo-insert-node-lines  (&optional title-p)
+;;
+;;     texinfo-indent-menu-description (column &optional region-p)
 
-; (Much of the following commentary ought eventually be incorporated
-; into the Texinfo Manual.)
+;; The `texinfo-column-for-description' variable specifies the column to
+;; which menu descriptions are indented.
 
-; The node and menu updating functions automatically
+;; Texinfo file structure
+;; ----------------------
 
-;   * insert missing `@node' lines,
-;   * 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.
+;; To use the updating commands, you must structure your Texinfo file
+;; hierarchically.  Each `@node' line, with the exception of the top
+;; node, must be accompanied by some kind of section line, such as an
+;; `@chapter' or `@section' line.  Each node-line/section-line
+;; combination must look like this:
 
-; Passed an argument, the `texinfo-update-node' and
-; `texinfo-make-menu' functions do their jobs in the region.
+;;      @node    Lists and Tables, Cross References, Structuring, Top
+;;      @comment node-name,        next,             previous,    up
+;;      @chapter Making Lists and Tables
 
-; These functions replace doing these jobs by hand.
-; You may find them helpful.
+;; or like this (without the `@comment' line):
 
-; In brief, the functions for creating or updating nodes and menus, are:
-; 
-;     texinfo-update-node (&optional region-p)            
-;     texinfo-every-node-update ()                        
-;     texinfo-sequential-node-update (&optional region-p)
-; 
-;     texinfo-make-menu (&optional region-p)              
-;     texinfo-all-menus-update ()                         
-;     texinfo-master-menu ()
-;
-;     texinfo-insert-node-lines  (&optional title-p)
-; 
-;     texinfo-indent-menu-description (column &optional region-p)
+;;      @node    Lists and Tables, Cross References, Structuring, Top
+;;      @chapter Making Lists and Tables
 
-; The `texinfo-column-for-description' variable specifies the column to
-; which menu descriptions are indented. 
+;; If the file has a `top' node, it must be called `top' or `Top' and
+;; be the first node in the file.
 
-; Texinfo file structure
-; ----------------------
+\f
+;;; The update node functions described in detail
 
-; To use the updating commands, you must structure your Texinfo file
-; hierarchically.  Each `@node' line, with the exception of the top
-; node, must be accompanied by some kind of section line, such as an
-; `@chapter' or `@section' line.  Each node-line/section-line
-; combination must look like this:
+;; The `texinfo-update-node' command with no prefix argument inserts
+;; the correct next, previous and up pointers for the node in which
+;; point is located (i.e., for the node preceding point).
 
-;      @node    Lists and Tables, Cross References, Structuring, Top
-;      @comment node-name,        next,             previous,    up
-;      @chapter Making Lists and Tables
+;; With prefix argument, the `texinfo-update-node' function inserts the
+;; correct next, previous and up pointers for the nodes inside the
+;; region.
 
-; or like this (without the `@comment' line):
+;; It does not matter whether the  `@node' line has pre-existing
+;; `Next', `Previous', or `Up' pointers in it.  They are removed.
 
-;      @node    Lists and Tables, Cross References, Structuring, Top
-;      @chapter Making Lists and Tables
+;; The `texinfo-every-node-update' function runs `texinfo-update-node'
+;; on the whole buffer.
 
-; If the file has a `top' node, it must be called `top' or `Top' and
-; be the first node in the file.
+;; 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.
 
 \f
-;;;; The updating functions in detail
-;    --------------------------------
-
-; The `texinfo-update-node' function without an argument inserts
-; the correct next, previous and up pointers for the node in which
-; point is located (i.e., for the node preceding point).
-
-; With an argument, the `texinfo-update-node' function inserts the
-; correct next, previous and up pointers for the nodes inside the
-; region.
-
-; It does not matter whether the  `@node' line has pre-existing
-; `Next', `Previous', or `Up' pointers in it.  They are removed.
-
-; 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-make-menu' function without an argument creates or
-; updates a menu for the section encompassing the node that follows
-; point.  With an argument, it makes or updates menus for the nodes
-; within or part of the marked region.
-
-; Whenever an existing menu is updated, the descriptions from
-; that menu are incorporated into the new menu.  This is done by copying
-; descriptions from the existing menu to the entries in the new menu
-; that have the same node names.  If the node names are different, the
-; descriptions are not copied to the new menu.
-
-; Menu entries that refer to other Info files are removed since they
-; are not a node within current buffer.  This is a deficiency.
-
-; The `texinfo-all-menus-update' function runs `texinfo-make-menu'
-; on the whole buffer.
-
-; The `texinfo-master-menu' function creates an extended menu located
-; after the top node.  (The file must have a top node.)  The function
-; first updates all the regular menus in the buffer (incorporating the
-; descriptions from pre-existing menus), and then constructs a master
-; menu that includes every entry from every other menu.  (However, the
-; function cannot update an already existing master menu; if one
-; exists, it must be removed before calling the function.)
-
-; The `texinfo-indent-menu-description' function indents every
-; description in the menu following point, to the specified column.
-; Non-nil argument (prefix, if interactive) means indent every
-; description in every menu in the region.  This function does not
-; indent second and subsequent lines of a multi-line description.
-
-; The `texinfo-insert-node-lines' function inserts `@node' before the
-; `@chapter', `@section', and such like lines of a region in a Texinfo
-; file where the `@node' lines are missing.
-; 
-; With a non-nil argument (prefix, if interactive), the function not
-; only inserts `@node' lines but also inserts the chapter or section
-; titles as the names of the corresponding nodes; and inserts titles
-; as node names in pre-existing `@node' lines that lack names.
-; 
-; Since node names should be more concise than section or chapter
-; titles, node names so inserted will need to be edited manually.
-
-\f 
-;;;; Menu Making Functions
-
-(defun texinfo-make-menu (&optional region-p)
+;;; 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
+;; point.  With an argument, it makes or updates menus for the nodes
+;; within or part of the marked region.
+
+;; Whenever an existing menu is updated, the descriptions from
+;; that menu are incorporated into the new menu.  This is done by copying
+;; descriptions from the existing menu to the entries in the new menu
+;; that have the same node names.  If the node names are different, the
+;; descriptions are not copied to the new menu.
+
+;; Menu entries that refer to other Info files are removed since they
+;; are not a node within current buffer.  This is a deficiency.
+
+;; The `texinfo-all-menus-update' function runs `texinfo-make-menu'
+;; on the whole buffer.
+
+;; The `texinfo-master-menu' function creates an extended menu located
+;; after the top node.  (The file must have a top node.)  The function
+;; first updates all the regular menus in the buffer (incorporating the
+;; descriptions from pre-existing menus), and then constructs a master
+;; menu that includes every entry from every other menu.  (However, the
+;; function cannot update an already existing master menu; if one
+;; exists, it must be removed before calling the function.)
+
+;; The `texinfo-indent-menu-description' function indents every
+;; description in the menu following point, to the specified column.
+;; Non-nil argument (prefix, if interactive) means indent every
+;; description in every menu in the region.  This function does not
+;; indent second and subsequent lines of a multi-line description.
+
+;; The `texinfo-insert-node-lines' function inserts `@node' before the
+;; `@chapter', `@section', and such like lines of a region in a Texinfo
+;; file where the `@node' lines are missing.
+;;
+;; With a non-nil argument (prefix, if interactive), the function not
+;; only inserts `@node' lines but also inserts the chapter or section
+;; titles as the names of the corresponding nodes; and inserts titles
+;; as node names in pre-existing `@node' lines that lack names.
+;;
+;; Since node names should be more concise than section or chapter
+;; titles, node names so inserted will need to be edited manually.
+
+\f
+;;; Code:
+
+(require 'texinfo)
+
+
+(defvar texinfo-master-menu-header
+  " --- The Detailed Node Listing ---\n"
+  "String inserted before lower level entries in Texinfo master menu.
+It comes after the chapter-level menu entries.")
+
+(defun texinfo-make-menu (&optional beginning end)
   "Without any prefix argument, make or update a menu.
 Make the menu for the section enclosing the node found following point.
 
-Non-nil argument (prefix, if interactive) means make or update menus
+A prefix argument means make or update menus
 for nodes within or part of the marked region.
 
 Whenever a menu exists, and is being updated, the descriptions that
 are associated with node names in the pre-existing menu are
 incorporated into the new menu.  Otherwise, the nodes' section titles
 are inserted as descriptions."
-  
-  (interactive "P")
-  (if (not region-p)
+
+  (interactive
+   (if prefix-arg
+       (list (point) (mark))))
+  (if (null beginning)
       (let ((level (texinfo-hierarchic-level)))
-        (texinfo-make-one-menu level)
-        (message "Done...updated the menu.  You may save the buffer."))
+       (texinfo-make-one-menu level)
+       (message "Menu updated"))
     ;; else
-    (message "Making or updating menus... ")
-    (let ((beginning (region-beginning))
-         (region-end (region-end))
-          (level (progn         ; find section type following point
-                   (goto-char (region-beginning))
-                   (texinfo-hierarchic-level))))
-      (if (= region-end beginning)
-          (error "Please mark a region!"))
-      (save-excursion
-        (save-restriction
-          (widen)
-          
-          (while  (texinfo-find-lower-level-node level region-end)
-            (setq level (texinfo-hierarchic-level)) ; new, lower level
-            (texinfo-make-one-menu level))
-          
-          (while (and (< (point) region-end)
-                      (texinfo-find-higher-level-node level region-end))
-            (setq level (texinfo-hierarchic-level))
-            (while (texinfo-find-lower-level-node level region-end)
-              (setq level (texinfo-hierarchic-level)) ; new, lower level
-              (texinfo-make-one-menu level))))))
-    (message "Done...updated menus.  You may save the buffer.")))
+    (message "Making or updating menus in %s... " (buffer-name))
+    (save-excursion
+      (goto-char (min beginning end))
+      ;; find section type following point
+      (let ((level (texinfo-hierarchic-level))
+           (region-end-marker (make-marker)))
+       (set-marker region-end-marker (max beginning end))
+       (save-restriction
+         (widen)
+
+         (while (texinfo-find-lower-level-node
+                 level (marker-position region-end-marker))
+           (setq level (texinfo-hierarchic-level)) ; new, lower level
+           (texinfo-make-one-menu level))
+
+         (while (and (< (point) (marker-position region-end-marker))
+                     (texinfo-find-higher-level-node
+                      level (marker-position region-end-marker)))
+           (setq level (texinfo-hierarchic-level))
+           ;; Don't allow texinfo-find-higher-level-node
+           ;; to find the same node again.
+           (forward-line 1)
+           (while (texinfo-find-lower-level-node
+                   level (marker-position region-end-marker))
+             (setq level (texinfo-hierarchic-level)) ; new, lower level
+             (texinfo-make-one-menu level))))))
+    (message "Making or updating menus in %s...done" (buffer-name))))
 
 (defun texinfo-make-one-menu (level)
   "Make a menu of all the appropriate nodes in this section.
-`Appropriate nodes' are those associated with sections that are 
+`Appropriate nodes' are those associated with sections that are
 at the level specified by LEVEL.  Point is left at the end of menu."
   (let*
       ((case-fold-search t)
@@ -202,94 +219,120 @@ at the level specified by LEVEL.  Point is left at the end of menu."
        (end (texinfo-update-menu-region-end level))
        (first (texinfo-menu-first-node beginning end))
        (node-name (progn
-                    (goto-char beginning)
-                    (texinfo-copy-node-name)))
+                   (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-delete-old-menu 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!")))
+      (push-mark (point-max) t)
+      (goto-char (point-min))
+      (message "Checking for a master menu in %s ... "(buffer-name))
+      (save-excursion
+       (if (search-forward texinfo-master-menu-header nil t)
+           (progn
+             ;; Check if @detailmenu kludge is used;
+             ;; if so, leave point before @detailmenu.
+             (search-backward "\n@detailmenu"
+                              (save-excursion (forward-line -3) (point))
+                              t)
+             ;; Remove detailed master menu listing
+             (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))
+           (texinfo-update-node (point-min) (point-max))))
+
+      (message "Updating all menus in %s ... " (buffer-name))
+      (texinfo-make-menu (point-max) (point-min))
+
+      (if master-menu-p
+         (progn
+           (message "Updating the master menu in %s... " (buffer-name))
+           (texinfo-master-menu nil))))
 
-  (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)
     (message "Done...updated all the menus.  You may save the buffer.")))
 
 (defun texinfo-find-lower-level-node (level region-end)
   "Search forward from point for node at any level lower than LEVEL.
-Search is limited to the end of the marked region, REGION-END, 
+Search is limited to the end of the marked region, REGION-END,
 and to the end of the menu region for the level.
 
 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.
 Search is limited to the end of the marked region, REGION-END.
 
 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."
+of the node if one is found; else do not move point.
+
+A `@node' line starting at point does count as a match;
+if the match is found there, the value is t and point does not move."
 
-  (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
+     ((< level 3)
+      (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))))))
 
 \f
-;;;; 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.
 Point is left at the end of the menu region, but the menu is not inserted.
 
-First argument is position from which to start making menu list; 
+First argument is position from which to start making menu list;
 second argument is end of region in which to try to locate entries;
 third argument is the level of the nodes that are the entries.
 
@@ -299,17 +342,19 @@ element consists only of the node name."
   (goto-char beginning)
   (let (new-menu-list)
     (while (texinfo-menu-locate-entry-p level end)
-      (setq new-menu-list 
-            (cons (cons 
-                   (texinfo-copy-node-name)
-                   (texinfo-copy-section-title))
-                  new-menu-list)))
+      (setq new-menu-list
+           (cons (cons
+                  (texinfo-copy-node-name)
+                  (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
@@ -317,17 +362,18 @@ forward from point, and leaves point at the beginning of the node.
 
 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.
@@ -336,16 +382,16 @@ Start with point at the beginning of the node line; copy the text
 after the node command up to the first comma on the line, if any, and
 return the text as a string.  Leaves point at the beginning of the
 line.  If there is no node name, returns an empty string."
-  
+
   (save-excursion
     (buffer-substring
      (progn (forward-word 1)              ; skip over node command
-            (skip-chars-forward " \t")    ; and over spaces
-            (point))
+           (skip-chars-forward " \t")    ; and over spaces
+           (point))
      (if (search-forward
-          ","
-          (save-excursion (end-of-line) (point)) t) ; bound search
-         (1- (point))
+         ","
+         (save-excursion (end-of-line) (point)) t) ; bound search
+        (1- (point))
        (end-of-line) (point)))))
 
 (defun texinfo-copy-section-title ()
@@ -361,16 +407,16 @@ must have been done by `texinfo-menu-locate-entry-p'."
   ;; instead of using `match-beginning'; such a variation would be
   ;; more general, but would waste information already collected
 
-  (goto-char (match-beginning 7))       ; match section name 
+  (goto-char (match-beginning 7))       ; match section name
 
   (buffer-substring
    (progn (forward-word 1)              ; skip over section type
-          (skip-chars-forward " \t")    ; and over spaces
-          (point))
+         (skip-chars-forward " \t")    ; and over spaces
+         (point))
    (progn (end-of-line) (point))))
 
 \f
-;;;; 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.
@@ -393,29 +439,78 @@ end of the section, and leaves point there where a menu ought to be."
 
 Point must be at beginning of old menu.
 
+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.
+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.
+            ;;
+            ;; Recognize both when looking for the description.
+            (concat "\\* \\("              ; so only menu entries are found
+                    (regexp-quote (car (car new-menu-list))) "::"
+                    "\\|"
+                    ".*: " (regexp-quote (car (car new-menu-list))) "[.,\t\n]"
+                    "\\)"
+                    )               ; so only complete entries are found
+            end-of-menu
+            t)
+           (setcdr (car new-menu-list)
+                   (texinfo-menu-copy-old-description end-of-menu))))
+      (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, 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.
+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 the description. The new menu is changed destructively.
-The old menu is the menu as it appears in the texinfo file."
-  
+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)))
+       (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
-             end-of-menu
-             t) 
-            (setcdr (car new-menu-list) 
-                    (texinfo-menu-copy-old-description end-of-menu))))
-      (setq new-menu-list (cdr 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
+                    "\\(.*\\): " (regexp-quote (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)
@@ -425,24 +520,25 @@ Single argument, END-OF-MENU, is position limiting search."
   (skip-chars-forward "[:.,\t\n ]+")
   ;; don't copy a carriage return at line beginning with asterisk!
   ;; do copy a description that begins with an `@'!
-  (if (and (looking-at "\\(\\w+\\|@\\)")    
-           (not (looking-at "\\(^\\* \\|^@end menu\\)")))  
+  ;; !! Known bug: does not copy descriptions starting with ^|\{?* etc.
+  (if (and (looking-at "\\(\\w+\\|@\\)")
+          (not (looking-at "\\(^\\* \\|^@end menu\\)")))
       (buffer-substring
        (point)
        (save-excursion
-         (re-search-forward "\\(^\\* \\|^@end menu\\)" end-of-menu t)
-         (forward-line -1)
-         (end-of-line)                  ; go to end of last description line
-         (point)))
+        (re-search-forward "\\(^\\* \\|^@end menu\\)" end-of-menu t)
+        (forward-line -1)
+        (end-of-line)                  ; go to end of last description line
+        (point)))
     ""))
 
 (defun texinfo-menu-end ()
-  "Return position of end of menu. Does not change location of point.
+  "Return position of end of menu, but don't move point.
 Signal an error if not end of menu."
   (save-excursion
     (if (re-search-forward "^@end menu" nil t)
-        (point)
-      (error "Menu does not have an end."))))
+       (point)
+      (error "Menu does not have an end"))))
 
 (defun texinfo-delete-old-menu (beginning first)
   "Delete the old menu.  Point must be in or after menu.
@@ -452,12 +548,12 @@ node within the section."
   ;; No third arg to search, so error if search fails.
   (re-search-backward "^@menu" beginning)
   (delete-region (point)
-                 (save-excursion
-                   (re-search-forward "^@end menu" first)
-                   (point))))
+                (save-excursion
+                  (re-search-forward "^@end menu" first)
+                  (point))))
 
 \f
-;;;; Inserting new menu
+;;; Inserting new menu
 
 ;; try 32, but perhaps 24 is better
 (defvar texinfo-column-for-description 32
@@ -470,60 +566,154 @@ texinfo-column-for-description.
 
 MENU-LIST has form:
 
-    \(\(\"node-name1\" . \"description\"\) 
-    \(\"node-name\" . \"description\"\) ... \)
+    \(\(\"node-name1\" . \"description\"\)
+    \(\"node-name2\" . \"description\"\) ... \)
+
+However, the description field might be nil.
+
+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."
 
-However, there does not need to be a description field."
-  
   (insert "@menu\n")
   (while menu-list
-    (if (cdr (car menu-list))       ; menu-list has description entry
-        (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
+    ;; 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
+         ;; 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))
+   "Updated \"%s\" level menu following node: %s ... " level node-name))
 
 \f
-;;;; 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.
 
-; Since the make-menu functions indent descriptions, these functions
-; are useful primarily for indenting a single menu specially.
+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]+"
+           (regexp-quote 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))))
+
+\f
+;;; Handling description indentation
+
+;; Since the make-menu functions indent descriptions, these functions
+;; are useful primarily for indenting a single menu specially.
 
 (defun texinfo-indent-menu-description (column &optional region-p)
-  "Indent every description in menu following point to COLUMN.  
+  "Indent every description in menu following point to COLUMN.
 Non-nil argument (prefix, if interactive) means indent every
 description in every menu in the region.  Does not indent second and
 subsequent lines of a multi-line description."
-  
+
   (interactive
    "nIndent menu descriptions to (column number): \nP")
   (save-excursion
     (save-restriction
       (widen)
       (if (not region-p)
-          (progn
-            (re-search-forward "^@menu")
-            (texinfo-menu-indent-description column)
-            (message
-             "Indented descriptions in menu.  You may save the buffer."))
-        ;;else
-        (message "Indenting every menu description in region... ")
-        (goto-char (region-beginning))
-        (while (and (< (point) (region-end))
-                    (texinfo-locate-menu-p))
-          (forward-line 1)
-          (texinfo-menu-indent-description column))
-        (message "Indenting done.  You may save the buffer.")))))
+         (progn
+           (re-search-forward "^@menu")
+           (texinfo-menu-indent-description column)
+           (message
+            "Indented descriptions in menu.  You may save the buffer."))
+       ;;else
+       (message "Indenting every menu description in region... ")
+       (goto-char (region-beginning))
+       (while (and (< (point) (region-end))
+                   (texinfo-locate-menu-p))
+         (forward-line 1)
+         (texinfo-menu-indent-description column))
+       (message "Indenting done.  You may save the buffer.")))))
 
 (defun texinfo-menu-indent-description (to-column-number)
   "Indent the Texinfo file menu description to TO-COLUMN-NUMBER.
@@ -532,25 +722,28 @@ leave point on the line before the `@end menu' line.  Does not indent
 second and subsequent lines of a multi-line description."
   (let* ((beginning-of-next-line (point)))
     (while (< beginning-of-next-line
-              (save-excursion     ; beginning of end menu line
-                (goto-char (texinfo-menu-end))
-                (beginning-of-line)
-                (point)))
-      (if (search-forward "::" (texinfo-menu-end) t)
-          (progn
-            (let ((beginning-white-space (point)))
-              (skip-chars-forward " \t")  ; skip over spaces
-              (if (looking-at "\\(@\\|\\w\\)+") ; if there is text
-                  (progn
-                    ;; remove pre-existing indentation
-                    (delete-region beginning-white-space (point))
-                    (indent-to-column to-column-number))))))
+             (save-excursion     ; beginning of end menu line
+               (goto-char (texinfo-menu-end))
+               (beginning-of-line)
+               (point)))
+
+      (if (re-search-forward  "\\* \\(.*::\\|.*: [^.,\t\n]+[.,\t]\\)"
+          (texinfo-menu-end)
+          t)
+         (progn
+           (let ((beginning-white-space (point)))
+             (skip-chars-forward " \t")  ; skip over spaces
+             (if (looking-at "\\(@\\|\\w\\)+") ; if there is text
+                 (progn
+                   ;; remove pre-existing indentation
+                   (delete-region beginning-white-space (point))
+                   (indent-to-column to-column-number))))))
       ;; position point at beginning of next line
-      (forward-line 1)                  
+      (forward-line 1)
       (setq beginning-of-next-line (point)))))
 
 \f
-;;;; 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.
@@ -566,7 +759,7 @@ menus in the buffer (incorporating descriptions from pre-existing
 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-exisitng master menu using the
+menu.  This action depends on the pre-existing master menu using the
 standard `texinfo-master-menu-header'.
 
 The master menu has the following format, which is adapted from the
@@ -586,64 +779,77 @@ 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))
+  (let ((case-fold-search t))
+    (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!"))
+    ;; 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 (search-forward texinfo-master-menu-header first-chapter t)
+         (progn
+           ;; Check if @detailmenu kludge is used;
+           ;; if so, leave point before @detailmenu.
+           (search-backward "\n@detailmenu"
+                            (save-excursion (forward-line -3) (point))
+                            t)
+           ;; Remove detailed master menu listing
+           (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 in %s ...first updating all nodes... "
+                  (buffer-name))
+         (texinfo-update-node (point-min) (point-max))
+
+         (message "Updating all menus in %s ... " (buffer-name))
+         (texinfo-make-menu (point-min) (point-max))))
+
+    (message "Now making the master menu in %s... " (buffer-name))
+    (goto-char (point-min))
+    (texinfo-insert-master-menu-list
+     (texinfo-master-menu-list))
 
-  (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.
 
-  ;; Remove extra newlines that texinfo-insert-master-menu-list
-  ;; may have inserted.
+    (save-excursion
+      (goto-char (point-min))
 
-  (save-excursion
-    (goto-char (point-min))
-    
-    (re-search-forward texinfo-master-menu-header)
-    (goto-char (match-beginning 0))
-    (insert "\n")
-    (delete-blank-lines)
-    
-    (re-search-backward "^@menu")
-    (forward-line -1)
-    (delete-blank-lines)
-    
-    (re-search-forward "^@end menu")
-    (forward-line 1)
-    (delete-blank-lines))
+      (if (search-forward texinfo-master-menu-header nil t)
+         (progn
+           (goto-char (match-beginning 0))
+           ;; Check if @detailmenu kludge is used;
+           ;; if so, leave point before @detailmenu.
+           (search-backward "\n@detailmenu"
+                            (save-excursion (forward-line -3) (point))
+                            t)
+           (insert "\n")
+           (delete-blank-lines)
+           (goto-char (point-min))))
+
+      (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."))
+    (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.
@@ -661,66 +867,88 @@ However, there does not need to be a title field."
 
   (let (master-menu-list)
     (while (texinfo-locate-menu-p)
-      (setq master-menu-list 
-            (cons (list
-                   (texinfo-copy-menu)
-                   (texinfo-copy-menu-title))
-                  master-menu-list)))
+      (setq master-menu-list
+           (cons (list
+                  (texinfo-copy-menu)
+                  (texinfo-copy-menu-title))
+                 master-menu-list)))
     (reverse master-menu-list)))
 
 (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)))
-  
-  (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
-    (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")))
+  (delete-region      ; buffer must have ordinary top menu
+   (point)
+   (save-excursion (re-search-forward "^@end menu") (point)))
 
-(defvar texinfo-master-menu-header
-  "\n --- The Detailed Node Listing ---\n"
-  "String inserted before lower level entries in Texinfo master menu.
-It comes after the chapter-level menu entries.")
+  (save-excursion
+    ;; `master-menu-inserted-p' is a kludge to tell
+    ;; whether to insert @end detailmenu (see bleow)
+    (let (master-menu-inserted-p)
+      ;; 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))
+
+      ;; Only insert detailed master menu if there is one....
+      (if (car (car master-menu-list))
+         (progn (setq master-menu-inserted-p t)
+                (insert (concat "\n@detailmenu\n"
+                                texinfo-master-menu-header))))
+
+      ;; @detailmenu added 5 Sept 1996 to `texinfo-master-menu-header'
+      ;; at Karl Berry's request to avert a bug in `makeinfo';
+      ;; all agree this is a bad kludge and should eventually be removed.
+      ;; @detailmenu ... @end detailmenu is a noop in `texinfmt.el'.
+      ;; See @end detailmenu below;
+      ;; also see `texinfo-all-menus-update' above, `texinfo-master-menu',
+      ;; `texinfo-multiple-files-update'.
+
+      ;; 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
+
+      ;; @detailmenu (see note above)
+      ;; Only insert @end detailmenu if a master menu was inserted.
+      (if master-menu-inserted-p
+         (insert "\n@end detailmenu"))
+      (insert "\n@end menu\n\n"))))
 
 (defun texinfo-locate-menu-p ()
   "Find the next menu in the texinfo file.
@@ -732,142 +960,155 @@ If a menu is not found, do not move point and return nil."
   "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.
 Start with point just after the word `menu' in the `@menu' line
 and leave point on the line before the `@end menu' line."
   (let* (this-menu-list
-         (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu'
-         (last-entry (save-excursion      ; position of beginning of
-                                          ; last `* ' entry
-                      (goto-char end-of-menu)
-                      (re-search-backward "^\* ") ; handle multi-line desc.
-                      (point))))
+        (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu'
+        (last-entry (save-excursion      ; position of beginning of
+                                         ; last `* ' entry
+                     (goto-char end-of-menu)
+                     ;; 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)
-          (progn
-            (setq this-menu-list
-                  (cons
-                   (buffer-substring 
-                    (point)
-                    ;; copy multi-line descriptions
-                    (save-excursion
-                      (re-search-forward "\\(^\* \\|^@e\\)" nil t)
-                      (- (point) 3)))
-                   this-menu-list)))))
+      (if (re-search-forward  "^\\* " end-of-menu t)
+         (progn
+           (setq this-menu-list
+                 (cons
+                  (buffer-substring
+                   (point)
+                   ;; copy multi-line descriptions
+                   (save-excursion
+                     (re-search-forward "\\(^\\* \\|^@e\\)" nil t)
+                     (- (point) 3)))
+                  this-menu-list)))))
     this-menu-list))
 
 \f
-;;;; Determining the hierarchical level in the texinfo file
+;;; Determining the hierarchical level in the texinfo file
 
-(defun texinfo-specific-section-type () 
+(defun texinfo-specific-section-type ()
   "Return the specific type of next section, as a string.
 For example, \"unnumberedsubsec\".  Return \"top\" for top node.
 
 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-no-properties
+        (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))
+    (cadr (assoc
+         (texinfo-specific-section-type)
+         texinfo-section-list))))
 
 \f
-;;;; Locating the major positions
+;;; Locating the major positions
 
-(defun texinfo-update-menu-region-beginning (level)  
+(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)))))
-
-(defun texinfo-update-menu-region-end (level)  
+  (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
+     ((< level 3)
+      (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.
 Return position; do not move point.  Thus, if this level is a
 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.  
+  "Locate first node of the section the menu will be placed in.
 Return position; do not move point.
-The menu will be located just before this position.  
+The menu will be located just before this position.
 
 First argument is the position of the beginning of the section in
 which the menu will be located; second argument is the position of the
 end of that region; it limits the search."
-  
+
   (save-excursion
     (goto-char beginning)
     (forward-line 1)
@@ -876,100 +1117,64 @@ end of that region; it limits the search."
     (point)))
 
 \f
-;;;; Alists and regular expressions for defining hierarchical levels
-
-(defvar texinfo-section-to-generic-alist
-  '(("top" . "top")
-
-    ("chapter" . "chapter")
-    ("unnumbered" . "chapter")
-    ("majorheading" . "chapter")
-    ("chapheading" . "chapter")
-    ("appendix" . "chapter")
-    
-    ("section" . "section")
-    ("unnumberedsec" . "section")
-    ("heading" . "section")
-    ("appendixsec" . "section")
-    
-    ("subsection" . "subsection")
-    ("unnumberedsubsec" . "subsection")
-    ("subheading" . "subsection")
-    ("appendixsubsec" . "subsection")
-    
-    ("subsubsection" . "subsubsection")
-    ("unnumberedsubsubsec" . "subsubsection")
-    ("subsubheading" . "subsubsection")
-    ("appendixsubsubsec" . "subsubsection"))
-  "*An alist of specific and corresponding generic Texinfo section types.
-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 
-  "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading"
-  "Regular expression matching just the Texinfo chapter level headings.")
-
-(defvar texinfo-section-level-regexp 
-  "section\\|unnumberedsec\\|heading \\|appendixsec"
+(defvar texinfo-section-level-regexp
+  (regexp-opt (texinfo-filter 3 texinfo-section-list))
   "Regular expression matching just the Texinfo section level headings.")
 
-(defvar texinfo-subsection-level-regexp 
-  "subsection\\|unnumberedsubsec\\|subheading\\|appendixsubsec"
+(defvar texinfo-subsection-level-regexp
+  (regexp-opt (texinfo-filter 4 texinfo-section-list))
   "Regular expression matching just the Texinfo subsection level headings.")
 
 (defvar texinfo-subsubsection-level-regexp
-  "subsubsection\\|unnumberedsubsubsec\\|subsubheading\\|appendixsubsubsec"
+  (regexp-opt (texinfo-filter 5 texinfo-section-list))
   "Regular expression matching just the Texinfo subsubsection level headings.")
 
 (defvar texinfo-update-menu-same-level-regexps
-  '(("top" . "top[ \t]+")
-    ("chapter" . 
-     (concat "\\(^@\\)\\(" texinfo-chapter-level-regexp "\\)[ \t]*"))
-    ("section" . 
-     (concat "\\(^@\\)\\(" texinfo-section-level-regexp "\\)[ \t]*"))
-    ("subsection" .  
-     (concat "\\(^@\\)\\(" texinfo-subsection-level-regexp "\\)[ \t]+"))
-    ("subsubsection" . 
-     (concat "\\(^@\\)\\(" texinfo-subsubsection-level-regexp "\\)[ \t]+")))
+  '((1 . "top[ \t]+")
+    (2 . (concat "\\(^@\\)\\(" texinfo-chapter-level-regexp "\\)\\>[ \t]*"))
+    (3 . (concat "\\(^@\\)\\(" texinfo-section-level-regexp "\\)\\>[ \t]*"))
+    (4 . (concat "\\(^@\\)\\(" texinfo-subsection-level-regexp "\\)\\>[ \t]+"))
+    (5 . (concat "\\(^@\\)\\(" texinfo-subsubsection-level-regexp "\\)\\>[ \t]+")))
   "*Regexps for searching for same level sections in a Texinfo file.
 The keys are strings specifying the general hierarchical level in the
 document; the values are regular expressions.")
 
 (defvar texinfo-update-menu-higher-regexps
-  '(("top" . "^@node [ \t]*DIR") 
-    ("chapter" . "^@node [ \t]*top[ \t]*\\(,\\|$\\)")
-    ("section" .
-     (concat 
+  '((1 . "^@node [ \t]*DIR")
+    (2 . "^@node [ \t]*top[ \t]*\\(,\\|$\\)")
+    (3 .
+     (concat
       "\\(^@\\("
       texinfo-chapter-level-regexp
-      "\\)[ \t]*\\)"))
-    ("subsection" .
-     (concat 
+      "\\)\\>[ \t]*\\)"))
+    (4 .
+     (concat
       "\\(^@\\("
       texinfo-section-level-regexp
       "\\|"
       texinfo-chapter-level-regexp
-      "\\)[ \t]*\\)"))
-    ("subsubsection" .
-     (concat 
+      "\\)\\>[ \t]*\\)"))
+    (5 .
+     (concat
       "\\(^@\\("
       texinfo-subsection-level-regexp
       "\\|"
       texinfo-section-level-regexp
       "\\|"
       texinfo-chapter-level-regexp
-      "\\)[ \t]*\\)")))
+      "\\)\\>[ \t]*\\)")))
   "*Regexps for searching for higher level sections in a Texinfo file.
 The keys are strings specifying the general hierarchical level in the
 document; the values are regular expressions.")
 
 (defvar texinfo-update-menu-lower-regexps
-  '(("top" . 
-     (concat 
+  '((1 .
+     (concat
       "\\(^@\\("
       texinfo-chapter-level-regexp
       "\\|"
@@ -978,45 +1183,45 @@ document; the values are regular expressions.")
       texinfo-subsection-level-regexp
       "\\|"
       texinfo-subsubsection-level-regexp
-      "\\)[ \t]*\\)"))
-    ("chapter" . 
-     (concat 
+      "\\)\\>[ \t]*\\)"))
+    (2 .
+     (concat
       "\\(^@\\("
       texinfo-section-level-regexp
       "\\|"
       texinfo-subsection-level-regexp
       "\\|"
       texinfo-subsubsection-level-regexp
-      "\\)[ \t]*\\)"))
-    ("section" .
-     (concat 
+      "\\)\\>[ \t]*\\)"))
+    (3 .
+     (concat
       "\\(^@\\("
       texinfo-subsection-level-regexp
       "\\|"
       texinfo-subsubsection-level-regexp
-      "\\)[ \t]+\\)"))
-    ("subsection" .
-     (concat 
+      "\\)\\>[ \t]+\\)"))
+    (4 .
+     (concat
       "\\(^@\\("
       texinfo-subsubsection-level-regexp
-      "\\)[ \t]+\\)"))
-    ("subsubsection" . "nothing lower"))
+      "\\)\\>[ \t]+\\)"))
+    ;; There's nothing below 5, use a bogus regexp that can't match.
+    (5 . "a\\(^\\)"))
   "*Regexps for searching for lower level sections in a Texinfo file.
 The keys are strings specifying the general hierarchical level in the
 document; the values are regular expressions.")
 
 \f
-;;;; Updating a Node
+;;; Updating a node
 
-(defun texinfo-update-node (&optional region-p)
+(defun texinfo-update-node (&optional beginning end)
   "Without any prefix argument, update the node in which point is located.
-Non-nil argument (prefix, if interactive) means update the nodes in the
-marked region.
+Interactively, a prefix argument means to operate on the region.
 
 The functions for creating or updating nodes and menus, and their
 keybindings, are:
 
-    texinfo-update-node (&optional region-p)    \\[texinfo-update-node]
+    texinfo-update-node (&optional beginning end)    \\[texinfo-update-node]
     texinfo-every-node-update ()                \\[texinfo-every-node-update]
     texinfo-sequential-node-update (&optional region-p)
 
@@ -1027,40 +1232,40 @@ keybindings, are:
     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."
-  
-  (interactive "P")
-  (if (not region-p)
-      (let ((auto-fill-hook nil)) ; update a single node
-        (if (not (re-search-backward "^@node" (point-min) t))
-            (error "Node line not found before this position."))
-        (texinfo-update-the-node)
-        (message "Done...updated the node.  You may save the buffer."))
+which menu descriptions are indented. Its default value is 32."
+
+  (interactive
+   (if prefix-arg
+       (list (point) (mark))))
+  (if (null beginning)
+      ;; Update a single node.
+      (let ((auto-fill-function nil) (auto-fill-hook nil))
+       (if (not (re-search-backward "^@node" (point-min) t))
+           (error "Node line not found before this position"))
+       (texinfo-update-the-node)
+       (message "Done...updated the node.  You may save the buffer."))
     ;; else
-    (let ((auto-fill-hook nil)
-          (beginning (region-beginning))
-         (end (region-end)))
-      (if (= end beginning)
-          (error "Please mark a region!"))
-      (save-restriction
-       (narrow-to-region beginning end)
-       (goto-char beginning)
-        (push-mark)
-       (while (re-search-forward "^@node" (point-max) t)
-          (beginning-of-line)            
-          (texinfo-update-the-node))
-        (message "Done...updated nodes in region.  You may save the buffer.")))))
+    (let ((auto-fill-function nil)
+         (auto-fill-hook nil))
+      (save-excursion
+       (save-restriction
+         (narrow-to-region beginning end)
+         (goto-char (point-min))
+         (while (re-search-forward "^@node" (point-max) t)
+           (beginning-of-line)
+           (texinfo-update-the-node))
+         (goto-char (point-max))
+         (message "Done...nodes updated in region.  You may save the buffer."))))))
 
 (defun texinfo-every-node-update ()
   "Update every node in a Texinfo file."
   (interactive)
   (save-excursion
-    (mark-whole-buffer)
-    (texinfo-update-node t)
+    (texinfo-update-node (point-min) (point-max))
     (message "Done...updated every node.       You may save the buffer.")))
 
 (defun texinfo-update-the-node ()
-  "Update one node.  Point must be at the beginning of node line.  
+  "Update one node.  Point must be at the beginning of node line.
 Leave point at the end of the node line."
   (texinfo-check-for-node-name)
   (texinfo-delete-existing-pointers)
@@ -1068,17 +1273,17 @@ Leave point at the end of the node line."
   (save-restriction
     (widen)
     (let*
-        ((case-fold-search t)
-         (level (texinfo-hierarchic-level))
-         (beginning (texinfo-update-menu-region-beginning level))
-         (end (texinfo-update-menu-region-end level)))
-      (if (string-equal level "top")
-          (texinfo-top-pointer-case)
-        ;; else
-        (texinfo-insert-pointer beginning end level 'next)
-        (texinfo-insert-pointer beginning end level 'previous)
-        (texinfo-insert-pointer beginning end level 'up)
-        (texinfo-clean-up-node-line)))))
+       ((case-fold-search t)
+        (level (texinfo-hierarchic-level))
+        (beginning (texinfo-update-menu-region-beginning level))
+        (end (texinfo-update-menu-region-end level)))
+      (if (eq level 1)
+         (texinfo-top-pointer-case)
+       ;; else
+       (texinfo-insert-pointer beginning end level 'next)
+       (texinfo-insert-pointer beginning end level 'previous)
+       (texinfo-insert-pointer beginning end level 'up)
+       (texinfo-clean-up-node-line)))))
 
 (defun texinfo-top-pointer-case ()
   "Insert pointers in the Top node.  This is a special case.
@@ -1089,50 +1294,54 @@ to `(dir)'.  Point must be at the beginning of the node line, and is
 left at the end of the node line."
 
   (texinfo-clean-up-node-line)
-  (insert ", " 
-          (save-excursion
-            ;; There may be an @chapter or other such command between
-            ;; the top node line and the next node line, as a title
-            ;; for an `ifinfo' section. This @chapter command must
-            ;; must be skipped.  So the procedure is to search for
-            ;; the next `@node' line, and then copy its name.
-            (if (re-search-forward "^@node" nil t)
-                (progn
-                  (beginning-of-line)
-                  (texinfo-copy-node-name))
-              " "))
-          ", (dir), (dir)"))
+  (insert ", "
+         (save-excursion
+           ;; There may be an @chapter or other such command between
+           ;; the top node line and the next node line, as a title
+           ;; for an `ifinfo' section. This @chapter command must
+           ;; must be skipped.  So the procedure is to search for
+           ;; the next `@node' line, and then copy its name.
+           (if (re-search-forward "^@node" nil t)
+               (progn
+                 (beginning-of-line)
+                 (texinfo-copy-node-name))
+             " "))
+         ", (dir), (dir)"))
 
 (defun texinfo-check-for-node-name ()
   "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.  
+  "Delete `Next', `Previous', and `Up' pointers.
 Starts from the current position of the cursor, and searches forward
 on the line for a comma and if one is found, deletes the rest of the
 line, including the comma.  Leaves point at beginning of line."
-  (if (search-forward "," (save-excursion (end-of-line) (point)) t)
-      (progn
-        (goto-char (1- (point)))
-        (kill-line nil)))
+  (let ((eol-point (save-excursion (end-of-line) (point))))
+    (if (search-forward "," eol-point t)
+       (delete-region (1- (point)) eol-point)))
   (beginning-of-line))
 
 (defun texinfo-find-pointer (beginning end level direction)
   "Move point to section associated with next, previous, or up pointer.
-Return type of pointer (either 'normal or 'no-pointer).
+Return type of pointer (either `normal' or `no-pointer').
 
 The first and second arguments bound the search for a pointer to the
 beginning and end, respectively, of the enclosing higher level
 section.  The third argument is a string specifying the general kind
-of section such as \"chapter\ or \"section\".  When looking for the
+of section such as \"chapter\" or \"section\".  When looking for the
 `Next' pointer, the section found will be at the same hierarchical
 level in the Texinfo file; when looking for the `Previous' pointer,
 the section found will be at the same or higher hierarchical level in
@@ -1140,68 +1349,98 @@ the Texinfo file; when looking for the `Up' pointer, the section found
 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.
-The argument is the kind of section, either normal or no-pointer."
+The argument is the kind of section, either `normal' or `no-pointer'."
   (let (name)
     (cond ((eq kind 'normal)
-           (end-of-line)                ; this handles prev node top case
-           (re-search-backward          ; when point is already 
-            "^@node"                    ; at the beginning of @node line
-            (save-excursion (forward-line -3))
-            t)
-           (setq name (texinfo-copy-node-name)))
+          (end-of-line)                ; this handles prev node top case
+          (re-search-backward          ; when point is already
+           "^@node"                    ; at the beginning of @node line
+           (save-excursion (forward-line -3))
+           t)
+          (setq name (texinfo-copy-node-name)))
          ((eq kind 'no-pointer)
+          ;; Don't need to put a blank in the pointer slot,
+          ;; since insert "' " always has a space
           (setq name " ")))    ; put a blank in the pointer slot
     name))
 
 (defun texinfo-insert-pointer (beginning end level direction)
   "Insert the `Next', `Previous' or `Up' node name at point.
-Move point forward.  
+Move point forward.
 
 The first and second arguments bound the search for a pointer to the
 beginning and end, respectively, of the enclosing higher level
 section.  The third argument is the hierarchical level of the Texinfo
 file, a string such as \"section\".  The fourth argument is direction
-towards which the pointer is directed, one of `next, `previous, or
-'up."
+towards which the pointer is directed, one of `next', `previous', or `up'."
 
   (end-of-line)
   (insert
@@ -1217,14 +1456,14 @@ towards which the pointer is directed, one of `next, `previous, or
   (delete-region (point) (save-excursion (end-of-line) (point))))
 
 \f
-;;;; 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
-; section contains one or more subsections, the section's `Next'
-; pointer will point to the subsection and not the following section.
-; (The subsection to which `Next' points will most likely be the first
-; item on the section's menu.)
+;;; 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
+;; section contains one or more subsections, the section's `Next'
+;; pointer will point to the subsection and not the following section.
+;; (The subsection to which `Next' points will most likely be the first
+;; item on the section's menu.)
 
 (defun texinfo-sequential-node-update (&optional region-p)
   "Update one node (or many) in a Texinfo file with sequential pointers.
@@ -1242,99 +1481,100 @@ This command makes it awkward to navigate among sections and
 subsections; it should be used only for those documents that are meant
 to be read like a novel rather than a reference, and for which the
 Info `g*' command is inadequate."
-  
+
   (interactive "P")
   (if (not region-p)
-      (let ((auto-fill-hook nil))   ; update a single node
-        (if (not (re-search-backward "^@node" (point-min) t))
-            (error "Node line not found before this position."))
-        (texinfo-sequentially-update-the-node)
-        (message 
-         "Done...sequentially updated the node .  You may save the buffer."))
+      ;; update a single node
+      (let ((auto-fill-function nil) (auto-fill-hook nil))
+       (if (not (re-search-backward "^@node" (point-min) t))
+           (error "Node line not found before this position"))
+       (texinfo-sequentially-update-the-node)
+       (message
+        "Done...sequentially updated the node .  You may save the buffer."))
     ;; else
-    (let ((auto-fill-hook nil)
-          (beginning (region-beginning))
-          (end (region-end)))
+    (let ((auto-fill-function nil)
+         (auto-fill-hook nil)
+         (beginning (region-beginning))
+         (end (region-end)))
       (if (= end beginning)
-          (error "Please mark a region!"))
+         (error "Please mark a region!"))
       (save-restriction
-        (narrow-to-region beginning end)
-        (goto-char beginning)
-        (push-mark)
-        (while (re-search-forward "^@node" (point-max) t)
-          (beginning-of-line)            
-          (texinfo-sequentially-update-the-node))
-        (message 
-         "Done...updated the nodes in sequence.  You may save the buffer.")))))
+       (narrow-to-region beginning end)
+       (goto-char beginning)
+       (push-mark (point) t)
+       (while (re-search-forward "^@node" (point-max) t)
+         (beginning-of-line)
+         (texinfo-sequentially-update-the-node))
+       (message
+        "Done...updated the nodes in sequence.  You may save the buffer.")))))
 
 (defun texinfo-sequentially-update-the-node ()
-  "Update one node such that the pointers are sequential. 
+  "Update one node such that the pointers are sequential.
 A `Next' or `Previous' pointer points to any preceding or following node,
 regardless of its hierarchical level."
 
-        (texinfo-check-for-node-name)
-        (texinfo-delete-existing-pointers)
-        (message 
-         "Sequentially updating node: %s ... " (texinfo-copy-node-name))
-        (save-restriction
-          (widen)
-          (let*
-              ((case-fold-search t)
-               (level (texinfo-hierarchic-level)))
-            (if (string-equal level "top")
-                (texinfo-top-pointer-case)
-              ;; else
-              (texinfo-sequentially-insert-pointer level 'next)
-              (texinfo-sequentially-insert-pointer level 'previous)
-              (texinfo-sequentially-insert-pointer level 'up)
-              (texinfo-clean-up-node-line)))))
+  (texinfo-check-for-node-name)
+  (texinfo-delete-existing-pointers)
+  (message
+   "Sequentially updating node: %s ... " (texinfo-copy-node-name))
+  (save-restriction
+    (widen)
+    (let* ((case-fold-search t)
+          (level (texinfo-hierarchic-level)))
+      (if (eq level 1)
+         (texinfo-top-pointer-case)
+       ;; else
+       (texinfo-sequentially-insert-pointer level 'next)
+       (texinfo-sequentially-insert-pointer level 'previous)
+       (texinfo-sequentially-insert-pointer level 'up)
+       (texinfo-clean-up-node-line)))))
 
 (defun texinfo-sequentially-find-pointer (level direction)
   "Find next or previous pointer sequentially in Texinfo file, or up pointer.
 Move point to section associated with the pointer.  Find point even if
 it is in a different section.
 
-Return type of pointer (either 'normal or 'no-pointer).
+Return type of pointer (either `normal' or `no-pointer').
 
 The first argument is a string specifying the general kind of section
-such as \"chapter\ or \"section\".  The section found will be at the
+such as \"chapter\" or \"section\".  The section found will be at the
 same hierarchical level in the Texinfo file, or, in the case of the up
-pointer, some level higher.  The second argument (one of 'next,
-'previous, or 'up) specifies whether to find the `Next', `Previous',
+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.
-Move point forward.  
+Move point forward.
 
 The first argument is the hierarchical level of the Texinfo file, a
 string such as \"section\".  The second argument is direction, one of
-`next, `previous, or 'up."
+`next', `previous', or `up'."
 
   (end-of-line)
   (insert
@@ -1344,75 +1584,90 @@ string such as \"section\".  The second argument is direction, one of
       (texinfo-sequentially-find-pointer level direction)))))
 
 \f
-;;;; 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.
+;;; 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
+node names in pre-existing `@node' lines that lack names."
+  (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."))))
 
 \f
-;;;; 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 
+;;  1. M-x texinfo-multiple-files-update
 ;;
 ;;     Read the include file list of an outer Texinfo file and
 ;;     update all highest level nodes in the files listed and insert a
 ;;     main menu in the outer file after its top node.
 
-;;  2. C-u M-x texinfo-multiple-files-update 
+;;  2. C-u M-x texinfo-multiple-files-update
 ;;
 ;;     Same as 1, but insert a master menu.  (Saves reupdating lower
 ;;     level menus and nodes.)  This command simply reads every menu,
@@ -1420,7 +1675,7 @@ node names in pre-existing @node lines that lack names."
 ;;     Similarly, if the lower level node pointers are wrong, they
 ;;     will stay wrong.
 
-;;  3. C-u 2 M-x texinfo-multiple-files-update 
+;;  3. C-u 2 M-x texinfo-multiple-files-update
 ;;
 ;;     Read the include file list of an outer Texinfo file and
 ;;     update all nodes and menus in the files listed and insert a
@@ -1429,28 +1684,28 @@ node names in pre-existing @node lines that lack names."
 ;;; Note: these functions:
 ;;;
 ;;;   * Do not save or delete any buffers.  You may fill up your memory.
-;;;   * Do not handle any pre-existing nodes in outer file.  
+;;;   * Do not handle any pre-existing nodes in outer file.
 ;;;     Hence, you may need a file for indices.
 
 \f
-;;;; 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."
   (let ((included-file-list (list outer-file))
-        start)
+       start)
     (save-excursion
       (switch-to-buffer (find-file-noselect outer-file))
       (widen)
       (goto-char (point-min))
       (while (re-search-forward "^@include" nil t)
-        (skip-chars-forward " \t")
-        (setq start (point))
-        (end-of-line)
-        (skip-chars-backward " \t")   
-        (setq included-file-list
-              (cons (buffer-substring start (point))
-                    included-file-list)))
+       (skip-chars-forward " \t")
+       (setq start (point))
+       (end-of-line)
+       (skip-chars-backward " \t")
+       (setq included-file-list
+             (cons (buffer-substring start (point))
+                   included-file-list)))
       (nreverse included-file-list))))
 
 (defun texinfo-copy-next-section-title ()
@@ -1461,25 +1716,27 @@ same place.  If there is no title, returns an empty string."
 
   (save-excursion
     (end-of-line)
-    (let ((section-end (or 
-                        (save-excursion
-                          (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)
-        ""))))
+    (let ((node-end (or
+                       (save-excursion
+                         (if (re-search-forward "\\(^@node\\)" nil t)
+                             (match-beginning 0)))
+                       (point-max))))
+      (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.
@@ -1493,43 +1750,48 @@ Requirements:
 
   * the first file in the FILES list must be the outer file,
   * each of the included files must contain exactly one highest
-    hierarchical level node, 
+    hierarchical level node,
   * this node must be the first node in the included file,
   * each highest hierarchical level node must be of the same type.
 
-Thus, normally, each included file contains one, and only one,
-chapter.
+Thus, normally, each included file contains one, and only one, chapter."
 
-The menu-list has the form:
+;; 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.
 
-    \(\(\"node-name1\" . \"title1\"\) 
-      \(\"node-name2\" . \"title2\"\) ... \)
+  (let ((case-fold-search t)
+       menu-list)
 
-However, there does not need to be a title field."
-  
-  (let (menu-list)
-    
     ;; Find the name of the first node of the first included file.
     (switch-to-buffer (find-file-noselect (car (cdr files))))
     (widen)
     (goto-char (point-min))
     (if (not (re-search-forward "^@node" nil t))
-        (error "No `@node' line found in %s !" (buffer-name)))
+       (error "No `@node' line found in %s !" (buffer-name)))
     (beginning-of-line)
     (texinfo-check-for-node-name)
     (setq next-node-name (texinfo-copy-node-name))
-    
+
     (setq menu-list
-          (cons (cons 
-                 next-node-name
-                 (texinfo-copy-next-section-title))
-                menu-list))
-    
+         (cons (cons
+                next-node-name
+                (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))
     (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
-        (error "This buffer needs a Top node!"))
+       (error "This buffer needs a Top node!"))
     (beginning-of-line)
     (texinfo-delete-existing-pointers)
     (end-of-line)
@@ -1537,68 +1799,81 @@ However, there does not need to be a title field."
     (beginning-of-line)
     (setq previous-node-name "Top")
     (setq files (cdr files))
-    
+
     (while files
-      
+
       (if (not (cdr files))
-          ;; No next file
-          (setq next-node-name "")
-        ;; Else,
-        ;; find the name of the first node in the next file.
-        (switch-to-buffer (find-file-noselect (car (cdr files))))
-        (widen)
-        (goto-char (point-min))
-        (if (not (re-search-forward "^@node" nil t))
-            (error "No `@node' line found in %s !" (buffer-name)))
-        (beginning-of-line)
-        (texinfo-check-for-node-name)
-        (setq next-node-name (texinfo-copy-node-name))
-        (setq menu-list
-              (cons (cons 
-                     next-node-name
-                     (texinfo-copy-next-section-title))
-                    menu-list)))
+         ;; No next file
+         (setq next-node-name "")
+       ;; Else,
+       ;; find the name of the first node in the next file.
+       (switch-to-buffer (find-file-noselect (car (cdr files))))
+       (widen)
+       (goto-char (point-min))
+       (if (not (re-search-forward "^@node" nil t))
+           (error "No `@node' line found in %s !" (buffer-name)))
+       (beginning-of-line)
+       (texinfo-check-for-node-name)
+       (setq next-node-name (texinfo-copy-node-name))
+       (setq menu-list
+             (cons (cons
+                    next-node-name
+                    (prog1 "" (forward-line 1)))
+                   ;; Use following to insert section titles automatically.
+                   ;; (texinfo-copy-next-section-title)
+                   menu-list)))
 
       ;; Go to node to be updated.
       (switch-to-buffer (find-file-noselect (car files)))
       (goto-char (point-min))
       (if (not (re-search-forward "^@node" nil t))
-          (error "No `@node' line found in %s !" (buffer-name)))
+         (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)
-      
+
       (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)))
 
 (defun texinfo-multi-files-insert-main-menu (menu-list)
   "Insert formatted main menu at point.
 Indents the first line of the description, if any, to the value of
-texinfo-column-for-description."
+`texinfo-column-for-description'."
 
   (insert "@menu\n")
   (while menu-list
-    (if (cdr (car menu-list))       ; menu-list has description entry
-        (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
+    ;; 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
+         ;; 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'.
@@ -1608,35 +1883,38 @@ be the files included within it.  A main menu must already exist."
   (save-excursion
     (let (master-menu-list)
       (while files-list
-        (switch-to-buffer (find-file-noselect (car files-list)))
-        (message "Working on: %s " (current-buffer))
-        (goto-char (point-min))
-        (setq master-menu-list
-              (append master-menu-list (texinfo-master-menu-list)))
-        (setq files-list (cdr files-list)))
+       (switch-to-buffer (find-file-noselect (car files-list)))
+       (message "Working on: %s " (current-buffer))
+       (goto-char (point-min))
+       (setq master-menu-list
+             (append master-menu-list (texinfo-master-menu-list)))
+       (setq files-list (cdr files-list)))
       master-menu-list)))
 
 \f
-;;;; 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.
+a master menu in OUTER-FILE.  Also, update the `Top' level node
+pointers of OUTER-FILE.
 
-The command also updates the `Top' level node pointers of OUTER-FILE.
-
-Notes: 
+Notes:
 
   * this command does NOT save any files--you must save the
     outer file and any modified, included files.
@@ -1648,27 +1926,33 @@ Notes:
 Requirements:
 
   * each of the included files must contain exactly one highest
-    hierarchical level node, 
+    hierarchical level node,
   * this highest node must be the first node in the included file,
   * each highest hierarchical level node must be of the same type.
 
 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)
-         main-menu-list
-         next-node-name
-         previous-node-name
-         (up-node-name "Top"))
+        (files included-file-list)
+        main-menu-list
+        next-node-name
+        previous-node-name
+        (up-node-name "Top"))
 
-;;; Update the pointers 
+;;; Update the pointers
 ;;; and collect the names of the nodes and titles
     (setq main-menu-list (texinfo-multi-file-update files update-everything))
 
@@ -1679,20 +1963,20 @@ chapter."
   (if (texinfo-old-menu-p
        (point-min)
        (save-excursion
-         (re-search-forward "^@include")
-         (beginning-of-line)
-         (point)))
+        (re-search-forward "^@include")
+        (beginning-of-line)
+        (point)))
 
       ;; If found, leave point after word `menu' on the `@menu' line.
       (progn
-        (texinfo-incorporate-descriptions main-menu-list)
-        ;; Delete existing menu.
-        (beginning-of-line)
-        (delete-region
-         (point)
-         (save-excursion (re-search-forward "^@end menu") (point)))
-        ;; Insert main menu
-        (texinfo-multi-files-insert-main-menu main-menu-list))
+       (texinfo-incorporate-descriptions main-menu-list)
+       ;; Delete existing menu.
+       (beginning-of-line)
+       (delete-region
+        (point)
+        (save-excursion (re-search-forward "^@end menu") (point)))
+       ;; Insert main menu
+       (texinfo-multi-files-insert-main-menu main-menu-list))
 
     ;; Else no current menu; insert it before `@include'
     (texinfo-multi-files-insert-main-menu main-menu-list))
@@ -1701,25 +1985,47 @@ chapter."
 
   (if make-master-menu
       (progn
-        ;; First, removing detailed part of any pre-existing master menu
-        (goto-char (point-min))
-        (if (re-search-forward texinfo-master-menu-header nil 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))))
-
-        ;; Create a master menu and insert it
-        (texinfo-insert-master-menu-list 
-         (texinfo-multi-file-master-menu-list 
-          included-file-list)))))
+       ;; First, removing detailed part of any pre-existing master menu
+       (goto-char (point-min))
+       (if (search-forward texinfo-master-menu-header nil t)
+           (progn
+             (goto-char (match-beginning 0))
+             ;; Check if @detailmenu kludge is used;
+             ;; if so, leave point before @detailmenu.
+             (search-backward "\n@detailmenu"
+                              (save-excursion (forward-line -3) (point))
+                              t)
+             ;; Remove detailed master menu listing
+             (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))))
+
+       ;; Create a master menu and insert it
+       (texinfo-insert-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."))
 
+\f
+;;; Place `provide' at end of file.
 (provide 'texnfo-upd)
 
 ;;; texnfo-upd.el ends here