diff lisp/electric/electric.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children b82b59fe008d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/electric/electric.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,183 @@
+;;; electric.el --- window maker and Command loop for `electric' modes.
+
+;; Copyright (C) 1985, 1986, 1992, 1995 Free Software Foundation, Inc.
+
+;; Author: K. Shane Hartman
+;; Maintainer: FSF
+;; Keywords: extensions
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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.
+
+;; XEmacs 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 XEmacs; see the file COPYING.  If not, write to the Free
+;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; Synched up with: FSF 19.30.97.
+
+;;; Commentary:
+
+; zaaaaaaap
+
+;;; Code:
+
+;; This loop is the guts for non-standard modes which retain control
+;; until some event occurs.  It is a `do-forever', the only way out is
+;; to throw.  It assumes that you have set up the keymap, window, and
+;; everything else: all it does is read commands and execute them -
+;; providing error messages should one occur (if there is no loop
+;; function - which see).  The required argument is a tag which should
+;; expect a value of nil if the user decides to punt. The second
+;; argument is the prompt to be used: if nil, use "->", if 'noprompt,
+;; don't use a prompt, if a string, use that string as prompt, and if
+;; a function of no variable, it will be evaluated in every iteration
+;; of the loop and its return value, which can be nil, 'noprompt or a
+;; string, will be used as prompt.  Given third argument non-nil, it
+;; INHIBITS quitting unless the user types C-g at toplevel.  This is
+;; so user can do things like C-u C-g and not get thrown out.  Fourth
+;; argument, if non-nil, should be a function of two arguments which
+;; is called after every command is executed.  The fifth argument, if
+;; provided, is the state variable for the function.  If the
+;; loop-function gets an error, the loop will abort WITHOUT throwing
+;; (moral: use unwind-protect around call to this function for any
+;; critical stuff).  The second argument for the loop function is the
+;; conditions for any error that occurred or nil if none.
+
+(defun Electric-command-loop (return-tag
+			      &optional prompt inhibit-quit
+					loop-function loop-state)
+
+  (let (cmd 
+        (err nil) 
+	(electrified-buffer (current-buffer)) ; XEmacs -
+        (prompt-string prompt))
+    (while t
+      (if (not (or (stringp prompt) (eq prompt nil) (eq prompt 'noprompt)))
+          (setq prompt-string (funcall prompt)))
+      (if (not (stringp prompt-string))
+          (if (eq prompt-string 'noprompt)
+              (setq prompt-string nil)
+            (setq prompt-string "->")))
+      (setq cmd (read-key-sequence prompt-string))
+      (or prefix-arg (setq last-command this-command))
+      (setq last-command-event (aref cmd (1- (length cmd)))
+	    current-mouse-event
+	      (and (or (button-press-event-p last-command-event)
+		       (button-release-event-p last-command-event)
+		       (menu-event-p last-command-event))
+		   last-command-event)
+	    this-command (if (menu-event-p last-command-event)
+			     last-command-event
+                             (key-binding cmd t))
+	    cmd this-command)
+      ;; This makes universal-argument-other-key work.
+      (setq universal-argument-num-events 0)
+      (if (or (prog1 quit-flag (setq quit-flag nil))
+	      (eq (event-to-character last-input-event) (quit-char)))
+	  (progn (setq unread-command-events nil
+		       prefix-arg nil)
+		 ;; If it wasn't cancelling a prefix character, then quit.
+		 (if (or (= (length (this-command-keys)) 1)
+			 (not inhibit-quit)) ; safety
+		     (progn (ding nil 'quit) ; XEmacs - 
+			    (message "Quit")
+			    (throw return-tag nil))
+		   (setq cmd nil))))
+      (setq current-prefix-arg prefix-arg)
+      (if cmd
+	  (condition-case conditions
+	      (progn (if (eventp cmd)
+			 (progn
+			   (let ((b (current-buffer)))
+			     (dispatch-event cmd)
+			     (if (not (eq b (current-buffer)))
+				 (throw return-tag (current-buffer)))))
+		       (command-execute cmd))
+		     (setq last-command this-command)
+		     (if (or (prog1 quit-flag (setq quit-flag nil))
+			     (eq (event-to-character last-input-event)
+				 (quit-char)))
+			 (progn (setq unread-command-events nil)
+				(if (not inhibit-quit)
+				    (progn (ding nil 'quit)
+					   (message "Quit")
+					   (throw return-tag nil))
+				  (message "Quit inhibited")
+				  (ding)))))
+	    (error (command-error conditions) ; XEmacs
+		   (sit-for 2)))
+	(ding nil 'undefined-key))
+            (and (not (eq (current-buffer) electrified-buffer)) ; XEmacs -
+	   (not (eq (selected-window) (minibuffer-window)))
+	   (progn (ding nil 'quit)
+		  (message "Leaving electric command loop %s."
+			   "because buffer has changed")
+		  (sit-for 2)
+		  (throw return-tag nil)))
+      (if loop-function (funcall loop-function loop-state err))))
+  ;; ####> - huh?  It should be impossible to ever get here...
+  (ding nil 'alarm)
+  (throw return-tag nil))
+
+;; This function is like pop-to-buffer, sort of. 
+;; The algorithm is
+;; If there is a window displaying buffer
+;; 	Select it
+;; Else if there is only one window
+;; 	Split it, selecting the window on the bottom with height being
+;; 	the lesser of max-height (if non-nil) and the number of lines in
+;;      the buffer to be displayed subject to window-min-height constraint.
+;; Else
+;; 	Switch to buffer in the current window.
+;;
+;; Then if max-height is nil, and not all of the lines in the buffer
+;; are displayed, grab the whole frame.
+;;
+;; Returns selected window on buffer positioned at point-min.
+
+(defun Electric-pop-up-window (buffer &optional max-height)
+  (let* ((win (or (get-buffer-window buffer) (selected-window)))
+	 (buf (get-buffer buffer))
+	 (one-window (one-window-p t))
+	 (pop-up-windows t)
+	 (target-height)
+	 (lines))
+    (if (not buf)
+	(error "Buffer %s does not exist" buffer)
+      (save-excursion
+	(set-buffer buf)
+	(setq lines (count-lines (point-min) (point-max)))
+	(setq target-height
+	      (min (max (if max-height (min max-height (1+ lines)) (1+ lines))
+			window-min-height)
+		   (save-window-excursion
+		     (delete-other-windows)
+		     (1- (window-height (selected-window)))))))
+      (cond ((and (eq (window-buffer win) buf))
+	     (select-window win))
+	    (one-window
+	     (goto-char (window-start win))
+	     (pop-to-buffer buffer)
+	     (setq win (selected-window))
+	     (enlarge-window (- target-height (window-height win))))
+	    (t
+	     (switch-to-buffer buf)))
+      (if (and (not max-height)
+	       (> target-height (window-height (selected-window))))
+	  (progn (goto-char (window-start win))
+		 (enlarge-window (- target-height (window-height win)))))
+      (goto-char (point-min))
+      win)))
+
+(provide 'electric)                           ; zaaaaaaap
+
+;;; electric.el ends here