comparison lisp/prim/modeline.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; modeline.el --- modeline hackery.
2
3 ;; Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995, 1996 Ben Wing.
5
6 ;; This file is part of XEmacs.
7
8 ;; XEmacs is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
11 ;; any later version.
12
13 ;; XEmacs is distributed in the hope that it will be useful, but
14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ;; General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with XEmacs; see the file COPYING. If not, write to the Free
20 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 ;;; Synched up with: Not in FSF.
23
24 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25 ;;; General mouse modeline stuff ;;;
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27
28 (defvar drag-modeline-event-lag 150
29 "*The amount of time to wait (in msecs) between drag modeline events
30 before updating the display. If this value is too small, dragging will
31 be choppy because redisplay cannot keep up. If it is too large, dragging
32 will be choppy because of the explicit redisplay delay specified.")
33
34 (defvar modeline-click-swaps-buffers nil
35 "*If non-nil, clicking on the modeline changes the current buffer.
36 Click on the left half of the modeline cycles forward through the
37 buffer list and clicking on the right half cycles backward.")
38
39 (defun mouse-drag-modeline (event)
40 "Resize the window by dragging the modeline.
41 This should be bound to a mouse button in `modeline-map'."
42 (interactive "e")
43 (or (button-press-event-p event)
44 (error "%s must be invoked by a mouse-press" this-command))
45 (or (event-over-modeline-p event)
46 (error "not over a modeline"))
47 (let ((depress-line (event-y event))
48 (mouse-down t)
49 (window (event-window event))
50 (old-window (selected-window))
51 (def-line-height (face-height 'default))
52 (prior-drag-modeline-event-time 0)
53 delta)
54 (while mouse-down
55 (setq event (next-event event))
56 (cond ((motion-event-p event)
57 (if (window-lowest-p window)
58 (error "can't drag bottommost modeline"))
59 (cond ((> (- (event-timestamp event)
60 prior-drag-modeline-event-time)
61 drag-modeline-event-lag)
62
63 (setq prior-drag-modeline-event-time (event-timestamp event))
64
65 (if (event-over-modeline-p event)
66 (setq delta 0)
67 (setq delta (- (event-y-pixel event)
68 (nth 3 (window-pixel-edges window))))
69 (if (> delta 0)
70 (setq delta (+ delta def-line-height)))
71 (setq delta (/ delta def-line-height)))
72
73 ;; cough sputter hack kludge. It shouldn't be possible
74 ;; to get in here when we are over the minibuffer. But
75 ;; it is happening and that cause next-vertical-window to
76 ;; return nil which does not lead to window-height returning
77 ;; anything remotely resembling a sensible value. So catch
78 ;; the situation and die a happy death.
79 ;;
80 ;; Oh, and the BLAT FOOP error messages suck as well but
81 ;; I don't know what should be there. This should be
82 ;; looked at again when the new redisplay is done.
83 (if (not (next-vertical-window window))
84 (error "Try again: dragging in minibuffer does nothing"))
85 (cond ((and (> delta 0)
86 (<= (- (window-height (next-vertical-window window))
87 delta)
88 window-min-height))
89 (setq delta (- (window-height
90 (next-vertical-window window))
91 window-min-height))
92 (if (< delta 0) (error "BLAT")))
93 ((and (< delta 0)
94 (< (+ (window-height window) delta)
95 window-min-height))
96 (setq delta (- window-min-height
97 (window-height window)))
98 (if (> delta 0) (error "FOOP"))))
99 (if (= delta 0)
100 nil
101 (select-window window)
102 (enlarge-window delta)
103 ;; The call to enlarge-window may have caused the old
104 ;; window to disappear. Don't try and select it in
105 ;; that case.
106 (if (window-live-p old-window)
107 (select-window old-window))
108 (sit-for 0)
109 ))))
110 ((button-release-event-p event)
111 (setq mouse-down nil)
112 (if modeline-click-swaps-buffers
113 (mouse-release-modeline event depress-line)))
114 ((or (button-press-event-p event)
115 (key-press-event-p event))
116 (error ""))
117 (t
118 (dispatch-event event)))
119 )))
120
121 ;; from Bob Weiner (bob_weiner@pts.mot.com)
122 (defun mouse-release-modeline (event line-num)
123 "Handle modeline click EVENT on LINE-NUM by switching buffers.
124 If click on left half of a frame's modeline, bury current buffer.
125 If click on right half of a frame's modeline, raise bottommost buffer.
126 Args are: EVENT, the mouse release event, and LINE-NUM, the line number
127 within the frame at which the mouse was first depressed."
128 (if (= line-num (event-y event))
129 ;; Button press and release are at same line, treat this as
130 ;; a click and switch buffers.
131 (if (< (event-x event) (/ (window-width (event-window event)) 2))
132 ;; On left half of modeline, bury current buffer,
133 ;; displaying second buffer on list.
134 (mouse-bury-buffer event)
135 ;; On right half of modeline, raise and display bottommost
136 ;; buffer in buffer list.
137 (mouse-unbury-buffer event))))
138
139 (defconst modeline-menu
140 '("Window Commands"
141 ["Delete Window Above" delete-window t]
142 ["Delete Other Windows" delete-other-windows t]
143 ["Split Window Above" split-window-vertically t]
144 ["Split Window Horizontally" split-window-horizontally t]
145 ["Balance Windows" balance-windows t]
146 ))
147
148 (defun modeline-menu (event)
149 (interactive "e")
150 (popup-menu-and-execute-in-window
151 (cons (format "Window Commands for %S:"
152 (buffer-name (event-buffer event)))
153 (cdr modeline-menu))
154 event))
155
156 (defvar modeline-map (make-sparse-keymap 'modeline-map)
157 "Keymap consulted for mouse-clicks on the modeline of a window.
158 This variable may be buffer-local; its value will be looked up in
159 the buffer of the window whose modeline was clicked upon.")
160
161 (define-key modeline-map 'button1 'mouse-drag-modeline)
162 ;; button2 selects the window without setting point
163 (define-key modeline-map 'button2 (lambda () (interactive "@")))
164 (define-key modeline-map 'button3 'modeline-menu)
165
166 (make-face 'modeline-mousable "Face for mousable portions of the modeline.")
167
168 (defmacro make-modeline-command-wrapper (command)
169 `#'(lambda (event)
170 (interactive "e")
171 (save-selected-window
172 (select-window (event-window event))
173 (call-interactively ',(eval command)))))
174
175 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
176 ;;; Minor modes ;;;
177 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
178
179 (defvar minor-mode-alist nil
180 "Alist saying how to show minor modes in the modeline.
181 Each element looks like (VARIABLE STRING);
182 STRING is included in the modeline iff VARIABLE's value is non-nil.
183
184 Actually, STRING need not be a string; any possible modeline element
185 is okay. See `modeline-format'.")
186
187 ;; Used by C code (lookup-key and friends) but defined here.
188 (defvar minor-mode-map-alist nil
189 "Alist of keymaps to use for minor modes.
190 Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read
191 key sequences and look up bindings iff VARIABLE's value is non-nil.
192 If two active keymaps bind the same key, the keymap appearing earlier
193 in the list takes precedence.")
194
195 (make-face 'modeline-mousable-minor-mode
196 "Face for mousable minor-mode strings in the modeline.")
197
198 (defvar modeline-mousable-minor-mode-extent (make-extent nil nil)
199 ;; alliteration at its finest.
200 "Extent managing the mousable minor mode modeline strings.")
201 (set-extent-face modeline-mousable-minor-mode-extent
202 'modeline-mousable-minor-mode)
203
204 ;; This replaces the idiom
205 ;;
206 ;; (or (assq 'isearch-mode minor-mode-alist)
207 ;; (setq minor-mode-alist
208 ;; (purecopy
209 ;; (append minor-mode-alist
210 ;; '((isearch-mode isearch-mode))))))
211
212 (defun add-minor-mode (toggle name &optional keymap after toggle-fun)
213 "Add a minor mode to `minor-mode-alist' and `minor-mode-map-alist'.
214 TOGGLE is a symbol whose value as a variable specifies whether the
215 minor mode is active. NAME is the name that should appear in the
216 modeline (it should be a string beginning with a space). KEYMAP is a
217 keymap to make active when the minor mode is active. AFTER is the
218 toggling symbol used for another minor mode. If AFTER is non-nil,
219 then it is used to position the new mode in the minor-mode alists.
220 TOGGLE-FUN specifies an interactive function that is called to toggle
221 the mode on and off; this affects what happens when button2 is pressed
222 on the mode, and when button3 is pressed somewhere in the list of
223 modes. If TOGGLE-FUN is nil and TOGGLE names an interactive function,
224 TOGGLE is used as the toggle function.
225
226 Example: (add-minor-mode 'view-minor-mode \" View\" view-mode-map)"
227 (let (el place
228 (add-elt #'(lambda (elt sym)
229 (cond ((null after) ; add to front
230 (set sym (cons elt (symbol-value sym))))
231 ((and (not (eq after t))
232 (setq place (memq (assq after
233 (symbol-value sym))
234 (symbol-value sym))))
235 (setq elt (cons elt (cdr place)))
236 (setcdr place elt))
237 (t
238 (set sym (append (symbol-value sym) (list elt))))
239 )
240 (symbol-value sym)))
241 toggle-keymap)
242 (if toggle-fun
243 (if (not (commandp toggle-fun))
244 (error "not an interactive function: %S" toggle-fun))
245 (if (commandp toggle)
246 (setq toggle-fun toggle)))
247 (if (and toggle-fun name)
248 (progn
249 (setq toggle-keymap (make-sparse-keymap
250 (intern (concat "modeline-minor-"
251 (symbol-name toggle)
252 "-map"))))
253 (define-key toggle-keymap 'button2
254 ;; defeat the DUMB-ASS byte-compiler, which tries to
255 ;; expand the macro at compile time and fucks up.
256 (eval '(make-modeline-command-wrapper toggle-fun)))
257 (put toggle 'modeline-toggle-function toggle-fun)))
258 (and name
259 (let ((hacked-name
260 (if toggle-keymap
261 (cons (let ((extent (make-extent nil nil)))
262 (set-extent-keymap extent toggle-keymap)
263 (set-extent-property
264 extent 'help-echo
265 (concat "button2 turns off "
266 (if (symbolp toggle-fun)
267 (symbol-name toggle-fun)
268 (symbol-name toggle))))
269 extent)
270 (cons
271 modeline-mousable-minor-mode-extent
272 name))
273 name)))
274 (if (setq el (assq toggle minor-mode-alist))
275 (setcdr el (list hacked-name))
276 (funcall add-elt
277 (list toggle hacked-name)
278 'minor-mode-alist))))
279 (and keymap
280 (if (setq el (assq toggle minor-mode-map-alist))
281 (setcdr el keymap)
282 (funcall add-elt
283 (cons toggle keymap)
284 'minor-mode-map-alist)))
285 ))
286
287 (add-minor-mode 'abbrev-mode " Abbrev")
288 (add-minor-mode 'overwrite-mode 'overwrite-mode)
289 (add-minor-mode 'auto-fill-function " Fill" nil nil 'auto-fill-mode)
290 ;; not really a minor mode...
291 (add-minor-mode 'defining-kbd-macro " Def")
292
293 (defun modeline-minor-mode-menu (event)
294 (interactive "e")
295 (popup-menu-and-execute-in-window
296 (cons (format "Minor Mode Commands for %S:"
297 (buffer-name (event-buffer event)))
298 (apply 'nconc
299 (mapcar
300 #'(lambda (x)
301 (let* ((toggle-sym (car x))
302 (toggle-fun
303 (or (get toggle-sym
304 'modeline-toggle-function)
305 (and (fboundp toggle-sym)
306 (commandp toggle-sym)
307 toggle-sym))))
308 (if (not toggle-fun) nil
309 (list (vector
310 (concat (if (and (boundp toggle-sym)
311 (symbol-value toggle-sym))
312 "turn off " "turn on ")
313 (if (symbolp toggle-fun)
314 (symbol-name toggle-fun)
315 (symbol-name toggle-sym)))
316
317 toggle-fun
318 t)))))
319 minor-mode-alist)))
320 event))
321
322 (defvar modeline-minor-mode-map (make-sparse-keymap 'modeline-minor-mode-map)
323 "Keymap consulted for mouse-clicks on the minor-mode modeline list.")
324 (define-key modeline-minor-mode-map 'button3 'modeline-minor-mode-menu)
325
326 (defvar modeline-minor-mode-extent (make-extent nil nil)
327 "Extent covering the minor mode modeline strings.")
328 (set-extent-face modeline-minor-mode-extent 'modeline-mousable)
329 (set-extent-keymap modeline-minor-mode-extent modeline-minor-mode-map)
330
331
332 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
333 ;;; Other ;;;
334 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
335
336 (defun modeline-buffers-menu (event)
337 (interactive "e")
338 (popup-menu-and-execute-in-window
339 '("Buffers Popup Menu"
340 :filter buffers-menu-filter
341 ["List All Buffers" list-buffers t]
342 "--"
343 )
344 event))
345
346 (defvar modeline-buffer-id-left-map
347 (make-sparse-keymap 'modeline-buffer-id-left-map)
348 "Keymap consulted for mouse-clicks on the left half of the buffer-id string.")
349
350 (defvar modeline-buffer-id-right-map
351 (make-sparse-keymap 'modeline-buffer-id-right-map)
352 "Keymap consulted for mouse-clicks on the right half of the buffer-id string.")
353
354 (define-key modeline-buffer-id-left-map 'button2 'mouse-unbury-buffer)
355 (define-key modeline-buffer-id-right-map 'button2 'mouse-bury-buffer)
356 (define-key modeline-buffer-id-left-map 'button3 'modeline-buffers-menu)
357 (define-key modeline-buffer-id-right-map 'button3 'modeline-buffers-menu)
358
359 (make-face 'modeline-buffer-id
360 "Face for the buffer ID string in the modeline.")
361
362 (defvar modeline-buffer-id-extent (make-extent nil nil)
363 "Extent covering the whole of the buffer-id string.")
364 (set-extent-face modeline-buffer-id-extent 'modeline-buffer-id)
365
366 (defvar modeline-buffer-id-left-extent (make-extent nil nil)
367 "Extent covering the left half of the buffer-id string.")
368 (set-extent-keymap modeline-buffer-id-left-extent
369 modeline-buffer-id-left-map)
370 (set-extent-property modeline-buffer-id-left-extent 'help-echo
371 "button2 cycles to the previous buffer")
372
373 (defvar modeline-buffer-id-right-extent (make-extent nil nil)
374 "Extent covering the right half of the buffer-id string.")
375 (set-extent-keymap modeline-buffer-id-right-extent
376 modeline-buffer-id-right-map)
377 (set-extent-property modeline-buffer-id-right-extent 'help-echo
378 "button2 cycles to the next buffer")
379
380 (defconst modeline-buffer-identification
381 (list (cons modeline-buffer-id-left-extent (purecopy "XEmacs:"))
382 (cons modeline-buffer-id-right-extent (purecopy " %17b")))
383 "Modeline control for identifying the buffer being displayed.
384 Its default value is \"XEmacs: %17b\" (NOT!). Major modes that edit things
385 other than ordinary files may change this (e.g. Info, Dired,...)")
386 (make-variable-buffer-local 'modeline-buffer-identification)
387
388 (defconst modeline-process nil
389 "Modeline control for displaying info on process status.
390 Normally nil in most modes, since there is no process to display.")
391 (make-variable-buffer-local 'modeline-process)
392
393 (defvar modeline-modified-map (make-sparse-keymap 'modeline-modified-map)
394 "Keymap consulted for mouse-clicks on the modeline-modified string.")
395 (define-key modeline-modified-map 'button2
396 (make-modeline-command-wrapper 'toggle-read-only))
397
398 (defvar modeline-modified-extent (make-extent nil nil)
399 "Extent covering the modeline-modified string.")
400 (set-extent-face modeline-modified-extent 'modeline-mousable)
401 (set-extent-keymap modeline-modified-extent modeline-modified-map)
402 (set-extent-property modeline-modified-extent 'help-echo
403 "button2 toggles the buffer's read-only status")
404
405 (defconst modeline-modified (purecopy '("--%1*%1+-"))
406 "Modeline control for displaying whether current buffer is modified.")
407 (make-variable-buffer-local 'modeline-modified)
408
409 (defvar modeline-narrowed-map (make-sparse-keymap 'modeline-narrowed-map)
410 "Keymap consulted for mouse-clicks on the modeline-narrowed string.")
411 (define-key modeline-narrowed-map 'button2
412 (make-modeline-command-wrapper 'widen))
413
414 (defvar modeline-narrowed-extent (make-extent nil nil)
415 "Extent covering the modeline-narrowed string.")
416 (set-extent-face modeline-narrowed-extent 'modeline-mousable)
417 (set-extent-keymap modeline-narrowed-extent modeline-narrowed-map)
418 (set-extent-property modeline-narrowed-extent 'help-echo
419 "button2 widens the buffer")
420
421 (setq-default modeline-format
422 (list (purecopy "")
423 (cons modeline-modified-extent
424 'modeline-modified)
425 (cons modeline-buffer-id-extent
426 'modeline-buffer-identification)
427 (purecopy " ")
428 'global-mode-string
429 (purecopy " %[(")
430 (cons modeline-minor-mode-extent
431 (list "" 'mode-name 'minor-mode-alist))
432 (cons modeline-narrowed-extent "%n")
433 'modeline-process
434 (purecopy ")%]----")
435 (purecopy '(line-number-mode "L%l--"))
436 (purecopy '(-3 . "%p"))
437 (purecopy "-%-")))