]> code.delx.au - gnu-emacs/blobdiff - lisp/startup.el
(locate): Remove dot at the end of error argument.
[gnu-emacs] / lisp / startup.el
index 0fffc1b90ec18bab6984ed7f82e6c90a0d5c4159..f9b2c2633d10c5b74db3f85bcf4ddbe8f84903bc 100644 (file)
@@ -56,7 +56,7 @@
 ;; --display DISPNAME        This option is handled by emacs.c
 ;; -------------------------
 ;; -nw                       Do not use a windows system (but use the
-;; --no-windows              terminal instead.)
+;; --no-window-system        terminal instead.)
 ;;                           This option is handled by emacs.c
 ;; -------------------------
 ;; -batch                    Execute noninteractively (messages go to stdout,
 (setq top-level '(normal-top-level))
 
 (defvar command-line-processed nil
-  "Non-nil once command line has been processed")
+  "Non-nil once command line has been processed.")
 
 (defgroup initialization nil
   "Emacs start-up procedure"
@@ -355,8 +355,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
     ;; This loop does a breadth-first tree walk on DIR's subtree,
     ;; putting each subdir into DIRS as its contents are examined.
     (while pending
-      (setq dirs (cons (car pending) dirs))
-      (setq pending (cdr pending))
+      (push (pop pending) dirs)
       (let* ((this-dir (car dirs))
             (contents (directory-files this-dir))
             (default-directory this-dir)
@@ -368,22 +367,20 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
        (setq attrs (or canonicalized
                        (nthcdr 10 (file-attributes this-dir))))
        (unless (member attrs normal-top-level-add-subdirs-inode-list)
-         (setq normal-top-level-add-subdirs-inode-list
-               (cons attrs normal-top-level-add-subdirs-inode-list))
-         (while contents
+         (push attrs normal-top-level-add-subdirs-inode-list)
+         (dolist (file contents)
            ;; The lower-case variants of RCS and CVS are for DOS/Windows.
-           (unless (member (car contents) '("." ".." "RCS" "CVS" "rcs" "cvs"))
-             (when (and (string-match "\\`[[:alnum:]]" (car contents))
+           (unless (member file '("." ".." "RCS" "CVS" "rcs" "cvs"))
+             (when (and (string-match "\\`[[:alnum:]]" file)
                         ;; Avoid doing a `stat' when it isn't necessary
                         ;; because that can cause trouble when an NFS server
                         ;; is down.
-                        (not (string-match "\\.elc?\\'" (car contents)))
-                        (file-directory-p (car contents)))
-               (let ((expanded (expand-file-name (car contents))))
+                        (not (string-match "\\.elc?\\'" file))
+                        (file-directory-p file))
+               (let ((expanded (expand-file-name file)))
                  (unless (file-exists-p (expand-file-name ".nosearch"
                                                           expanded))
-                   (setq pending (nconc pending (list expanded)))))))
-           (setq contents (cdr contents))))))
+                   (setq pending (nconc pending (list expanded)))))))))))
     (normal-top-level-add-to-load-path (cdr (nreverse dirs)))))
 
 ;; This function is called from a subdirs.el file.
@@ -426,7 +423,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
     (let ((tail load-path)
          new)
       (while tail
-       (setq new (cons (car tail) new))
+       (push (car tail) new)
        (condition-case nil
            (let ((default-directory (car tail)))
              (load (expand-file-name "subdirs.el" (car tail)) t t t)))
@@ -717,7 +714,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
     (while (and (not done) args)
       (let ((longopts '(("--no-init-file") ("--no-site-file") ("--user")
                        ("--debug-init") ("--iconic") ("--icon-type")))
-           (argi (car args))
+           (argi (pop args))
            (argval nil))
        ;; Handle --OPTION=VALUE format.
        (if (and (string-match "\\`--" argi)
@@ -735,35 +732,25 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
                      (setq argi (substring (car elt) 1)))
                  (setq argval nil)))))
        (cond
-        ((or (string-equal argi "-q")
-             (string-equal argi "-no-init-file"))
-         (setq init-file-user nil
-               args (cdr args)))
-        ((or (string-equal argi "-u")
-             (string-equal argi "-user"))
+        ((member argi '("-q" "-no-init-file"))
+         (setq init-file-user nil))
+        ((member argi '("-u" "-user"))
          (or argval
-             (setq args (cdr args)
-                   argval (car args)))
+             (setq argval (pop args)))
          (setq init-file-user argval
-               argval nil
-               args (cdr args)))
+               argval nil))
         ((string-equal argi "-no-site-file")
-         (setq site-run-file nil
-               args (cdr args)))
+         (setq site-run-file nil))
         ((string-equal argi "-debug-init")
-         (setq init-file-debug t
-               args (cdr args)))
+         (setq init-file-debug t))
         ((string-equal argi "-iconic")
-         (setq initial-frame-alist
-               (cons '(visibility . icon) initial-frame-alist))
-         (setq args (cdr args)))
+         (push '(visibility . icon) initial-frame-alist))
         ((or (string-equal argi "-icon-type")
              (string-equal argi "-i")
              (string-equal argi "-itype"))
-         (setq default-frame-alist
-               (cons '(icon-type . t) default-frame-alist))
-         (setq args (cdr args)))
-        (t (setq done t)))
+         (push '(icon-type . t) default-frame-alist))
+        ;; Push the popped arg back on the list of arguments.
+        (t (push argi args) (setq done t)))
        ;; Was argval set but not used?
        (and argval
             (error "Option `%s' doesn't allow an argument" argi))))
@@ -778,7 +765,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
   ;; If frame was created with a menu bar, set menu-bar-mode on.
   (if (and (not noninteractive)
           (or (not (memq window-system '(x w32)))
-              (> (cdr (assq 'menu-bar-lines (frame-parameters))) 0)))
+              (> (frame-parameter nil 'menu-bar-lines) 0)))
       (menu-bar-mode t))
 
   ;; If frame was created with a tool bar, switch tool-bar-mode on.
@@ -800,7 +787,12 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
     (when (or (memq system-type '(ms-dos windows-nt))
              (and (memq window-system '(x))
                   (fboundp 'x-backspace-delete-keys-p)
-                  (x-backspace-delete-keys-p)))
+                  (x-backspace-delete-keys-p))
+             ;; If the terminal Emacs is running on has erase char
+             ;; set to ^H, use the Backspace key for deleting
+             ;; backward and, and the Delete key for deleting forward.
+             (and (null window-system)
+                  (eq tty-erase-char 8)))
       (setq-default normal-erase-is-backspace t)
       (normal-erase-is-backspace-mode 1)))
 
@@ -868,7 +860,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
              (lambda ()
                (if init-file-user
                    (let ((user-init-file-1
-                          (cond 
+                          (cond
                            ((eq system-type 'ms-dos)
                             (concat "~" init-file-user "/_emacs"))
                            ((eq system-type 'windows-nt)
@@ -877,7 +869,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
                               "~/_emacs"))
                            ((eq system-type 'vax-vms) 
                             "sys$login:.emacs")
-                           (t 
+                           (t
                             (concat "~" init-file-user "/.emacs")))))
                      ;; This tells `load' to store the file name found
                      ;; into user-init-file.
@@ -888,7 +880,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
                      ;; set user-init-file conclusively to nil;
                      ;; don't let it be set from default.el.
                      (if (eq user-init-file t)
-                         (setq user-init-file nil))
+                         (setq user-init-file user-init-file-1))
                      
                      ;; If we loaded a compiled file, set
                      ;; `user-init-file' to the source version if that
@@ -944,6 +936,15 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
                        (mapconcat 'prin1-to-string (cdr error) ", "))
               (pop-to-buffer "*Messages*")
               (setq init-file-had-error t)))))
+
+       ;; If the user has a file of abbrevs, read it.
+       (if (file-exists-p abbrev-file-name)
+           (quietly-read-abbrev-file abbrev-file-name))
+
+       ;; If the abbrevs came entirely from the init file or the
+       ;; abbrevs file, they do not need saving.
+       (setq abbrevs-changed nil)
+
        ;; If we can tell that the init file altered debug-on-error,
        ;; arrange to preserve the value that it set up.
        (or (eq debug-on-error debug-on-error-initial)
@@ -1088,7 +1089,7 @@ Values less than 60 seconds are ignored."
 (defvar fancy-current-text nil)
 (defvar fancy-splash-help-echo nil)
 (defvar fancy-splash-stop-time nil)
-
+(defvar fancy-splash-outer-buffer nil)
 
 (defun fancy-splash-insert (&rest args)
   "Insert text into the current buffer, with faces.
@@ -1125,6 +1126,12 @@ where FACE is a valid face specification, as it can be used with
        (let ((pos (/ (- window-width image-width) 2)))
          (insert (propertize " " 'display `(space :align-to ,pos))))
 
+       ;; Change the color of the XPM version of the splash image
+       ;; so that it is visible with a dark frame background.
+       (when (and (memq 'xpm img)
+                  (eq (frame-parameter nil 'background-mode) 'dark))
+         (setq img (append img '(:color-symbols (("#000000" . "gray30"))))))
+
        ;; Insert the image with a help-echo and a keymap.
        (let ((map (make-sparse-keymap))
              (help-echo "mouse-2: browse http://www.gnu.org/"))
@@ -1145,7 +1152,11 @@ where FACE is a valid face specification, as it can be used with
     (fancy-splash-insert
      :face '(variable-pitch :foreground "red")
      "GNU Emacs is one component of the GNU operating system."))
-  (insert "\n"))
+  (insert "\n")
+  (unless (equal (buffer-name fancy-splash-outer-buffer) "*scratch*")
+    (fancy-splash-insert :face 'variable-pitch
+                        (substitute-command-keys
+                         "Type \\[recenter] to begin editing your file.\n"))))
 
 
 (defun fancy-splash-tail ()
@@ -1157,8 +1168,24 @@ where FACE is a valid face specification, as it can be used with
                         (emacs-version)
                         "\n"
                         :face '(variable-pitch :height 0.5)
-                        "Copyright (C) 2001 Free Software Foundation, Inc.")))
-
+                        "Copyright (C) 2001 Free Software Foundation, Inc.")
+    (and auto-save-list-file-prefix
+        ;; Don't signal an error if the
+        ;; directory for auto-save-list files
+        ;; does not yet exist.
+        (file-directory-p (file-name-directory
+                           auto-save-list-file-prefix))
+        (directory-files
+         (file-name-directory auto-save-list-file-prefix)
+         nil
+         (concat "\\`"
+                 (regexp-quote (file-name-nondirectory
+                                auto-save-list-file-prefix)))
+         t)
+        (fancy-splash-insert :face '(variable-pitch :foreground "red")
+                             "\n\nIf an Emacs session crashed recently, "
+                             "type M-x recover-session RET\nto recover"
+                             " the files you were editing."))))
 
 (defun fancy-splash-screens-1 (buffer)
   "Timer function displaying a splash screen."
@@ -1190,12 +1217,14 @@ where FACE is a valid face specification, as it can be used with
 (defun fancy-splash-screens ()
   "Display fancy splash screens when Emacs starts."
   (setq fancy-splash-help-echo (startup-echo-area-message))
-  (switch-to-buffer "GNU Emacs")
   (setq tab-width 20)
   (let ((old-hourglass display-hourglass)
-       (splash-buffer (current-buffer))
+       (fancy-splash-outer-buffer (current-buffer))
+       splash-buffer
        (old-minor-mode-map-alist minor-mode-map-alist)
        timer)
+    (switch-to-buffer "GNU Emacs")
+    (setq splash-buffer (current-buffer))
     (catch 'stop-splashing
       (unwind-protect
          (let ((map (make-sparse-keymap)))
@@ -1250,87 +1279,303 @@ where FACE is a valid face specification, as it can be used with
 
 (defun command-line-1 (command-line-args-left)
   (or noninteractive (input-pending-p) init-file-had-error
-       (and inhibit-startup-echo-area-message
-            user-init-file
-            (or (and (get 'inhibit-startup-echo-area-message 'saved-value)
-                     (equal inhibit-startup-echo-area-message
-                            (if (string= init-file-user "")
-                                (user-login-name)
-                              init-file-user)))
-                ;; Wasn't set with custom; see if .emacs has a setq.
-                (let ((buffer (get-buffer-create " *temp*")))
-                  (prog1
-                      (condition-case nil
-                          (save-excursion
-                            (set-buffer buffer)
-                            (insert-file-contents user-init-file)
-                            (re-search-forward
-                             (concat
-                              "([ \t\n]*setq[ \t\n]+"
-                              "inhibit-startup-echo-area-message[ \t\n]+"
-                              (regexp-quote
-                               (prin1-to-string
-                                (if (string= init-file-user "")
-                                    (user-login-name)
-                                  init-file-user)))
-                              "[ \t\n]*)")
-                             nil t))
-                        (error nil))
-                    (kill-buffer buffer)))))
-       (display-startup-echo-area-message))
-  (if (null command-line-args-left)
-      (cond ((and (not inhibit-startup-message) (not noninteractive)
-                 ;; Don't clobber a non-scratch buffer if init file
-                 ;; has selected it.
-                 (string= (buffer-name) "*scratch*"))
-            ;; If there are no switches to process, we might as well
-            ;; run this hook now, and there may be some need to do it
-            ;; before doing any output.
-            (and term-setup-hook
-                 (run-hooks 'term-setup-hook))
-            ;; Don't let the hook be run twice.
-            (setq term-setup-hook nil)
-
-            ;; It's important to notice the user settings before we
-            ;; display the startup message; otherwise, the settings
-            ;; won't take effect until the user gives the first
-            ;; keystroke, and that's distracting.
-            (when (fboundp 'frame-notice-user-settings)
-              (frame-notice-user-settings))
-
-            (when window-setup-hook
-              (run-hooks 'window-setup-hook)
-              (setq window-setup-hook nil))
-            
-            (when (display-popup-menus-p)
-              (precompute-menubar-bindings))
-            (setq menubar-bindings-done t)
-            
-            ;; Do this now to avoid an annoying delay if the user
-            ;; clicks the menu bar during the sit-for.
-            (when (= (buffer-size) 0)
-              (let ((buffer-undo-list t)
-                    (tab-width 8)
-                    (wait-for-input t))
-                (unwind-protect
-                    (when (not (input-pending-p))
-                      (goto-char (point-max))
-                      ;; The convention for this piece of code is that
-                      ;; each piece of output starts with one or two newlines
-                      ;; and does not end with any newlines.
-                      (insert "Welcome to GNU Emacs")
-                      (if (eq system-type 'gnu/linux)
-                          (insert ", one component of a Linux-based GNU system."))
-                      (insert "\n")
-                      
-                      (if (assq 'display (frame-parameters))
-                          
-                          (if (use-fancy-splash-screens-p)
-                              (progn
-                                (setq wait-for-input nil)
-                                (fancy-splash-screens))
-                            (progn
-                              (insert "\
+      ;; t if the init file says to inhibit the echo area startup message.
+      (and inhibit-startup-echo-area-message
+          user-init-file
+          (or (and (get 'inhibit-startup-echo-area-message 'saved-value)
+                   (equal inhibit-startup-echo-area-message
+                          (if (string= init-file-user "")
+                              (user-login-name)
+                            init-file-user)))
+              ;; Wasn't set with custom; see if .emacs has a setq.
+              (let ((buffer (get-buffer-create " *temp*")))
+                (prog1
+                    (condition-case nil
+                        (save-excursion
+                          (set-buffer buffer)
+                          (insert-file-contents user-init-file)
+                          (re-search-forward
+                           (concat
+                            "([ \t\n]*setq[ \t\n]+"
+                            "inhibit-startup-echo-area-message[ \t\n]+"
+                            (regexp-quote
+                             (prin1-to-string
+                              (if (string= init-file-user "")
+                                  (user-login-name)
+                                init-file-user)))
+                            "[ \t\n]*)")
+                           nil t))
+                      (error nil))
+                  (kill-buffer buffer)))))
+      (display-startup-echo-area-message))
+
+  ;; Delay 2 seconds after an init file error message
+  ;; was displayed, so user can read it.
+  (if init-file-had-error
+      (sit-for 2))
+
+  (if command-line-args-left
+      ;; We have command args; process them.
+      (let ((dir command-line-default-directory)
+           (file-count 0)
+           first-file-buffer
+           tem
+           just-files ;; t if this follows the magic -- option.
+           ;; This includes our standard options' long versions
+           ;; and long versions of what's on command-switch-alist.
+           (longopts
+            (append '(("--funcall") ("--load") ("--insert") ("--kill")
+                      ("--directory") ("--eval") ("--execute")
+                      ("--find-file") ("--visit") ("--file"))
+                    (mapcar (lambda (elt)
+                              (list (concat "-" (car elt))))
+                            command-switch-alist)))
+           (line 0)
+           (column 0))
+
+       ;; Add the long X options to longopts.
+       (dolist (tem command-line-x-option-alist)
+         (if (string-match "^--" (car tem))
+             (push (list (car tem)) longopts)))
+
+       ;; Loop, processing options.
+       (while (and command-line-args-left)
+         (let* ((argi (car command-line-args-left))
+                (orig-argi argi)
+                argval completion
+                ;; List of directories specified in -L/--directory,
+                ;; in reverse of the order specified.
+                extra-load-path
+                (initial-load-path load-path))
+           (setq command-line-args-left (cdr command-line-args-left))
+
+           ;; Do preliminary decoding of the option.
+           (if just-files
+               ;; After --, don't look for options; treat all args as files.
+               (setq argi "")
+             ;; Convert long options to ordinary options
+             ;; and separate out an attached option argument into argval.
+             (if (string-match "^--[^=]*=" argi)
+                 (setq argval (substring argi (match-end 0))
+                       argi (substring argi 0 (1- (match-end 0)))))
+             (if (equal argi "--")
+                 (setq completion nil)
+               (setq completion (try-completion argi longopts)))
+             (if (eq completion t)
+                 (setq argi (substring argi 1))
+               (if (stringp completion)
+                   (let ((elt (assoc completion longopts)))
+                     (or elt
+                         (error "Option `%s' is ambiguous" argi))
+                     (setq argi (substring (car elt) 1)))
+                 (setq argval nil argi orig-argi))))
+
+           ;; Execute the option.
+           (cond ((setq tem (assoc argi command-switch-alist))
+                  (if argval
+                      (let ((command-line-args-left
+                             (cons argval command-line-args-left)))
+                        (funcall (cdr tem) argi))
+                    (funcall (cdr tem) argi)))
+
+                 ((member argi '("-f"  ;what the manual claims
+                                 "-funcall"
+                                 "-e")) ; what the source used to say
+                  (if argval
+                      (setq tem (intern argval))
+                    (setq tem (intern (car command-line-args-left)))
+                    (setq command-line-args-left (cdr command-line-args-left)))
+                  (if (arrayp (symbol-function tem))
+                      (command-execute tem)
+                    (funcall tem)))
+
+                 ((member argi '("-eval" "-execute"))
+                  (if argval
+                      (setq tem argval)
+                    (setq tem (car command-line-args-left))
+                    (setq command-line-args-left (cdr command-line-args-left)))
+                  (eval (read tem)))
+                 ;; Set the default directory as specified in -L.
+
+                 ((member argi '("-L" "-directory"))
+                  (if argval
+                      (setq tem argval)
+                    (setq tem (car command-line-args-left)
+                          command-line-args-left (cdr command-line-args-left)))
+                  (setq tem (command-line-normalize-file-name tem))
+                  (setq extra-load-path
+                        (cons (expand-file-name tem) extra-load-path))
+                  (setq load-path (append (nreverse extra-load-path)
+                                          initial-load-path)))
+
+                 ((member argi '("-l" "-load"))
+                  (if argval
+                      (setq tem argval)
+                    (setq tem (car command-line-args-left)
+                          command-line-args-left (cdr command-line-args-left)))
+                  (let ((file (command-line-normalize-file-name tem)))
+                    ;; Take file from default dir if it exists there;
+                    ;; otherwise let `load' search for it.
+                    (if (file-exists-p (expand-file-name file))
+                        (setq file (expand-file-name file)))
+                    (load file nil t)))
+
+                 ((string-equal argi "-insert")
+                  (if argval
+                      (setq tem argval)
+                    (setq tem (car command-line-args-left)
+                          command-line-args-left (cdr command-line-args-left)))
+                  (or (stringp tem)
+                      (error "File name omitted from `-insert' option"))
+                  (insert-file-contents (command-line-normalize-file-name tem)))
+
+                 ((string-equal argi "-kill")
+                  (kill-emacs t))
+
+                 ((string-match "^\\+[0-9]+\\'" argi)
+                  (setq line (string-to-int argi)))
+
+                 ((string-match "^\\+\\([0-9]+\\):\\([0-9]+\\)\\'" argi)
+                  (setq line (string-to-int (match-string 1 argi))
+                        column (string-to-int (match-string 2 argi))))
+
+                 ((setq tem (assoc argi command-line-x-option-alist))
+                  ;; Ignore X-windows options and their args if not using X.
+                  (setq command-line-args-left
+                        (nthcdr (nth 1 tem) command-line-args-left)))
+
+                 ((member argi '("-find-file" "-file" "-visit"))
+                  ;; An explicit option to specify visiting a file.
+                  (if argval
+                      (setq tem argval)
+                    (setq tem (car command-line-args-left)
+                          command-line-args-left (cdr command-line-args-left)))
+                  (unless (stringp tem)
+                    (error "File name omitted from `%s' option" argi))
+                  (setq file-count (1+ file-count))
+                  (let ((file (expand-file-name
+                               (command-line-normalize-file-name tem) dir)))
+                    (if (= file-count 1)
+                        (setq first-file-buffer (find-file file))
+                      (find-file-other-window file)))
+                  (or (zerop line)
+                      (goto-line line))
+                  (setq line 0)
+                  (unless (< column 1)
+                    (move-to-column (1- column)))
+                  (setq column 0))
+
+                 ((equal argi "--")
+                  (setq just-files t))
+                 (t
+                  ;; We have almost exhausted our options. See if the
+                  ;; user has made any other command-line options available
+                  (let ((hooks command-line-functions) ;; lrs 7/31/89
+                        (did-hook nil))
+                    (while (and hooks
+                                (not (setq did-hook (funcall (car hooks)))))
+                      (setq hooks (cdr hooks)))
+                    (if (not did-hook)
+                      ;; Ok, presume that the argument is a file name
+                        (progn
+                          (if (string-match "\\`-" argi)
+                              (error "Unknown option `%s'" argi))
+                          (setq file-count (1+ file-count))
+                          (let ((file
+                                 (expand-file-name
+                                  (command-line-normalize-file-name orig-argi)
+                                  dir)))
+                            (if (= file-count 1)
+                                (setq first-file-buffer (find-file file))
+                              (find-file-other-window file)))
+                          (or (zerop line)
+                              (goto-line line))
+                          (setq line 0)
+                          (unless (< column 1)
+                            (move-to-column (1- column)))
+                          (setq column 0))))))))
+       ;; If 3 or more files visited, and not all visible,
+       ;; show user what they all are.  But leave the last one current.
+       (and (> file-count 2)
+            (not noninteractive)
+            (not inhibit-startup-buffer-menu)
+            (or (get-buffer-window first-file-buffer)
+                (list-buffers)))))
+
+  ;; Maybe display a startup screen.
+  (when (and (not inhibit-startup-message) (not noninteractive)
+            ;; Don't display startup screen if init file
+            ;; has started some sort of server.
+            (not (and (fboundp 'process-list)
+                      (process-list))))
+    ;; Display a startup screen, after some preparations.
+
+    ;; If there are no switches to process, we might as well
+    ;; run this hook now, and there may be some need to do it
+    ;; before doing any output.
+    (and term-setup-hook
+        (run-hooks 'term-setup-hook))
+    ;; Don't let the hook be run twice.
+    (setq term-setup-hook nil)
+
+    ;; It's important to notice the user settings before we
+    ;; display the startup message; otherwise, the settings
+    ;; won't take effect until the user gives the first
+    ;; keystroke, and that's distracting.
+    (when (fboundp 'frame-notice-user-settings)
+      (frame-notice-user-settings))
+
+    ;; If there are no switches to process, we might as well
+    ;; run this hook now, and there may be some need to do it
+    ;; before doing any output.
+    (when window-setup-hook
+      (run-hooks 'window-setup-hook)
+      ;; Don't let the hook be run twice.
+      (setq window-setup-hook nil))
+
+    ;; Do this now to avoid an annoying delay if the user
+    ;; clicks the menu bar during the sit-for.
+    (when (display-popup-menus-p)
+      (precompute-menubar-bindings))
+    (setq menubar-bindings-done t)
+
+    ;; If *scratch* is selected and it is empty, insert an
+    ;; initial message saying not to create a file there.
+    (when (and initial-scratch-message
+              (string= (buffer-name) "*scratch*")
+              (= 0 (buffer-size)))
+      (insert initial-scratch-message)
+      (set-buffer-modified-p nil))
+
+    ;; If user typed input during all that work,
+    ;; abort the startup screen.  Otherwise, display it now.
+    (let ((buffer (current-buffer)))
+      (when (not (input-pending-p))
+       (if (and (display-graphic-p)
+                (use-fancy-splash-screens-p))
+           (fancy-splash-screens)
+         (with-current-buffer (get-buffer-create "GNU Emacs")
+           (let ((tab-width 8)
+                 (mode-line-format (propertize "---- %b %-" 
+                                               'face '(:weight bold))))
+
+             ;; The convention for this piece of code is that
+             ;; each piece of output starts with one or two newlines
+             ;; and does not end with any newlines.
+             (insert "Welcome to GNU Emacs")
+             (if (eq system-type 'gnu/linux)
+                 (insert ", one component of a Linux-based GNU system."))
+             (insert "\n")
+
+             (unless (equal (buffer-name buffer) "*scratch*")
+               (insert (substitute-command-keys
+                        "\nType \\[recenter] to begin editing your file.\n")))
+
+             (if (display-mouse-p)
+                 ;; The user can use the mouse to activate menus
+                 ;; so give help in terms of menu items.
+                 (progn
+                   (insert "\
 You can do basic editing with the menu bar and scroll bar using the mouse.
 
 Useful File menu items:
@@ -1345,295 +1590,100 @@ Copying Conditions    Conditions for redistributing and changing Emacs.
 Getting New Versions   How to obtain the latest version of Emacs.
 Ordering Manuals       How to order manuals from the FSF.
 ")
-                              (insert "\n\n" (emacs-version)
-                                      "
-Copyright (C) 2001 Free Software Foundation, Inc.")))
-                        
-                        ;; If keys have their default meanings,
-                        ;; use precomputed string to save lots of time.
-                        (if (and (eq (key-binding "\C-h") 'help-command)
-                                 (eq (key-binding "\C-xu") 'advertised-undo)
-                                 (eq (key-binding "\C-x\C-c") 'save-buffers-kill-emacs)
-                                 (eq (key-binding "\C-ht") 'help-with-tutorial)
-                                 (eq (key-binding "\C-hi") 'info)
-                                 (eq (key-binding "\C-h\C-n") 'view-emacs-news))
-                            (insert "
+                   (insert "\n\n" (emacs-version)
+                           "
+Copyright (C) 2001 Free Software Foundation, Inc."))
+
+               ;; No mouse menus, so give help using kbd commands.
+
+               ;; If keys have their default meanings,
+               ;; use precomputed string to save lots of time.
+               (if (and (eq (key-binding "\C-h") 'help-command)
+                        (eq (key-binding "\C-xu") 'advertised-undo)
+                        (eq (key-binding "\C-x\C-c") 'save-buffers-kill-emacs)
+                        (eq (key-binding "\C-ht") 'help-with-tutorial)
+                        (eq (key-binding "\C-hi") 'info)
+                        (eq (key-binding "\C-h\C-n") 'view-emacs-news))
+                   (insert "
 Get help          C-h  (Hold down CTRL and press h)
 Undo changes      C-x u       Exit Emacs               C-x C-c
 Get a tutorial    C-h t       Use Info to read docs    C-h i
 Ordering manuals   C-h RET")
-                          (insert (substitute-command-keys
-                                   (format "\n
+                 (insert (substitute-command-keys
+                          (format "\n
 Get help          %s
 Undo changes      \\[advertised-undo]
 Exit Emacs        \\[save-buffers-kill-emacs]
 Get a tutorial    \\[help-with-tutorial]
 Use Info to read docs  \\[info]
 Ordering manuals   \\[view-order-manuals]"
-                                           (let ((where (where-is-internal
-                                                         'help-command nil t)))
-                                             (if where
-                                                 (key-description where)
-                                               "M-x help"))))))
-                        ;; Say how to use the menu bar
-                        ;; if that is not with the mouse.
-                        (if (and (eq (key-binding "\M-`") 'tmm-menubar)
-                                 (eq (key-binding [f10]) 'tmm-menubar))
-                            (insert "
+                                  (let ((where (where-is-internal
+                                                'help-command nil t)))
+                                    (if where
+                                        (key-description where)
+                                      "M-x help"))))))
+
+               ;; Say how to use the menu bar with the keyboard.
+               (if (and (eq (key-binding "\M-`") 'tmm-menubar)
+                        (eq (key-binding [f10]) 'tmm-menubar))
+                   (insert "
 Activate menubar   F10  or  ESC `  or   M-`")
-                          (insert (substitute-command-keys "
+                 (insert (substitute-command-keys "
 Activate menubar     \\[tmm-menubar]")))
 
-                        (if (display-mouse-p)
-                            (insert "
-Mode-specific menu   C-mouse-3 (third button, with CTRL)"))
-                        ;; Many users seem to have problems with these.
-                        (insert "
+               ;; Many users seem to have problems with these.
+               (insert "
 \(`C-' means use the CTRL key.  `M-' means use the Meta (or Alt) key.
 If you have no Meta key, you may instead type ESC followed by the character.)")
-                        (and auto-save-list-file-prefix
-                             ;; Don't signal an error if the
-                             ;; directory for auto-save-list files
-                             ;; does not yet exist.
-                             (file-directory-p (file-name-directory
-                                                auto-save-list-file-prefix))
-                             (directory-files
-                              (file-name-directory auto-save-list-file-prefix)
-                              nil
-                              (concat "\\`"
-                                      (regexp-quote (file-name-nondirectory
-                                                     auto-save-list-file-prefix)))
-                              t)
-                             (insert "\n\nIf an Emacs session crashed recently, "
-                                     "type M-x recover-session RET\nto recover"
-                                     " the files you were editing."))
 
-                        (insert "\n\n" (emacs-version)
-                                "
+               (insert "\n\n" (emacs-version)
+                       "
 Copyright (C) 2001 Free Software Foundation, Inc.")
-                        (if (and (eq (key-binding "\C-h\C-c") 'describe-copying)
-                                 (eq (key-binding "\C-h\C-d") 'describe-distribution)
-                                 (eq (key-binding "\C-h\C-w") 'describe-no-warranty))
-                            (insert 
-                             "\n
+
+               (if (and (eq (key-binding "\C-h\C-c") 'describe-copying)
+                        (eq (key-binding "\C-h\C-d") 'describe-distribution)
+                        (eq (key-binding "\C-h\C-w") 'describe-no-warranty))
+                   (insert 
+                    "\n
 GNU Emacs comes with ABSOLUTELY NO WARRANTY; type C-h C-w for full details.
 Emacs is Free Software--Free as in Freedom--so you can redistribute copies
 of Emacs and modify it; type C-h C-c to see the conditions.
 Type C-h C-d for information on getting the latest version.")
-                          (insert (substitute-command-keys
-                                   "\n
+                 (insert (substitute-command-keys
+                          "\n
 GNU Emacs comes with ABSOLUTELY NO WARRANTY; type \\[describe-no-warranty] for full details.
 Emacs is Free Software--Free as in Freedom--so you can redistribute copies
 of Emacs and modify it; type \\[describe-copying] to see the conditions.
 Type \\[describe-distribution] for information on getting the latest version."))))
-                      (goto-char (point-min))
-
-                      (set-buffer-modified-p nil)
-                      (when wait-for-input
-                        (sit-for 120)))
-                  
-                  (with-current-buffer (get-buffer "*scratch*")
-                    (erase-buffer)
-                    (when initial-scratch-message
-                      (insert initial-scratch-message))
-                    (set-buffer-modified-p nil)))))))
-    
-    ;; Delay 2 seconds after the init file error message
-    ;; was displayed, so user can read it.
-    (if init-file-had-error
-       (sit-for 2))
-    (let ((dir command-line-default-directory)
-         (file-count 0)
-         first-file-buffer
-         tem
-         just-files;; t if this follows the magic -- option.
-         ;; This includes our standard options' long versions
-         ;; and long versions of what's on command-switch-alist.
-         (longopts
-          (append '(("--funcall") ("--load") ("--insert") ("--kill")
-                    ("--directory") ("--eval") ("--execute")
-                    ("--find-file") ("--visit") ("--file"))
-                  (mapcar (lambda (elt)
-                            (list (concat "-" (car elt))))
-                          command-switch-alist)))
-         (line 0)
-         (column 0))
-
-      ;; Add the long X options to longopts.
-      (setq tem command-line-x-option-alist)
-      (while tem
-       (if (string-match "^--" (car (car tem)))
-           (setq longopts (cons (list (car (car tem))) longopts)))
-       (setq tem (cdr tem)))
-
-      ;; Loop, processing options.
-      (while (and command-line-args-left)
-       (let* ((argi (car command-line-args-left))
-              (orig-argi argi)
-              argval completion
-              ;; List of directories specified in -L/--directory,
-              ;; in reverse of the order specified.
-              extra-load-path
-              (initial-load-path load-path))
-         (setq command-line-args-left (cdr command-line-args-left))
-
-         ;; Do preliminary decoding of the option.
-         (if just-files
-             ;; After --, don't look for options; treat all args as files.
-             (setq argi "")
-           ;; Convert long options to ordinary options
-           ;; and separate out an attached option argument into argval.
-           (if (string-match "^--[^=]*=" argi)
-               (setq argval (substring argi (match-end 0))
-                     argi (substring argi 0 (1- (match-end 0)))))
-           (if (equal argi "--")
-               (setq completion nil)
-             (setq completion (try-completion argi longopts)))
-           (if (eq completion t)
-               (setq argi (substring argi 1))
-             (if (stringp completion)
-                 (let ((elt (assoc completion longopts)))
-                   (or elt
-                       (error "Option `%s' is ambiguous" argi))
-                   (setq argi (substring (car elt) 1)))
-               (setq argval nil argi orig-argi))))
-
-         ;; Execute the option.
-         (cond ((setq tem (assoc argi command-switch-alist))
-                (if argval
-                    (let ((command-line-args-left
-                           (cons argval command-line-args-left)))
-                      (funcall (cdr tem) argi))
-                  (funcall (cdr tem) argi)))
-               
-               ((or (string-equal argi "-f") ;what the manual claims
-                    (string-equal argi "-funcall")
-                    (string-equal argi "-e")) ; what the source used to say
-                (if argval
-                    (setq tem (intern argval))
-                  (setq tem (intern (car command-line-args-left)))
-                  (setq command-line-args-left (cdr command-line-args-left)))
-                (if (arrayp (symbol-function tem))
-                    (command-execute tem)
-                  (funcall tem)))
-               
-               ((or (string-equal argi "-eval")
-                    (string-equal argi "-execute"))
-                (if argval
-                    (setq tem argval)
-                  (setq tem (car command-line-args-left))
-                  (setq command-line-args-left (cdr command-line-args-left)))
-                (eval (read tem)))
-               ;; Set the default directory as specified in -L.
-               
-               ((or (string-equal argi "-L")
-                    (string-equal argi "-directory"))
-                (if argval
-                    (setq tem argval)
-                  (setq tem (car command-line-args-left)
-                        command-line-args-left (cdr command-line-args-left)))
-                (setq tem (command-line-normalize-file-name tem))
-                (setq extra-load-path
-                      (cons (expand-file-name tem) extra-load-path))
-                (setq load-path (append (nreverse extra-load-path)
-                                        initial-load-path)))
-               
-               ((or (string-equal argi "-l")
-                    (string-equal argi "-load"))
-                (if argval
-                    (setq tem argval)
-                  (setq tem (car command-line-args-left)
-                        command-line-args-left (cdr command-line-args-left)))
-                (let ((file (command-line-normalize-file-name tem)))
-                  ;; Take file from default dir if it exists there;
-                  ;; otherwise let `load' search for it.
-                  (if (file-exists-p (expand-file-name file))
-                      (setq file (expand-file-name file)))
-                  (load file nil t)))
-               
-               ((string-equal argi "-insert")
-                (if argval
-                    (setq tem argval)
-                  (setq tem (car command-line-args-left)
-                        command-line-args-left (cdr command-line-args-left)))
-                (or (stringp tem)
-                    (error "File name omitted from `-insert' option"))
-                (insert-file-contents (command-line-normalize-file-name tem)))
-               
-               ((string-equal argi "-kill")
-                (kill-emacs t))
-               
-               ((string-match "^\\+[0-9]+\\'" argi)
-                (setq line (string-to-int argi)))
-               
-               ((string-match "^\\+\\([0-9]+\\):\\([0-9]+\\)\\'" argi)
-                (setq line (string-to-int (match-string 1 argi))
-                      column (string-to-int (match-string 2 argi))))
-
-               ((setq tem (assoc argi command-line-x-option-alist))
-                ;; Ignore X-windows options and their args if not using X.
-                (setq command-line-args-left
-                      (nthcdr (nth 1 tem) command-line-args-left)))
-               
-               ((or (string-equal argi "-find-file")
-                    (string-equal argi "-file")
-                    (string-equal argi "-visit"))
-                ;; An explicit option to specify visiting a file.
-                (if argval
-                    (setq tem argval)
-                  (setq tem (car command-line-args-left)
-                        command-line-args-left (cdr command-line-args-left)))
-                (unless (stringp tem)
-                  (error "File name omitted from `%s' option" argi))
-                (setq file-count (1+ file-count))
-                (let ((file (expand-file-name
-                             (command-line-normalize-file-name tem) dir)))
-                  (if (= file-count 1)
-                      (setq first-file-buffer (find-file file))
-                    (find-file-other-window file)))
-                (or (zerop line)
-                    (goto-line line))
-                (setq line 0)
-                (unless (< column 1)
-                  (move-to-column (1- column)))
-                (setq column 0))
-               
-               ((equal argi "--")
-                (setq just-files t))
-               (t
-                ;; We have almost exhausted our options. See if the
-                ;; user has made any other command-line options available
-                (let ((hooks command-line-functions);; lrs 7/31/89
-                      (did-hook nil))
-                  (while (and hooks
-                              (not (setq did-hook (funcall (car hooks)))))
-                    (setq hooks (cdr hooks)))
-                  (if (not did-hook)
-                      ;; Ok, presume that the argument is a file name
-                      (progn
-                        (if (string-match "\\`-" argi)
-                            (error "Unknown option `%s'" argi))
-                        (setq file-count (1+ file-count))
-                        (let ((file
-                               (expand-file-name
-                                (command-line-normalize-file-name orig-argi)
-                                dir)))
-                          (if (= file-count 1)
-                              (setq first-file-buffer (find-file file))
-                            (find-file-other-window file)))
-                        (or (zerop line)
-                            (goto-line line))
-                        (setq line 0)
-                        (unless (< column 1)
-                          (move-to-column (1- column)))
-                        (setq column 0))))))))
-      ;; If 3 or more files visited, and not all visible,
-      ;; show user what they all are.  But leave the last one current.
-      (and (> file-count 2)
-          (not noninteractive)
-          (not inhibit-startup-buffer-menu)       
-          (or (get-buffer-window first-file-buffer)
-              (list-buffers))))))
+
+             ;; The rest of the startup screen is the same on all
+             ;; kinds of terminals.
+
+             ;; Give information on recovering, if there was a crash.
+             (and auto-save-list-file-prefix
+                  ;; Don't signal an error if the
+                  ;; directory for auto-save-list files
+                  ;; does not yet exist.
+                  (file-directory-p (file-name-directory
+                                     auto-save-list-file-prefix))
+                  (directory-files
+                   (file-name-directory auto-save-list-file-prefix)
+                   nil
+                   (concat "\\`"
+                           (regexp-quote (file-name-nondirectory
+                                          auto-save-list-file-prefix)))
+                   t)
+                  (insert "\n\nIf an Emacs session crashed recently, "
+                          "type M-x recover-session RET\nto recover"
+                          " the files you were editing."))
+
+             ;; Display the input that we set up in the buffer.
+             (set-buffer-modified-p nil)
+             (goto-char (point-min))
+             (save-window-excursion
+               (switch-to-buffer (current-buffer))
+               (sit-for 120))))
+         (kill-buffer "GNU Emacs"))))))
 
 
 (defun command-line-normalize-file-name (file)