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