Mercurial > hg > xemacs
comparison 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 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:107d592c5f4a |
|---|---|
| 1 ;;; rooms facility for gnuemacs | |
| 2 | |
| 3 ;;; Copyright Henry S. Thompson 1990 | |
| 4 | |
| 5 ;;; Last edited: Wed Sep 14 08:48:27 1994 | |
| 6 | |
| 7 ;;; v19.19 version | |
| 8 | |
| 9 (provide 'rooms) | |
| 10 (require 'prompt-for-word) | |
| 11 | |
| 12 (defvar rooms-table nil "a-list of rooms in the form (name . window-specs)") | |
| 13 | |
| 14 (defvar frames-table nil "a-list of room to frame mappings") | |
| 15 | |
| 16 (defvar rooms-map (let ((new (copy-keymap pfw-map))) | |
| 17 (define-key new "\C-r" 'minibuffer-complete-and-exit) | |
| 18 new) | |
| 19 "allow ^R as synonym for CR in prompt-for-word") | |
| 20 | |
| 21 (defmacro room-name (room) (list 'car room)) | |
| 22 (defmacro room-window-specs (room) (list 'cdr room)) | |
| 23 (defmacro make-room (name window-specs) (list 'cons name window-specs)) | |
| 24 | |
| 25 (defvar current-room nil "the current room") | |
| 26 | |
| 27 (defvar previous-room nil "the previous room") | |
| 28 | |
| 29 ;; a window spec is of the form (buffer-name constitution . edges) | |
| 30 (defmacro ws-buffer-name (ws) (list 'car ws)) | |
| 31 (defmacro ws-constitution (ws) (list 'car (list 'cdr ws))) | |
| 32 (defmacro ws-edges (ws) (list 'cdr (list 'cdr ws))) | |
| 33 (defmacro make-ws (buffer-name constitution edges) | |
| 34 (list 'cons buffer-name | |
| 35 (list 'cons constitution edges))) | |
| 36 | |
| 37 (defun rooms-top (redraw) | |
| 38 "top level for rooms - prompts for room name and goes there. | |
| 39 Prefix arg forces room's frame to its defined contents. | |
| 40 Typing overrides initial suggestion, exiting completes. To name a new room | |
| 41 exit with ^N | |
| 42 To redefine an existing room, exit with ^R" | |
| 43 (interactive "PIf prefixed, forces room's frame, if any, to its defined contents") | |
| 44 (let ((name (prompt-for-word "Room: " (or (room-name previous-room) "") | |
| 45 rooms-table (if rooms-table | |
| 46 rooms-map))) | |
| 47 (e-o-c last-input-char) | |
| 48 room) | |
| 49 (cond ((eq e-o-c 18) ; ^R | |
| 50 (rooms-redefine-query name)) | |
| 51 (t | |
| 52 (if (setq room (assoc name rooms-table)) | |
| 53 (rooms-goto room redraw) | |
| 54 (rooms-new-query name)))))) | |
| 55 | |
| 56 (defun rooms-goto (room &optional redraw) "switch frame to ROOM's config" | |
| 57 (let ((room (if (stringp room) | |
| 58 (or (assoc room rooms-table) | |
| 59 (error "No room named %s" room)) | |
| 60 room)) | |
| 61 st-entry) | |
| 62 (if (not (eq room current-room)) | |
| 63 (setq previous-room current-room)) | |
| 64 (setq current-room room) | |
| 65 ;; lazy if mapped to frame and not redraw | |
| 66 (if (setq st-entry (assoc (room-name room) frames-table)) | |
| 67 ;; very tricky -- appears to be the only order that works! | |
| 68 (progn | |
| 69 ; (focus-frame (cdr st-entry)) | |
| 70 (select-frame (cdr st-entry)) | |
| 71 (raise-frame (cdr st-entry)) ; gwm/empty.gwm/emacs-19.28 pblm??? | |
| 72 (if redraw (establish-room room))) | |
| 73 (establish-room room)))) | |
| 74 | |
| 75 (defun rooms-new-query (name) | |
| 76 "check to see if new room or definition wanted" | |
| 77 (if (y-or-n-p (concat "Define a new room named " | |
| 78 name | |
| 79 "? ")) | |
| 80 (rooms-new name) | |
| 81 (message ""))) | |
| 82 | |
| 83 (defun rooms-redefine-query (name) "check to see if new room wanted" | |
| 84 (if (y-or-n-p (concat "Redefine the room named " | |
| 85 name | |
| 86 "? ")) | |
| 87 (progn (setq rooms-table (delq (or (assoc name rooms-table) | |
| 88 (error "shouldnt")) | |
| 89 rooms-table)) | |
| 90 (rooms-new name)) | |
| 91 (message ""))) | |
| 92 | |
| 93 (defun rooms-new (name) "define a new room named NAME as per the current frame" | |
| 94 (interactive "sroom name for current frame: ") | |
| 95 (let ((here (selected-window)) | |
| 96 (looping t) | |
| 97 spec top-p next all-specs) | |
| 98 ;; collect specs for all windows on frame, noting top one | |
| 99 (setq next here) | |
| 100 (while looping | |
| 101 (setq spec (window-edges next)) | |
| 102 (setq all-specs (cons (make-ws (buffer-name (window-buffer next)) | |
| 103 nil | |
| 104 spec) | |
| 105 all-specs)) | |
| 106 (if (= (car (cdr spec)) 0) ; check for top | |
| 107 (progn (setq top-p all-specs) | |
| 108 (setq all-specs nil))) | |
| 109 (setq next (previous-window next)) | |
| 110 (if (eq next here) | |
| 111 (setq looping nil))) | |
| 112 (setq rooms-table | |
| 113 (cons | |
| 114 (make-room name | |
| 115 (nconc top-p | |
| 116 all-specs)) | |
| 117 rooms-table)) | |
| 118 (message (concat name " defined as current frame configuration")))) | |
| 119 | |
| 120 (global-set-key "\eo" 'rooms-top) | |
| 121 | |
| 122 (defun define-rooms (spec-list) "define rooms from specs" | |
| 123 (let ((spp spec-list)) | |
| 124 (while spp | |
| 125 (establish-room (car spp) t) | |
| 126 (setq spp (cdr spp))))) | |
| 127 | |
| 128 (defun establish-room (r-spec &optional create) "define room from spec" | |
| 129 ;; a room-spec is of the form (name . window-specs) | |
| 130 ;; a window spec is of the form (buffer-name constitution . edges) | |
| 131 ;; a buffer-name is either a string, in which case the constitution will be | |
| 132 ;; left to create it, or (<string>), in which case a new buffer of that name | |
| 133 ;; will be generated first. | |
| 134 ;; a constitution is either nil, a file name to be visited, or a form | |
| 135 ;; to be evaluated | |
| 136 ;; if create is nil, buffer is not touched (constitution is ignored) | |
| 137 (let ((r-name (room-name r-spec)) | |
| 138 (w-specs (room-window-specs r-spec)) | |
| 139 (used -1) | |
| 140 w-spec st-entry) | |
| 141 (if create | |
| 142 (while w-specs | |
| 143 (setq w-spec (car w-specs)) | |
| 144 (let ((buf-name (ws-buffer-name w-spec)) | |
| 145 (const (ws-constitution w-spec))) | |
| 146 ;; initialise the buffer | |
| 147 (if (consp buf-name) | |
| 148 (set-buffer (generate-new-buffer (car buf-name)))) | |
| 149 (if const | |
| 150 (condition-case foo | |
| 151 (if (stringp const) | |
| 152 (find-file const) | |
| 153 (eval const)) | |
| 154 (error (message "%s" foo))))) | |
| 155 (setq w-specs (cdr w-specs)))) | |
| 156 (setq w-specs (room-window-specs r-spec)) | |
| 157 (switch-to-buffer (let ((b-n (ws-buffer-name (car w-specs)))) | |
| 158 (if (consp b-n) | |
| 159 (car b-n) | |
| 160 b-n))) | |
| 161 (delete-other-windows) | |
| 162 (setq w-specs (cdr w-specs)) | |
| 163 (while w-specs | |
| 164 (setq w-spec (car w-specs)) | |
| 165 (let ((buf-name (ws-buffer-name w-spec)) | |
| 166 (edges (ws-edges w-spec))) | |
| 167 ;; make a window of the right size | |
| 168 ;; we assume full-width windows for now, with specs in top-to-bottom | |
| 169 (let ((top (1- (car (cdr edges))))) | |
| 170 (split-window-vertically (- top used)) | |
| 171 (setq used top)) | |
| 172 (other-window 1) | |
| 173 (switch-to-buffer (if (consp buf-name) | |
| 174 (car buf-name) | |
| 175 buf-name))) | |
| 176 (setq w-specs (cdr w-specs))) | |
| 177 (if create | |
| 178 (setq rooms-table (nconc rooms-table (list r-spec)))))) | |
| 179 | |
| 180 (defun make-frame-for-room (&optional name xpos ypos ixpos iypos) | |
| 181 "prompts for room name and makes a frame for it. | |
| 182 Typing overrides initial suggestion, exiting completes." | |
| 183 (interactive) | |
| 184 (let ((name (or name | |
| 185 (prompt-for-word "Room: " (or (room-name previous-room) "") | |
| 186 rooms-table (if rooms-table | |
| 187 rooms-map)))) | |
| 188 room) | |
| 189 (if (not (setq room (assoc name rooms-table))) | |
| 190 (error "no room named %s" name) | |
| 191 (let ((last-w-edges (ws-edges (last-element (room-window-specs room)))) | |
| 192 (st-entry (assoc name frames-table)) | |
| 193 ;; assume (falsely) that new frame will be like old one | |
| 194 (parms (frame-parameters nil)) | |
| 195 (sys-name (substring (system-name) 0 | |
| 196 (string-match "\\." (system-name)))) | |
| 197 frame) | |
| 198 (let ((width (car (cdr (cdr last-w-edges)))) | |
| 199 (height (+ | |
| 200 (or (cdr (assoc 'menu-bar-lines parms)) 0) | |
| 201 1 ; allowing 1 for mode line | |
| 202 (if (let ((mb (cdr (assoc 'minibuffer parms)))) | |
| 203 (or | |
| 204 (eq mb t) | |
| 205 (and (windowp mb) | |
| 206 (eq (window-frame mb) | |
| 207 (selected-frame))))) | |
| 208 1 | |
| 209 0) | |
| 210 (car (cdr (cdr (cdr last-w-edges)))))) | |
| 211 (x-slop (+ (* 2 (+ (cdr (assoc 'border-width parms)) | |
| 212 (cdr (assoc 'internal-border-width parms)))) | |
| 213 (if (cdr (assoc 'vertical-scroll-bars parms)) | |
| 214 19 | |
| 215 0))) | |
| 216 (y-slop (+ (* 2 (+ (cdr (assoc 'border-width parms)) | |
| 217 (cdr (assoc 'internal-border-width parms)))) | |
| 218 (if (cdr (assoc 'horizontal-scroll-bars parms)) | |
| 219 19 | |
| 220 0) | |
| 221 16 ; window title bar | |
| 222 )) | |
| 223 (title | |
| 224 (concat name | |
| 225 ":" (user-login-name) | |
| 226 (concat "@" sys-name) | |
| 227 ))) | |
| 228 (let ((args (list | |
| 229 (cons 'width width) | |
| 230 (cons 'height height) | |
| 231 ;; Note that x-parse-geometry doesn't handle all position cases | |
| 232 (cons 'left | |
| 233 (if xpos | |
| 234 (+ (if (string-match | |
| 235 "^[+]" xpos) | |
| 236 0 | |
| 237 (- | |
| 238 (x-display-pixel-width) | |
| 239 (+ (* (face-width (get-face 'default)) | |
| 240 width) | |
| 241 x-slop))) | |
| 242 (car (read-from-string xpos) | |
| 243 )) | |
| 244 0)) | |
| 245 (cons 'top | |
| 246 (if ypos | |
| 247 (+ (if (string-match | |
| 248 "^[+]" ypos) | |
| 249 0 | |
| 250 (- | |
| 251 (x-display-pixel-height) | |
| 252 (+ (* (face-height (get-face 'default)) | |
| 253 height) | |
| 254 y-slop))) | |
| 255 (car | |
| 256 (read-from-string ypos))) | |
| 257 0)) | |
| 258 (cons 'name title)))) | |
| 259 (setq frame | |
| 260 (make-frame args)))) | |
| 261 (if st-entry | |
| 262 (rplacd st-entry frame) | |
| 263 (setq frames-table (cons (cons name frame) | |
| 264 frames-table))) | |
| 265 (if (or ixpos iypos) | |
| 266 (position-frame-icon (or ixpos | |
| 267 (car | |
| 268 (cdr | |
| 269 (assoc 'left | |
| 270 (frame-parameters frame))))) | |
| 271 (or iypos (car | |
| 272 (cdr | |
| 273 (assoc 'top | |
| 274 (frame-parameters frame))))) | |
| 275 frame))) | |
| 276 (rooms-goto room t)))) | |
| 277 | |
| 278 (defun make-screen-for-room (&optional name xpos ypos ixpos iypos) | |
| 279 (make-frame-for-room name xpos ypos ixpos iypos)) | |
| 280 | |
| 281 (defun position-frame-icon (x y frame) | |
| 282 "fiddle to get the icon for a frame in a specified place" | |
| 283 ) | |
| 284 | |
| 285 (defun last-element (list) | |
| 286 "Return last element of LIST." | |
| 287 (let ((last nil)) | |
| 288 (while list | |
| 289 (if (null (cdr list)) | |
| 290 (setq last (car list))) | |
| 291 (setq list (cdr list))) | |
| 292 last | |
| 293 )) |
