+;; Actual initialization is below.
+(defvar mode-line-position nil
+ "Mode-line control for displaying the position in the buffer.
+Normally displays the buffer percentage and, optionally, the
+buffer size, the line number and the column number.")
+
+(defvar mode-line-modes nil
+ "Mode-line control for displaying major and minor modes.")
+
+(defvar mode-line-major-mode-keymap
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mode-line mouse-2] 'describe-mode)
+ (define-key map [mode-line down-mouse-3] 'mode-line-mode-menu-1)
+ map) "\
+Keymap to display on major mode.")
+
+(defvar mode-line-minor-mode-keymap
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mode-line mouse-2] 'mode-line-minor-mode-help)
+ (define-key map [mode-line down-mouse-3] 'mode-line-mode-menu-1)
+ (define-key map [header-line down-mouse-3] 'mode-line-mode-menu-1)
+ map) "\
+Keymap to display on minor modes.")
+
+(let* ((help-echo
+ ;; The multi-line message doesn't work terribly well on the
+ ;; bottom mode line... Better ideas?
+ ;; "\
+ ;; mouse-1: select window, mouse-2: delete others, mouse-3: delete,
+ ;; drag-mouse-1: resize, C-mouse-2: split horizontally"
+ "mouse-1: select (drag to resize), mouse-2: delete others, mouse-3: delete this")
+ (dashes (propertize "--" 'help-echo help-echo)))
+ (setq-default mode-line-format
+ (list
+ (propertize "-" 'help-echo help-echo)
+ 'mode-line-mule-info
+ 'mode-line-modified
+ 'mode-line-frame-identification
+ 'mode-line-buffer-identification
+ (propertize " " 'help-echo help-echo)
+ 'mode-line-position
+ '(vc-mode vc-mode)
+ (propertize " " 'help-echo help-echo)
+ 'mode-line-modes
+ `(which-func-mode ("" which-func-format ,dashes))
+ `(global-mode-string (,dashes global-mode-string))
+ (propertize "-%-" 'help-echo help-echo)))
+
+ (setq-default mode-line-modes
+ (list
+ (propertize "%[(" 'help-echo help-echo)
+ `(:propertize ("" mode-name)
+ help-echo "mouse-2: help for current major mode"
+ local-map ,mode-line-major-mode-keymap)
+ '("" mode-line-process)
+ `(:propertize ("" minor-mode-alist)
+ help-echo "mouse-2: help for minor modes, mouse-3: minor mode menu"
+ local-map ,mode-line-minor-mode-keymap)
+ (propertize "%n" 'help-echo "mouse-2: widen"
+ 'local-map (make-mode-line-mouse-map
+ 'mouse-2 #'mode-line-widen))
+ (propertize ")%]--" 'help-echo help-echo)))
+
+ (setq-default mode-line-position
+ `((-3 ,(propertize "%p" 'help-echo help-echo))
+ (size-indication-mode
+ (8 ,(propertize " of %I" 'help-echo help-echo)))
+ (line-number-mode
+ ((column-number-mode
+ (10 ,(propertize " (%l,%c)" 'help-echo help-echo))
+ (6 ,(propertize " L%l" 'help-echo help-echo))))
+ ((column-number-mode
+ (5 ,(propertize " C%c" 'help-echo help-echo))))))))
+
+(defvar mode-line-buffer-identification-keymap nil "\
+Keymap for what is displayed by `mode-line-buffer-identification'.")
+
+(defun last-buffer () "\
+Return the last non-hidden buffer in the buffer list."
+ ;; This logic is more or less copied from bury-buffer,
+ ;; except that we reverse the buffer list.
+ (let ((list (nreverse (buffer-list (selected-frame))))
+ (pred (frame-parameter nil 'buffer-predicate))
+ found notsogood)
+ (while (and list (not found))
+ (unless (or (eq (aref (buffer-name (car list)) 0) ? )
+ ;; If the selected frame has a buffer_predicate,
+ ;; disregard buffers that don't fit the predicate.
+ (and pred (not (funcall pred (car list)))))
+ (if (get-buffer-window (car list) 'visible)
+ (or notsogood (eq (car list) (current-buffer)))
+ (setq found (car list))))
+ (pop list))
+ (or found notsogood
+ (get-buffer "*scratch*")
+ (progn
+ (set-buffer-major-mode
+ (get-buffer-create "*scratch*"))
+ (get-buffer "*scratch*")))))
+
+(defun unbury-buffer () "\
+Switch to the last buffer in the buffer list."
+ (interactive)
+ (switch-to-buffer (last-buffer)))
+
+(defun mode-line-unbury-buffer (event) "\
+Call `unbury-buffer' in this window."
+ (interactive "e")
+ (save-selected-window
+ (select-window (posn-window (event-start event)))
+ (unbury-buffer)))
+
+(defun mode-line-bury-buffer (event) "\
+Like `bury-buffer', but temporarily select EVENT's window."
+ (interactive "e")
+ (save-selected-window
+ (select-window (posn-window (event-start event)))
+ (bury-buffer)))
+
+(defun mode-line-other-buffer () "\
+Switch to the most recently selected buffer other than the current one."
+ (interactive)
+ (switch-to-buffer (other-buffer)))
+
+(defvar mode-line-mode-menu (make-sparse-keymap "Minor Modes") "\
+Menu of mode operations in the mode line.")
+
+(defun mode-line-mode-menu-1 (event)
+ (interactive "e")
+ (save-selected-window
+ (select-window (posn-window (event-start event)))
+ (let* ((selection (mode-line-mode-menu event))
+ (binding (and selection (lookup-key mode-line-mode-menu
+ (vector (car selection))))))
+ (if binding
+ (call-interactively binding)))))
+
+(defmacro bound-and-true-p (var)
+ "Return the value of symbol VAR if it is bound, else nil."
+ `(and (boundp (quote ,var)) ,var))
+
+(define-key mode-line-mode-menu [overwrite-mode]
+ `(menu-item ,(purecopy "Overwrite (Ovwrt)") overwrite-mode
+ :button (:toggle . overwrite-mode)))
+(define-key mode-line-mode-menu [outline-minor-mode]
+ `(menu-item ,(purecopy "Outline (Outl)") outline-minor-mode
+ :button (:toggle . (bound-and-true-p outline-minor-mode))))
+(define-key mode-line-mode-menu [line-number-mode]
+ `(menu-item ,(purecopy "Line number") line-number-mode
+ :button (:toggle . line-number-mode)))
+(define-key mode-line-mode-menu [highlight-changes-mode]
+ `(menu-item ,(purecopy "Highlight changes (Chg)") highlight-changes-mode
+ :button (:toggle . highlight-changes-mode)))
+(define-key mode-line-mode-menu [glasses-mode]
+ `(menu-item ,(purecopy "Glasses (o^o)") glasses-mode
+ :button (:toggle . (bound-and-true-p glasses-mode))))
+(define-key mode-line-mode-menu [hide-ifdef-mode]
+ `(menu-item ,(purecopy "Hide ifdef (Ifdef)") hide-ifdef-mode
+ :button (:toggle . (bound-and-true-p hide-ifdef-mode))))
+(define-key mode-line-mode-menu [font-lock-mode]
+ `(menu-item ,(purecopy "Font Lock") font-lock-mode
+ :button (:toggle . font-lock-mode)))
+(define-key mode-line-mode-menu [flyspell-mode]
+ `(menu-item ,(purecopy "Flyspell (Fly)") flyspell-mode
+ :button (:toggle . (bound-and-true-p flyspell-mode))))
+(define-key mode-line-mode-menu [column-number-mode]
+ `(menu-item ,(purecopy "Column number") column-number-mode
+ :button (:toggle . column-number-mode)))
+(define-key mode-line-mode-menu [auto-fill-mode]
+ `(menu-item ,(purecopy "Auto Fill (Fill)") auto-fill-mode
+ :button (:toggle . auto-fill-function)))
+(define-key mode-line-mode-menu [auto-revert-mode]
+ `(menu-item ,(purecopy "Auto revert (ARev)") auto-revert-mode
+ :button (:toggle . auto-revert-mode)))
+(define-key mode-line-mode-menu [abbrev-mode]
+ `(menu-item ,(purecopy "Abbrev (Abbrev)") abbrev-mode
+ :button (:toggle . abbrev-mode)))
+
+(defun mode-line-mode-menu (event)
+ (interactive "@e")
+ (x-popup-menu event mode-line-mode-menu))
+
+(defun mode-line-minor-mode-help (event)
+ "Describe minor mode for EVENT occured on minor modes area of the mode line."
+ (interactive "@e")
+ (let ((indicator (car (nth 4 (car (cdr event))))))
+ (describe-minor-mode-from-indicator indicator)))
+
+;; Add menu of buffer operations to the buffer identification part
+;; of the mode line.or header line.
+;
+(let ((map (make-sparse-keymap)))
+ ;; Bind down- events so that the global keymap won't ``shine
+ ;; through''.
+ (define-key map [mode-line down-mouse-1] 'ignore)
+ (define-key map [mode-line mouse-1] 'mode-line-unbury-buffer)
+ (define-key map [header-line down-mouse-1] 'ignore)
+ (define-key map [header-line mouse-1] 'mode-line-unbury-buffer)
+ (define-key map [header-line down-mouse-3] 'ignore)
+ (define-key map [mode-line mouse-3] 'mode-line-bury-buffer)
+ (define-key map [header-line down-mouse-3] 'ignore)
+ (define-key map [header-line mouse-3] 'mode-line-bury-buffer)
+ (setq mode-line-buffer-identification-keymap map))
+
+(defun propertized-buffer-identification (fmt)
+ "Return a list suitable for `mode-line-buffer-identification'.
+FMT is a format specifier such as \"%12b\". This function adds
+text properties for face, help-echo, and local-map to it."
+ (list (propertize fmt
+ 'face '(:weight bold)
+ 'help-echo
+ (purecopy "mouse-1: previous buffer, mouse-3: next buffer")
+ 'local-map mode-line-buffer-identification-keymap)))
+
+(setq-default mode-line-buffer-identification
+ (propertized-buffer-identification "%12b"))