;;;; windows.jl -- Window handling
;;;  Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>

;;; This file is part of Jade.

;;; Jade 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.

;;; Jade 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 Jade; see the file COPYING.  If not, write to
;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

(defvar window-list (cons (current-window) nil)
  "List of all opened windows.")

(defvar window-closed-hook '(close-window)
  "Hook called when an input event saying that a window should be closed
is received.")

(defun open-window (&optional buffer x y w h)
  "Creates a new window display BUFFER or the buffer that the current window is
showing."
  (interactive)
  (let
      ((old-buf-list buffer-list)
       win)
    (unless buffer
      (setq buffer (current-buffer)))
    (when (setq win (make-window x y w h))
      (setq window-list (cons win window-list))
      (with-window win
	(setq buffer-list (cons buffer (delq buffer
					     (copy-sequence old-buf-list))))
	(set-current-buffer buffer win))
      win)))

(defun close-window (&optional win)
  "Close window WIN, or the current window."
  (interactive)
  (unless win
    (setq win (current-window)))
  (if (= (window-count) 1)
      (save-and-quit)
    (setq window-list (delq win window-list))
    (destroy-window win)))

(defun close-other-windows (&optional win)
  "Close all windows except for WIN, or the current one."
  (interactive)
  (unless win
    (setq win (current-window)))
  (setq window-list (delq win window-list))
  (while window-list
    (destroy-window (car window-list))
    (setq window-list (cdr window-list)))
  (setq window-list (cons win nil)))

(defun add-buffer (buffer)
  "Make sure that BUFFER is in the `buffer-list' of all open windows. It gets
put at the end of the list."
  (let
      ((win-list window-list))
    (while (consp win-list)
      (with-window (car win-list)
	(setq buffer-list (nconc (delq buffer buffer-list) (cons buffer nil))))
      (setq win-list (cdr win-list)))))

(defun remove-buffer (buffer)
  "Delete all references to BUFFER in any of the windows' `buffer-list'"
  (let
      ((win-list window-list))
    (while (consp win-list)
      (with-window (car win-list)
	(setq buffer-list (delq buffer buffer-list))
	(when (eq (current-buffer (car win-list)) buffer)
	  (set-current-buffer (car buffer-list) (car win-list))))
      (setq win-list (cdr win-list)))))

(defun in-other-window (command)
  "Switches to the `other' window then calls the command COMMAND in it."
  (goto-other-window)
  (call-command command))

(defun goto-other-window ()
  "Switch to the `other' window."
  (interactive)
  (set-current-window (other-window) t))

(defun in-new-window (command)
  (goto-new-window)
  (call-command command))

(defun goto-new-window ()
  (interactive)
  (set-current-window (open-window) t))

(defun other-window ()
  "(other-window)
Return the `other' window."
  (if (= 1 (window-count))
      (open-window)
    (if (eq (car window-list) (current-window))
	(car (cdr window-list))
      (car window-list))))

(defun toggle-iconic ()
  "Toggle the current window between iconified and normal states."
  (interactive)
  (if (window-asleep-p)
      (unsleep-window)
    (sleep-window)))
