comparison lisp/prim/frame.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; frame.el --- multi-frame management independent of window systems.
2
3 ;;;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
4 ;;;; Copyright (C) 1995, 1996 Ben Wing.
5
6 ;; Maintainer: FSF
7 ;; Keywords: internal
8
9 ;; This file is part of XEmacs.
10
11 ;; XEmacs is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; XEmacs is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ;; General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with XEmacs; see the file COPYING. If not, write to the Free
23 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24
25 ;;; Synched up with: FSF 19.30.
26
27 ;;; Code:
28
29 ; No need for `frame-creation-function'.
30
31 ;;; The initial value given here for this must ask for a minibuffer.
32 ;;; There must always exist a frame with a minibuffer, and after we
33 ;;; delete the terminal frame, this will be the only frame.
34 (defvar initial-frame-plist '(minibuffer t)
35 "Plist of frame properties for creating the initial X window frame.
36 You can set this in your `.emacs' file; for example,
37 (setq initial-frame-plist '(top 1 left 1 width 80 height 55))
38 Properties specified here supersede the values given in `default-frame-plist'.
39 The format of this can also be an alist for backward compatibility.
40
41 If the value calls for a frame without a minibuffer, and you have not created
42 a minibuffer frame on your own, one is created according to
43 `minibuffer-frame-plist'.
44
45 You can specify geometry-related options for just the initial frame
46 by setting this variable in your `.emacs' file; however, they won't
47 take effect until Emacs reads `.emacs', which happens after first creating
48 the frame. If you want the frame to have the proper geometry as soon
49 as it appears, you need to use this three-step process:
50 * Specify X resources to give the geometry you want.
51 * Set `default-frame-plist' to override these options so that they
52 don't affect subsequent frames.
53 * Set `initial-frame-plist' in a way that matches the X resources,
54 to override what you put in `default-frame-plist'.")
55
56 (defvar minibuffer-frame-plist '(width 80 height 2 menubar-visible-p nil
57 default-toolbar-visible-p nil)
58 "Plist of frame properties for initially creating a minibuffer frame.
59 You can set this in your `.emacs' file; for example,
60 (setq minibuffer-frame-plist '(top 1 left 1 width 80 height 2))
61 Properties specified here supersede the values given in
62 `default-frame-plist'.
63 The format of this can also be an alist for backward compatibility.")
64
65 (defvar pop-up-frame-plist nil
66 "Plist of frame properties used when creating pop-up frames.
67 Pop-up frames are used for completions, help, and the like.
68 This variable can be set in your init file, like this:
69 (setq pop-up-frame-plist '(width 80 height 20))
70 These supersede the values given in `default-frame-plist'.
71 The format of this can also be an alist for backward compatibility.")
72
73 (setq pop-up-frame-function
74 (function (lambda ()
75 (make-frame pop-up-frame-plist))))
76
77 (defvar special-display-frame-plist '(height 14 width 80 unsplittable t)
78 "*Plist of frame properties used when creating special frames.
79 Special frames are used for buffers whose names are in
80 `special-display-buffer-names' and for buffers whose names match
81 one of the regular expressions in `special-display-regexps'.
82 This variable can be set in your init file, like this:
83 (setq special-display-frame-plist '(width 80 height 20))
84 These supersede the values given in `default-frame-plist'.
85 The format of this can also be an alist for backward compatibility.")
86
87 (defun safe-alist-to-plist (cruftiness)
88 (if (consp (car cruftiness))
89 (alist-to-plist cruftiness)
90 cruftiness))
91
92 ;; Display BUFFER in its own frame, reusing an existing window if any.
93 ;; Return the window chosen.
94 ;; Currently we do not insist on selecting the window within its frame.
95 ;; If ARGS is a plist, use it as a list of frame property specs.
96 ;; #### Change, not compatible with FSF: This stuff is all so incredibly
97 ;; junky anyway that I doubt it makes any difference.
98 ;; If ARGS is a list whose car is t,
99 ;; use (cadr ARGS) as a function to do the work.
100 ;; Pass it BUFFER as first arg, and (cddr ARGS) gives the rest of the args.
101 (defun special-display-popup-frame (buffer &optional args)
102 ;; if we can't display simultaneous multiple frames, just return
103 ;; nil and let the normal behavior take over.
104 (and (device-on-window-system-p)
105 (if (and args (eq t (car args)))
106 (apply (cadr args) buffer (cddr args))
107 (let ((window (get-buffer-window buffer t)))
108 (if window
109 ;; If we have a window already, make it visible.
110 (let ((frame (window-frame window)))
111 (make-frame-visible frame)
112 (raise-frame frame)
113 window)
114 ;; If no window yet, make one in a new frame.
115 (let ((frame
116 (make-frame (append (safe-alist-to-plist args)
117 (safe-alist-to-plist
118 special-display-frame-plist)))))
119 (set-window-buffer (frame-selected-window frame) buffer)
120 (set-window-dedicated-p (frame-selected-window frame) t)
121 (frame-selected-window frame)))))))
122
123 (setq special-display-function 'special-display-popup-frame)
124
125 ;;; Handle delete-frame events from the X server.
126 ;(defun handle-delete-frame (event)
127 ; (interactive "e")
128 ; (let ((frame (posn-window (event-start event)))
129 ; (i 0)
130 ; (tail (frame-list)))
131 ; (while tail
132 ; (and (frame-visible-p (car tail))
133 ; (not (eq (car tail) frame))
134 ; (setq i (1+ i)))
135 ; (setq tail (cdr tail)))
136 ; (if (> i 0)
137 ; (delete-frame frame t)
138 ; (kill-emacs))))
139
140
141 ;;;; Arrangement of frames at startup
142
143 ;;; 1) Load the window system startup file from the lisp library and read the
144 ;;; high-priority arguments (-q and the like). The window system startup
145 ;;; file should create any frames specified in the window system defaults.
146 ;;;
147 ;;; 2) If no frames have been opened, we open an initial text frame.
148 ;;;
149 ;;; 3) Once the init file is done, we apply any newly set properties
150 ;;; in initial-frame-plist to the frame.
151
152 ;; These are now called explicitly at the proper times,
153 ;; since that is easier to understand.
154 ;; Actually using hooks within Emacs is bad for future maintenance. --rms.
155 ;; (add-hook 'before-init-hook 'frame-initialize)
156 ;; (add-hook 'window-setup-hook 'frame-notice-user-settings)
157
158 ;;; If we create the initial frame, this is it.
159 (defvar frame-initial-frame nil)
160
161 ;; Record the properties used in frame-initialize to make the initial frame.
162 (defvar frame-initial-frame-plist)
163
164 (defvar frame-initial-geometry-arguments nil)
165
166 (defun canonicalize-frame-plists ()
167 (setq initial-frame-plist (safe-alist-to-plist initial-frame-plist))
168 (setq default-frame-plist (safe-alist-to-plist default-frame-plist)))
169
170 ;;; startup.el calls this function before loading the user's init
171 ;;; file - if there is no frame with a minibuffer open now, create
172 ;;; one to display messages while loading the init file.
173 (defun frame-initialize ()
174 ;; In batch mode, we actually use the initial terminal device for output.
175 (canonicalize-frame-plists)
176 (if (not (noninteractive))
177 (progn
178 ;; Don't call select-frame here - focus is a matter of WM policy.
179
180 ;; If there is no frame with a minibuffer besides the terminal
181 ;; frame, then we need to create the opening frame. Make sure
182 ;; it has a minibuffer, but let initial-frame-plist omit the
183 ;; minibuffer spec.
184 (or (delq terminal-frame (minibuffer-frame-list))
185 (progn
186 (setq frame-initial-frame-plist
187 (append initial-frame-plist default-frame-plist))
188 ;; FSFmacs has scroll-bar junk here that we don't need.
189 (setq default-minibuffer-frame
190 (setq frame-initial-frame
191 (make-frame initial-frame-plist
192 (car (delq terminal-device
193 (device-list))))))
194 ;; Delete any specifications for window geometry properties
195 ;; so that we won't reapply them in frame-notice-user-settings.
196 ;; It would be wrong to reapply them then,
197 ;; because that would override explicit user resizing.
198 (setq initial-frame-plist
199 (frame-remove-geometry-props initial-frame-plist))))
200 ;; At this point, we know that we have a frame open, so we
201 ;; can delete the terminal device.
202 (delete-device terminal-device)
203 (setq terminal-frame nil)
204
205 ;; FSFmacs sets frame-creation-function here, but no need.
206 )))
207
208 ;;; startup.el calls this function after loading the user's init
209 ;;; file. Now default-frame-plist and initial-frame-plist contain
210 ;;; information to which we must react; do what needs to be done.
211 (defun frame-notice-user-settings ()
212
213 ;; FSFmacs has menu-bar junk here that we don't need.
214
215 (canonicalize-frame-plists)
216
217 ;; Creating and deleting frames may shift the selected frame around,
218 ;; and thus the current buffer. Protect against that. We don't
219 ;; want to use save-excursion here, because that may also try to set
220 ;; the buffer of the selected window, which fails when the selected
221 ;; window is the minibuffer.
222 (let ((old-buffer (current-buffer)))
223
224 ;; If the initial frame is still around, apply initial-frame-plist
225 ;; and default-frame-plist to it.
226 (if (frame-live-p frame-initial-frame)
227
228 ;; The initial frame we create above always has a minibuffer.
229 ;; If the user wants to remove it, or make it a minibuffer-only
230 ;; frame, then we'll have to delete the current frame and make a
231 ;; new one; you can't remove or add a root window to/from an
232 ;; existing frame.
233 ;;
234 ;; NOTE: default-frame-plist was nil when we created the
235 ;; existing frame. We need to explicitly include
236 ;; default-frame-plist in the properties of the screen we
237 ;; create here, so that its new value, gleaned from the user's
238 ;; .emacs file, will be applied to the existing screen.
239 (if (not (eq (car
240 (or (and (lax-plist-member
241 initial-frame-plist 'minibuffer)
242 (list (lax-plist-get initial-frame-plist
243 'minibuffer)))
244 (and (lax-plist-member default-frame-plist
245 'minibuffer)
246 (list (lax-plist-get default-frame-plist
247 'minibuffer)))
248 '(t)))
249 t))
250 ;; Create the new frame.
251 (let (props
252 )
253 ;; If the frame isn't visible yet, wait till it is.
254 ;; If the user has to position the window,
255 ;; Emacs doesn't know its real position until
256 ;; the frame is seen to be visible.
257
258 (if (frame-property frame-initial-frame 'initially-unmapped)
259 nil
260 (while (not (frame-visible-p frame-initial-frame))
261 (sleep-for 1)))
262 (setq props (frame-properties frame-initial-frame))
263 ;; Get rid of `name' unless it was specified explicitly before.
264 (or (lax-plist-member frame-initial-frame-plist 'name)
265 (setq props (lax-plist-remprop props 'name)))
266 (setq props (append initial-frame-plist default-frame-plist
267 props
268 nil))
269 ;; Get rid of `reverse', because that was handled
270 ;; when we first made the frame.
271 (laxputf props 'reverse nil)
272 ;; Get rid of `window-id', otherwise make-frame will
273 ;; think we're trying to setup an external widget.
274 (laxremf props 'window-id)
275 (if (lax-plist-member frame-initial-geometry-arguments 'height)
276 (laxremf props 'height))
277 (if (lax-plist-member frame-initial-geometry-arguments 'width)
278 (laxremf props 'width))
279 (if (lax-plist-member frame-initial-geometry-arguments 'left)
280 (laxremf props 'left))
281 (if (lax-plist-member frame-initial-geometry-arguments 'top)
282 (laxremf props 'top))
283
284 ;; Now create the replacement initial frame.
285 (make-frame
286 ;; Use the geometry args that created the existing
287 ;; frame, rather than the props we get for it.
288 (append '(user-size t user-position t)
289 frame-initial-geometry-arguments
290 props))
291 ;; The initial frame, which we are about to delete, may be
292 ;; the only frame with a minibuffer. If it is, create a
293 ;; new one.
294 (or (delq frame-initial-frame (minibuffer-frame-list))
295 (make-initial-minibuffer-frame nil))
296
297 ;; If the initial frame is serving as a surrogate
298 ;; minibuffer frame for any frames, we need to wean them
299 ;; onto a new frame. The default-minibuffer-frame
300 ;; variable must be handled similarly.
301 (let ((users-of-initial
302 (filtered-frame-list
303 #'(lambda (frame)
304 (and (not (eq frame frame-initial-frame))
305 (eq (window-frame
306 (minibuffer-window frame))
307 frame-initial-frame))))))
308 (if (or users-of-initial
309 (eq default-minibuffer-frame frame-initial-frame))
310
311 ;; Choose an appropriate frame. Prefer frames which
312 ;; are only minibuffers.
313 (let* ((new-surrogate
314 (car
315 (or (filtered-frame-list
316 #'(lambda (frame)
317 (eq 'only
318 (frame-property frame 'minibuffer))))
319 (minibuffer-frame-list))))
320 (new-minibuffer (minibuffer-window new-surrogate)))
321
322 (if (eq default-minibuffer-frame frame-initial-frame)
323 (setq default-minibuffer-frame new-surrogate))
324
325 ;; Wean the frames using frame-initial-frame as
326 ;; their minibuffer frame.
327 (mapcar
328 #'
329 (lambda (frame)
330 (set-frame-property frame 'minibuffer
331 new-minibuffer))
332 users-of-initial))))
333
334 ;; Redirect events enqueued at this frame to the new frame.
335 ;; Is this a good idea?
336 ;; Probably not, since this whole redirect-frame-focus
337 ;; stuff is a load of trash, and so is this function we're in.
338 ;; --ben
339 ;(redirect-frame-focus frame-initial-frame new)
340
341 ;; Finally, get rid of the old frame.
342 (delete-frame frame-initial-frame t))
343
344 ;; Otherwise, we don't need all that rigamarole; just apply
345 ;; the new properties.
346 (let (newprops allprops tail)
347 (setq allprops (append initial-frame-plist
348 default-frame-plist))
349 (if (lax-plist-member frame-initial-geometry-arguments 'height)
350 (laxremf allprops 'height))
351 (if (lax-plist-member frame-initial-geometry-arguments 'width)
352 (remf allprops 'width))
353 (if (lax-plist-member frame-initial-geometry-arguments 'left)
354 (laxremf allprops 'left))
355 (if (lax-plist-member frame-initial-geometry-arguments 'top)
356 (laxremf allprops 'top))
357 (setq tail allprops)
358 ;; Find just the props that have changed since we first
359 ;; made this frame. Those are the ones actually set by
360 ;; the init file. For those props whose values we already knew
361 ;; (such as those spec'd by command line options)
362 ;; it is undesirable to specify the parm again
363 ;; once the user has seen the frame and been able to alter it
364 ;; manually.
365 (while tail
366 (let (newval oldval)
367 (setq oldval (lax-plist-get frame-initial-frame-plist
368 (car tail)))
369 (setq newval (lax-plist-get allprops (car tail)))
370 (or (eq oldval newval)
371 (laxputf newprops (car tail) newval)))
372 (setq tail (cddr tail)))
373 (set-frame-properties frame-initial-frame newprops)
374 ;silly FSFmacs junk
375 ;if (lax-plist-member newprops 'font)
376 ; (frame-update-faces frame-initial-frame))
377
378 )))
379
380 ;; Restore the original buffer.
381 (set-buffer old-buffer)
382
383 ;; Make sure the initial frame can be GC'd if it is ever deleted.
384 ;; Make sure frame-notice-user-settings does nothing if called twice.
385 (setq frame-initial-frame nil)))
386
387 (defun make-initial-minibuffer-frame (device)
388 (let ((props (append '(minibuffer only)
389 (safe-alist-to-plist minibuffer-frame-plist))))
390 (make-frame props device)))
391
392
393 ;;;; Creation of additional frames, and other frame miscellanea
394
395 (defun get-other-frame ()
396 "Return some frame other than the current frame, creating one if necessary."
397 (let* ((this (selected-frame))
398 ;; search visible frames first
399 (next (next-frame this 'visible-nomini)))
400 ;; then search iconified frames
401 (if (eq this next)
402 (setq next (next-frame 'visible-iconic-nomini)))
403 (if (eq this next)
404 ;; otherwise, make a new frame
405 (make-frame)
406 next)))
407
408 (defun next-multiframe-window ()
409 "Select the next window, regardless of which frame it is on."
410 (interactive)
411 (select-window (next-window (selected-window)
412 (> (minibuffer-depth) 0)
413 t)))
414
415 (defun previous-multiframe-window ()
416 "Select the previous window, regardless of which frame it is on."
417 (interactive)
418 (select-window (previous-window (selected-window)
419 (> (minibuffer-depth) 0)
420 t)))
421
422 (defun make-frame-on-device (type connection &optional props)
423 "Create a frame of type TYPE on CONNECTION.
424 TYPE should be a symbol naming the device type, i.e. one of
425
426 x An X display. CONNECTION should be a standard display string
427 such as \"unix:0\", or nil for the display specified on the
428 command line or in the DISPLAY environment variable. Only if
429 support for X was compiled into XEmacs.
430 tty A standard TTY connection or terminal. CONNECTION should be
431 a TTY device name such as \"/dev/ttyp2\" (as determined by
432 the Unix command `tty') or nil for XEmacs' standard input
433 and output (usually the TTY in which XEmacs started). Only
434 if support for TTY's was compiled into XEmacs.
435 ns A connection to a machine running the NeXTstep windowing
436 system. Not currently implemented.
437 win32 A connection to a machine running Microsoft Windows NT or
438 Windows 95. Not currently implemented.
439 pc A direct-write MS-DOS frame. Not currently implemented.
440
441 PROPS should be an plist of properties, as in the call to `make-frame'.
442
443 If a connection to CONNECTION already exists, it is reused; otherwise,
444 a new connection is opened."
445 (make-frame props (make-device type connection props)))
446
447 ;; Alias, kept temporarily.
448 (defalias 'new-frame 'make-frame)
449
450 ; FSFmacs has make-frame here. We have it in C, so no need for
451 ; frame-creation-function.
452
453 (defun filtered-frame-list (predicate &optional device)
454 "Return a list of all live frames which satisfy PREDICATE.
455 If optional second arg DEVICE is non-nil, restrict the frames
456 returned to that device."
457 (let ((frames (if device (device-frame-list device)
458 (frame-list)))
459 good-frames)
460 (while (consp frames)
461 (if (funcall predicate (car frames))
462 (setq good-frames (cons (car frames) good-frames)))
463 (setq frames (cdr frames)))
464 good-frames))
465
466 (defun minibuffer-frame-list (&optional device)
467 "Return a list of all frames with their own minibuffers.
468 If optional second arg DEVICE is non-nil, restrict the frames
469 returned to that device."
470 (filtered-frame-list
471 #'(lambda (frame)
472 (eq frame (window-frame (minibuffer-window frame))))
473 device))
474
475 (defun frame-minibuffer-only-p (frame)
476 "Return non-nil if FRAME is a minibuffer-only frame."
477 (eq (frame-root-window frame) (minibuffer-window frame)))
478
479 (defun frame-remove-geometry-props (plist)
480 "Return the property list PLIST, but with geometry specs removed.
481 This deletes all bindings in PLIST for `top', `left', `width',
482 `height', `user-size' and `user-position' properties.
483 Emacs uses this to avoid overriding explicit moves and resizings from
484 the user during startup."
485 (setq plist (canonicalize-lax-plist (copy-sequence plist)))
486 (mapcar #'(lambda (propname)
487 (if (lax-plist-member plist propname)
488 (progn
489 (setq frame-initial-geometry-arguments
490 (cons propname
491 (cons (lax-plist-get plist propname)
492 frame-initial-geometry-arguments)))
493 (setq plist (lax-plist-remprop plist propname)))))
494 '(height width top left user-size user-position))
495 plist)
496
497 (defun other-frame (arg)
498 "Select the ARG'th different visible frame, and raise it.
499 All frames are arranged in a cyclic order.
500 This command selects the frame ARG steps away in that order.
501 A negative ARG moves in the opposite order."
502 (interactive "p")
503 (let ((frame (selected-frame)))
504 (while (> arg 0)
505 (setq frame (next-frame frame 'visible-nomini))
506 (setq arg (1- arg)))
507 (while (< arg 0)
508 (setq frame (previous-frame frame 'visible-nomini))
509 (setq arg (1+ arg)))
510 (raise-frame frame)
511 (select-frame frame)
512 ;this is a bad idea; you should in general never warp the
513 ;pointer unless the user asks for this. Furthermore,
514 ;our version of `set-mouse-position' takes a window,
515 ;not a frame.
516 ;(set-mouse-position (selected-frame) (1- (frame-width)) 0)
517 ;some weird FSFmacs randomness
518 ;(if (fboundp 'unfocus-frame)
519 ; (unfocus-frame))))
520 ))
521
522 ;; XEmacs-added utility functions
523
524 ; this is in C in FSFmacs
525 (defun frame-list ()
526 "Return a list of all frames on all devices/consoles."
527 (apply 'append (mapcar 'device-frame-list (device-list))))
528
529 (defun frame-type (&optional frame)
530 "Return the type of the specified frame (e.g. `x' or `tty').
531 This is equivalent to the type of the frame's device.
532 Value is `tty' for a tty frame (a character-only terminal),
533 `x' for a frame that is an X window,
534 `ns' for a frame that is a NeXTstep window (not yet implemeted),
535 `win32' for a frame that is a Windows or Windows NT window (not yet
536 implemented),
537 `pc' for a frame that is a direct-write MS-DOS frame (not yet implemented),
538 `stream' for a stream frame (which acts like a stdio stream), and
539 `dead' for a deleted frame."
540 (or frame (setq frame (selected-frame)))
541 (if (not (frame-live-p frame)) 'dead
542 (device-type (frame-device frame))))
543
544 (defun device-or-frame-p (object)
545 "Return non-nil if OBJECT is a device or frame."
546 (or (devicep object)
547 (framep object)))
548
549 (defun device-or-frame-type (device-or-frame)
550 "Return the type (e.g. `x' or `tty') of DEVICE-OR-FRAME.
551 DEVICE-OR-FRAME should be a device or a frame object. See `device-type'
552 for a description of the possible types."
553 (if (devicep device-or-frame)
554 (device-type device-or-frame)
555 (frame-type device-or-frame)))
556
557 (defun fw-frame (obj)
558 "Given a frame or window, return the associated frame.
559 Return nil otherwise."
560 (cond ((windowp obj) (window-frame obj))
561 ((framep obj) obj)
562 (t nil)))
563
564
565 ;;;; Frame configurations
566
567 (defun current-frame-configuration ()
568 "Return a list describing the positions and states of all frames.
569 Its car is `frame-configuration'.
570 Each element of the cdr is a list of the form (FRAME PLIST WINDOW-CONFIG),
571 where
572 FRAME is a frame object,
573 PLIST is a property list specifying some of FRAME's properties, and
574 WINDOW-CONFIG is a window configuration object for FRAME."
575 (cons 'frame-configuration
576 (mapcar (function
577 (lambda (frame)
578 (list frame
579 (frame-properties frame)
580 (current-window-configuration frame))))
581 (frame-list))))
582
583 (defun set-frame-configuration (configuration &optional nodelete)
584 "Restore the frames to the state described by CONFIGURATION.
585 Each frame listed in CONFIGURATION has its position, size, window
586 configuration, and other properties set as specified in CONFIGURATION.
587 Ordinarily, this function deletes all existing frames not
588 listed in CONFIGURATION. But if optional second argument NODELETE
589 is given and non-nil, the unwanted frames are iconified instead."
590 (or (frame-configuration-p configuration)
591 (signal 'wrong-type-argument
592 (list 'frame-configuration-p configuration)))
593 (let ((config-plist (cdr configuration))
594 frames-to-delete)
595 (mapcar (function
596 (lambda (frame)
597 (let ((properties (assq frame config-plist)))
598 (if properties
599 (progn
600 (set-frame-properties
601 frame
602 ;; Since we can't set a frame's minibuffer status,
603 ;; we might as well omit the parameter altogether.
604 (lax-plist-remprop (nth 1 properties) 'minibuffer))
605 (set-window-configuration (nth 2 properties)))
606 (setq frames-to-delete (cons frame frames-to-delete))))))
607 (frame-list))
608 (if nodelete
609 ;; Note: making frames invisible here was tried
610 ;; but led to some strange behavior--each time the frame
611 ;; was made visible again, the window manager asked afresh
612 ;; for where to put it.
613 (mapcar 'iconify-frame frames-to-delete)
614 (mapcar 'delete-frame frames-to-delete))))
615
616 ; this function is in subr.el in FSFmacs.
617 ; that's because they don't always include frame.el, while we do.
618
619 (defun frame-configuration-p (object)
620 "Return non-nil if OBJECT seems to be a frame configuration.
621 Any list whose car is `frame-configuration' is assumed to be a frame
622 configuration."
623 (and (consp object)
624 (eq (car object) 'frame-configuration)))
625
626
627 ;; FSFmacs has functions `frame-width', `frame-height' here.
628 ;; We have them in C.
629
630 ;; FSFmacs has weird functions `set-default-font', `set-background-color',
631 ;; `set-foreground-color' here. They don't do sensible things like
632 ;; set faces; instead they set frame properties (??!!) and call
633 ;; useless functions such as `frame-update-faces' and
634 ;; `frame-update-face-colors'.
635
636 ;; FSFmacs has functions `set-cursor-color', `set-mouse-color', and
637 ;; `set-border-color', which refer to frame properties.
638 ;; #### We need to use specifiers here.
639
640 ;(defun auto-raise-mode (arg)
641 ; "Toggle whether or not the selected frame should auto-raise.
642 ;With arg, turn auto-raise mode on if and only if arg is positive.
643 ;Note that this controls Emacs's own auto-raise feature.
644 ;Some window managers allow you to enable auto-raise for certain windows.
645 ;You can use that for Emacs windows if you wish, but if you do,
646 ;that is beyond the control of Emacs and this command has no effect on it."
647 ; (interactive "P")
648 ; (if (null arg)
649 ; (setq arg
650 ; (if (frame-property (selected-frame) 'auto-raise)
651 ; -1 1)))
652 ; (set-frame-property (selected-frame) 'auto-raise (> arg 0)))
653
654 ;(defun auto-lower-mode (arg)
655 ; "Toggle whether or not the selected frame should auto-lower.
656 ;With arg, turn auto-lower mode on if and only if arg is positive.
657 ;Note that this controls Emacs's own auto-lower feature.
658 ;Some window managers allow you to enable auto-lower for certain windows.
659 ;You can use that for Emacs windows if you wish, but if you do,
660 ;that is beyond the control of Emacs and this command has no effect on it."
661 ; (interactive "P")
662 ; (if (null arg)
663 ; (setq arg
664 ; (if (frame-property (selected-frame) 'auto-lower)
665 ; -1 1)))
666 ; (set-frame-property (selected-frame) 'auto-lower (> arg 0)))
667
668 ;; FSFmacs has silly functions `toggle-scroll-bar',
669 ;; `toggle-horizontal-scrollbar'
670
671 ;;; Iconifying emacs.
672 ;;;
673 ;;; The function iconify-emacs replaces every non-iconified emacs window
674 ;;; with a *single* icon. Iconified emacs windows are left alone. When
675 ;;; emacs is in this globally-iconified state, de-iconifying any emacs icon
676 ;;; will uniconify all frames that were visible, and iconify all frames
677 ;;; that were not. This is done by temporarily changing the value of
678 ;;; `map-frame-hook' to `deiconify-emacs' (which should never be called
679 ;;; except from the map-frame-hook while emacs is iconified).
680 ;;;
681 ;;; The title of the icon representing all emacs frames is controlled by
682 ;;; the variable `icon-name'. This is done by temporarily changing the
683 ;;; value of `frame-icon-title-format'. Unfortunately, this changes the
684 ;;; titles of all emacs icons, not just the "big" icon.
685 ;;;
686 ;;; It would be nice if existing icons were removed and restored by
687 ;;; iconifying the emacs process, but I couldn't make that work yet.
688
689 (defvar icon-name nil) ; set this at run time, not load time.
690
691 (defvar iconification-data nil)
692
693 (defun iconify-emacs ()
694 "Replace every non-iconified FRAME with a *single* icon.
695 Iconified frames are left alone. When XEmacs is in this
696 globally-iconified state, de-iconifying any emacs icon will uniconify
697 all frames that were visible, and iconify all frames that were not."
698 (interactive)
699 (if iconification-data (error "already iconified?"))
700 (let* ((frames (frame-list))
701 (rest frames)
702 (me (selected-frame))
703 frame)
704 (while rest
705 (setq frame (car rest))
706 (setcar rest (cons frame (frame-visible-p frame)))
707 ; (if (memq (cdr (car rest)) '(icon nil))
708 ; (progn
709 ; (make-frame-visible frame) ; deiconify, and process the X event
710 ; (sleep-for 500 t) ; process X events; I really want to XSync() here
711 ; ))
712 (or (eq frame me) (make-frame-invisible frame))
713 (setq rest (cdr rest)))
714 (or (boundp 'map-frame-hook) (setq map-frame-hook nil))
715 (or icon-name
716 (setq icon-name (concat invocation-name " @ " (system-name))))
717 (setq iconification-data
718 (list frame-icon-title-format map-frame-hook frames)
719 frame-icon-title-format icon-name
720 map-frame-hook 'deiconify-emacs)
721 (iconify-frame me)))
722
723 (defun deiconify-emacs (&optional ignore)
724 (or iconification-data (error "not iconified?"))
725 (setq frame-icon-title-format (car iconification-data)
726 map-frame-hook (car (cdr iconification-data))
727 iconification-data (car (cdr (cdr iconification-data))))
728 (while iconification-data
729 (let ((visibility (cdr (car iconification-data))))
730 (cond ((eq visibility 't)
731 (make-frame-visible (car (car iconification-data))))
732 ; (t ;; (eq visibility 'icon)
733 ; (make-frame-visible (car (car iconification-data)))
734 ; (sleep-for 500 t) ; process X events; I really want to XSync() here
735 ; (iconify-frame (car (car iconification-data))))
736 ;; (t nil)
737 ))
738 (setq iconification-data (cdr iconification-data))))
739
740 (defun suspend-or-iconify-emacs ()
741 "Calls iconify-emacs if frame is an X frame, otherwise calls suspend-emacs"
742 (interactive)
743 (if (eq (frame-type (selected-frame)) 'x)
744 (iconify-emacs)
745 (suspend-emacs)))
746
747
748 ;;; auto-raise and auto-lower
749
750 (defvar auto-raise-frame nil
751 "*If true, frames will be raised to the top when selected.
752 Under X, most ICCCM-compliant window managers will have an option to do this
753 for you, but this variable is provided in case you're using a broken WM.")
754
755 (defvar auto-lower-frame nil
756 "*If true, frames will be lowered to the bottom when no longer selected.
757 Under X, most ICCCM-compliant window managers will have an option to do this
758 for you, but this variable is provided in case you're using a broken WM.")
759
760 (defun default-select-frame-hook ()
761 "Implements the `auto-raise-frame' variable.
762 For use as the value of `select-frame-hook'."
763 (if auto-raise-frame (raise-frame (selected-frame))))
764
765 (defun default-deselect-frame-hook ()
766 "Implements the `auto-lower-frame' variable.
767 For use as the value of `deselect-frame-hook'."
768 (if auto-lower-frame (lower-frame (selected-frame))))
769
770 (or select-frame-hook
771 (add-hook 'select-frame-hook 'default-select-frame-hook))
772
773 (or deselect-frame-hook
774 (add-hook 'deselect-frame-hook 'default-deselect-frame-hook))
775
776 (defun default-drag-and-drop-functions (frame filepath)
777 "Implements the `drag-and-drop-functions' variable.
778 For use as the value of `drag-and-drop-functions'.
779 This default simply pops up the file in the selected frame."
780 (let ((x pop-up-windows))
781 (setq pop-up-windows nil)
782 (pop-to-buffer (find-file-noselect filepath) nil frame)
783 (make-frame-visible frame)
784 (setq pop-up-windows x)))
785
786 (and (boundp 'drag-and-drop-functions)
787 (or drag-and-drop-functions
788 (add-hook 'drag-and-drop-functions 'default-drag-and-drop-functions)))
789
790
791 ;;; Application-specific frame-management
792
793 (defvar get-frame-for-buffer-default-frame-name nil
794 "The default frame to select; see doc of `get-frame-for-buffer'.")
795
796 (defvar get-frame-for-buffer-default-instance-limit nil)
797
798 (defun get-frame-name-for-buffer (buffer)
799 (let ((mode (and (get-buffer buffer)
800 (save-excursion (set-buffer buffer)
801 major-mode))))
802 (or (get mode 'frame-name)
803 get-frame-for-buffer-default-frame-name)))
804
805
806 (defun get-frame-for-buffer-make-new-frame (buffer &optional frame-name)
807 (let* ((fr (make-frame (and frame-name (list (cons 'name frame-name)))))
808 (w (frame-root-window fr)))
809 ;;
810 ;; Make the one buffer being displayed in this newly created
811 ;; frame be the buffer of interest, instead of something
812 ;; random, so that it won't be shown in two-window mode.
813 ;; Avoid calling switch-to-buffer here, since that's something
814 ;; people might want to call this routine from.
815 ;;
816 ;; (If the root window doesn't have a buffer, then that means
817 ;; there is more than one window on the frame, which can only
818 ;; happen if the user has done something funny on the frame-
819 ;; creation-hook. If that's the case, leave it alone.)
820 ;;
821 (if (window-buffer w)
822 (set-window-buffer w buffer))
823 fr))
824
825 (defun get-frame-for-buffer-noselect (buffer
826 &optional not-this-window-p on-frame)
827 "Return a frame in which to display BUFFER.
828 This is a subroutine of `get-frame-for-buffer' (which see)."
829 (let (name limit)
830 (cond
831 ((or on-frame (eq (selected-window) (minibuffer-window)))
832 ;; don't switch frames if a frame was specified, or to list
833 ;; completions from the minibuffer, etc.
834 nil)
835
836 ((setq name (get-frame-name-for-buffer buffer))
837 ;;
838 ;; This buffer's mode expressed a preference for a frame of a particular
839 ;; name. That always takes priority.
840 ;;
841 (let ((limit (get name 'instance-limit))
842 (matching-frames '())
843 frames frame already-visible)
844 ;; Sort the list so that iconic frames will be found last. They
845 ;; will be used too, but mapped frames take precedence. And
846 ;; fully visible frames come before occluded frames.
847 (setq frames
848 (sort (frame-list)
849 #'(lambda (s1 s2)
850 (cond ((frame-totally-visible-p s2)
851 nil)
852 ((not (frame-visible-p s2))
853 (frame-visible-p s1))
854 ((not (frame-totally-visible-p s2))
855 (and (frame-visible-p s1)
856 (frame-totally-visible-p s1)))))))
857 ;; but the selected frame should come first, even if it's occluded,
858 ;; to minimize thrashing.
859 (setq frames (cons (selected-frame)
860 (delq (selected-frame) frames)))
861
862 (setq name (symbol-name name))
863 (while frames
864 (setq frame (car frames))
865 (if (equal name (frame-name frame))
866 (if (get-buffer-window buffer frame)
867 (setq already-visible frame
868 frames nil)
869 (setq matching-frames (cons frame matching-frames))))
870 (setq frames (cdr frames)))
871 (cond (already-visible
872 already-visible)
873 ((or (null matching-frames)
874 (eq limit 0) ; means create with reckless abandon
875 (and limit (< (length matching-frames) limit)))
876 (get-frame-for-buffer-make-new-frame buffer name))
877 (t
878 ;; do not switch any of the window/buffer associations in an
879 ;; existing frame; this function only picks a frame; the
880 ;; determination of which windows on it get reused is up to
881 ;; display-buffer itself.
882 ;; (or (window-dedicated-p (selected-window))
883 ;; (switch-to-buffer buffer))
884 (car matching-frames)))))
885
886 ((setq limit get-frame-for-buffer-default-instance-limit)
887 ;;
888 ;; This buffer's mode did not express a preference for a frame of a
889 ;; particular name, but the user wants a new frame rather than
890 ;; reusing the existing one.
891 (let* ((defname
892 (or (plist-get default-frame-plist 'name)
893 default-frame-name))
894 (frames
895 (sort (filtered-frame-list #'(lambda (x)
896 (or (frame-visible-p x)
897 (frame-iconified-p x))))
898 #'(lambda (s1 s2)
899 (cond ((and (frame-visible-p s1)
900 (not (frame-visible-p s2))))
901 ((and (frame-visible-p s2)
902 (not (frame-visible-p s1)))
903 nil)
904 ((and (equal (frame-name s1) defname)
905 (not (equal (frame-name s2) defname))))
906 ((and (equal (frame-name s2) defname)
907 (not (equal (frame-name s1) defname)))
908 nil)
909 ((frame-totally-visible-p s2)
910 nil)
911 (t))))))
912 ;; put the selected frame last. The user wants a new frame,
913 ;; so don't reuse the existing one unless forced to.
914 (setq frames (append (delq (selected-frame) frames) (list frames)))
915 (if (or (eq limit 0) ; means create with reckless abandon
916 (< (length frames) limit))
917 (get-frame-for-buffer-make-new-frame buffer)
918 (car frames))))
919
920 (t
921 ;;
922 ;; This buffer's mode did not express a preference for a frame of a
923 ;; particular name. So try to find a frame already displaying this
924 ;; buffer.
925 ;;
926 (let ((w (or (get-buffer-window buffer 'visible) ; check visible first
927 (get-buffer-window buffer 0)))) ; then iconic
928 (cond ((null w)
929 ;; It's not in any window - return nil, meaning no frame has
930 ;; preference.
931 nil)
932 ((and not-this-window-p
933 (eq (selected-frame) (window-frame w)))
934 ;; It's in a window, but on this frame, and we have been
935 ;; asked to pick another window. Return nil, meaning no
936 ;; frame has preference.
937 nil)
938 (t
939 ;; Otherwise, return the frame of the buffer's window.
940 (window-frame w))))))))
941
942
943 ;; The pre-display-buffer-function is called for effect, so this needs to
944 ;; actually select the frame it wants. Fdisplay_buffer() takes notice of
945 ;; changes to the selected frame.
946 (defun get-frame-for-buffer (buffer &optional not-this-window-p on-frame)
947 "Select and return a frame in which to display BUFFER.
948 Normally, the buffer will simply be displayed in the current frame.
949 But if the symbol naming the major-mode of the buffer has a 'frame-name
950 property (which should be a symbol), then the buffer will be displayed in
951 a frame of that name. If there is no frame of that name, then one is
952 created.
953
954 If the major-mode doesn't have a 'frame-name property, then the frame
955 named by `get-frame-for-buffer-default-frame-name' will be used. If
956 that is nil (the default) then the currently selected frame will used.
957
958 If the frame-name symbol has an 'instance-limit property (an integer)
959 then each time a buffer of the mode in question is displayed, a new frame
960 with that name will be created, until there are `instance-limit' of them.
961 If instance-limit is 0, then a new frame will be created each time.
962
963 If a buffer is already displayed in a frame, then `instance-limit' is
964 ignored, and that frame is used.
965
966 If the frame-name symbol has a 'frame-defaults property, then that is
967 prepended to the `default-frame-plist' when creating a frame for the
968 first time.
969
970 This function may be used as the value of `pre-display-buffer-function',
971 to cause the display-buffer function and its callers to exhibit the above
972 behavior."
973 (let ((frame (get-frame-for-buffer-noselect
974 buffer not-this-window-p on-frame)))
975 (if (not (eq frame (selected-frame)))
976 frame
977 (select-frame frame)
978 (or (frame-visible-p frame)
979 ;; If the frame was already visible, just focus on it.
980 ;; If it wasn't visible (it was just created, or it used
981 ;; to be iconified) then uniconify, raise, etc.
982 (make-frame-visible frame))
983 frame)))
984
985 (defun frames-of-buffer (&optional buffer visible-only)
986 "Return list of frames that BUFFER is currently being displayed on.
987 If the buffer is being displayed on the currently selected frame, that frame
988 is first in the list. VISIBLE-ONLY will only list non-iconified frames."
989 (let ((list (windows-of-buffer buffer))
990 (cur-frame (selected-frame))
991 next-frame frames save-frame)
992
993 (while list
994 (if (memq (setq next-frame (window-frame (car list)))
995 frames)
996 nil
997 (if (eq cur-frame next-frame)
998 (setq save-frame next-frame)
999 (and
1000 (or (not visible-only)
1001 (eq t (frame-visible-p next-frame)))
1002 (setq frames (append frames (list next-frame))))))
1003 (setq list (cdr list)))
1004
1005 (if save-frame
1006 (append (list save-frame) frames)
1007 frames)))
1008
1009 (defun show-temp-buffer-in-current-frame (buffer)
1010 "For use as the value of temp-buffer-show-function:
1011 always displays the buffer in the current frame, regardless of the behavior
1012 that would otherwise be introduced by the `pre-display-buffer-function', which
1013 is normally set to `get-frame-for-buffer' (which see)."
1014 (let ((pre-display-buffer-function nil)) ; turn it off, whatever it is
1015 (let ((window (display-buffer buffer)))
1016 (if (not (eq (last-nonminibuf-frame) (window-frame window)))
1017 ;; only the pre-display-buffer-function should ever do this.
1018 (error "display-buffer switched frames on its own!!"))
1019 (setq minibuffer-scroll-window window)
1020 (set-window-start window 1) ; obeys narrowing
1021 (set-window-point window 1)
1022 nil)))
1023
1024 (setq pre-display-buffer-function 'get-frame-for-buffer)
1025 (setq temp-buffer-show-function 'show-temp-buffer-in-current-frame)
1026
1027
1028 ;; from Bob Weiner <bweiner@pts.mot.com>, modified by Ben Wing
1029 (defun delete-other-frames (&optional frame)
1030 "Delete all but FRAME (or the selected frame)."
1031 (interactive)
1032 (mapcar 'delete-frame (delq (or frame (selected-frame)) (frame-list))))
1033
1034 ;; By adding primitives to directly access the window hierarchy,
1035 ;; we can move many functions into Lisp. We do it this way
1036 ;; because the implementations are simpler in Lisp, and because
1037 ;; new functions like this can be added without requiring C
1038 ;; additions.
1039
1040 (defun frame-utmost-window-2 (window position left-right-p major-end-p
1041 minor-end-p)
1042 ;; LEFT-RIGHT-P means we're looking for the leftmost or rightmost
1043 ;; window, instead of the highest or lowest. In this case, we
1044 ;; say that the "major axis" goes left-to-right instead of top-to-
1045 ;; bottom. The "minor axis" always goes perpendicularly.
1046 ;;
1047 ;; If MAJOR-END-P is t, we're looking for a windows that abut the
1048 ;; end (i.e. right or bottom) of the major axis, instead of the
1049 ;; start.
1050 ;;
1051 ;; If MINOR-END-P is t, then we want to start counting from the
1052 ;; end of the minor axis instead of the beginning.
1053 ;;
1054 ;; Here's the general idea: Imagine we're trying to count the number
1055 ;; of windows that abut the top; call this function foo(). So, we
1056 ;; start with the root window. If this is a vertical combination
1057 ;; window, then foo() applied to the root window is the same as
1058 ;; foo() applied to the first child. If the root is a horizontal
1059 ;; combination window, then foo() applied to the root is the
1060 ;; same as the sum of foo() applied to each of the children.
1061 ;; Otherwise, the root window is a leaf window, and foo() is 1.
1062 ;; Now it's clear that, each time foo() encounters a leaf window,
1063 ;; it's encountering a different window that abuts the top.
1064 ;; With a little examining, you can see that foo encounters the
1065 ;; top-abutting windows in order from left to right. We can
1066 ;; modify foo() to return the nth top-abutting window by simply
1067 ;; keeping a global variable that is decremented each time
1068 ;; foo() encounters a leaf window and would return 1. If the
1069 ;; global counter gets to zero, we've encountered the window
1070 ;; we were looking for, so we exit right away using a `throw'.
1071 ;; Otherwise, we make sure that all normal paths return nil.
1072
1073 (let (child)
1074 (cond ((setq child (if left-right-p
1075 (window-first-hchild window)
1076 (window-first-vchild window)))
1077 (if major-end-p
1078 (while (window-next-child child)
1079 (setq child (window-next-child child))))
1080 (frame-utmost-window-2 child position left-right-p major-end-p
1081 minor-end-p))
1082 ((setq child (if left-right-p
1083 (window-first-vchild window)
1084 (window-first-hchild window)))
1085 (if minor-end-p
1086 (while (window-next-child child)
1087 (setq child (window-next-child child))))
1088 (while child
1089 (frame-utmost-window-2 child position left-right-p major-end-p
1090 minor-end-p)
1091 (setq child (if minor-end-p
1092 (window-previous-child child)
1093 (window-next-child child))))
1094 nil)
1095 (t
1096 (setcar position (1- (car position)))
1097 (if (= (car position) 0)
1098 (throw 'fhw-exit window)
1099 nil)))))
1100
1101 (defun frame-utmost-window-1 (frame position left-right-p major-end-p)
1102 (let (minor-end-p)
1103 (or frame (setq frame (selected-frame)))
1104 (or position (setq position 0))
1105 (if (>= position 0)
1106 (setq position (1+ position))
1107 (setq minor-end-p t)
1108 (setq position (- position)))
1109 (catch 'fhw-exit
1110 ;; we use a cons here as a simple form of call-by-reference.
1111 ;; scheme has "boxes" for the same purpose.
1112 (frame-utmost-window-2 (frame-root-window frame) (list position)
1113 left-right-p major-end-p minor-end-p))))
1114
1115
1116 (defun frame-highest-window (&optional frame position)
1117 "Return the highest window on FRAME which is at POSITION.
1118 If omitted, FRAME defaults to the currently selected frame.
1119 POSITION is used to distinguish between multiple windows that abut
1120 the top of the frame: 0 means the leftmost window abutting the
1121 top of the frame, 1 the next-leftmost, etc. POSITION can also
1122 be less than zero: -1 means the rightmost window abutting the
1123 top of the frame, -2 the next-rightmost, etc.
1124 If omitted, POSITION defaults to 0, i.e. the leftmost highest window.
1125 If there is no window at the given POSITION, return nil."
1126 (frame-utmost-window-1 frame position nil nil))
1127
1128 (defun frame-lowest-window (&optional frame position)
1129 "Return the lowest window on FRAME which is at POSITION.
1130 If omitted, FRAME defaults to the currently selected frame.
1131 POSITION is used to distinguish between multiple windows that abut
1132 the bottom of the frame: 0 means the leftmost window abutting the
1133 bottom of the frame, 1 the next-leftmost, etc. POSITION can also
1134 be less than zero: -1 means the rightmost window abutting the
1135 bottom of the frame, -2 the next-rightmost, etc.
1136 If omitted, POSITION defaults to 0, i.e. the leftmost lowest window.
1137 If there is no window at the given POSITION, return nil."
1138 (frame-utmost-window-1 frame position nil t))
1139
1140 (defun frame-leftmost-window (&optional frame position)
1141 "Return the leftmost window on FRAME which is at POSITION.
1142 If omitted, FRAME defaults to the currently selected frame.
1143 POSITION is used to distinguish between multiple windows that abut
1144 the left edge of the frame: 0 means the highest window abutting the
1145 left edge of the frame, 1 the next-highest, etc. POSITION can also
1146 be less than zero: -1 means the lowest window abutting the
1147 left edge of the frame, -2 the next-lowest, etc.
1148 If omitted, POSITION defaults to 0, i.e. the highest leftmost window.
1149 If there is no window at the given POSITION, return nil."
1150 (frame-utmost-window-1 frame position t nil))
1151
1152 (defun frame-rightmost-window (&optional frame position)
1153 "Return the rightmost window on FRAME which is at POSITION.
1154 If omitted, FRAME defaults to the currently selected frame.
1155 POSITION is used to distinguish between multiple windows that abut
1156 the right edge of the frame: 0 means the highest window abutting the
1157 right edge of the frame, 1 the next-highest, etc. POSITION can also
1158 be less than zero: -1 means the lowest window abutting the
1159 right edge of the frame, -2 the next-lowest, etc.
1160 If omitted, POSITION defaults to 0, i.e. the highest rightmost window.
1161 If there is no window at the given POSITION, return nil."
1162 (frame-utmost-window-1 frame position t t))
1163
1164
1165
1166 ;; frame properties.
1167
1168 (defun set-frame-property (frame prop val)
1169 "Set property PROP of FRAME to VAL. See `set-frame-properties'."
1170 (set-frame-properties frame (list prop val)))
1171
1172 (defun frame-height (&optional frame)
1173 "Return number of lines available for display on FRAME."
1174 (or frame (setq frame (selected-frame)))
1175 (frame-property frame 'height))
1176
1177 (defun frame-width (&optional frame)
1178 "Return number of columns available for display on FRAME."
1179 (or frame (setq frame (selected-frame)))
1180 (frame-property frame 'width))
1181
1182 (put 'cursor-color 'frame-property-alias [text-cursor background])
1183 (put 'modeline 'frame-property-alias 'has-modeline-p)
1184
1185
1186 (provide 'frame)
1187
1188 ;;; frame.el ends here