* keyboard.c (kbd_buffer_get_event): Protect assignment to
[bpt/emacs.git] / src / frame.c
CommitLineData
ff11dfa1 1/* Generic frame functions.
7c299e7a 2 Copyright (C) 1989, 1992, 1993 Free Software Foundation.
dc6f92b8
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
1113d9db 8the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
d5e7c279
JB
20#include <stdio.h>
21
dc6f92b8 22#include "config.h"
cc38027b
JB
23#include "lisp.h"
24#include "frame.h"
e5d77022 25
ff11dfa1 26#ifdef MULTI_FRAME
e5d77022 27
bff19c8d 28#include "buffer.h"
dc6f92b8 29#include "window.h"
d5e7c279 30#include "termhooks.h"
dc6f92b8 31
2f0b07e0
JB
32/* These help us bind and responding to switch-frame events. */
33#include "commands.h"
34#include "keyboard.h"
35
dc6f92b8 36Lisp_Object Vemacs_iconified;
ff11dfa1
JB
37Lisp_Object Vframe_list;
38Lisp_Object Vterminal_frame;
39Lisp_Object Vdefault_minibuffer_frame;
40Lisp_Object Vdefault_frame_alist;
fd0c2bd1
JB
41
42/* Evaluate this expression to rebuild the section of syms_of_frame
43 that initializes and staticpros the symbols declared below. Note
44 that Emacs 18 has a bug that keeps C-x C-e from being able to
45 evaluate this expression.
46
47(progn
48 ;; Accumulate a list of the symbols we want to initialize from the
49 ;; declarations at the top of the file.
50 (goto-char (point-min))
51 (search-forward "/\*&&& symbols declared here &&&*\/\n")
52 (let (symbol-list)
53 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
54 (setq symbol-list
55 (cons (buffer-substring (match-beginning 1) (match-end 1))
56 symbol-list))
57 (forward-line 1))
58 (setq symbol-list (nreverse symbol-list))
59 ;; Delete the section of syms_of_... where we initialize the symbols.
60 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
61 (let ((start (point)))
62 (while (looking-at "^ Q")
63 (forward-line 2))
64 (kill-region start (point)))
65 ;; Write a new symbol initialization section.
66 (while symbol-list
67 (insert (format " %s = intern (\"" (car symbol-list)))
68 (let ((start (point)))
69 (insert (substring (car symbol-list) 1))
70 (subst-char-in-region start (point) ?_ ?-))
71 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
72 (setq symbol-list (cdr symbol-list)))))
73 */
74
75/*&&& symbols declared here &&&*/
76Lisp_Object Qframep;
dbc4e1c1 77Lisp_Object Qframe_live_p;
fd0c2bd1
JB
78Lisp_Object Qheight;
79Lisp_Object Qicon;
bc93c097 80Lisp_Object Qminibuffer;
fd0c2bd1
JB
81Lisp_Object Qmodeline;
82Lisp_Object Qname;
fd0c2bd1
JB
83Lisp_Object Qonly;
84Lisp_Object Qunsplittable;
85Lisp_Object Qwidth;
86Lisp_Object Qx;
dc6f92b8
JB
87
88extern Lisp_Object Vminibuffer_list;
89extern Lisp_Object get_minibuffer ();
074577b8
JB
90
91extern Lisp_Object Vlast_event_frame;
dc6f92b8 92\f
ff11dfa1
JB
93DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
94 "Return non-nil if OBJECT is a frame.\n\
95Value is t for a termcap frame (a character-only terminal),\n\
96`x' for an Emacs frame that is really an X window.\n\
97Also see `live-frame-p'.")
f9898cc6
JB
98 (object)
99 Lisp_Object object;
dc6f92b8 100{
ff11dfa1 101 if (XTYPE (object) != Lisp_Frame)
dc6f92b8 102 return Qnil;
ff11dfa1 103 switch (XFRAME (object)->output_method)
dc6f92b8
JB
104 {
105 case output_termcap:
106 return Qt;
107 case output_x_window:
fd0c2bd1 108 return Qx;
dc6f92b8
JB
109 default:
110 abort ();
111 }
112}
113
dbc4e1c1 114DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
ff11dfa1
JB
115 "Return non-nil if OBJECT is a frame which has not been deleted.\n\
116Value is nil if OBJECT is not a live frame. If object is a live\n\
117frame, the return value indicates what sort of output device it is\n\
118displayed on. Value is t for a termcap frame (a character-only\n\
119terminal), `x' for an Emacs frame being displayed in an X window.")
f9898cc6
JB
120 (object)
121 Lisp_Object object;
122{
ff11dfa1
JB
123 return ((FRAMEP (object)
124 && FRAME_LIVE_P (XFRAME (object)))
125 ? Fframep (object)
f9898cc6
JB
126 : Qnil);
127}
128
ff11dfa1
JB
129struct frame *
130make_frame (mini_p)
dc6f92b8
JB
131 int mini_p;
132{
ff11dfa1
JB
133 Lisp_Object frame;
134 register struct frame *f;
dc6f92b8
JB
135 register Lisp_Object root_window;
136 register Lisp_Object mini_window;
137
ff11dfa1 138 frame = Fmake_vector (((sizeof (struct frame) - (sizeof (Lisp_Vector)
d5e7c279
JB
139 - sizeof (Lisp_Object)))
140 / sizeof (Lisp_Object)),
dc6f92b8 141 make_number (0));
ff11dfa1
JB
142 XSETTYPE (frame, Lisp_Frame);
143 f = XFRAME (frame);
144
145 f->cursor_x = 0;
146 f->cursor_y = 0;
147 f->current_glyphs = 0;
148 f->desired_glyphs = 0;
149 f->visible = 0;
323405de 150 f->async_visible = 0;
ff11dfa1
JB
151 f->display.nothing = 0;
152 f->iconified = 0;
323405de 153 f->async_iconified = 0;
ff11dfa1
JB
154 f->wants_modeline = 1;
155 f->auto_raise = 0;
156 f->auto_lower = 0;
157 f->no_split = 0;
158 f->garbaged = 0;
159 f->has_minibuffer = mini_p;
a42e9724 160 f->focus_frame = Qnil;
804518aa 161 f->explicit_name = 0;
a42e9724
JB
162 f->can_have_scrollbars = 0;
163 f->has_vertical_scrollbars = 0;
ff11dfa1 164 f->param_alist = Qnil;
7c299e7a
JB
165 f->scrollbars = Qnil;
166 f->condemned_scrollbars = Qnil;
dc6f92b8 167
cc38027b 168 root_window = make_window ();
dc6f92b8
JB
169 if (mini_p)
170 {
cc38027b 171 mini_window = make_window ();
dc6f92b8
JB
172 XWINDOW (root_window)->next = mini_window;
173 XWINDOW (mini_window)->prev = root_window;
174 XWINDOW (mini_window)->mini_p = Qt;
ff11dfa1
JB
175 XWINDOW (mini_window)->frame = frame;
176 f->minibuffer_window = mini_window;
dc6f92b8
JB
177 }
178 else
179 {
180 mini_window = Qnil;
181 XWINDOW (root_window)->next = Qnil;
ff11dfa1 182 f->minibuffer_window = Qnil;
dc6f92b8
JB
183 }
184
ff11dfa1 185 XWINDOW (root_window)->frame = frame;
dc6f92b8
JB
186
187 /* 10 is arbitrary,
188 just so that there is "something there."
ff11dfa1 189 Correct size will be set up later with change_frame_size. */
dc6f92b8 190
ff11dfa1
JB
191 f->width = 10;
192 f->height = 10;
dc6f92b8
JB
193
194 XFASTINT (XWINDOW (root_window)->width) = 10;
195 XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
196
197 if (mini_p)
198 {
199 XFASTINT (XWINDOW (mini_window)->width) = 10;
200 XFASTINT (XWINDOW (mini_window)->top) = 9;
201 XFASTINT (XWINDOW (mini_window)->height) = 1;
202 }
203
ff11dfa1 204 /* Choose a buffer for the frame's root window. */
5bce042c
JB
205 {
206 Lisp_Object buf;
207
208 XWINDOW (root_window)->buffer = Qt;
209 buf = Fcurrent_buffer ();
210 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
211 a space), try to find another one. */
212 if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
c3c73481 213 buf = Fother_buffer (buf, Qnil);
5bce042c
JB
214 Fset_window_buffer (root_window, buf);
215 }
216
dc6f92b8
JB
217 if (mini_p)
218 {
219 XWINDOW (mini_window)->buffer = Qt;
220 Fset_window_buffer (mini_window,
265a9e55 221 (NILP (Vminibuffer_list)
dc6f92b8
JB
222 ? get_minibuffer (0)
223 : Fcar (Vminibuffer_list)));
224 }
225
ff11dfa1
JB
226 f->root_window = root_window;
227 f->selected_window = root_window;
d5e7c279
JB
228 /* Make sure this window seems more recently used than
229 a newly-created, never-selected window. */
ff11dfa1 230 XFASTINT (XWINDOW (f->selected_window)->use_time) = ++window_select_count;
dc6f92b8 231
ff11dfa1 232 Vframe_list = Fcons (frame, Vframe_list);
dc6f92b8 233
ff11dfa1 234 return f;
dc6f92b8
JB
235}
236\f
ff11dfa1 237/* Make a frame using a separate minibuffer window on another frame.
dc6f92b8
JB
238 MINI_WINDOW is the minibuffer window to use. nil means use the
239 default (the global minibuffer). */
240
ff11dfa1
JB
241struct frame *
242make_frame_without_minibuffer (mini_window)
dc6f92b8
JB
243 register Lisp_Object mini_window;
244{
ff11dfa1 245 register struct frame *f;
dc6f92b8
JB
246
247 /* Choose the minibuffer window to use. */
265a9e55 248 if (NILP (mini_window))
dc6f92b8 249 {
ff11dfa1
JB
250 if (XTYPE (Vdefault_minibuffer_frame) != Lisp_Frame)
251 error ("default-minibuffer-frame must be set when creating minibufferless frames");
252 if (! FRAME_LIVE_P (XFRAME (Vdefault_minibuffer_frame)))
253 error ("default-minibuffer-frame must be a live frame");
254 mini_window = XFRAME (Vdefault_minibuffer_frame)->minibuffer_window;
dc6f92b8
JB
255 }
256 else
257 {
774910eb 258 CHECK_LIVE_WINDOW (mini_window, 0);
dc6f92b8
JB
259 }
260
ff11dfa1
JB
261 /* Make a frame containing just a root window. */
262 f = make_frame (0);
dc6f92b8
JB
263
264 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 265 f->minibuffer_window = mini_window;
dc6f92b8 266 Fset_window_buffer (mini_window,
265a9e55 267 (NILP (Vminibuffer_list)
dc6f92b8
JB
268 ? get_minibuffer (0)
269 : Fcar (Vminibuffer_list)));
ff11dfa1 270 return f;
dc6f92b8
JB
271}
272
ff11dfa1 273/* Make a frame containing only a minibuffer window. */
dc6f92b8 274
ff11dfa1
JB
275struct frame *
276make_minibuffer_frame ()
dc6f92b8 277{
ff11dfa1 278 /* First make a frame containing just a root window, no minibuffer. */
dc6f92b8 279
ff11dfa1 280 register struct frame *f = make_frame (0);
dc6f92b8 281 register Lisp_Object mini_window;
ff11dfa1 282 register Lisp_Object frame;
dc6f92b8 283
ff11dfa1 284 XSET (frame, Lisp_Frame, f);
dc6f92b8 285
804518aa 286 f->auto_raise = 0;
ff11dfa1
JB
287 f->auto_lower = 0;
288 f->no_split = 1;
289 f->wants_modeline = 0;
290 f->has_minibuffer = 1;
dc6f92b8
JB
291
292 /* Now label the root window as also being the minibuffer.
293 Avoid infinite looping on the window chain by marking next pointer
294 as nil. */
295
ff11dfa1 296 mini_window = f->minibuffer_window = f->root_window;
dc6f92b8
JB
297 XWINDOW (mini_window)->mini_p = Qt;
298 XWINDOW (mini_window)->next = Qnil;
804518aa 299 XWINDOW (mini_window)->prev = Qnil;
ff11dfa1 300 XWINDOW (mini_window)->frame = frame;
dc6f92b8
JB
301
302 /* Put the proper buffer in that window. */
303
304 Fset_window_buffer (mini_window,
265a9e55 305 (NILP (Vminibuffer_list)
dc6f92b8
JB
306 ? get_minibuffer (0)
307 : Fcar (Vminibuffer_list)));
ff11dfa1 308 return f;
dc6f92b8
JB
309}
310\f
ff11dfa1 311/* Construct a frame that refers to the terminal (stdin and stdout). */
dc6f92b8 312
ff11dfa1
JB
313struct frame *
314make_terminal_frame ()
dc6f92b8 315{
ff11dfa1
JB
316 register struct frame *f;
317
318 Vframe_list = Qnil;
319 f = make_frame (1);
320 f->name = build_string ("terminal");
a42e9724 321 FRAME_SET_VISIBLE (f, 1);
ff11dfa1
JB
322 f->display.nothing = 1; /* Nonzero means frame isn't deleted. */
323 XSET (Vterminal_frame, Lisp_Frame, f);
324 return f;
dc6f92b8
JB
325}
326\f
2f0b07e0 327DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
8693ca83 328 "Select the frame FRAME. FRAME's selected window becomes \"the\"\n\
d5e7c279 329selected window. If the optional parameter NO-ENTER is non-nil, don't\n\
2f0b07e0
JB
330focus on that frame.\n\
331\n\
332This function is interactive, and may be bound to the ``switch-frame''\n\
333event; when invoked this way, it switches to the frame named in the\n\
334event. When called from lisp, FRAME may be a ``switch-frame'' event;\n\
a42e9724
JB
335if it is, select the frame named in the event.\n\
336\n\
337Changing the selected frame can change focus redirections. See\n\
338`redirect-frame-focus' for details.")
ff11dfa1
JB
339 (frame, no_enter)
340 Lisp_Object frame, no_enter;
dc6f92b8 341{
2f0b07e0
JB
342 /* If FRAME is a switch-frame event, extract the frame we should
343 switch to. */
344 if (CONSP (frame)
345 && EQ (XCONS (frame)->car, Qswitch_frame)
346 && CONSP (XCONS (frame)->cdr))
347 frame = XCONS (XCONS (frame)->cdr)->car;
348
ff11dfa1 349 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 350
ff11dfa1
JB
351 if (selected_frame == XFRAME (frame))
352 return frame;
dc6f92b8 353
a42e9724
JB
354 /* If a frame's focus has been redirected toward the currently
355 selected frame, we should change the redirection to point to the
356 newly selected frame. This means that if the focus is redirected
357 from a minibufferless frame to a surrogate minibuffer frame, we
358 can use `other-window' to switch between all the frames using
359 that minibuffer frame, and the focus redirection will follow us
360 around. */
361 {
362 Lisp_Object tail;
363
364 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
365 {
366 Lisp_Object focus;
367
368 if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
369 abort ();
370
371 focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
372
373 if (XTYPE (focus) == Lisp_Frame
374 && XFRAME (focus) == selected_frame)
375 Fredirect_frame_focus (XCONS (tail)->car, frame);
376 }
377 }
378
ff11dfa1
JB
379 selected_frame = XFRAME (frame);
380 if (! FRAME_MINIBUF_ONLY_P (selected_frame))
381 last_nonminibuf_frame = selected_frame;
d5e7c279 382
ff11dfa1 383 Fselect_window (XFRAME (frame)->selected_window);
dc6f92b8 384
dbc4e1c1 385 /* I think this should be done with a hook. */
dc6f92b8 386#ifdef HAVE_X_WINDOWS
fd0c2bd1 387 if (FRAME_X_P (XFRAME (frame))
265a9e55 388 && NILP (no_enter))
dc6f92b8 389 {
ff11dfa1 390 Ffocus_frame (frame);
dc6f92b8 391 }
dc6f92b8 392#endif
ff11dfa1 393 choose_minibuf_frame ();
dc6f92b8 394
074577b8
JB
395 /* We want to make sure that the next event generates a frame-switch
396 event to the appropriate frame. This seems kludgey to me, but
397 before you take it out, make sure that evaluating something like
398 (select-window (frame-root-window (new-frame))) doesn't end up
399 with your typing being interpreted in the new frame instead of
400 the one you're actually typing in. */
401 Vlast_event_frame = Qnil;
402
ff11dfa1 403 return frame;
dc6f92b8
JB
404}
405
ff11dfa1
JB
406DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
407 "Return the frame that is now selected.")
dc6f92b8
JB
408 ()
409{
410 Lisp_Object tem;
ff11dfa1 411 XSET (tem, Lisp_Frame, selected_frame);
dc6f92b8
JB
412 return tem;
413}
414
ff11dfa1
JB
415DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
416 "Return the frame object that window WINDOW is on.")
dc6f92b8
JB
417 (window)
418 Lisp_Object window;
419{
774910eb 420 CHECK_LIVE_WINDOW (window, 0);
ff11dfa1 421 return XWINDOW (window)->frame;
dc6f92b8
JB
422}
423
ff11dfa1 424DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
8693ca83
JB
425 "Returns the root-window of FRAME.\n\
426If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
427 (frame)
428 Lisp_Object frame;
dc6f92b8 429{
ff11dfa1
JB
430 if (NILP (frame))
431 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 432 else
ff11dfa1 433 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 434
ff11dfa1 435 return XFRAME (frame)->root_window;
dc6f92b8
JB
436}
437
ff11dfa1
JB
438DEFUN ("frame-selected-window", Fframe_selected_window,
439 Sframe_selected_window, 0, 1, 0,
8693ca83
JB
440 "Return the selected window of frame object FRAME.\n\
441If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
442 (frame)
443 Lisp_Object frame;
dc6f92b8 444{
ff11dfa1
JB
445 if (NILP (frame))
446 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 447 else
ff11dfa1 448 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 449
ff11dfa1 450 return XFRAME (frame)->selected_window;
dc6f92b8
JB
451}
452
ff11dfa1 453DEFUN ("frame-list", Fframe_list, Sframe_list,
dc6f92b8 454 0, 0, 0,
ff11dfa1 455 "Return a list of all frames.")
dc6f92b8
JB
456 ()
457{
ff11dfa1 458 return Fcopy_sequence (Vframe_list);
dc6f92b8
JB
459}
460
ff11dfa1 461/* Return the next frame in the frame list after FRAME.
ff11dfa1
JB
462 If MINIBUF is nil, exclude minibuffer-only frames.
463 If MINIBUF is a window, include only frames using that window for
d06a8a56
JB
464 their minibuffer.
465 If MINIBUF is non-nil, and not a window, include all frames. */
dc6f92b8 466Lisp_Object
ff11dfa1
JB
467next_frame (frame, minibuf)
468 Lisp_Object frame;
f9898cc6 469 Lisp_Object minibuf;
dc6f92b8
JB
470{
471 Lisp_Object tail;
472 int passed = 0;
473
ff11dfa1
JB
474 /* There must always be at least one frame in Vframe_list. */
475 if (! CONSP (Vframe_list))
f9898cc6
JB
476 abort ();
477
dbc4e1c1
JB
478 /* If this frame is dead, it won't be in Vframe_list, and we'll loop
479 forever. Forestall that. */
480 CHECK_LIVE_FRAME (frame, 0);
481
dc6f92b8 482 while (1)
ff11dfa1 483 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
dc6f92b8 484 {
d06a8a56
JB
485 Lisp_Object f = XCONS (tail)->car;
486
dc6f92b8 487 if (passed)
d5e7c279 488 {
d06a8a56
JB
489 /* Decide whether this frame is eligible to be returned. */
490
491 /* If we've looped all the way around without finding any
492 eligible frames, return the original frame. */
493 if (EQ (f, frame))
494 return f;
495
496 /* Let minibuf decide if this frame is acceptable. */
497 if (NILP (minibuf))
498 {
499 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
500 return f;
501 }
502 else if (XTYPE (minibuf) == Lisp_Window)
503 {
504 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
505 return f;
506 }
507 else
ff11dfa1 508 return f;
d5e7c279 509 }
dc6f92b8 510
d06a8a56 511 if (EQ (frame, f))
dc6f92b8
JB
512 passed++;
513 }
514}
515
ff11dfa1 516/* Return the previous frame in the frame list before FRAME.
ff11dfa1
JB
517 If MINIBUF is nil, exclude minibuffer-only frames.
518 If MINIBUF is a window, include only frames using that window for
d06a8a56
JB
519 their minibuffer.
520 If MINIBUF is non-nil and not a window, include all frames. */
dc6f92b8 521Lisp_Object
ff11dfa1
JB
522prev_frame (frame, minibuf)
523 Lisp_Object frame;
f9898cc6 524 Lisp_Object minibuf;
dc6f92b8
JB
525{
526 Lisp_Object tail;
527 Lisp_Object prev;
528
ff11dfa1
JB
529 /* There must always be at least one frame in Vframe_list. */
530 if (! CONSP (Vframe_list))
f9898cc6
JB
531 abort ();
532
dc6f92b8 533 prev = Qnil;
d06a8a56 534 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
f9898cc6 535 {
d06a8a56 536 Lisp_Object f = XCONS (tail)->car;
f9898cc6 537
d06a8a56
JB
538 if (XTYPE (f) != Lisp_Frame)
539 abort ();
f9898cc6 540
d06a8a56
JB
541 if (EQ (frame, f) && !NILP (prev))
542 return prev;
f9898cc6 543
d06a8a56
JB
544 /* Decide whether this frame is eligible to be returned,
545 according to minibuf. */
546 if (NILP (minibuf))
547 {
548 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
549 prev = f;
f9898cc6 550 }
d06a8a56
JB
551 else if (XTYPE (minibuf) == Lisp_Window)
552 {
553 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
554 prev = f;
555 }
556 else
557 prev = f;
f9898cc6 558 }
d06a8a56
JB
559
560 /* We've scanned the entire list. */
561 if (NILP (prev))
562 /* We went through the whole frame list without finding a single
563 acceptable frame. Return the original frame. */
564 return frame;
565 else
566 /* There were no acceptable frames in the list before FRAME; otherwise,
567 we would have returned directly from the loop. Since PREV is the last
568 acceptable frame in the list, return it. */
569 return prev;
dc6f92b8
JB
570}
571
ff11dfa1
JB
572DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
573 "Return the next frame in the frame list after FRAME.\n\
a42e9724 574By default, skip minibuffer-only frames.\n\
d06a8a56 575If omitted, FRAME defaults to the selected frame.\n\
8693ca83
JB
576If optional argument MINIFRAME is non-nil, include minibuffer-only frames.\n\
577If MINIFRAME is a window, include only frames using that window for their\n\
d06a8a56 578minibuffer.\n\
8693ca83 579If MINIFRAME is non-nil and not a window, include all frames.")
ff11dfa1 580 (frame, miniframe)
8693ca83 581 Lisp_Object frame, miniframe;
dc6f92b8
JB
582{
583 Lisp_Object tail;
584
ff11dfa1
JB
585 if (NILP (frame))
586 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 587 else
ff11dfa1 588 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 589
ff11dfa1 590 return next_frame (frame, miniframe);
dc6f92b8 591}
dbc4e1c1 592
dc6f92b8 593\f
ff11dfa1
JB
594DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 1, "",
595 "Delete FRAME, permanently eliminating it from use.\n\
596If omitted, FRAME defaults to the selected frame.\n\
597A frame may not be deleted if its minibuffer is used by other frames.")
598 (frame)
599 Lisp_Object frame;
dc6f92b8 600{
ff11dfa1 601 struct frame *f;
dc6f92b8 602
ff11dfa1 603 if (EQ (frame, Qnil))
dc6f92b8 604 {
ff11dfa1
JB
605 f = selected_frame;
606 XSET (frame, Lisp_Frame, f);
dc6f92b8
JB
607 }
608 else
609 {
ff11dfa1
JB
610 CHECK_FRAME (frame, 0);
611 f = XFRAME (frame);
dc6f92b8
JB
612 }
613
ff11dfa1 614 if (! FRAME_LIVE_P (f))
074577b8 615 return Qnil;
f9898cc6 616
ff11dfa1
JB
617 /* Are there any other frames besides this one? */
618 if (f == selected_frame && EQ (next_frame (frame, Qt), frame))
619 error ("Attempt to delete the only frame");
d5e7c279 620
ff11dfa1
JB
621 /* Does this frame have a minibuffer, and is it the surrogate
622 minibuffer for any other frame? */
fd0c2bd1 623 if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
dc6f92b8 624 {
ff11dfa1 625 Lisp_Object frames;
1113d9db 626
ff11dfa1
JB
627 for (frames = Vframe_list;
628 CONSP (frames);
629 frames = XCONS (frames)->cdr)
1113d9db 630 {
ff11dfa1 631 Lisp_Object this = XCONS (frames)->car;
1113d9db 632
ff11dfa1
JB
633 if (! EQ (this, frame)
634 && EQ (frame,
635 (WINDOW_FRAME
1113d9db 636 (XWINDOW
ff11dfa1
JB
637 (FRAME_MINIBUF_WINDOW
638 (XFRAME (this)))))))
639 error ("Attempt to delete a surrogate minibuffer frame");
1113d9db 640 }
dc6f92b8
JB
641 }
642
ff11dfa1
JB
643 /* Don't let the frame remain selected. */
644 if (f == selected_frame)
629a12cf 645 Fselect_frame (next_frame (frame, Qt), Qnil);
dc6f92b8 646
ff11dfa1
JB
647 /* Don't allow minibuf_window to remain on a deleted frame. */
648 if (EQ (f->minibuffer_window, minibuf_window))
dc6f92b8 649 {
ff11dfa1 650 Fset_window_buffer (selected_frame->minibuffer_window,
dc6f92b8 651 XWINDOW (minibuf_window)->buffer);
ff11dfa1 652 minibuf_window = selected_frame->minibuffer_window;
dc6f92b8
JB
653 }
654
4a88b3b0
JB
655 /* Mark all the windows that used to be on FRAME as deleted, and then
656 remove the reference to them. */
657 delete_all_subwindows (XWINDOW (f->root_window));
658 f->root_window = Qnil;
659
ff11dfa1 660 Vframe_list = Fdelq (frame, Vframe_list);
a42e9724 661 FRAME_SET_VISIBLE (f, 0);
dc6f92b8 662
8678b9cc
JB
663 /* Since some events are handled at the interrupt level, we may get
664 an event for f at any time; if we zero out the frame's display
665 now, then we may trip up the event-handling code. Instead, we'll
666 promise that the display of the frame must be valid until we have
667 called the window-system-dependent frame destruction routine. */
dbc4e1c1
JB
668
669 /* I think this should be done with a hook. */
d5e7c279 670#ifdef HAVE_X_WINDOWS
fd0c2bd1 671 if (FRAME_X_P (f))
8678b9cc 672 x_destroy_window (f);
d5e7c279
JB
673#endif
674
8678b9cc
JB
675 f->display.nothing = 0;
676
ff11dfa1 677 /* If we've deleted the last_nonminibuf_frame, then try to find
d5e7c279 678 another one. */
ff11dfa1 679 if (f == last_nonminibuf_frame)
d5e7c279 680 {
ff11dfa1 681 Lisp_Object frames;
1113d9db 682
ff11dfa1 683 last_nonminibuf_frame = 0;
d5e7c279 684
ff11dfa1
JB
685 for (frames = Vframe_list;
686 CONSP (frames);
687 frames = XCONS (frames)->cdr)
d5e7c279 688 {
ff11dfa1
JB
689 f = XFRAME (XCONS (frames)->car);
690 if (!FRAME_MINIBUF_ONLY_P (f))
d5e7c279 691 {
ff11dfa1 692 last_nonminibuf_frame = f;
d5e7c279
JB
693 break;
694 }
695 }
696 }
dc6f92b8 697
ff11dfa1
JB
698 /* If we've deleted Vdefault_minibuffer_frame, try to find another
699 one. Prefer minibuffer-only frames, but also notice frames
1113d9db 700 with other windows. */
ff11dfa1 701 if (EQ (frame, Vdefault_minibuffer_frame))
1113d9db 702 {
ff11dfa1 703 Lisp_Object frames;
1113d9db 704
ff11dfa1
JB
705 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
706 Lisp_Object frame_with_minibuf = Qnil;
1113d9db 707
ff11dfa1
JB
708 for (frames = Vframe_list;
709 CONSP (frames);
710 frames = XCONS (frames)->cdr)
1113d9db 711 {
ff11dfa1 712 Lisp_Object this = XCONS (frames)->car;
1113d9db 713
ff11dfa1 714 if (XTYPE (this) != Lisp_Frame)
1113d9db 715 abort ();
ff11dfa1 716 f = XFRAME (this);
1113d9db 717
fd0c2bd1 718 if (FRAME_HAS_MINIBUF_P (f))
1113d9db 719 {
ff11dfa1
JB
720 frame_with_minibuf = this;
721 if (FRAME_MINIBUF_ONLY_P (f))
1113d9db
JB
722 break;
723 }
724 }
725
ff11dfa1
JB
726 /* We know that there must be some frame with a minibuffer out
727 there. If this were not true, all of the frames present
1113d9db 728 would have to be minibufferless, which implies that at some
ff11dfa1 729 point their minibuffer frames must have been deleted, but
1113d9db 730 that is prohibited at the top; you can't delete surrogate
ff11dfa1
JB
731 minibuffer frames. */
732 if (NILP (frame_with_minibuf))
1113d9db
JB
733 abort ();
734
ff11dfa1 735 Vdefault_minibuffer_frame = frame_with_minibuf;
1113d9db
JB
736 }
737
dc6f92b8
JB
738 return Qnil;
739}
740\f
741/* Return mouse position in character cell units. */
742
f9898cc6 743DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
ff11dfa1 744 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
f9898cc6 745If Emacs is running on a mouseless terminal or hasn't been programmed\n\
ff11dfa1 746to read the mouse position, it returns the selected frame for FRAME\n\
f9898cc6
JB
747and nil for X and Y.")
748 ()
dc6f92b8 749{
ff11dfa1 750 FRAME_PTR f;
dbc4e1c1
JB
751 Lisp_Object lispy_dummy;
752 enum scrollbar_part party_dummy;
753 Lisp_Object x, y;
754 unsigned long long_dummy;
dc6f92b8 755
f9898cc6 756 if (mouse_position_hook)
dbc4e1c1
JB
757 (*mouse_position_hook) (&f,
758 &lispy_dummy, &party_dummy,
759 &x, &y,
760 &long_dummy);
f9898cc6
JB
761 else
762 {
ff11dfa1 763 f = selected_frame;
f9898cc6
JB
764 x = y = Qnil;
765 }
dc6f92b8 766
dbc4e1c1
JB
767 XSET (lispy_dummy, Lisp_Frame, f);
768 return Fcons (lispy_dummy, Fcons (make_number (x), make_number (y)));
dc6f92b8
JB
769}
770
771DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
ff11dfa1
JB
772 "Move the mouse pointer to the center of cell (X,Y) in FRAME.\n\
773WARNING: If you use this under X, you should do `unfocus-frame' afterwards.")
774 (frame, x, y)
775 Lisp_Object frame, x, y;
dc6f92b8 776{
ff11dfa1 777 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
778 CHECK_NUMBER (x, 2);
779 CHECK_NUMBER (y, 1);
780
dbc4e1c1 781 /* I think this should be done with a hook. */
dc6f92b8 782#ifdef HAVE_X_WINDOWS
fd0c2bd1 783 if (FRAME_X_P (XFRAME (frame)))
dc6f92b8 784 /* Warping the mouse will cause enternotify and focus events. */
ff11dfa1 785 x_set_mouse_position (XFRAME (frame), x, y);
dc6f92b8
JB
786#endif
787
788 return Qnil;
789}
790\f
791#if 0
792/* ??? Can this be replaced with a Lisp function?
06b1a5ef
JB
793 It is used in minibuf.c. Can we get rid of that?
794 Yes. All uses in minibuf.c are gone, and parallels to these
ff11dfa1 795 functions have been defined in frame.el. */
dc6f92b8 796
ff11dfa1 797DEFUN ("frame-configuration", Fframe_configuration, Sframe_configuration,
dc6f92b8 798 0, 0, 0,
ff11dfa1
JB
799 "Return object describing current frame configuration.\n\
800The frame configuration is the current mouse position and selected frame.\n\
801This object can be given to `restore-frame-configuration'\n\
802to restore this frame configuration.")
dc6f92b8
JB
803 ()
804{
f9898cc6 805 Lisp_Object c, time;
dc6f92b8 806
f9898cc6 807 c = Fmake_vector (make_number(4), Qnil);
ff11dfa1 808 XVECTOR (c)->contents[0] = Fselected_frame();
f9898cc6
JB
809 if (mouse_position_hook)
810 (*mouse_position_hook) (&XVECTOR (c)->contents[1]
811 &XVECTOR (c)->contents[2],
812 &XVECTOR (c)->contents[3],
813 &time);
dc6f92b8
JB
814 return c;
815}
816
ff11dfa1
JB
817DEFUN ("restore-frame-configuration", Frestore_frame_configuration,
818 Srestore_frame_configuration,
dc6f92b8 819 1, 1, 0,
ff11dfa1 820 "Restores frame configuration CONFIGURATION.")
dc6f92b8
JB
821 (config)
822 Lisp_Object config;
823{
ff11dfa1 824 Lisp_Object x_pos, y_pos, frame;
dc6f92b8
JB
825
826 CHECK_VECTOR (config, 0);
827 if (XVECTOR (config)->size != 3)
828 {
ff11dfa1 829 error ("Wrong size vector passed to restore-frame-configuration");
dc6f92b8 830 }
ff11dfa1
JB
831 frame = XVECTOR (config)->contents[0];
832 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 833
ff11dfa1 834 Fselect_frame (frame, Qnil);
dc6f92b8
JB
835
836#if 0
ff11dfa1 837 /* This seems to interfere with the frame selection mechanism. jla */
f9898cc6
JB
838 x_pos = XVECTOR (config)->contents[2];
839 y_pos = XVECTOR (config)->contents[3];
ff11dfa1 840 set_mouse_position (frame, XINT (x_pos), XINT (y_pos));
dc6f92b8
JB
841#endif
842
ff11dfa1 843 return frame;
dc6f92b8
JB
844}
845#endif
846\f
ff11dfa1 847DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
1aa66088 848 0, 1, 0,
ff11dfa1 849 "Make the frame FRAME visible (assuming it is an X-window).\n\
8693ca83
JB
850Also raises the frame so that nothing obscures it.\n\
851If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
852 (frame)
853 Lisp_Object frame;
dc6f92b8 854{
1aa66088 855 if (NILP (frame))
7500877e 856 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 857
ff11dfa1 858 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 859
dbc4e1c1 860 /* I think this should be done with a hook. */
fd0c2bd1
JB
861#ifdef HAVE_X_WINDOWS
862 if (FRAME_X_P (XFRAME (frame)))
ff11dfa1 863 x_make_frame_visible (XFRAME (frame));
fd0c2bd1 864#endif
dc6f92b8 865
ff11dfa1 866 return frame;
dc6f92b8
JB
867}
868
ff11dfa1 869DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
1aa66088 870 0, 1, "",
8693ca83
JB
871 "Make the frame FRAME invisible (assuming it is an X-window).\n\
872If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
873 (frame)
874 Lisp_Object frame;
dc6f92b8 875{
1aa66088 876 if (NILP (frame))
7500877e 877 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 878
ff11dfa1 879 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 880
dbc4e1c1 881 /* I think this should be done with a hook. */
fd0c2bd1
JB
882#ifdef HAVE_X_WINDOWS
883 if (FRAME_X_P (XFRAME (frame)))
ff11dfa1 884 x_make_frame_invisible (XFRAME (frame));
fd0c2bd1 885#endif
dc6f92b8
JB
886
887 return Qnil;
888}
889
ff11dfa1 890DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
1aa66088 891 0, 1, "",
8693ca83
JB
892 "Make the frame FRAME into an icon.\n\
893If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
894 (frame)
895 Lisp_Object frame;
dc6f92b8 896{
1aa66088 897 if (NILP (frame))
7500877e 898 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 899
ff11dfa1 900 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 901
dbc4e1c1 902 /* I think this should be done with a hook. */
fd0c2bd1
JB
903#ifdef HAVE_X_WINDOWS
904 if (FRAME_X_P (XFRAME (frame)))
ff11dfa1 905 x_iconify_frame (XFRAME (frame));
fd0c2bd1 906#endif
dc6f92b8
JB
907
908 return Qnil;
909}
910
ff11dfa1 911DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
dc6f92b8 912 1, 1, 0,
ff11dfa1
JB
913 "Return t if FRAME is now \"visible\" (actually in use for display).\n\
914A frame that is not \"visible\" is not updated and, if it works through\n\
dc6f92b8 915a window system, it may not show at all.\n\
fd0c2bd1 916Return the symbol `icon' if frame is visible only as an icon.")
ff11dfa1
JB
917 (frame)
918 Lisp_Object frame;
dc6f92b8 919{
ff11dfa1 920 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 921
a42e9724 922 if (FRAME_VISIBLE_P (XFRAME (frame)))
dc6f92b8 923 return Qt;
a42e9724 924 if (FRAME_ICONIFIED_P (XFRAME (frame)))
fd0c2bd1 925 return Qicon;
dc6f92b8
JB
926 return Qnil;
927}
928
ff11dfa1 929DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
dc6f92b8 930 0, 0, 0,
ff11dfa1 931 "Return a list of all frames now \"visible\" (being updated).")
dc6f92b8
JB
932 ()
933{
ff11dfa1
JB
934 Lisp_Object tail, frame;
935 struct frame *f;
dc6f92b8
JB
936 Lisp_Object value;
937
938 value = Qnil;
ff11dfa1 939 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
dc6f92b8 940 {
ff11dfa1
JB
941 frame = XCONS (tail)->car;
942 if (XTYPE (frame) != Lisp_Frame)
dc6f92b8 943 continue;
ff11dfa1 944 f = XFRAME (frame);
a42e9724 945 if (FRAME_VISIBLE_P (f))
ff11dfa1 946 value = Fcons (frame, value);
dc6f92b8
JB
947 }
948 return value;
949}
d5e7c279
JB
950
951
dbc4e1c1
JB
952DEFUN ("frame-to-front", Fframe_to_front, Sframe_to_front, 1, 1, 0,
953 "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
954If FRAME is invisible, make it visible.\n\
955If Emacs is displaying on an ordinary terminal or some other device which\n\
956doesn't support multiple overlapping frames, this function does nothing.")
957 (frame)
958 Lisp_Object frame;
959{
960 CHECK_LIVE_FRAME (frame, 0);
961
962 if (frame_raise_lower_hook)
963 (*frame_raise_lower_hook) (XFRAME (frame), 1);
964
965 return Qnil;
966}
967
968DEFUN ("frame-to-back", Fframe_to_back, Sframe_to_back, 1, 1, 0,
969 "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
970If Emacs is displaying on an ordinary terminal or some other device which\n\
971doesn't support multiple overlapping frames, this function does nothing.")
972 (frame)
973 Lisp_Object frame;
974{
975 CHECK_LIVE_FRAME (frame, 0);
976
977 if (frame_raise_lower_hook)
978 (*frame_raise_lower_hook) (XFRAME (frame), 0);
979
980 return Qnil;
981}
982
d5e7c279 983\f
ff11dfa1 984DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
d5e7c279 985 1, 2, 0,
ff11dfa1 986 "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
a42e9724
JB
987In other words, switch-frame events caused by events in FRAME will\n\
988request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
989FOCUS-FRAME after reading an event typed at FRAME.\n\
d5e7c279 990\n\
a42e9724 991If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
ff11dfa1 992cancelled, and the frame again receives its own keystrokes.\n\
d5e7c279 993\n\
a42e9724
JB
994Focus redirection is useful for temporarily redirecting keystrokes to\n\
995a surrogate minibuffer frame when a frame doesn't have its own\n\
996minibuffer window.\n\
d5e7c279 997\n\
a42e9724
JB
998A frame's focus redirection can be changed by select-frame. If frame\n\
999FOO is selected, and then a different frame BAR is selected, any\n\
1000frames redirecting their focus to FOO are shifted to redirect their\n\
1001focus to BAR. This allows focus redirection to work properly when the\n\
1002user switches from one frame to another using `select-window'.\n\
1003\n\
1004This means that a frame whose focus is redirected to itself is treated\n\
1005differently from a frame whose focus is redirected to nil; the former\n\
1006is affected by select-frame, while the latter is not.\n\
1007\n\
1008The redirection lasts until `redirect-frame-focus' is called to change it.")
ff11dfa1
JB
1009 (frame, focus_frame)
1010 Lisp_Object frame, focus_frame;
d5e7c279 1011{
ff11dfa1 1012 CHECK_LIVE_FRAME (frame, 0);
f9898cc6 1013
a42e9724 1014 if (! NILP (focus_frame))
ff11dfa1 1015 CHECK_LIVE_FRAME (focus_frame, 1);
d5e7c279 1016
ff11dfa1 1017 XFRAME (frame)->focus_frame = focus_frame;
d5e7c279 1018
ff11dfa1
JB
1019 if (frame_rehighlight_hook)
1020 (*frame_rehighlight_hook) ();
d5e7c279
JB
1021
1022 return Qnil;
1023}
1024
1025
ff11dfa1
JB
1026DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
1027 "Return the frame to which FRAME's keystrokes are currently being sent.\n\
a42e9724 1028This returns nil if FRAME's focus is not redirected.\n\
ff11dfa1
JB
1029See `redirect-frame-focus'.")
1030 (frame)
1031 Lisp_Object frame;
d5e7c279 1032{
ff11dfa1 1033 CHECK_LIVE_FRAME (frame, 0);
a42e9724 1034
ff11dfa1 1035 return FRAME_FOCUS_FRAME (XFRAME (frame));
d5e7c279
JB
1036}
1037
1038
dc6f92b8
JB
1039\f
1040Lisp_Object
ff11dfa1
JB
1041get_frame_param (frame, prop)
1042 register struct frame *frame;
dc6f92b8
JB
1043 Lisp_Object prop;
1044{
1045 register Lisp_Object tem;
1046
ff11dfa1 1047 tem = Fassq (prop, frame->param_alist);
dc6f92b8
JB
1048 if (EQ (tem, Qnil))
1049 return tem;
1050 return Fcdr (tem);
1051}
1052
1053void
fd0c2bd1 1054store_in_alist (alistptr, prop, val)
dc6f92b8 1055 Lisp_Object *alistptr, val;
fd0c2bd1 1056 Lisp_Object prop;
dc6f92b8
JB
1057{
1058 register Lisp_Object tem;
dc6f92b8 1059
dc6f92b8
JB
1060 tem = Fassq (prop, *alistptr);
1061 if (EQ (tem, Qnil))
1062 *alistptr = Fcons (Fcons (prop, val), *alistptr);
1063 else
1064 Fsetcdr (tem, val);
1065}
1066
1067void
ff11dfa1
JB
1068store_frame_param (f, prop, val)
1069 struct frame *f;
dc6f92b8
JB
1070 Lisp_Object prop, val;
1071{
1072 register Lisp_Object tem;
1073
ff11dfa1 1074 tem = Fassq (prop, f->param_alist);
dc6f92b8 1075 if (EQ (tem, Qnil))
ff11dfa1 1076 f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
dc6f92b8
JB
1077 else
1078 Fsetcdr (tem, val);
bc93c097
JB
1079
1080 if (EQ (prop, Qminibuffer)
1081 && XTYPE (val) == Lisp_Window)
1082 {
1083 if (! MINI_WINDOW_P (XWINDOW (val)))
1084 error ("Surrogate minibuffer windows must be minibuffer windows.");
1085
fd0c2bd1 1086 if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
ff11dfa1 1087 error ("Can't change the surrogate minibuffer of a frame with its own minibuffer.");
bc93c097
JB
1088
1089 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 1090 f->minibuffer_window = val;
bc93c097 1091 }
dc6f92b8
JB
1092}
1093
ff11dfa1
JB
1094DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
1095 "Return the parameters-alist of frame FRAME.\n\
dc6f92b8 1096It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
dc6d9681
JB
1097The meaningful PARMs depend on the kind of frame.\n\
1098If FRAME is omitted, return information on the currently selected frame.")
ff11dfa1
JB
1099 (frame)
1100 Lisp_Object frame;
dc6f92b8
JB
1101{
1102 Lisp_Object alist;
ff11dfa1 1103 struct frame *f;
dc6f92b8 1104
ff11dfa1
JB
1105 if (EQ (frame, Qnil))
1106 f = selected_frame;
dc6f92b8
JB
1107 else
1108 {
ff11dfa1
JB
1109 CHECK_FRAME (frame, 0);
1110 f = XFRAME (frame);
dc6f92b8
JB
1111 }
1112
ff11dfa1 1113 if (f->display.nothing == 0)
dc6f92b8
JB
1114 return Qnil;
1115
ff11dfa1 1116 alist = Fcopy_alist (f->param_alist);
fd0c2bd1
JB
1117 store_in_alist (&alist, Qname, f->name);
1118 store_in_alist (&alist, Qheight, make_number (f->height));
1119 store_in_alist (&alist, Qwidth, make_number (f->width));
1120 store_in_alist (&alist, Qmodeline, (f->wants_modeline ? Qt : Qnil));
1121 store_in_alist (&alist, Qminibuffer,
39acc701 1122 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
fd0c2bd1
JB
1123 : (FRAME_MINIBUF_ONLY_P (f) ? Qonly
1124 : FRAME_MINIBUF_WINDOW (f))));
1125 store_in_alist (&alist, Qunsplittable, (f->no_split ? Qt : Qnil));
1126
dbc4e1c1 1127 /* I think this should be done with a hook. */
fd0c2bd1
JB
1128#ifdef HAVE_X_WINDOWS
1129 if (FRAME_X_P (f))
ff11dfa1 1130 x_report_frame_params (f, &alist);
fd0c2bd1 1131#endif
dc6f92b8
JB
1132 return alist;
1133}
1134
ff11dfa1
JB
1135DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
1136 Smodify_frame_parameters, 2, 2, 0,
1137 "Modify the parameters of frame FRAME according to ALIST.\n\
dc6f92b8
JB
1138ALIST is an alist of parameters to change and their new values.\n\
1139Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
ff11dfa1
JB
1140The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
1141 (frame, alist)
1142 Lisp_Object frame, alist;
dc6f92b8 1143{
fd0c2bd1 1144 FRAME_PTR f;
dc6f92b8
JB
1145 register Lisp_Object tail, elt, prop, val;
1146
ff11dfa1
JB
1147 if (EQ (frame, Qnil))
1148 f = selected_frame;
dc6f92b8
JB
1149 else
1150 {
ff11dfa1
JB
1151 CHECK_LIVE_FRAME (frame, 0);
1152 f = XFRAME (frame);
dc6f92b8
JB
1153 }
1154
dbc4e1c1 1155 /* I think this should be done with a hook. */
fd0c2bd1
JB
1156#ifdef HAVE_X_WINDOWS
1157 if (FRAME_X_P (f))
1158#if 1
1159 x_set_frame_parameters (f, alist);
1160#else
dc6f92b8
JB
1161 for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
1162 {
1163 elt = Fcar (tail);
1164 prop = Fcar (elt);
1165 val = Fcdr (elt);
fd0c2bd1 1166 x_set_frame_param (f, prop, val, get_frame_param (f, prop));
ff11dfa1 1167 store_frame_param (f, prop, val);
dc6f92b8 1168 }
fd0c2bd1
JB
1169#endif
1170#endif
dc6f92b8
JB
1171
1172 return Qnil;
1173}
1174\f
1175
dc6d9681
JB
1176#if 0
1177/* This function isn't useful enough by itself to include; we need to
1178 add functions to allow the user to find the size of a font before
1179 this is actually useful. */
1180
ff11dfa1
JB
1181DEFUN ("frame-pixel-size", Fframe_pixel_size,
1182 Sframe_pixel_size, 1, 1, 0,
1183 "Return a cons (width . height) of FRAME's size in pixels.")
1184 (frame)
1185 Lisp_Object frame;
dc6f92b8 1186{
ff11dfa1 1187 register struct frame *f;
dc6f92b8
JB
1188 int width, height;
1189
ff11dfa1
JB
1190 CHECK_LIVE_FRAME (frame, 0);
1191 f = XFRAME (frame);
dc6f92b8 1192
ff11dfa1
JB
1193 return Fcons (make_number (x_pixel_width (f)),
1194 make_number (x_pixel_height (f)));
dc6f92b8 1195}
dc6d9681
JB
1196#endif
1197
1198#if 0
1199/* These functions have no C callers, and can be written nicely in lisp. */
dc6f92b8 1200
ff11dfa1
JB
1201DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 0, 0,
1202 "Return number of lines available for display on selected frame.")
dc6f92b8
JB
1203 ()
1204{
ff11dfa1 1205 return make_number (FRAME_HEIGHT (selected_frame));
dc6f92b8
JB
1206}
1207
ff11dfa1
JB
1208DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 0, 0,
1209 "Return number of columns available for display on selected frame.")
dc6f92b8
JB
1210 ()
1211{
ff11dfa1 1212 return make_number (FRAME_WIDTH (selected_frame));
dc6f92b8 1213}
dc6d9681 1214#endif
dc6f92b8 1215
ff11dfa1
JB
1216DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
1217 "Specify that the frame FRAME has LINES lines.\n\
dc6f92b8 1218Optional third arg non-nil means that redisplay should use LINES lines\n\
ff11dfa1
JB
1219but that the idea of the actual height of the frame should not be changed.")
1220 (frame, rows, pretend)
fd0c2bd1 1221 Lisp_Object frame, rows, pretend;
dc6f92b8 1222{
ff11dfa1 1223 register struct frame *f;
dc6f92b8
JB
1224
1225 CHECK_NUMBER (rows, 0);
ff11dfa1
JB
1226 if (NILP (frame))
1227 f = selected_frame;
dc6f92b8
JB
1228 else
1229 {
ff11dfa1
JB
1230 CHECK_LIVE_FRAME (frame, 0);
1231 f = XFRAME (frame);
dc6f92b8
JB
1232 }
1233
dbc4e1c1 1234 /* I think this should be done with a hook. */
fd0c2bd1
JB
1235#ifdef HAVE_X_WINDOWS
1236 if (FRAME_X_P (f))
dc6f92b8 1237 {
ff11dfa1
JB
1238 if (XINT (rows) != f->width)
1239 x_set_window_size (f, f->width, XINT (rows));
dc6f92b8
JB
1240 }
1241 else
fd0c2bd1
JB
1242#endif
1243 change_frame_size (f, XINT (rows), 0, !NILP (pretend), 0);
dc6f92b8
JB
1244 return Qnil;
1245}
1246
ff11dfa1
JB
1247DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
1248 "Specify that the frame FRAME has COLS columns.\n\
dc6f92b8 1249Optional third arg non-nil means that redisplay should use COLS columns\n\
ff11dfa1
JB
1250but that the idea of the actual width of the frame should not be changed.")
1251 (frame, cols, pretend)
fd0c2bd1 1252 Lisp_Object frame, cols, pretend;
dc6f92b8 1253{
ff11dfa1 1254 register struct frame *f;
dc6f92b8 1255 CHECK_NUMBER (cols, 0);
ff11dfa1
JB
1256 if (NILP (frame))
1257 f = selected_frame;
dc6f92b8
JB
1258 else
1259 {
ff11dfa1
JB
1260 CHECK_LIVE_FRAME (frame, 0);
1261 f = XFRAME (frame);
dc6f92b8
JB
1262 }
1263
dbc4e1c1 1264 /* I think this should be done with a hook. */
fd0c2bd1
JB
1265#ifdef HAVE_X_WINDOWS
1266 if (FRAME_X_P (f))
dc6f92b8 1267 {
ff11dfa1
JB
1268 if (XINT (cols) != f->width)
1269 x_set_window_size (f, XINT (cols), f->height);
dc6f92b8
JB
1270 }
1271 else
fd0c2bd1
JB
1272#endif
1273 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0);
dc6f92b8
JB
1274 return Qnil;
1275}
1276
ff11dfa1
JB
1277DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
1278 "Sets size of FRAME to COLS by ROWS, measured in characters.")
1279 (frame, cols, rows)
1280 Lisp_Object frame, cols, rows;
dc6f92b8 1281{
ff11dfa1 1282 register struct frame *f;
dc6f92b8
JB
1283 int mask;
1284
ff11dfa1 1285 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1286 CHECK_NUMBER (cols, 2);
1287 CHECK_NUMBER (rows, 1);
ff11dfa1 1288 f = XFRAME (frame);
dc6f92b8 1289
dbc4e1c1 1290 /* I think this should be done with a hook. */
fd0c2bd1
JB
1291#ifdef HAVE_X_WINDOWS
1292 if (FRAME_X_P (f))
dc6f92b8 1293 {
ff11dfa1
JB
1294 if (XINT (rows) != f->height || XINT (cols) != f->width)
1295 x_set_window_size (f, XINT (cols), XINT (rows));
dc6f92b8
JB
1296 }
1297 else
fd0c2bd1
JB
1298#endif
1299 change_frame_size (f, XINT (rows), XINT (cols), 0, 0);
dc6f92b8
JB
1300
1301 return Qnil;
1302}
1303
ff11dfa1
JB
1304DEFUN ("set-frame-position", Fset_frame_position,
1305 Sset_frame_position, 3, 3, 0,
1306 "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
f9898cc6 1307If XOFFSET or YOFFSET are negative, they are interpreted relative to\n\
ff11dfa1 1308the leftmost or bottommost position FRAME could occupy without going\n\
fd0c2bd1 1309off the screen.")
ff11dfa1
JB
1310 (frame, xoffset, yoffset)
1311 Lisp_Object frame, xoffset, yoffset;
dc6f92b8 1312{
ff11dfa1 1313 register struct frame *f;
dc6f92b8
JB
1314 int mask;
1315
ff11dfa1 1316 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1317 CHECK_NUMBER (xoffset, 1);
1318 CHECK_NUMBER (yoffset, 2);
ff11dfa1 1319 f = XFRAME (frame);
dc6f92b8 1320
dbc4e1c1 1321 /* I think this should be done with a hook. */
fd0c2bd1
JB
1322#ifdef HAVE_X_WINDOWS
1323 if (FRAME_X_P (f))
ff11dfa1 1324 x_set_offset (f, XINT (xoffset), XINT (yoffset));
fd0c2bd1 1325#endif
dc6f92b8
JB
1326
1327 return Qt;
1328}
dc6d9681 1329
dc6f92b8 1330\f
dc6f92b8
JB
1331#ifndef HAVE_X11
1332DEFUN ("rubber-band-rectangle", Frubber_band_rectangle, Srubber_band_rectangle,
1333 3, 3, "",
ff11dfa1
JB
1334 "Ask user to specify a window position and size on FRAME with the mouse.\n\
1335Arguments are FRAME, NAME and GEO. NAME is a name to be displayed as\n\
dc6f92b8
JB
1336the purpose of this rectangle. GEO is an X-windows size spec that can\n\
1337specify defaults for some sizes/positions. If GEO specifies everything,\n\
1338the mouse is not used.\n\
ff11dfa1
JB
1339Returns a list of five values: (FRAME LEFT TOP WIDTH HEIGHT).")
1340 (frame, name, geo)
1341 Lisp_Object frame;
dc6f92b8
JB
1342 Lisp_Object name;
1343 Lisp_Object geo;
1344{
1345 int vals[4];
1346 Lisp_Object nums[4];
1347 int i;
1348
ff11dfa1 1349 CHECK_FRAME (frame, 0);
dc6f92b8
JB
1350 CHECK_STRING (name, 1);
1351 CHECK_STRING (geo, 2);
1352
ff11dfa1 1353 switch (XFRAME (frame)->output_method)
dc6f92b8
JB
1354 {
1355 case output_x_window:
ff11dfa1 1356 x_rubber_band (XFRAME (frame), &vals[0], &vals[1], &vals[2], &vals[3],
dc6f92b8
JB
1357 XSTRING (geo)->data, XSTRING (name)->data);
1358 break;
1359
1360 default:
1361 return Qnil;
1362 }
1363
1364 for (i = 0; i < 4; i++)
1365 XFASTINT (nums[i]) = vals[i];
ff11dfa1 1366 return Fcons (frame, Flist (4, nums));
dc6f92b8
JB
1367 return Qnil;
1368}
1369#endif /* not HAVE_X11 */
1370\f
ff11dfa1 1371choose_minibuf_frame ()
dc6f92b8 1372{
ff11dfa1
JB
1373 /* For lowest-level minibuf, put it on currently selected frame
1374 if frame has a minibuffer. */
d06a8a56 1375
dc6f92b8 1376 if (minibuf_level == 0
ff11dfa1 1377 && selected_frame != 0
d06a8a56 1378 && !EQ (minibuf_window, selected_frame->minibuffer_window))
dc6f92b8 1379 {
d06a8a56
JB
1380 /* I don't think that any frames may validly have a null minibuffer
1381 window anymore. */
1382 if (NILP (selected_frame->minibuffer_window))
1383 abort ();
1384
ff11dfa1 1385 Fset_window_buffer (selected_frame->minibuffer_window,
dc6f92b8 1386 XWINDOW (minibuf_window)->buffer);
ff11dfa1 1387 minibuf_window = selected_frame->minibuffer_window;
dc6f92b8
JB
1388 }
1389}
1390\f
ff11dfa1 1391syms_of_frame ()
dc6f92b8 1392{
fd0c2bd1 1393 /*&&& init symbols here &&&*/
ff11dfa1 1394 Qframep = intern ("framep");
ff11dfa1 1395 staticpro (&Qframep);
dbc4e1c1
JB
1396 Qframe_live_p = intern ("frame-live-p");
1397 staticpro (&Qframe_live_p);
fd0c2bd1
JB
1398 Qheight = intern ("height");
1399 staticpro (&Qheight);
1400 Qicon = intern ("icon");
1401 staticpro (&Qicon);
1402 Qminibuffer = intern ("minibuffer");
bc93c097 1403 staticpro (&Qminibuffer);
fd0c2bd1
JB
1404 Qmodeline = intern ("modeline");
1405 staticpro (&Qmodeline);
1406 Qname = intern ("name");
1407 staticpro (&Qname);
fd0c2bd1
JB
1408 Qonly = intern ("only");
1409 staticpro (&Qonly);
1410 Qunsplittable = intern ("unsplittable");
1411 staticpro (&Qunsplittable);
1412 Qwidth = intern ("width");
1413 staticpro (&Qwidth);
1414 Qx = intern ("x");
1415 staticpro (&Qx);
dc6f92b8 1416
ff11dfa1 1417 staticpro (&Vframe_list);
dc6f92b8 1418
ff11dfa1
JB
1419 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
1420 "The initial frame-object, which represents Emacs's stdout.");
dc6f92b8
JB
1421
1422 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
ff11dfa1 1423 "Non-nil if all of emacs is iconified and frame updates are not needed.");
dc6f92b8
JB
1424 Vemacs_iconified = Qnil;
1425
ff11dfa1
JB
1426 DEFVAR_LISP ("default-minibuffer-frame", &Vdefault_minibuffer_frame,
1427 "Minibufferless frames use this frame's minibuffer.\n\
f9898cc6 1428\n\
ff11dfa1 1429Emacs cannot create minibufferless frames unless this is set to an\n\
f9898cc6
JB
1430appropriate surrogate.\n\
1431\n\
1432Emacs consults this variable only when creating minibufferless\n\
ff11dfa1 1433frames; once the frame is created, it sticks with its assigned\n\
f9898cc6
JB
1434minibuffer, no matter what this variable is set to. This means that\n\
1435this variable doesn't necessarily say anything meaningful about the\n\
ff11dfa1 1436current set of frames, or where the minibuffer is currently being\n\
f9898cc6 1437displayed.");
ff11dfa1 1438 Vdefault_minibuffer_frame = Qnil;
dc6f92b8 1439
ff11dfa1
JB
1440 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
1441 "Alist of default values for frame creation.\n\
5bce042c 1442These may be set in your init file, like this:\n\
ff11dfa1 1443 (setq default-frame-alist '((width . 80) (height . 55)))\n\
5bce042c
JB
1444These override values given in window system configuration data, like\n\
1445X Windows' defaults database.\n\
ff11dfa1
JB
1446For values specific to the first Emacs frame, see `initial-frame-alist'.\n\
1447For values specific to the separate minibuffer frame, see\n\
1448`minibuffer-frame-alist'.");
1449 Vdefault_frame_alist = Qnil;
1450
1451 defsubr (&Sframep);
dbc4e1c1 1452 defsubr (&Sframe_live_p);
ff11dfa1
JB
1453 defsubr (&Sselect_frame);
1454 defsubr (&Sselected_frame);
1455 defsubr (&Swindow_frame);
1456 defsubr (&Sframe_root_window);
1457 defsubr (&Sframe_selected_window);
1458 defsubr (&Sframe_list);
1459 defsubr (&Snext_frame);
1460 defsubr (&Sdelete_frame);
f9898cc6 1461 defsubr (&Smouse_position);
dc6f92b8
JB
1462 defsubr (&Sset_mouse_position);
1463#if 0
ff11dfa1
JB
1464 defsubr (&Sframe_configuration);
1465 defsubr (&Srestore_frame_configuration);
dc6f92b8 1466#endif
ff11dfa1
JB
1467 defsubr (&Smake_frame_visible);
1468 defsubr (&Smake_frame_invisible);
1469 defsubr (&Siconify_frame);
1470 defsubr (&Sframe_visible_p);
1471 defsubr (&Svisible_frame_list);
dbc4e1c1
JB
1472 defsubr (&Sframe_to_front);
1473 defsubr (&Sframe_to_back);
ff11dfa1
JB
1474 defsubr (&Sredirect_frame_focus);
1475 defsubr (&Sframe_focus);
1476 defsubr (&Sframe_parameters);
1477 defsubr (&Smodify_frame_parameters);
1265558a 1478#if 0
ff11dfa1
JB
1479 defsubr (&Sframe_pixel_size);
1480 defsubr (&Sframe_height);
1481 defsubr (&Sframe_width);
1265558a 1482#endif
ff11dfa1
JB
1483 defsubr (&Sset_frame_height);
1484 defsubr (&Sset_frame_width);
1485 defsubr (&Sset_frame_size);
1486 defsubr (&Sset_frame_position);
dc6f92b8
JB
1487#ifndef HAVE_X11
1488 defsubr (&Srubber_band_rectangle);
1489#endif /* HAVE_X11 */
1490}
e5d77022 1491
2f0b07e0
JB
1492keys_of_frame ()
1493{
1494 initial_define_lispy_key (global_map, "switch-frame", "select-frame");
1495}
1496
d06a8a56 1497#else /* not MULTI_FRAME */
fd0c2bd1 1498
cc38027b
JB
1499/* If we're not using multi-frame stuff, we still need to provide some
1500 support functions. */
1501
1502/* Unless this function is defined, providing set-frame-height and
1503 set-frame-width doesn't help compatibility any, since they both
1504 want this as their first argument. */
1505DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1506 "Return the frame that is now selected.")
1507 ()
1508{
1509 Lisp_Object tem;
1510 XFASTINT (tem) = 0;
1511 return tem;
1512}
fd0c2bd1
JB
1513
1514DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
1515 "Specify that the frame FRAME has LINES lines.\n\
1516Optional third arg non-nil means that redisplay should use LINES lines\n\
1517but that the idea of the actual height of the frame should not be changed.")
1518 (frame, rows, pretend)
1519 Lisp_Object frame, rows, pretend;
1520{
1521 CHECK_NUMBER (rows, 0);
1522
1523 change_frame_size (0, XINT (rows), 0, !NILP (pretend), 0);
1524 return Qnil;
1525}
1526
1527DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
1528 "Specify that the frame FRAME has COLS columns.\n\
1529Optional third arg non-nil means that redisplay should use COLS columns\n\
1530but that the idea of the actual width of the frame should not be changed.")
1531 (frame, cols, pretend)
1532 Lisp_Object frame, cols, pretend;
1533{
1534 CHECK_NUMBER (cols, 0);
1535
1536 change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
1537 return Qnil;
1538}
1539
1540DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
1541 "Sets size of FRAME to COLS by ROWS, measured in characters.")
1542 (frame, cols, rows)
1543 Lisp_Object frame, cols, rows;
1544{
1545 CHECK_NUMBER (cols, 2);
1546 CHECK_NUMBER (rows, 1);
1547
1548 change_frame_size (0, XINT (rows), XINT (cols), 0, 0);
1549
1550 return Qnil;
1551}
1552
cc38027b
JB
1553DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 0, 0,
1554 "Return number of lines available for display on selected frame.")
1555 ()
1556{
1557 return make_number (FRAME_HEIGHT (selected_frame));
1558}
1559
1560DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 0, 0,
1561 "Return number of columns available for display on selected frame.")
1562 ()
1563{
1564 return make_number (FRAME_WIDTH (selected_frame));
1565}
1566
1567/* These are for backward compatibility with Emacs 18. */
1568
fd0c2bd1
JB
1569DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
1570 "Tell redisplay that the screen has LINES lines.\n\
1571Optional second arg non-nil means that redisplay should use LINES lines\n\
1572but that the idea of the actual height of the screen should not be changed.")
1573 (lines, pretend)
1574 Lisp_Object lines, pretend;
1575{
1576 CHECK_NUMBER (lines, 0);
1577
1578 change_frame_size (0, XINT (lines), 0, !NILP (pretend), 0);
1579 return Qnil;
1580}
1581
1582DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
1583 "Tell redisplay that the screen has COLS columns.\n\
1584Optional second arg non-nil means that redisplay should use COLS columns\n\
1585but that the idea of the actual width of the screen should not be changed.")
1586 (cols, pretend)
1587 Lisp_Object cols, pretend;
1588{
1589 CHECK_NUMBER (cols, 0);
1590
1591 change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
1592 return Qnil;
1593}
1594
fd0c2bd1
JB
1595syms_of_frame ()
1596{
1597 defsubr (&Sset_frame_height);
1598 defsubr (&Sset_frame_width);
1599 defsubr (&Sset_frame_size);
1600 defsubr (&Sset_screen_height);
1601 defsubr (&Sset_screen_width);
1602 defsubr (&Sframe_height);
1603 Ffset (intern ("screen-height"), intern ("frame-height"));
1604 defsubr (&Sframe_width);
1605 Ffset (intern ("screen-width"), intern ("frame-width"));
1606}
1607
2f0b07e0
JB
1608keys_of_frame ()
1609{
1610}
1611
fd0c2bd1
JB
1612#endif /* not MULTI_FRAME */
1613
1614
1615
1616