1 ;;; escreen.el --- emacs window session manager
3 ;;; Copyright (C) 1992, 94, 95, 97, 2001 Noah S. Friedman
5 ;;; Author: Noah Friedman <friedman@splode.com>
6 ;;; Maintainer: friedman@splode.com
7 ;;; Keywords: extensions
8 ;;; Created: 1992-03-23
10 ;;; $Id: escreen.el,v 1.1.1.1 2004-03-15 16:25:50 viteno Exp $
12 ;; This program is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with this program; if not, you can either send email to this
24 ;; program's maintainer or write to: The Free Software Foundation,
25 ;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
29 ;; To install, put this file in your load-path, byte-compile it, and add
30 ;; the following to your .emacs:
35 ;; If you are using Emacs 18 or Emacs 19, you may have trouble loading this
36 ;; program because of the customs syntax officially introduced in Emacs 20.
37 ;; In that case, first load cust-stub.el, available from
39 ;; http://www.splode.com/~friedman/software/emacs-lisp/
41 ;; Updates to escreen.el will also be made available on that page.
44 ;; * wicos.el, written by Heikki Suopanki <suopanki@phoenix.oulu.fi>
45 ;; * `screen', written by Oliver Laumann, Juergen Weigert,
46 ;; and Michael Schroeder.
49 ;; * per-frame screen configurations
50 ;; * symbolic names for screens (a la wicos.el)
51 ;; * switching active screen from pull-down menu from menubar
52 ;; * switching active screen from escreen menu
53 ;; * persistance of screens across instances of emacs
54 ;; (this may be impossible to do sanely.)
58 ;; Variable declarations -- can be set by user
61 "Window configuration management"
65 (defcustom escreen-max-screens 10
66 "*Maximum number of screens that may be created."
70 (defcustom escreen-new-screen-default-buffer "*scratch*"
71 "*Default buffer to display in newly-created screens."
75 (defcustom escreen-restore-killed-buffers nil
76 "*If non-nil, automatically revisit files if they have been killed.
77 That is, if a buffer was killed while in another screen session,
78 recreate them, visiting whatever file they were visiting."
82 (defcustom escreen-preserve-buffer-list-order t
83 "*If non-nil, preserve buffer list for each screen when switching.
84 When returning to a previously-saved screen, the buffer list order is
85 restored. Buffers which have been created since the saved screen was last
86 visited, are put at the end of the list but the relative order is preserved.
88 This buffer list order is returned by the function `buffer-list' and
89 affects the behavior of `other-buffer', etc.
91 In Emacs 20 and later, each frame has its own ordered buffer list.
92 Switching screen sessions affects the selected frame's buffer list only."
96 (defcustom escreen-number-mode t
97 "*If non-nil, display current escreen number in mode line."
101 (defcustom escreen-install-number-mode-format t
102 "*If non-nil, install `escreen-mode-line-format' on `global-mode-string'.
103 This is performed by `escreen-install'."
107 (defcustom escreen-goto-screen-hook nil
108 "*Hook to run after `escreen-goto-screen' completes.
109 An example function that can make use of this hook is
110 `escreen-enable-number-mode-if-more-than-one-screen'."
114 (defcustom escreen-menu-mode-hook nil
115 "*Hook to run by `escreen-menu' after everything else."
122 (defcustom escreen-prefix-char "\C-\\"
123 "*Character prefixing escreen commands.
124 If you wish to change this, you must also do
126 (global-set-key escreen-prefix-char 'escreen-prefix)
128 to update the prefix in the global keymap."
132 (defvar escreen-map nil
133 "*Keymap for escreen commands.")
136 (setq escreen-map (make-sparse-keymap))
137 (define-key escreen-map escreen-prefix-char 'escreen-goto-last-screen)
138 (define-key escreen-map "0" 'escreen-goto-screen-0)
139 (define-key escreen-map "1" 'escreen-goto-screen-1)
140 (define-key escreen-map "2" 'escreen-goto-screen-2)
141 (define-key escreen-map "3" 'escreen-goto-screen-3)
142 (define-key escreen-map "4" 'escreen-goto-screen-4)
143 (define-key escreen-map "5" 'escreen-goto-screen-5)
144 (define-key escreen-map "6" 'escreen-goto-screen-6)
145 (define-key escreen-map "7" 'escreen-goto-screen-7)
146 (define-key escreen-map "8" 'escreen-goto-screen-8)
147 (define-key escreen-map "9" 'escreen-goto-screen-9)
148 (define-key escreen-map "?" 'escreen-help)
149 (define-key escreen-map "\C-b" 'escreen-menu)
150 (define-key escreen-map "a" 'escreen-get-active-screen-numbers)
151 (define-key escreen-map "b" 'escreen-get-current-screen-number)
152 (define-key escreen-map "c" 'escreen-create-screen)
153 (define-key escreen-map "g" 'escreen-goto-screen)
154 (define-key escreen-map "k" 'escreen-kill-screen)
155 (define-key escreen-map "n" 'escreen-goto-next-screen)
156 (define-key escreen-map "p" 'escreen-goto-prev-screen)))
158 (defalias 'escreen-prefix escreen-map)
161 ;;; Internal variables. Do not set these yourself.
163 ;; This should not be modified by the user. The information it provides is
164 ;; critical and the calling conventions are different than for
165 ;; escreen-map-data-format. The order here is important too.
166 ;; Do not change this data structure without also changing the
167 ;; escreen-configuration-data-map-critical-* accessors.
168 (defvar escreen-map-critical-data-format
169 (list 'current-buffer
170 (function (lambda () (buffer-name)))
173 ;; If you want to add or change this list, it's best to set
174 ;; escreen-configuration-alist to nil and run escreen-install afterward.
175 ;; Otherwise, the new table will be used with old data and may cause errors.
177 ;; Note that resetting escreen in this way loses all but the current
178 ;; window configuration.
179 (defvar escreen-map-data-format
180 '((escreen-map-save-window-start . escreen-map-restore-window-start)
181 (mark-marker . escreen-map-restore-mark-marker)
182 (escreen-map-save-point . escreen-map-restore-point)
183 (escreen-map-save-narrowed-region . escreen-map-restore-narrowed-region)
184 (escreen-map-save-truncate-lines . escreen-map-restore-truncate-lines)
185 (escreen-map-save-mode-line-face . escreen-map-restore-mode-line-face)
186 (escreen-map-save-menu-bar-mode . escreen-map-restore-menu-bar-mode)
187 (buffer-list . escreen-map-restore-buffer-list)))
189 ;; Keeps track of escreen state (window config, buffers, etc.)
190 ;; The structure of each elt is
192 ;; (screen-number #<window-configuration>
193 ;; (((critical-data-buffer-1) user-data-buffer-1 ...)
194 ;; ((critical-data-buffer-2) user-data-buffer-2 ...)
196 ;; selected-window-number)
198 (defvar escreen-configuration-alist nil)
200 ;; Current screen number. Smallest possible screen number is 0.
201 (defvar escreen-current-screen-number 0)
203 ;; Current screen number as a string.
204 ;; Smallest possible screen number is 0.
205 (defvar escreen-current-screen-string
206 (int-to-string escreen-current-screen-number))
208 ;; Last-visited screen number. Smallest possible screen number is 0.
209 (defvar escreen-last-screen-number 0)
211 ;; Highest screen number currently in use.
212 (defvar escreen-highest-screen-number-used 0)
214 ;; It's ok to change this, but it makes use of internal variables
215 (defvar escreen-mode-line-format
216 '(escreen-number-mode ("S" escreen-current-screen-string " ")))
220 (defun escreen-install ()
222 (global-set-key escreen-prefix-char 'escreen-prefix)
224 ;; Install screen number on global-mode-string
225 (and escreen-install-number-mode-format
226 (let ((elt '("" escreen-mode-line-format)))
227 (or (escreen-member elt global-mode-string)
228 (setq global-mode-string
229 (cons elt global-mode-string)))))
231 (if escreen-number-mode
232 (escreen-number-mode 1))
234 ;; Initialize escreen-configuration-alist by placing current window
236 (escreen-save-current-screen-configuration))
238 (defun escreen-number-mode (&optional prefix)
239 "*Toggle escreen-number-mode (see variable docstring).
240 If called with a positive prefix argument, always enable.
241 If called with a negative prefix argument, always disable.
242 If called with no prefix argument, toggle current state."
244 (setq escreen-number-mode
246 (not escreen-number-mode))
248 (>= (prefix-numeric-value prefix) 0)))))
251 (defun escreen-create-screen ()
252 "Create a new screen and switch to it.
253 New screen will display one window with the buffer specified by
254 `escreen-new-screen-default-buffer'."
256 (let ((new-screen-number (escreen-first-unused-screen-number)))
257 (or new-screen-number
258 (error "escreen: No more screens (see \"escreen-max-screens\")"))
259 ;; Save window configuration before switching to a new one.
260 (escreen-save-current-screen-configuration)
261 (and (> new-screen-number escreen-highest-screen-number-used)
262 (setq escreen-highest-screen-number-used new-screen-number))
263 (setq escreen-last-screen-number escreen-current-screen-number)
264 (setq escreen-current-screen-number new-screen-number)
265 (setq escreen-current-screen-string (int-to-string new-screen-number))
266 (delete-other-windows)
267 (switch-to-buffer escreen-new-screen-default-buffer)
268 ;; Save new window configuration so that it's in the alist.
269 (escreen-save-current-screen-configuration))
270 ;; We run this hook because, in a sense, we have gone to a new
271 ;; screen. but we don't actually call escreen-goto-screen because of the
272 ;; extra setup work here.
273 (run-hooks 'escreen-goto-screen-hook))
275 (defun escreen-kill-screen (&optional number)
276 "Kill current screen, or screen given by optional argument NUMBER.
277 No error occurs if the specified screen number doesn't exist.
278 You cannot kill the last existing screen.
279 Switch to previous screen if killing active one."
281 (let* ((screen-number (or number escreen-current-screen-number))
282 (killing-current-screen-p (eq escreen-current-screen-number
284 (screen-data (escreen-configuration-escreen screen-number))
287 (and killing-current-screen-p
288 (escreen-configuration-one-screen-p)
289 (error "escreen: only one screen, can't kill."))
290 ;; Don't bother looking for previous screen number unless killing
291 ;; current screen, because only then do we need to switch screens.
292 (and killing-current-screen-p
293 (setq previous-screen (escreen-get-prev-screen-number)))
294 (escreen-configuration-escreen-delete screen-data)
295 (and (eq screen-number escreen-highest-screen-number-used)
296 ;; We're killing the screen with the highest number.
297 ;; Look for the next highest number.
298 (setq escreen-highest-screen-number-used
299 (car (sort (escreen-configuration-screen-numbers) '>))))
300 (and killing-current-screen-p
301 (escreen-goto-screen previous-screen 'dont-update-current))))))
304 (defun escreen-goto-screen (number &optional dont-update-current)
305 "Switch to screen number N.
306 Optional arg DONT-UPDATE-CURRENT means don't save the current screen
307 configuration, though this isn't intended to be used interactively."
308 (interactive "NGo to escreen number: ")
309 (let ((screen-data (escreen-configuration-escreen number)))
311 (error "escreen: %d: invalid screen number." number))
312 (or dont-update-current
313 (escreen-save-current-screen-configuration))
314 (escreen-restore-screen-map screen-data)
315 (setq escreen-current-screen-string (int-to-string number))
316 (or dont-update-current
317 (setq escreen-last-screen-number escreen-current-screen-number))
318 (setq escreen-current-screen-number number))
319 (run-hooks 'escreen-goto-screen-hook))
321 (defun escreen-goto-last-screen ()
322 "Switch to the last visited screen."
324 (let ((n (if (= escreen-last-screen-number escreen-current-screen-number)
325 (escreen-get-next-screen-number escreen-last-screen-number)
326 escreen-last-screen-number)))
327 (setq escreen-last-screen-number escreen-current-screen-number)
328 (escreen-goto-screen n)))
330 (defun escreen-goto-prev-screen (&optional n)
331 "Switch to the previous screen.
332 This is the nearest lower-numbered existing screen from the current one,
333 wrapping around list of screens if necessary.
334 If prefix arg N given, jump to the Nth previous screen."
337 (escreen-goto-prev-or-next-screen-internal (- n) 'next)
338 (escreen-goto-prev-or-next-screen-internal n 'prev)))
340 (defun escreen-goto-next-screen (&optional n)
341 "Switch to the next screen.
342 This is the nearest greater-numbered existing screen from the current one,
343 wrapping around list of screens if necessary.
344 If prefix arg N given, jump to the Nth next screen."
347 (escreen-goto-prev-or-next-screen-internal (- n) 'prev)
348 (escreen-goto-prev-or-next-screen-internal n 'next)))
350 (defun escreen-goto-prev-or-next-screen-internal (n prev-or-next)
351 (let ((total (length (escreen-get-active-screen-numbers)))
352 (func (if (eq prev-or-next 'next)
353 'escreen-get-next-screen-number
354 'escreen-get-prev-screen-number))
356 (screen-number escreen-current-screen-number))
358 ;; Trim off excess amount so we do fewer iterations, since
359 ;; wrapping over the total number of screens even once is
360 ;; wasteful and slow.
361 (setq n (- n (* (/ n total) total))))
363 (setq screen-number (funcall func screen-number)
365 (escreen-goto-screen screen-number)))
367 (defun escreen-goto-screen-0 () (interactive) (escreen-goto-screen 0))
368 (defun escreen-goto-screen-1 () (interactive) (escreen-goto-screen 1))
369 (defun escreen-goto-screen-2 () (interactive) (escreen-goto-screen 2))
370 (defun escreen-goto-screen-3 () (interactive) (escreen-goto-screen 3))
371 (defun escreen-goto-screen-4 () (interactive) (escreen-goto-screen 4))
372 (defun escreen-goto-screen-5 () (interactive) (escreen-goto-screen 5))
373 (defun escreen-goto-screen-6 () (interactive) (escreen-goto-screen 6))
374 (defun escreen-goto-screen-7 () (interactive) (escreen-goto-screen 7))
375 (defun escreen-goto-screen-8 () (interactive) (escreen-goto-screen 8))
376 (defun escreen-goto-screen-9 () (interactive) (escreen-goto-screen 9))
379 (defun escreen-get-current-screen-number ()
380 "Returns the currently selected screen number.
381 If called interactively, also print this result in the minibuffer."
384 (message "escreen: current screen is number %d"
385 escreen-current-screen-number)
386 escreen-current-screen-number))
388 (defun escreen-get-active-screen-numbers ()
389 "Print a list of the active screen numbers in the echo area.
390 Returns a list of numbers which represent screen numbers presently in use."
392 (let ((screen-list (sort (escreen-configuration-screen-numbers) '<))
393 (str "escreen: active screens:"))
396 (mapcar (function (lambda (num)
397 (setq str (format "%s %d" str num))))
402 (defun escreen-help ()
403 "Display a short summary of escreen commands."
405 (if (string-lessp emacs-version "19")
406 ;; emacs 18 couldn't list only bindings with a common prefix.
408 ;; Emacs 19 can handle escreen-prefix-char (as a string) directly, but
409 ;; for XEmacs, it must be converted to a vector.
410 (describe-bindings (escreen-string-to-vector escreen-prefix-char))))
412 (defun escreen-string-to-vector (s)
413 (let* ((l (length s))
414 (v (make-vector l nil))
417 (aset v i (aref s i))
422 ;; Return the first unused number available for designation as a screen
423 ;; number, or nil if escreen-max-screens screens are already in use.
424 (defun escreen-first-unused-screen-number ()
426 (while (and (< number escreen-max-screens)
427 (escreen-configuration-escreen number))
428 (setq number (1+ number)))
429 (and (< number escreen-max-screens) number)))
431 ;; Save window configuration, buffer configuration, and current marks and
432 ;; point for each displayed buffer for the current screen.
433 (defun escreen-save-current-screen-configuration ()
434 (let ((screen-data (escreen-screen-defined))
435 (new-alist-member nil))
437 (setcdr screen-data (escreen-save-screen-map))
438 (setq new-alist-member (cons escreen-current-screen-number
439 (escreen-save-screen-map)))
440 (setq escreen-configuration-alist
441 (cons new-alist-member escreen-configuration-alist)))))
443 ;; Return attributes for screen N, or nil if it doesn't exist.
444 (defun escreen-screen-defined (&optional n)
445 (escreen-configuration-escreen (or n escreen-current-screen-number)))
447 ;; Return nearest number less than current screen number that is
448 ;; an active screen, wrapping around end of screen list if necessary.
449 (defun escreen-get-prev-screen-number (&optional current-screen-number)
450 (or current-screen-number
451 (setq current-screen-number escreen-current-screen-number))
452 (if (eq 0 escreen-highest-screen-number-used)
454 ;; Decrement/wrap current screen number
455 (setq current-screen-number (1- current-screen-number))
456 (and (< current-screen-number 0)
457 (setq current-screen-number escreen-highest-screen-number-used))
458 (while (not (assq current-screen-number escreen-configuration-alist))
459 ;; Decrement/wrap current screen number
460 (setq current-screen-number (1- current-screen-number))
461 (and (< current-screen-number 0)
462 (setq current-screen-number escreen-highest-screen-number-used)))
463 current-screen-number))
465 ;; Return nearest number greater than current screen number that is
466 ;; an active screen, wrapping around end of screen list if necessary.
467 (defun escreen-get-next-screen-number (&optional current-screen-number)
468 (or current-screen-number
469 (setq current-screen-number escreen-current-screen-number))
470 (if (eq 0 escreen-highest-screen-number-used)
472 ;; Increment/wrap current screen number
473 (setq current-screen-number (1+ current-screen-number))
474 (and (> current-screen-number escreen-highest-screen-number-used)
475 (setq current-screen-number 0))
476 (while (not (assq current-screen-number escreen-configuration-alist))
477 ;; Increment/wrap current screen number
478 (setq current-screen-number (1+ current-screen-number))
479 (and (> current-screen-number escreen-highest-screen-number-used)
480 (setq current-screen-number 0)))
481 current-screen-number))
484 ;;; Primitive accessors for escreen-configuration-alist
486 (defun escreen-configuration-escreen (number)
487 (assq number escreen-configuration-alist))
489 (defun escreen-configuration-escreen-delete (data)
490 (setq escreen-configuration-alist
491 (delq (if (numberp data)
492 (escreen-configuration-escreen data)
494 escreen-configuration-alist)))
496 (defun escreen-configuration-screen-numbers ()
497 (mapcar 'car escreen-configuration-alist))
499 (defun escreen-configuration-one-screen-p ()
500 (>= 1 (length escreen-configuration-alist)))
502 ;; Sort the alist so that they are in order numerically.
503 (defun escreen-configuration-alist-sort-by-number ()
504 (setq escreen-configuration-alist
505 (sort escreen-configuration-alist
506 (function (lambda (a b)
507 (< (car a) (car b)))))))
509 ;;; map-data sub-accessors
511 (defun escreen-configuration-screen-number (l)
514 (defun escreen-configuration-window-data-configuration (l)
517 (defun escreen-configuration-data-map (l)
520 (defun escreen-configuration-selected-window-count (l)
523 ;;; screen map data accessors
525 (defun escreen-configuration-data-map-critical (data)
528 (defun escreen-configuration-data-map-user (data)
531 ;;; critical map data accessors
533 (defun escreen-configuration-data-map-critical-buffer (crit-map)
536 (defun escreen-configuration-data-map-critical-buffer-name (crit-map)
539 (defun escreen-configuration-data-map-critical-buffer-file-name (crit-map)
543 (defun escreen-save-screen-map ()
544 (let ((config (current-window-configuration))
547 (sel-window (selected-window))
548 (first-window (escreen-first-window))
551 (save-window-excursion
552 (select-window first-window)
553 (while (not (eq window first-window))
554 (cond ((null sel-window))
555 ((eq (selected-window) sel-window)
556 (setq sel-window nil))
558 (setq sel-win-count (1+ sel-win-count))))
560 (cons (cons (escreen-save-critical-data)
561 (escreen-save-user-data))
563 (setq window (select-window (next-window)))
564 (set-buffer (window-buffer (selected-window))))))
565 (list config (nreverse win-data) sel-win-count)))
567 (defun escreen-restore-screen-map (map)
568 (let ((config (escreen-configuration-window-data-configuration map))
569 (map (escreen-configuration-data-map map))
570 (sel-win-number (escreen-configuration-selected-window-count map))
573 (set-window-configuration config)
574 (select-window (escreen-first-window))
576 (and (= win-count sel-win-number)
577 (setq sel-win (selected-window)))
578 (setq win-count (1+ win-count))
580 (escreen-restore-critical-data
581 (escreen-configuration-data-map-critical (car map)))
583 (escreen-restore-user-data
584 (escreen-configuration-data-map-user (car map)))
585 (select-window (next-window))
586 (setq map (cdr map)))
587 (select-window (or sel-win (escreen-first-window)))))
589 (defun escreen-save-critical-data ()
590 (mapcar 'funcall escreen-map-critical-data-format))
592 (defun escreen-restore-critical-data (data)
593 (let ((buffer (escreen-configuration-data-map-critical-buffer data))
595 (escreen-configuration-data-map-critical-buffer-name data))
597 (escreen-configuration-data-map-critical-buffer-file-name data)))
598 (cond ((escreen-killed-buffer-p buffer)
599 (cond ((null escreen-restore-killed-buffers)
600 (set-window-buffer (selected-window)
602 escreen-new-screen-default-buffer)))
603 ((stringp buf-file-name)
604 (setq buffer (find-file-noselect buf-file-name))
605 (set-window-buffer (selected-window) buffer)
606 (or (get-buffer buffer-name)
607 (rename-buffer buffer-name)))
609 (set-window-buffer (selected-window)
611 escreen-new-screen-default-buffer)))))
613 (set-window-buffer (selected-window) buffer)))))
615 (defun escreen-save-user-data ()
616 (mapcar (function (lambda (pair) (funcall (car pair))))
617 escreen-map-data-format))
619 (defun escreen-restore-user-data (data)
620 (let ((funlist escreen-map-data-format))
621 (while (and data funlist)
622 (funcall (cdr (car funlist)) (car data))
623 (setq funlist (cdr funlist))
624 (setq data (cdr data)))))
627 ;; Functions used to save and restore screen configuration state.
628 ;; These are mapped over via presence in escreen-map-data-format.
630 (defun escreen-map-save-window-start ()
631 (escreen-make-marker (window-start)))
633 (defun escreen-map-restore-window-start (p)
634 (and (escreen-position-valid-p p)
635 (set-window-start (selected-window) p t)))
637 (defun escreen-map-restore-mark-marker (mark)
638 (cond ((escreen-position-valid-p mark)
639 (set-marker (or (mark-marker)
640 ;; when XEmacs zmacs-regions are set, mark-marker
641 ;; can return nil unless optional arg forcep is
643 ;; In Emacs transient-mark-mode, mark-marker will
644 ;; still return a marker, so no magic needed.
646 (marker-position mark)
647 (marker-buffer mark)))))
649 (defun escreen-map-save-point ()
650 ;; If there is a process mark in the current buffer and point is at it,
651 ;; then return the process mark also. That way, when we return to this
652 ;; screen, point will be at the end of the process output even if that
653 ;; has advanced since then. Otherwise, just use a before-insertion
654 ;; marker (if supported).
655 (let* ((point-mark (escreen-make-marker (point-marker) nil t))
656 (proc (get-buffer-process (current-buffer)))
657 (proc-mark (and proc (process-mark proc))))
658 (if (and (escreen-position-valid-p proc-mark)
659 (= proc-mark (point)))
660 (cons proc-mark point-mark)
663 (defun escreen-map-restore-point (pos)
665 (cond ((escreen-position-valid-p (car pos))
666 (goto-char (car pos)))
667 ((escreen-position-valid-p (cdr pos))
668 (goto-char (cdr pos)))))
670 (and (escreen-position-valid-p pos)
673 (defun escreen-map-save-narrowed-region ()
674 (cons (and (> (point-min) 1)
675 (escreen-make-marker (point-min)))
676 (and (<= (point-max) (buffer-size))
677 (escreen-make-marker (point-max) nil t))))
679 (defun escreen-map-restore-narrowed-region (reg)
680 (let ((size (1+ (buffer-size)))
681 (beg (or (car reg) (point-min)))
682 (end (or (cdr reg) (point-max))))
683 (and (escreen-position-valid-p beg)
684 (escreen-position-valid-p end)
687 (narrow-to-region beg end))))
689 (defun escreen-map-save-truncate-lines ()
692 (defun escreen-map-restore-truncate-lines (v)
693 (setq truncate-lines v))
695 (defun escreen-map-save-mode-line-face ()
696 (cond ((fboundp 'face-reverse-p)
697 ;; XEmacs mode line face properties
698 (list (face-reverse-p 'modeline)
699 (face-background 'modeline)
700 (face-foreground 'modeline)))
701 ((boundp 'mode-line-inverse-video)
702 mode-line-inverse-video)))
704 (defun escreen-map-restore-mode-line-face (v)
705 (cond ((fboundp 'face-reverse-p)
706 (set-face-reverse-p 'modeline (nth 0 v))
707 (set-face-background 'modeline (nth 1 v))
708 (set-face-foreground 'modeline (nth 2 v)))
709 ((boundp 'mode-line-inverse-video)
710 (setq mode-line-inverse-video v))))
712 ;; Emacs 19.30 and beyond supports menu bars on ascii terminals, but beware
713 ;; of turning them off or on once escreen is loaded; if a stored window
714 ;; configuration was for a frame with a menu bar, but there is no menu bar
715 ;; presently, that will crash emacs. This fatal bug is present in all
716 ;; versions of Emacs prior to 21.0.
717 (defun escreen-map-save-menu-bar-mode ()
718 (and (boundp 'menu-bar-mode)
721 (defun escreen-map-restore-menu-bar-mode (v)
722 (cond ((fboundp 'menu-bar-mode)
725 (menu-bar-mode -1)))))
727 (defun escreen-map-restore-buffer-list (olist)
728 (and escreen-preserve-buffer-list-order
729 (escreen-set-buffer-list-order olist)))
732 (defun escreen-killed-buffer-p (buffer)
733 (not (if (fboundp 'buffer-live-p)
734 (buffer-live-p buffer)
735 ;; Emacs 18 doesn't have buffer-live-p.
736 ;; Killed buffers have no names.
737 (buffer-name buffer))))
739 (defun escreen-position-valid-p (pos)
741 (<= pos (1+ (buffer-size))))
743 (and (eq (marker-buffer pos) (current-buffer))
744 (numberp (marker-position pos))
745 (<= pos (1+ (buffer-size)))))
748 (defun escreen-set-buffer-list-order (olist)
751 (setq buf (car olist))
753 (setq buf (get-buffer buf)))
754 (cond ((escreen-killed-buffer-p buf))
758 (setq firstbuf buf))))
759 (setq olist (cdr olist)))
760 (setq olist (buffer-list))
761 (while (not (eq (car olist) firstbuf))
762 (bury-buffer (car olist))
763 (setq olist (cdr olist)))))
765 ;; Copy existing marker, or make a new one from point.
766 ;; Emacs 19.30 and later can create markers which are advanced if text is
767 ;; inserted before them, without needing to call insert-before-markers
768 ;; explicitly. This is useful for storing point, mark, etc. since the
769 ;; buffer may be edited while we are in other escreens.
770 (defun escreen-make-marker (pos &optional buffer insertion-type)
771 (let ((new-marker nil))
773 (setq new-marker (copy-marker pos))
775 (set-marker new-marker (marker-position pos) buffer)))
777 (setq new-marker (make-marker))
778 (set-marker new-marker pos buffer)))
779 (and (fboundp 'set-marker-insertion-type)
780 (set-marker-insertion-type new-marker insertion-type))
783 (defun escreen-first-window ()
784 (cond ((fboundp 'frame-highest-window)
785 (funcall 'frame-highest-window))
786 ((fboundp 'frame-first-window)
787 (funcall 'frame-first-window))
791 (let ((win (selected-window)))
792 (while (not (escreen-first-window-p win))
793 (setq win (next-window win)))
796 (defun escreen-first-window-p (win)
797 (let ((edges (escreen-window-edges win)))
798 (and (= (nth 0 edges) 0)
799 (= (nth 1 edges) 0))))
802 (defun escreen-menu ()
804 (escreen-configuration-alist-sort-by-number)
805 (let ((escreen-menu-buffer (get-buffer-create "*Escreen List*"))
806 alist data-map screen-number)
807 ;; Display buffer now so update of screen cofiguration will be correct.
808 (display-buffer escreen-menu-buffer)
809 ;; Update escreen-configuration-alist to contain up-to-date information
810 ;; on current screen, since we'll be displaying data about it.
811 (escreen-save-current-screen-configuration)
812 (setq alist escreen-configuration-alist)
814 (set-buffer escreen-menu-buffer)
815 (setq buffer-read-only nil)
817 (insert " Screen Buffers\n ------ -------\n")
819 (setq screen-data (car alist))
820 (setq alist (cdr alist))
822 (setq screen-number (escreen-configuration-screen-number screen-data))
823 (setq data-map (escreen-configuration-data-map screen-data))
825 (if (= screen-number escreen-current-screen-number)
826 (insert (format "*%-6d " screen-number))
827 (insert (format " %-6d " screen-number)))
829 (insert (if (> (current-column) 0) "" " ")
830 (escreen-configuration-data-map-critical-buffer-name
831 (escreen-configuration-data-map-critical (car data-map)))
833 (setq data-map (cdr data-map)))
835 (escreen-menu-mode))))
837 (defun escreen-menu-mode ()
839 (kill-all-local-variables)
840 (setq buffer-undo-list t)
841 (setq truncate-lines t)
842 (setq buffer-read-only t)
843 (setq major-mode 'escreen-menu-mode)
844 (setq mode-name "Escreen Menu")
845 (run-hooks 'escreen-menu-mode-hook))
848 ;; Install this by doing
850 ;; (add-hook 'escreen-goto-screen-hook
851 ;; 'escreen-enable-number-mode-if-more-than-one-screen)
853 ;; By doing so, escreen-number-mode is disabled whenever only a single
854 ;; escreen is in use. The only reason for doing this, however, is to save
855 ;; valuable mode line real estate.
856 (defun escreen-enable-number-mode-if-more-than-one-screen ()
857 (if (> (length (escreen-get-active-screen-numbers)) 1)
858 (escreen-number-mode 1)
859 (escreen-number-mode -1))
860 (escreen-force-mode-line-update t))
863 ;;; Compatiblity tweaks for Emacs 19, 18, and XEmacs.
865 (defun escreen-window-edges (&rest args)
866 (apply (if (fboundp 'window-edges)
868 ;; For XEmacs 19.13 and later.
872 (defun escreen-force-mode-line-update (&optional allp)
873 (if (fboundp 'force-mode-line-update)
874 (force-mode-line-update allp)
875 ;; Emacs 18 doesn't have force-mode-line-update
876 (and all (save-excursion (set-buffer (other-buffer))))
877 (set-buffer-modified-p (buffer-modified-p))))
879 ;; Some versions of emacs 18 did not have `member'.
880 (defun escreen-member (x y)
881 (if (fboundp 'member)
883 (while (and y (not (equal x (car y))))
889 ;;; escreen.el ends here