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 ))