Mercurial > hg > xemacs
diff lucid/rooms.el @ 0:107d592c5f4a
DICE versions, used by pers/common, recursive, I think/hope
author | Henry S. Thompson <ht@inf.ed.ac.uk> |
---|---|
date | Mon, 08 Feb 2021 11:44:37 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lucid/rooms.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,293 @@ +;;; rooms facility for gnuemacs + +;;; Copyright Henry S. Thompson 1990 + +;;; Last edited: Wed Sep 14 08:48:27 1994 + +;;; v19.19 version + +(provide 'rooms) +(require 'prompt-for-word) + +(defvar rooms-table nil "a-list of rooms in the form (name . window-specs)") + +(defvar frames-table nil "a-list of room to frame mappings") + +(defvar rooms-map (let ((new (copy-keymap pfw-map))) + (define-key new "\C-r" 'minibuffer-complete-and-exit) + new) + "allow ^R as synonym for CR in prompt-for-word") + +(defmacro room-name (room) (list 'car room)) +(defmacro room-window-specs (room) (list 'cdr room)) +(defmacro make-room (name window-specs) (list 'cons name window-specs)) + +(defvar current-room nil "the current room") + +(defvar previous-room nil "the previous room") + +;; a window spec is of the form (buffer-name constitution . edges) +(defmacro ws-buffer-name (ws) (list 'car ws)) +(defmacro ws-constitution (ws) (list 'car (list 'cdr ws))) +(defmacro ws-edges (ws) (list 'cdr (list 'cdr ws))) +(defmacro make-ws (buffer-name constitution edges) + (list 'cons buffer-name + (list 'cons constitution edges))) + +(defun rooms-top (redraw) + "top level for rooms - prompts for room name and goes there. +Prefix arg forces room's frame to its defined contents. +Typing overrides initial suggestion, exiting completes. To name a new room +exit with ^N +To redefine an existing room, exit with ^R" + (interactive "PIf prefixed, forces room's frame, if any, to its defined contents") + (let ((name (prompt-for-word "Room: " (or (room-name previous-room) "") + rooms-table (if rooms-table + rooms-map))) + (e-o-c last-input-char) + room) + (cond ((eq e-o-c 18) ; ^R + (rooms-redefine-query name)) + (t + (if (setq room (assoc name rooms-table)) + (rooms-goto room redraw) + (rooms-new-query name)))))) + +(defun rooms-goto (room &optional redraw) "switch frame to ROOM's config" + (let ((room (if (stringp room) + (or (assoc room rooms-table) + (error "No room named %s" room)) + room)) + st-entry) + (if (not (eq room current-room)) + (setq previous-room current-room)) + (setq current-room room) + ;; lazy if mapped to frame and not redraw + (if (setq st-entry (assoc (room-name room) frames-table)) + ;; very tricky -- appears to be the only order that works! + (progn +; (focus-frame (cdr st-entry)) + (select-frame (cdr st-entry)) + (raise-frame (cdr st-entry)) ; gwm/empty.gwm/emacs-19.28 pblm??? + (if redraw (establish-room room))) + (establish-room room)))) + +(defun rooms-new-query (name) + "check to see if new room or definition wanted" + (if (y-or-n-p (concat "Define a new room named " + name + "? ")) + (rooms-new name) + (message ""))) + +(defun rooms-redefine-query (name) "check to see if new room wanted" + (if (y-or-n-p (concat "Redefine the room named " + name + "? ")) + (progn (setq rooms-table (delq (or (assoc name rooms-table) + (error "shouldnt")) + rooms-table)) + (rooms-new name)) + (message ""))) + +(defun rooms-new (name) "define a new room named NAME as per the current frame" + (interactive "sroom name for current frame: ") + (let ((here (selected-window)) + (looping t) + spec top-p next all-specs) + ;; collect specs for all windows on frame, noting top one + (setq next here) + (while looping + (setq spec (window-edges next)) + (setq all-specs (cons (make-ws (buffer-name (window-buffer next)) + nil + spec) + all-specs)) + (if (= (car (cdr spec)) 0) ; check for top + (progn (setq top-p all-specs) + (setq all-specs nil))) + (setq next (previous-window next)) + (if (eq next here) + (setq looping nil))) + (setq rooms-table + (cons + (make-room name + (nconc top-p + all-specs)) + rooms-table)) + (message (concat name " defined as current frame configuration")))) + +(global-set-key "\eo" 'rooms-top) + +(defun define-rooms (spec-list) "define rooms from specs" + (let ((spp spec-list)) + (while spp + (establish-room (car spp) t) + (setq spp (cdr spp))))) + +(defun establish-room (r-spec &optional create) "define room from spec" + ;; a room-spec is of the form (name . window-specs) + ;; a window spec is of the form (buffer-name constitution . edges) + ;; a buffer-name is either a string, in which case the constitution will be + ;; left to create it, or (<string>), in which case a new buffer of that name + ;; will be generated first. + ;; a constitution is either nil, a file name to be visited, or a form + ;; to be evaluated + ;; if create is nil, buffer is not touched (constitution is ignored) + (let ((r-name (room-name r-spec)) + (w-specs (room-window-specs r-spec)) + (used -1) + w-spec st-entry) + (if create + (while w-specs + (setq w-spec (car w-specs)) + (let ((buf-name (ws-buffer-name w-spec)) + (const (ws-constitution w-spec))) + ;; initialise the buffer + (if (consp buf-name) + (set-buffer (generate-new-buffer (car buf-name)))) + (if const + (condition-case foo + (if (stringp const) + (find-file const) + (eval const)) + (error (message "%s" foo))))) + (setq w-specs (cdr w-specs)))) + (setq w-specs (room-window-specs r-spec)) + (switch-to-buffer (let ((b-n (ws-buffer-name (car w-specs)))) + (if (consp b-n) + (car b-n) + b-n))) + (delete-other-windows) + (setq w-specs (cdr w-specs)) + (while w-specs + (setq w-spec (car w-specs)) + (let ((buf-name (ws-buffer-name w-spec)) + (edges (ws-edges w-spec))) + ;; make a window of the right size + ;; we assume full-width windows for now, with specs in top-to-bottom + (let ((top (1- (car (cdr edges))))) + (split-window-vertically (- top used)) + (setq used top)) + (other-window 1) + (switch-to-buffer (if (consp buf-name) + (car buf-name) + buf-name))) + (setq w-specs (cdr w-specs))) + (if create + (setq rooms-table (nconc rooms-table (list r-spec)))))) + +(defun make-frame-for-room (&optional name xpos ypos ixpos iypos) + "prompts for room name and makes a frame for it. +Typing overrides initial suggestion, exiting completes." + (interactive) + (let ((name (or name + (prompt-for-word "Room: " (or (room-name previous-room) "") + rooms-table (if rooms-table + rooms-map)))) + room) + (if (not (setq room (assoc name rooms-table))) + (error "no room named %s" name) + (let ((last-w-edges (ws-edges (last-element (room-window-specs room)))) + (st-entry (assoc name frames-table)) + ;; assume (falsely) that new frame will be like old one + (parms (frame-parameters nil)) + (sys-name (substring (system-name) 0 + (string-match "\\." (system-name)))) + frame) + (let ((width (car (cdr (cdr last-w-edges)))) + (height (+ + (or (cdr (assoc 'menu-bar-lines parms)) 0) + 1 ; allowing 1 for mode line + (if (let ((mb (cdr (assoc 'minibuffer parms)))) + (or + (eq mb t) + (and (windowp mb) + (eq (window-frame mb) + (selected-frame))))) + 1 + 0) + (car (cdr (cdr (cdr last-w-edges)))))) + (x-slop (+ (* 2 (+ (cdr (assoc 'border-width parms)) + (cdr (assoc 'internal-border-width parms)))) + (if (cdr (assoc 'vertical-scroll-bars parms)) + 19 + 0))) + (y-slop (+ (* 2 (+ (cdr (assoc 'border-width parms)) + (cdr (assoc 'internal-border-width parms)))) + (if (cdr (assoc 'horizontal-scroll-bars parms)) + 19 + 0) + 16 ; window title bar + )) + (title + (concat name + ":" (user-login-name) + (concat "@" sys-name) + ))) + (let ((args (list + (cons 'width width) + (cons 'height height) + ;; Note that x-parse-geometry doesn't handle all position cases + (cons 'left + (if xpos + (+ (if (string-match + "^[+]" xpos) + 0 + (- + (x-display-pixel-width) + (+ (* (face-width (get-face 'default)) + width) + x-slop))) + (car (read-from-string xpos) + )) + 0)) + (cons 'top + (if ypos + (+ (if (string-match + "^[+]" ypos) + 0 + (- + (x-display-pixel-height) + (+ (* (face-height (get-face 'default)) + height) + y-slop))) + (car + (read-from-string ypos))) + 0)) + (cons 'name title)))) + (setq frame + (make-frame args)))) + (if st-entry + (rplacd st-entry frame) + (setq frames-table (cons (cons name frame) + frames-table))) + (if (or ixpos iypos) + (position-frame-icon (or ixpos + (car + (cdr + (assoc 'left + (frame-parameters frame))))) + (or iypos (car + (cdr + (assoc 'top + (frame-parameters frame))))) + frame))) + (rooms-goto room t)))) + +(defun make-screen-for-room (&optional name xpos ypos ixpos iypos) + (make-frame-for-room name xpos ypos ixpos iypos)) + +(defun position-frame-icon (x y frame) + "fiddle to get the icon for a frame in a specified place" +) + +(defun last-element (list) + "Return last element of LIST." + (let ((last nil)) + (while list + (if (null (cdr list)) + (setq last (car list))) + (setq list (cdr list))) + last + ))