Major rewrite to behave more like a minor mode.
[bpt/emacs.git] / lisp / startup.el
index 2742984..4de390c 100644 (file)
@@ -65,8 +65,10 @@ with the contents of the startup message.")
 (defconst inhibit-startup-echo-area-message nil
   "*Non-nil inhibits the initial startup echo area message.
 Inhibition takes effect only if your `.emacs' file contains
-a line of the form
+a line of this form:
  (setq inhibit-startup-echo-area-message \"YOUR-USER-NAME\")
+If your `.emacs' file is byte-compiled, use the following form instead:
+ (eval '(setq inhibit-startup-echo-area-message \"YOUR-USER-NAME\"))
 Thus, someone else using a copy of your `.emacs' file will see
 the startup message unless he personally acts to inhibit it.")
 
@@ -79,6 +81,9 @@ Elements look like (SWITCH-STRING . HANDLER-FUNCTION).
 HANDLER-FUNCTION receives switch name as sole arg;
 remaining command-line args are in the variable `command-line-args-left'.")
 
+(defvar command-line-args-left nil
+  "List of command-line args not yet processed.")
+
 (defvar command-line-functions nil    ;; lrs 7/31/89
   "List of functions to process unrecognized command-line arguments.
 Each function should access the dynamically bound variables
@@ -87,6 +92,10 @@ arguments).  The function should return non-nil only if it recognizes and
 processes `argi'.  If it does so, it may consume successive arguments by
 altering `command-line-args-left' to remove them.")
 
+(defvar command-line-default-directory nil
+  "Default directory to use for command line arguments.
+This is normally copied from `default-directory' when Emacs starts.")
+
 (defvar before-init-hook nil
   "Functions to call after handling urgent options but before init files.
 The frame system uses this to open frames to display messages while
@@ -119,12 +128,13 @@ the user's init file.")
 
 (defvar init-file-user nil
   "Identity of user whose `.emacs' file is or was read.
-The value may be the null string or a string containing a user's name.
-If the value is a null string, it means that the init file was taken from
-the user that originally logged in.
+The value is nil if no init file is being used; otherwise, it may be either
+the null string, meaning that the init file was taken from the user that
+originally logged in, or it may be a string containing a user's name.
 
-In all cases, `(concat \"~\" init-file-user \"/\")' evaluates to the
-directory name of the directory where the `.emacs' file was looked for.")
+In either of the latter cases, `(concat \"~\" init-file-user \"/\")'
+evaluates to the name of the directory where the `.emacs' file was
+looked for.")
 
 (defvar site-run-file "site-start"
   "File containing site-wide run-time initializations.
@@ -134,6 +144,14 @@ higher incidence of change, don't make sense to load into emacs'
 dumped image.  Thus, the run-time load order is: 1. file described in
 this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'.")
 
+(defconst iso-8859-1-locale-regexp "8859[-_]?1"
+  "Regexp that specifies when to enable the ISO 8859-1 character set.
+We do that if this regexp matches the locale name
+specified by the LC_ALL, LC_CTYPE and LANG environment variables.")
+
+(defvar user-mail-address nil
+  "Full mailing address of this user.")
+
 (defvar init-file-debug nil)
 
 (defvar init-file-had-error nil)
@@ -158,24 +176,42 @@ this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'.")
                           (delete (concat "PWD=" pwd)
                                   process-environment)))))))
     (setq default-directory (abbreviate-file-name default-directory))
-    (unwind-protect
-       (command-line)
-      ;; Do this again, in case .emacs defined more abbreviations.
-      (setq default-directory (abbreviate-file-name default-directory))
-      (run-hooks 'emacs-startup-hook)
-      (and term-setup-hook
-          (run-hooks 'term-setup-hook))
-      ;; Modify the initial frame based on what .emacs puts into
-      ;; ...-frame-alist.
-      (if (fboundp 'frame-notice-user-settings)
-         (frame-notice-user-settings))
-      ;; Now we know the user's default font, so add it to the menu.
-      (if (fboundp 'font-menu-add-default)
-         (font-menu-add-default))
-      (and window-setup-hook
-          (run-hooks 'window-setup-hook)))))
+    (setq user-mail-address (concat (user-login-name) "@" (system-name)))
+    (let ((menubar-bindings-done nil))
+      (unwind-protect
+         (command-line)
+       ;; Do this again, in case .emacs defined more abbreviations.
+       (setq default-directory (abbreviate-file-name default-directory))
+       (run-hooks 'emacs-startup-hook)
+       (and term-setup-hook
+            (run-hooks 'term-setup-hook))
+       ;; Modify the initial frame based on what .emacs puts into
+       ;; ...-frame-alist.
+       (if (fboundp 'frame-notice-user-settings)
+           (frame-notice-user-settings))
+       ;; Now we know the user's default font, so add it to the menu.
+       (if (fboundp 'font-menu-add-default)
+           (font-menu-add-default))
+       (and window-setup-hook
+            (run-hooks 'window-setup-hook))
+       (or menubar-bindings-done
+           (precompute-menubar-bindings))))))
+
+;; Precompute the keyboard equivalents in the menu bar items.
+(defun precompute-menubar-bindings ()
+  (if (eq window-system 'x)
+      (let ((submap (lookup-key global-map [menu-bar])))
+       (while submap
+         (and (consp (car submap))
+              (symbolp (car (car submap)))
+              (stringp (car-safe (cdr (car submap))))
+              (keymapp (cdr (cdr (car submap))))
+              (x-popup-menu nil (cdr (cdr (car submap)))))
+         (setq submap (cdr submap))))))
 
 (defun command-line ()
+  (setq command-line-default-directory default-directory)
+
   ;; See if we should import version-control from the environment variable.
   (let ((vc (getenv "VERSION_CONTROL")))
     (cond ((eq vc nil))                        ;don't do anything if not set
@@ -189,6 +225,20 @@ this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'.")
               (string= vc "simple"))
           (setq version-control 'never))))
 
+  (if (let ((ctype
+            ;; Use the first of these three envvars that has a nonempty value.
+            (or (let ((string (getenv "LC_ALL")))
+                  (and (not (equal string "")) string))
+                (let ((string (getenv "LC_CTYPE")))
+                  (and (not (equal string "")) string))
+                (let ((string (getenv "LANG")))
+                  (and (not (equal string "")) string)))))
+       (and ctype
+            (string-match iso-8859-1-locale-regexp ctype)))
+      (progn 
+       (standard-display-european t)
+       (require 'iso-syntax)))
+
   ;;! This has been commented out; I currently find the behavior when
   ;;! split-window-keep-point is nil disturbing, but if I can get used
   ;;! to it, then it would be better to eliminate the option.
@@ -196,13 +246,31 @@ this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'.")
   ;;! (setq split-window-keep-point (> baud-rate 2400))
 
   ;; Read window system's init file if using a window system.
-  (if (and window-system (not noninteractive))
-      (load (concat term-file-prefix
-                   (symbol-name window-system)
-                   "-win")
-           ;; Every window system should have a startup file;
-           ;; barf if we can't find it.
-           nil t))
+  (condition-case error
+      (if (and window-system (not noninteractive))
+         (load (concat term-file-prefix
+                       (symbol-name window-system)
+                       "-win")
+               ;; Every window system should have a startup file;
+               ;; barf if we can't find it.
+               nil t))
+    ;; If we can't read it, print the error message and exit.
+    (error
+     (princ
+      (if (eq (car error) 'error)
+         (apply 'concat (cdr error))
+       (if (memq 'file-error (get (car error) 'error-conditions))
+           (format "%s: %s"
+                    (nth 1 error)
+                    (mapconcat '(lambda (obj) (prin1-to-string obj t))
+                               (cdr (cdr error)) ", "))
+         (format "%s: %s"
+                  (get (car error) 'error-message)
+                  (mapconcat '(lambda (obj) (prin1-to-string obj t))
+                             (cdr error) ", "))))
+      'external-debugging-output)
+     (setq window-system nil)
+     (kill-emacs)))
 
   (let ((done nil)
        (args (cdr command-line-args)))
@@ -241,10 +309,14 @@ this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'.")
     (setcdr command-line-args args))
 
   ;; Under X Windows, this creates the X frame and deletes the terminal frame.
-  (if (fboundp 'frame-initialize)
-      (frame-initialize))
   (if (fboundp 'face-initialize)
       (face-initialize))
+  (if (fboundp 'frame-initialize)
+      (frame-initialize))
+  ;; If frame was created with a menu bar, set menu-bar-mode on.
+  (if (and (eq window-system 'x)
+          (> (cdr (assq 'menu-bar-lines (frame-parameters))) 0))
+      (menu-bar-mode t))
 
   (run-hooks 'before-init-hook)
 
@@ -295,10 +367,10 @@ this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'.")
              (setq init-file-had-error nil))
          (error (message "Error in init file: %s%s%s"
                          (get (car error) 'error-message)
-                         (if (cdr error) ": ")
+                         (if (cdr error) ": " "")
                          (mapconcat 'prin1-to-string (cdr error) ", "))
                 (setq init-file-had-error t))))
-      ;; If we can tell that the init file altered debug-on-error.,
+      ;; 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)
          (setq debug-on-error-should-be-set t
@@ -382,6 +454,10 @@ this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'.")
             (and window-setup-hook
                  (run-hooks 'window-setup-hook))
             (setq window-setup-hook nil)
+            ;; Do this now to avoid an annoying delay if the user
+            ;; clicks the menu bar during the sit-for.
+            (precompute-menubar-bindings)
+            (setq menubar-bindings-done t)
             (unwind-protect
                 (progn
                   (insert (emacs-version)
@@ -422,7 +498,7 @@ Type \\[describe-distribution] for information on getting the latest version."))
                 (set-buffer (get-buffer "*scratch*"))
                 (erase-buffer)
                 (set-buffer-modified-p nil)))))
-    (let ((dir default-directory)
+    (let ((dir command-line-default-directory)
          (file-count 0)
          first-file-buffer
          (line 0))