;; ecb-winman-support.el - support of several window managers
;; Copyright (C) 2000 - 2003 Klaus Berndl,
;; Free Software Foundation, Inc.
;; Author: Klaus Berndl
;; Maintainer: Klaus Berndl
;; Keywords: browser, code, programming, tools, escreen, winring
;; Created: 2003
;; This program is free software; you can redistribute it and/or modify it under
;; the terms of the GNU General Public License as published by the Free Software
;; Foundation; either version 2, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
;; details.
;; You should have received a copy of the GNU General Public License along with
;; GNU Emacs; see the file COPYING. If not, write to the Free Software
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;; $Id$
;;; Commentary
;;
;; This library contains support for several window-managers so they interact
;; well with ECB. Currently the following window-managers are supported by ECB:
;; - winring.el: Written by Barry A. Warsaw , get it from
;; http://www.python.org/emacs/
;; - escreen.el: Written by Noah Friedman , get it from
;; http://www.splode.com/~friedman/software/emacs-lisp/
;;
;; Note: With one of these window-managers installed and active you can run
;; applications like Gnus, VM or BBDB in the same frame as ECB! Just use
;; different window-configurations (winring.el) or escreens (escreen.el) for
;; ECB and the other applications. Especially with winring.el you can give
;; every configuration a descriptive name like "ECB" or "Gnus" ; afterwards
;; you can jump to a window-configuration by name!
;;; Installation and enabling
;;
;; This library is installed autom. with ECB. But every support must be
;; enabled explicitly:
;; - winring: Call `ecb-winman-winring-enable-support'. This *must* be done
;; *before* the first call to any winring-command, so also before calling
;; `winring-initialize'!
;; - escreen: Call `ecb-winman-escreen-enable-support'. This *must* be done
;; *before* the first call to any escreen-command, so also before calling
;; `escreen-install'!
;;
;; You can also put into your .emacs:
;; (ecb-winman-winring-enable-support) or/and
;; (ecb-winman-escreen-enable-support)
;;; Deinstallation
;;
;; Just run `ecb-winman-escreen-disable-support' rsp.
;; `ecb-winman-winring-disable-support'.
;;; Usage
;;
;; After enabling the support of one of the supported window-managers just go
;; on as described in the commentary or introduction of the respective
;; library-file(s) of the window-manager. Here is a short description:
;; - winring: Run `winring-initialize'. If ECB is active then the resulting
;; window-configuration is the ECB-window-configuration. Otherwise you can
;; create the ECB-window-configuration when you first time call
;; `winring-new-configuration' with name equal to `ecb-winman-winring-name'.
;; In general you can run all commands of the winring-library. If you jump
;; to the ECB-window-configuration then ECB will be autom. activated and if
;; you leave the ECB-window-configuration then ECB will autom. deactivated.
;; - escreen: Run `escreen-install' (deactivates ECB if currently
;; running), `escreen-create-screen', `escreen-goto-screen' etc. The latter
;; ones activate autom. ECB if creating or selecting the escreen with number
;; `ecb-escreen-number' (default = 1) and deactivate ECB autom. if leaving
;; the ECB-escreen.
;;; BUGS
;;
;; Currently not known
;; Thanks to Johann "Myrkraverk" Oskarsson
;; for the first trigger for this support-library. He has suggested to
;; integrate ECB with escreen.
;;; Code
(eval-when-compile
(require 'silentcomp))
(require 'ecb-util)
(silentcomp-defvar escreen-current-screen-number)
(defgroup ecb-winman-support nil
"Settings for supporting several window-managers.
Currently winring and escreen are supported."
:group 'ecb
:prefix "ecb-winman-")
(defcustom ecb-winman-escreen-number 1
"*Number of the escreen which is reserved for ECB.
If you go to the escreen with this number you go always to the escreen with
activated ECB. All other escreen-numbers are escreens with deactivated ECB!"
:group 'ecb-winman-support
:group 'ecb-most-important
:type 'integer)
(defcustom ecb-winman-winring-name "ECB"
"*Name of the winring-window-configuration reserved for ECB.
If you go to the window-configuration with this name you go always to the
window-configuration with activated ECB. All other window-configuration are
configurations with deactivated ECB!"
:group 'ecb-winman-support
:group 'ecb-most-important
:type 'string)
;; support for the library escreen.el ----------------------------------------
(defconst ecb-winman-escreen-adviced-functions
'((escreen-save-current-screen-configuration . before))
"These functions of escreen are adviced if escreen is active during ECB is
active. Each element of the list is a cons-cell where the car is the
function-symbol and the cdr the advice-class \(before, around or after). If a
function should be adviced with more than one class \(e.g. with a before and
an after-advice) then for every class a cons must be added to this list.")
(defun ecb-winman-escreen-enable-support ()
"Load the escreen-library and enable the ECB-support for it.
This does not install or activate escreen! For this you have still to call
`escreen-install'! For further documentation about escreen see the file
escreen.el!"
(interactive)
(if (locate-library "escreen")
(condition-case nil
(progn
(require 'escreen)
(ecb-enable-advices ecb-winman-escreen-adviced-functions)
(add-hook 'escreen-goto-screen-hook
'ecb-winman-escreen-goto-escreen-hook)
(ecb-info-message "Support for escreen enabled."))
(error
(ecb-winman-escreen-disable-support)
(ecb-error "The escreen-support can not be properly installed!")))
(ecb-error "The library escreen.el can not be found!")))
(defun ecb-winman-escreen-disable-support ()
"Disable the escreen-support of ECB."
(interactive)
(ecb-disable-advices ecb-winman-escreen-adviced-functions)
(when (featurep 'escreen)
(remove-hook 'escreen-goto-screen-hook
'ecb-winman-escreen-goto-escreen-hook)))
(defun ecb-winman-escreen-goto-escreen-hook ()
"Activate ECB if we go to the escreen with number `ecb-escreen-number'."
(if (and (boundp 'ecb-minor-mode)
(not ecb-minor-mode)
(= escreen-current-screen-number
ecb-winman-escreen-number))
(let ((ecb-split-edit-window-after-start 'before-deactivation))
(ecb-activate))))
(defadvice escreen-save-current-screen-configuration (before ecb)
"escreen can only handle screen-configurations if ECB is deactivated. This
is because ECB handles its window-creation completely by itself and because it
uses dedicated windows. So we deactivate ECB before running this function."
(if (and (boundp 'ecb-minor-mode)
ecb-minor-mode
(equal ecb-frame (selected-frame)))
(let ((ecb-split-edit-window-after-start 'before-deactivation))
(ecb-deactivate))))
;; support for the library winring.el ---------------------------------------
(defconst ecb-winman-winring-adviced-functions
'((winring-save-current-configuration . before)
(winring-initialize . after)
(winring-duplicate-configuration . before)
(winring-restore-configuration . before)
(winring-set-name . after))
"These functions of winring are adviced if winring is active during ECB is
active. Each element of the list is a cons-cell where the car is the
function-symbol and the cdr the advice-class \(before, around or after). If a
function should be adviced with more than one class \(e.g. with a before and
an after-advice) then for every class a cons must be added to this list.")
(defun ecb-winman-winring-enable-support ()
"Load the winring-library and enable the ECB-support for it.
This does not install or activate winring! For this you have still to call
`winring-initialize'! For further documentation about winring see the file
winring.el!"
(interactive)
(if (locate-library "winring")
(condition-case nil
(progn
(require 'winring)
(ecb-enable-advices ecb-winman-winring-adviced-functions)
(ecb-info-message "Support for winring enabled."))
(error
(ecb-winman-winring-disable-support)
(ecb-error "The winring-support can not be properly installed!")))
(ecb-error "The library winring.el can not be found!")))
(defun ecb-winman-winring-disable-support ()
"Disable the winring-support of ECB."
(interactive)
(ecb-disable-advices ecb-winman-winring-adviced-functions))
(defvar ecb-winman-winring-ecb-frame nil
"Frame for which the ECB-window-configuration was set first time.")
(defadvice winring-set-name (after ecb)
"Store frame if name is equal with `ecb-winman-winring-name' and activate
ECB if we set the name `ecb-winman-winring-name'."
;; Because this is an after advice of winring-name-of-current returns here
;; already the new name!
(when (ecb-string= (winring-name-of-current) ecb-winman-winring-name)
;; we do this only the first time
(when (null ecb-winman-winring-ecb-frame)
(setq ecb-winman-winring-ecb-frame
(or (ad-get-arg 1) (selected-frame))))
;; now we activate ECB if necessary
(when (and (boundp 'ecb-minor-mode)
(not ecb-minor-mode)
(equal (or (ad-get-arg 1)
(selected-frame)) ecb-winman-winring-ecb-frame))
(let ((ecb-split-edit-window-after-start 'before-deactivation))
(ecb-activate)))))
(defadvice winring-duplicate-configuration (before ecb)
"Prevent the ECB-window-configuration from being duplicated."
(if (ecb-string= (winring-name-of-current) ecb-winman-winring-name)
(ecb-error "The ECB-window-configuration can not be duplicated!")))
(defadvice winring-restore-configuration (before ecb)
"Deactivates ECB if the ECB-window-configuration is active."
(if (and (ecb-string= (winring-name-of-current) ecb-winman-winring-name)
(boundp 'ecb-minor-mode)
ecb-minor-mode)
(let ((ecb-split-edit-window-after-start 'before-deactivation))
(ecb-deactivate))))
(defadvice winring-save-current-configuration (before ecb)
"winring can only handle window-configurations if ECB is deactivated. This
is because ECB handles its window-creation completely by itself and because it
uses dedicated windows. So we deactivate ECB before running this function."
(if (and (boundp 'ecb-minor-mode)
ecb-minor-mode
(equal ecb-frame (selected-frame)))
(let ((ecb-split-edit-window-after-start 'before-deactivation))
(ecb-deactivate))))
(defadvice winring-initialize (after ecb)
"If ECB is active when winring is initialized then this initial
window-configuration gets always the name `ecb-winman-winring-name'."
(if (and (boundp 'ecb-minor-mode)
ecb-minor-mode
(equal ecb-frame (selected-frame)))
(winring-set-name ecb-winman-winring-name)))
;; not supported window-managing functions------------------------------------
(defconst ecb-winman-not-supported-function-advices
(if ecb-running-xemacs
'((winner-mode . before)
(winner-redo . before)
(winner-undo . before)
(push-window-configuration . before)
(pop-window-configuration . before)
(unpop-window-configuration . before))
'((winner-mode . before)
(winner-redo . before)
(winner-undo . before))))
(defadvice winner-mode (before ecb)
"Prevents `winner-mode' from being activated for the ECB-frame."
(if (equal (selected-frame) ecb-frame)
(ecb-error "Can't use winner-mode functions in the ecb-frame.")))
(defadvice winner-redo (before ecb)
"Prevents `winner-redo' from being used within the ECB-frame."
(if (equal (selected-frame) ecb-frame)
(ecb-error "Can't use winner-mode functions in the ecb-frame.")))
(defadvice winner-undo (before ecb)
"Prevents `winner-undo' from being used within the ECB-frame."
(if (equal (selected-frame) ecb-frame)
(ecb-error "Can't use winner-mode functions in the ecb-frame.")))
(when ecb-running-xemacs
(defadvice push-window-configuration (before ecb)
(if (and (equal (selected-frame) ecb-frame)
(interactive-p))
(ecb-error "Can't use interactive push-window-configuration in the ecb-frame.")))
(defadvice pop-window-configuration (before ecb)
(if (and (equal (selected-frame) ecb-frame)
(interactive-p))
(ecb-error "Can't use interactive pop-window-configuration in the ecb-frame.")))
(defadvice unpop-window-configuration (before ecb)
(if (and (equal (selected-frame) ecb-frame)
(interactive-p))
(ecb-error "Can't use interactive unpop-window-configuration in the ecb-frame.")))
)
;; we disable all advices per default.
(ecb-disable-advices ecb-winman-winring-adviced-functions)
(ecb-disable-advices ecb-winman-escreen-adviced-functions)
(ecb-disable-advices ecb-winman-not-supported-function-advices)
(silentcomp-provide 'ecb-winman-support)
;;; ecb-winman-support.el ends here