(Fframe_list): Don't return a tooltip frame.
[bpt/emacs.git] / src / frame.c
CommitLineData
ff11dfa1 1/* Generic frame functions.
e9c96c62
GM
2 Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001
3 Free Software Foundation.
dc6f92b8
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
1113d9db 9the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
dc6f92b8 21
18160b98 22#include <config.h>
565620a5
RS
23
24#include <stdio.h>
cc38027b 25#include "lisp.h"
71025e5e 26#include "charset.h"
6d55d620 27#ifdef HAVE_X_WINDOWS
dfcf069d 28#include "xterm.h"
71025e5e 29#endif
8f23f280
AI
30#ifdef WINDOWSNT
31#include "w32term.h"
32#endif
1a578e9b
AC
33#ifdef macintosh
34#include "macterm.h"
35#endif
2538fae4
AI
36#include "buffer.h"
37/* These help us bind and responding to switch-frame events. */
38#include "commands.h"
39#include "keyboard.h"
cc38027b 40#include "frame.h"
a1dfb88a
KH
41#ifdef HAVE_WINDOW_SYSTEM
42#include "fontset.h"
43#endif
bc1ed486 44#include "termhooks.h"
dfcf069d 45#include "dispextern.h"
f769f1b2 46#include "window.h"
87485d6f
MW
47#ifdef MSDOS
48#include "msdos.h"
4aec4b29 49#include "dosfns.h"
87485d6f 50#endif
e5d77022 51
fd0c2bd1 52Lisp_Object Qframep;
dbc4e1c1 53Lisp_Object Qframe_live_p;
fd0c2bd1
JB
54Lisp_Object Qheight;
55Lisp_Object Qicon;
bc93c097 56Lisp_Object Qminibuffer;
fd0c2bd1
JB
57Lisp_Object Qmodeline;
58Lisp_Object Qname;
fd0c2bd1
JB
59Lisp_Object Qonly;
60Lisp_Object Qunsplittable;
fa8fdbf9 61Lisp_Object Qmenu_bar_lines;
9ea173e8 62Lisp_Object Qtool_bar_lines;
fd0c2bd1
JB
63Lisp_Object Qwidth;
64Lisp_Object Qx;
fbd6baed 65Lisp_Object Qw32;
bb221971 66Lisp_Object Qpc;
574a1a90 67Lisp_Object Qmac;
f7af3f7b 68Lisp_Object Qvisible;
329ca574 69Lisp_Object Qbuffer_predicate;
fa54c6ae 70Lisp_Object Qbuffer_list;
61eaa912 71Lisp_Object Qtitle;
8b60f7bc 72Lisp_Object Qdisplay_type;
6345f6aa 73Lisp_Object Qbackground_mode;
3df1fda2 74Lisp_Object Qinhibit_default_face_x_resources;
dc6f92b8 75
a249de79 76Lisp_Object Vterminal_frame;
a1aaa23f 77Lisp_Object Vdefault_frame_alist;
beb0bc36 78Lisp_Object Vmouse_position_function;
a249de79
RS
79\f
80static void
81set_menu_bar_lines_1 (window, n)
82 Lisp_Object window;
83 int n;
84{
85 struct window *w = XWINDOW (window);
86
57aeea1e 87 XSETFASTINT (w->last_modified, 0);
a249de79
RS
88 XSETFASTINT (w->top, XFASTINT (w->top) + n);
89 XSETFASTINT (w->height, XFASTINT (w->height) - n);
4336c705
GM
90
91 if (INTEGERP (w->orig_top))
92 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
93 if (INTEGERP (w->orig_height))
94 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
a249de79
RS
95
96 /* Handle just the top child in a vertical split. */
97 if (!NILP (w->vchild))
98 set_menu_bar_lines_1 (w->vchild, n);
99
100 /* Adjust all children in a horizontal split. */
101 for (window = w->hchild; !NILP (window); window = w->next)
102 {
103 w = XWINDOW (window);
104 set_menu_bar_lines_1 (window, n);
105 }
106}
107
e48f782c 108void
a249de79
RS
109set_menu_bar_lines (f, value, oldval)
110 struct frame *f;
111 Lisp_Object value, oldval;
112{
113 int nlines;
114 int olines = FRAME_MENU_BAR_LINES (f);
115
116 /* Right now, menu bars don't work properly in minibuf-only frames;
117 most of the commands try to apply themselves to the minibuffer
e3678b64 118 frame itself, and get an error because you can't switch buffers
a249de79
RS
119 in or split the minibuffer window. */
120 if (FRAME_MINIBUF_ONLY_P (f))
121 return;
122
123 if (INTEGERP (value))
124 nlines = XINT (value);
125 else
126 nlines = 0;
127
57aeea1e
RS
128 if (nlines != olines)
129 {
130 windows_or_buffers_changed++;
131 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
132 FRAME_MENU_BAR_LINES (f) = nlines;
133 set_menu_bar_lines_1 (f->root_window, nlines - olines);
18082e2d 134 adjust_glyphs (f);
57aeea1e 135 }
a249de79
RS
136}
137\f
a249de79
RS
138Lisp_Object Vemacs_iconified;
139Lisp_Object Vframe_list;
a249de79 140
2d764c78
EZ
141struct x_output tty_display;
142
dc6f92b8
JB
143extern Lisp_Object Vminibuffer_list;
144extern Lisp_Object get_minibuffer ();
84386599
RS
145extern Lisp_Object Fhandle_switch_frame ();
146extern Lisp_Object Fredirect_frame_focus ();
a54d3a73 147extern Lisp_Object x_get_focus_frame ();
dc6f92b8 148\f
ff11dfa1
JB
149DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
150 "Return non-nil if OBJECT is a frame.\n\
151Value is t for a termcap frame (a character-only terminal),\n\
87485d6f 152`x' for an Emacs frame that is really an X window,\n\
2d764c78
EZ
153`w32' for an Emacs frame that is a window on MS-Windows display,\n\
154`mac' for an Emacs frame on a Macintosh display,\n\
87485d6f 155`pc' for a direct-write MS-DOS frame.\n\
e6b27a8f 156See also `frame-live-p'.")
f9898cc6
JB
157 (object)
158 Lisp_Object object;
dc6f92b8 159{
e35d291d 160 if (!FRAMEP (object))
dc6f92b8 161 return Qnil;
ff11dfa1 162 switch (XFRAME (object)->output_method)
dc6f92b8
JB
163 {
164 case output_termcap:
165 return Qt;
166 case output_x_window:
fd0c2bd1 167 return Qx;
fbd6baed
GV
168 case output_w32:
169 return Qw32;
bb221971
RS
170 case output_msdos_raw:
171 return Qpc;
574a1a90
RS
172 case output_mac:
173 return Qmac;
dc6f92b8
JB
174 default:
175 abort ();
176 }
177}
178
dbc4e1c1 179DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
ff11dfa1
JB
180 "Return non-nil if OBJECT is a frame which has not been deleted.\n\
181Value is nil if OBJECT is not a live frame. If object is a live\n\
182frame, the return value indicates what sort of output device it is\n\
183displayed on. Value is t for a termcap frame (a character-only\n\
184terminal), `x' for an Emacs frame being displayed in an X window.")
f9898cc6
JB
185 (object)
186 Lisp_Object object;
187{
ff11dfa1
JB
188 return ((FRAMEP (object)
189 && FRAME_LIVE_P (XFRAME (object)))
190 ? Fframep (object)
f9898cc6
JB
191 : Qnil);
192}
193
ff11dfa1
JB
194struct frame *
195make_frame (mini_p)
dc6f92b8
JB
196 int mini_p;
197{
ff11dfa1
JB
198 Lisp_Object frame;
199 register struct frame *f;
dc6f92b8
JB
200 register Lisp_Object root_window;
201 register Lisp_Object mini_window;
e9c96c62
GM
202
203 f = allocate_frame ();
36af7d69 204 XSETFRAME (frame, f);
ff11dfa1 205
18082e2d
GM
206 f->desired_matrix = 0;
207 f->current_matrix = 0;
208 f->desired_pool = 0;
209 f->current_pool = 0;
210 f->glyphs_initialized_p = 0;
211 f->decode_mode_spec_buffer = 0;
ff11dfa1 212 f->visible = 0;
323405de 213 f->async_visible = 0;
7556890b 214 f->output_data.nothing = 0;
ff11dfa1 215 f->iconified = 0;
323405de 216 f->async_iconified = 0;
ff11dfa1
JB
217 f->wants_modeline = 1;
218 f->auto_raise = 0;
219 f->auto_lower = 0;
220 f->no_split = 0;
10689a01 221 f->garbaged = 1;
ff11dfa1 222 f->has_minibuffer = mini_p;
a42e9724 223 f->focus_frame = Qnil;
804518aa 224 f->explicit_name = 0;
fd2777e0 225 f->can_have_scroll_bars = 0;
3a43d2dd 226 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
ff11dfa1 227 f->param_alist = Qnil;
fd2777e0
JB
228 f->scroll_bars = Qnil;
229 f->condemned_scroll_bars = Qnil;
306cc902 230 f->face_alist = Qnil;
18082e2d 231 f->face_cache = NULL;
9dd935ee 232 f->menu_bar_items = Qnil;
c8b8e7e3
RS
233 f->menu_bar_vector = Qnil;
234 f->menu_bar_items_used = 0;
329ca574 235 f->buffer_predicate = Qnil;
fa54c6ae 236 f->buffer_list = Qnil;
b4f0ee5d
KH
237#ifdef MULTI_KBOARD
238 f->kboard = initial_kboard;
239#endif
aec6e486 240 f->namebuf = 0;
2b1c9cfb 241 f->title = Qnil;
18082e2d 242 f->menu_bar_window = Qnil;
9ea173e8 243 f->tool_bar_window = Qnil;
61752261 244 f->tool_bar_items = Qnil;
9ea173e8 245 f->desired_tool_bar_string = f->current_tool_bar_string = Qnil;
61752261 246 f->n_tool_bar_items = 0;
dc6f92b8 247
cc38027b 248 root_window = make_window ();
dc6f92b8
JB
249 if (mini_p)
250 {
cc38027b 251 mini_window = make_window ();
dc6f92b8
JB
252 XWINDOW (root_window)->next = mini_window;
253 XWINDOW (mini_window)->prev = root_window;
254 XWINDOW (mini_window)->mini_p = Qt;
ff11dfa1
JB
255 XWINDOW (mini_window)->frame = frame;
256 f->minibuffer_window = mini_window;
dc6f92b8
JB
257 }
258 else
259 {
260 mini_window = Qnil;
261 XWINDOW (root_window)->next = Qnil;
ff11dfa1 262 f->minibuffer_window = Qnil;
dc6f92b8
JB
263 }
264
ff11dfa1 265 XWINDOW (root_window)->frame = frame;
dc6f92b8
JB
266
267 /* 10 is arbitrary,
268 just so that there is "something there."
ff11dfa1 269 Correct size will be set up later with change_frame_size. */
dc6f92b8 270
3a43d2dd 271 SET_FRAME_WIDTH (f, 10);
ff11dfa1 272 f->height = 10;
dc6f92b8 273
f4e93c40
KH
274 XSETFASTINT (XWINDOW (root_window)->width, 10);
275 XSETFASTINT (XWINDOW (root_window)->height, (mini_p ? 9 : 10));
dc6f92b8
JB
276
277 if (mini_p)
278 {
f4e93c40
KH
279 XSETFASTINT (XWINDOW (mini_window)->width, 10);
280 XSETFASTINT (XWINDOW (mini_window)->top, 9);
281 XSETFASTINT (XWINDOW (mini_window)->height, 1);
dc6f92b8
JB
282 }
283
ff11dfa1 284 /* Choose a buffer for the frame's root window. */
5bce042c
JB
285 {
286 Lisp_Object buf;
287
288 XWINDOW (root_window)->buffer = Qt;
289 buf = Fcurrent_buffer ();
290 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
291 a space), try to find another one. */
292 if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
98ce1622 293 buf = Fother_buffer (buf, Qnil, Qnil);
fa54c6ae 294
18082e2d
GM
295 /* Use set_window_buffer, not Fset_window_buffer, and don't let
296 hooks be run by it. The reason is that the whole frame/window
297 arrangement is not yet fully intialized at this point. Windows
298 don't have the right size, glyph matrices aren't initialized
299 etc. Running Lisp functions at this point surely ends in a
300 SEGV. */
301 set_window_buffer (root_window, buf, 0);
fa54c6ae 302 f->buffer_list = Fcons (buf, Qnil);
5bce042c
JB
303 }
304
dc6f92b8
JB
305 if (mini_p)
306 {
307 XWINDOW (mini_window)->buffer = Qt;
18082e2d
GM
308 set_window_buffer (mini_window,
309 (NILP (Vminibuffer_list)
310 ? get_minibuffer (0)
311 : Fcar (Vminibuffer_list)),
312 0);
dc6f92b8
JB
313 }
314
ff11dfa1
JB
315 f->root_window = root_window;
316 f->selected_window = root_window;
d5e7c279
JB
317 /* Make sure this window seems more recently used than
318 a newly-created, never-selected window. */
f4e93c40 319 XSETFASTINT (XWINDOW (f->selected_window)->use_time, ++window_select_count);
dc6f92b8 320
ff11dfa1 321 return f;
dc6f92b8
JB
322}
323\f
bba88bb1 324#ifdef HAVE_WINDOW_SYSTEM
ff11dfa1 325/* Make a frame using a separate minibuffer window on another frame.
dc6f92b8
JB
326 MINI_WINDOW is the minibuffer window to use. nil means use the
327 default (the global minibuffer). */
328
ff11dfa1 329struct frame *
b0660239 330make_frame_without_minibuffer (mini_window, kb, display)
dc6f92b8 331 register Lisp_Object mini_window;
662ac59a 332 KBOARD *kb;
b0660239 333 Lisp_Object display;
dc6f92b8 334{
ff11dfa1 335 register struct frame *f;
363b873b 336 struct gcpro gcpro1;
dc6f92b8 337
b0660239
KH
338 if (!NILP (mini_window))
339 CHECK_LIVE_WINDOW (mini_window, 0);
dc6f92b8 340
662ac59a 341#ifdef MULTI_KBOARD
b0660239
KH
342 if (!NILP (mini_window)
343 && XFRAME (XWINDOW (mini_window)->frame)->kboard != kb)
662ac59a
KH
344 error ("frame and minibuffer must be on the same display");
345#endif
346
ff11dfa1
JB
347 /* Make a frame containing just a root window. */
348 f = make_frame (0);
dc6f92b8 349
b0660239
KH
350 if (NILP (mini_window))
351 {
352 /* Use default-minibuffer-frame if possible. */
353 if (!FRAMEP (kb->Vdefault_minibuffer_frame)
354 || ! FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame)))
355 {
363b873b
RS
356 Lisp_Object frame_dummy;
357
358 XSETFRAME (frame_dummy, f);
359 GCPRO1 (frame_dummy);
b0660239 360 /* If there's no minibuffer frame to use, create one. */
363b873b
RS
361 kb->Vdefault_minibuffer_frame =
362 call1 (intern ("make-initial-minibuffer-frame"), display);
363 UNGCPRO;
b0660239 364 }
363b873b 365
b0660239
KH
366 mini_window = XFRAME (kb->Vdefault_minibuffer_frame)->minibuffer_window;
367 }
a2812a26 368
ff11dfa1 369 f->minibuffer_window = mini_window;
a2812a26
RS
370
371 /* Make the chosen minibuffer window display the proper minibuffer,
372 unless it is already showing a minibuffer. */
373 if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
374 Fset_window_buffer (mini_window,
375 (NILP (Vminibuffer_list)
376 ? get_minibuffer (0)
377 : Fcar (Vminibuffer_list)));
ff11dfa1 378 return f;
dc6f92b8
JB
379}
380
ff11dfa1 381/* Make a frame containing only a minibuffer window. */
dc6f92b8 382
ff11dfa1
JB
383struct frame *
384make_minibuffer_frame ()
dc6f92b8 385{
ff11dfa1 386 /* First make a frame containing just a root window, no minibuffer. */
dc6f92b8 387
ff11dfa1 388 register struct frame *f = make_frame (0);
dc6f92b8 389 register Lisp_Object mini_window;
ff11dfa1 390 register Lisp_Object frame;
dc6f92b8 391
2d80a27a 392 XSETFRAME (frame, f);
dc6f92b8 393
804518aa 394 f->auto_raise = 0;
ff11dfa1
JB
395 f->auto_lower = 0;
396 f->no_split = 1;
397 f->wants_modeline = 0;
398 f->has_minibuffer = 1;
dc6f92b8
JB
399
400 /* Now label the root window as also being the minibuffer.
401 Avoid infinite looping on the window chain by marking next pointer
402 as nil. */
403
ff11dfa1 404 mini_window = f->minibuffer_window = f->root_window;
dc6f92b8
JB
405 XWINDOW (mini_window)->mini_p = Qt;
406 XWINDOW (mini_window)->next = Qnil;
804518aa 407 XWINDOW (mini_window)->prev = Qnil;
ff11dfa1 408 XWINDOW (mini_window)->frame = frame;
dc6f92b8
JB
409
410 /* Put the proper buffer in that window. */
411
412 Fset_window_buffer (mini_window,
265a9e55 413 (NILP (Vminibuffer_list)
dc6f92b8
JB
414 ? get_minibuffer (0)
415 : Fcar (Vminibuffer_list)));
ff11dfa1 416 return f;
dc6f92b8 417}
bba88bb1 418#endif /* HAVE_WINDOW_SYSTEM */
dc6f92b8 419\f
ff11dfa1 420/* Construct a frame that refers to the terminal (stdin and stdout). */
dc6f92b8 421
bb1513c9
RS
422static int terminal_frame_count;
423
ff11dfa1
JB
424struct frame *
425make_terminal_frame ()
dc6f92b8 426{
ff11dfa1 427 register struct frame *f;
d063751a 428 Lisp_Object frame;
bb1513c9
RS
429 char name[20];
430
b4f0ee5d
KH
431#ifdef MULTI_KBOARD
432 if (!initial_kboard)
433 {
434 initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
435 init_kboard (initial_kboard);
a1b658dd
KH
436 initial_kboard->next_kboard = all_kboards;
437 all_kboards = initial_kboard;
b4f0ee5d
KH
438 }
439#endif
440
bb1513c9
RS
441 /* The first call must initialize Vframe_list. */
442 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
443 Vframe_list = Qnil;
ff11dfa1 444
ff11dfa1 445 f = make_frame (1);
d063751a 446
2d80a27a 447 XSETFRAME (frame, f);
d063751a
RS
448 Vframe_list = Fcons (frame, Vframe_list);
449
bb1513c9 450 terminal_frame_count++;
0303e8da
RS
451 sprintf (name, "F%d", terminal_frame_count);
452 f->name = build_string (name);
bb1513c9 453
bb1513c9
RS
454 f->visible = 1; /* FRAME_SET_VISIBLE wd set frame_garbaged. */
455 f->async_visible = 1; /* Don't let visible be cleared later. */
bb221971
RS
456#ifdef MSDOS
457 f->output_data.x = &the_only_x_display;
2d764c78
EZ
458 if (!inhibit_window_system
459 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
460 || XFRAME (selected_frame)->output_method == output_msdos_raw))
65606f5e
EZ
461 {
462 f->output_method = output_msdos_raw;
463 /* This initialization of foreground and background pixels is
464 only important for the initial frame created in temacs. If
465 we don't do that, we get black background and foreground in
466 the dumped Emacs because the_only_x_display is a static
467 variable, hence it is born all-zeroes, and zero is the code
468 for the black color. Other frames all inherit their pixels
469 from what's already in the_only_x_display. */
470 if ((!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
471 && f->output_data.x->background_pixel == 0
472 && f->output_data.x->foreground_pixel == 0)
473 {
474 f->output_data.x->background_pixel = FACE_TTY_DEFAULT_BG_COLOR;
475 f->output_data.x->foreground_pixel = FACE_TTY_DEFAULT_FG_COLOR;
476 }
477 }
2d764c78
EZ
478 else
479 f->output_method = output_termcap;
480#else
4ec0d3c1 481#ifdef WINDOWSNT
ff8d4bf4 482 f->output_method = output_termcap;
4ec0d3c1
AI
483 f->output_data.x = &tty_display;
484#else
574a1a90 485#ifdef macintosh
1a578e9b
AC
486 make_mac_terminal_frame (f);
487#else
2d764c78 488 f->output_data.x = &tty_display;
1a578e9b 489#endif /* macintosh */
4ec0d3c1 490#endif /* WINDOWSNT */
2d764c78 491#endif /* MSDOS */
574a1a90 492
1a6d3623
EZ
493 if (!noninteractive)
494 init_frame_faces (f);
1a578e9b 495
ff11dfa1 496 return f;
dc6f92b8 497}
bb1513c9
RS
498
499DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
4bc7e3ad
RS
500 1, 1, 0, "Create an additional terminal frame.\n\
501You can create multiple frames on a text-only terminal in this way.\n\
502Only the selected terminal frame is actually displayed.\n\
503This function takes one argument, an alist specifying frame parameters.\n\
504In practice, generally you don't need to specify any parameters.\n\
505Note that changing the size of one terminal frame automatically affects all.")
bb1513c9
RS
506 (parms)
507 Lisp_Object parms;
508{
509 struct frame *f;
574a1a90 510 Lisp_Object frame, tem;
8d2666fe 511 struct frame *sf = SELECTED_FRAME ();
bb1513c9 512
541580aa 513#ifdef MSDOS
2d764c78
EZ
514 if (sf->output_method != output_msdos_raw
515 && sf->output_method != output_termcap)
bb221971 516 abort ();
574a1a90
RS
517#else /* not MSDOS */
518
519#ifdef macintosh
8d2666fe 520 if (sf->output_method != output_mac)
574a1a90 521 error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
bb221971 522#else
8d2666fe 523 if (sf->output_method != output_termcap)
bb1513c9 524 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
bb221971 525#endif
574a1a90 526#endif /* not MSDOS */
bb1513c9
RS
527
528 f = make_terminal_frame ();
574a1a90 529
8d2666fe
GM
530 change_frame_size (f, FRAME_HEIGHT (sf),
531 FRAME_WIDTH (sf), 0, 0, 0);
18082e2d 532 adjust_glyphs (f);
bb1513c9
RS
533 calculate_costs (f);
534 XSETFRAME (frame, f);
8adfc1ec 535 Fmodify_frame_parameters (frame, Vdefault_frame_alist);
bb1513c9 536 Fmodify_frame_parameters (frame, parms);
87f1940e
EZ
537
538 /* Make the frame face alist be frame-specific, so that each
539 frame could change its face definitions independently. */
8d2666fe 540 f->face_alist = Fcopy_alist (sf->face_alist);
87f1940e
EZ
541 /* Simple Fcopy_alist isn't enough, because we need the contents of
542 the vectors which are the CDRs of associations in face_alist to
543 be copied as well. */
544 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
545 XCDR (XCAR (tem)) = Fcopy_sequence (XCDR (XCAR (tem)));
bb1513c9
RS
546 return frame;
547}
1e8324d9 548
dc6f92b8 549\f
1e8324d9
GM
550/* Perform the switch to frame FRAME.
551
552 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
553 FRAME1 as frame.
554
555 If TRACK is non-zero and the frame that currently has the focus
556 redirects its focus to the selected frame, redirect that focused
557 frame's focus to FRAME instead.
558
559 FOR_DELETION non-zero means that the selected frame is being
560 deleted, which includes the possibility that the frame's display
561 is dead. */
562
61f94483 563Lisp_Object
1e8324d9
GM
564do_switch_frame (frame, track, for_deletion)
565 Lisp_Object frame;
566 int track, for_deletion;
dc6f92b8 567{
8d2666fe
GM
568 struct frame *sf = SELECTED_FRAME ();
569
2f0b07e0
JB
570 /* If FRAME is a switch-frame event, extract the frame we should
571 switch to. */
572 if (CONSP (frame)
7539e11f
KR
573 && EQ (XCAR (frame), Qswitch_frame)
574 && CONSP (XCDR (frame)))
575 frame = XCAR (XCDR (frame));
2f0b07e0 576
09907c3a
KH
577 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
578 a switch-frame event to arrive after a frame is no longer live,
579 especially when deleting the initial frame during startup. */
580 CHECK_FRAME (frame, 0);
581 if (! FRAME_LIVE_P (XFRAME (frame)))
582 return Qnil;
dc6f92b8 583
8d2666fe 584 if (sf == XFRAME (frame))
ff11dfa1 585 return frame;
dc6f92b8 586
0aed85f4
KH
587 /* This is too greedy; it causes inappropriate focus redirection
588 that's hard to get rid of. */
589#if 0
a42e9724
JB
590 /* If a frame's focus has been redirected toward the currently
591 selected frame, we should change the redirection to point to the
592 newly selected frame. This means that if the focus is redirected
593 from a minibufferless frame to a surrogate minibuffer frame, we
594 can use `other-window' to switch between all the frames using
595 that minibuffer frame, and the focus redirection will follow us
596 around. */
0aed85f4
KH
597 if (track)
598 {
599 Lisp_Object tail;
a42e9724 600
7539e11f 601 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
0aed85f4
KH
602 {
603 Lisp_Object focus;
a42e9724 604
7539e11f 605 if (!FRAMEP (XCAR (tail)))
0aed85f4 606 abort ();
a42e9724 607
7539e11f 608 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
a42e9724 609
8d2666fe 610 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
7539e11f 611 Fredirect_frame_focus (XCAR (tail), frame);
0aed85f4
KH
612 }
613 }
614#else /* ! 0 */
615 /* Instead, apply it only to the frame we're pointing to. */
032d78fe 616#ifdef HAVE_WINDOW_SYSTEM
1e8324d9 617 if (track && FRAME_WINDOW_P (XFRAME (frame)))
0aed85f4
KH
618 {
619 Lisp_Object focus, xfocus;
620
d7266360 621 xfocus = x_get_focus_frame (XFRAME (frame));
0aed85f4
KH
622 if (FRAMEP (xfocus))
623 {
624 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
8d2666fe 625 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
0aed85f4
KH
626 Fredirect_frame_focus (xfocus, frame);
627 }
628 }
629#endif /* HAVE_X_WINDOWS */
630#endif /* ! 0 */
a42e9724 631
1e8324d9 632 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
550f0e6a
GM
633 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
634
8d2666fe
GM
635 selected_frame = frame;
636 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
637 last_nonminibuf_frame = XFRAME (selected_frame);
d5e7c279 638
ff11dfa1 639 Fselect_window (XFRAME (frame)->selected_window);
dc6f92b8 640
074577b8 641 /* We want to make sure that the next event generates a frame-switch
eb8c3be9 642 event to the appropriate frame. This seems kludgy to me, but
074577b8
JB
643 before you take it out, make sure that evaluating something like
644 (select-window (frame-root-window (new-frame))) doesn't end up
645 with your typing being interpreted in the new frame instead of
646 the one you're actually typing in. */
ef352596 647 internal_last_event_frame = Qnil;
074577b8 648
ff11dfa1 649 return frame;
dc6f92b8
JB
650}
651
0aed85f4
KH
652DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
653 "Select the frame FRAME.\n\
654Subsequent editing commands apply to its selected window.\n\
655The selection of FRAME lasts until the next time the user does\n\
656something to select a different frame, or until the next time this\n\
657function is called.")
658 (frame, no_enter)
659 Lisp_Object frame, no_enter;
660{
1e8324d9 661 return do_switch_frame (frame, 1, 0);
0aed85f4
KH
662}
663
664
665DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
666 "Handle a switch-frame event EVENT.\n\
667Switch-frame events are usually bound to this function.\n\
668A switch-frame event tells Emacs that the window manager has requested\n\
669that the user's events be directed to the frame mentioned in the event.\n\
670This function selects the selected window of the frame of EVENT.\n\
671\n\
672If EVENT is frame object, handle it as if it were a switch-frame event\n\
673to that frame.")
735eeca3
EN
674 (event, no_enter)
675 Lisp_Object event, no_enter;
0aed85f4 676{
6951cd71
KH
677 /* Preserve prefix arg that the command loop just cleared. */
678 current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
e05169e2 679 call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
1e8324d9 680 return do_switch_frame (event, 0, 0);
0aed85f4
KH
681}
682
1c212787
KH
683DEFUN ("ignore-event", Fignore_event, Signore_event, 0, 0, "",
684 "Do nothing, but preserve any prefix argument already specified.\n\
685This is a suitable binding for iconify-frame and make-frame-visible.")
686 ()
687{
688 current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
689 return Qnil;
690}
0aed85f4 691
ff11dfa1
JB
692DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
693 "Return the frame that is now selected.")
dc6f92b8
JB
694 ()
695{
8d2666fe 696 return selected_frame;
dc6f92b8 697}
4a7cfafc 698\f
ff11dfa1
JB
699DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
700 "Return the frame object that window WINDOW is on.")
dc6f92b8
JB
701 (window)
702 Lisp_Object window;
703{
774910eb 704 CHECK_LIVE_WINDOW (window, 0);
ff11dfa1 705 return XWINDOW (window)->frame;
dc6f92b8
JB
706}
707
ba32f2db
KH
708DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
709 "Returns the topmost, leftmost window of FRAME.\n\
710If omitted, FRAME defaults to the currently selected frame.")
711 (frame)
712 Lisp_Object frame;
713{
714 Lisp_Object w;
715
716 if (NILP (frame))
8d2666fe 717 w = SELECTED_FRAME ()->root_window;
ba32f2db
KH
718 else
719 {
720 CHECK_LIVE_FRAME (frame, 0);
721 w = XFRAME (frame)->root_window;
722 }
723 while (NILP (XWINDOW (w)->buffer))
724 {
725 if (! NILP (XWINDOW (w)->hchild))
726 w = XWINDOW (w)->hchild;
727 else if (! NILP (XWINDOW (w)->vchild))
728 w = XWINDOW (w)->vchild;
729 else
730 abort ();
731 }
732 return w;
733}
734
5add3885
RS
735DEFUN ("active-minibuffer-window", Factive_minibuffer_window,
736 Sactive_minibuffer_window, 0, 0, 0,
737 "Return the currently active minibuffer window, or nil if none.")
738 ()
739{
740 return minibuf_level ? minibuf_window : Qnil;
741}
742
ff11dfa1 743DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
8693ca83
JB
744 "Returns the root-window of FRAME.\n\
745If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
746 (frame)
747 Lisp_Object frame;
dc6f92b8 748{
8d2666fe
GM
749 Lisp_Object window;
750
ff11dfa1 751 if (NILP (frame))
8d2666fe 752 window = SELECTED_FRAME ()->root_window;
f9898cc6 753 else
8d2666fe
GM
754 {
755 CHECK_LIVE_FRAME (frame, 0);
756 window = XFRAME (frame)->root_window;
757 }
758
759 return window;
dc6f92b8
JB
760}
761
ff11dfa1
JB
762DEFUN ("frame-selected-window", Fframe_selected_window,
763 Sframe_selected_window, 0, 1, 0,
8693ca83
JB
764 "Return the selected window of frame object FRAME.\n\
765If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
766 (frame)
767 Lisp_Object frame;
dc6f92b8 768{
8d2666fe
GM
769 Lisp_Object window;
770
ff11dfa1 771 if (NILP (frame))
8d2666fe 772 window = SELECTED_FRAME ()->selected_window;
f9898cc6 773 else
8d2666fe
GM
774 {
775 CHECK_LIVE_FRAME (frame, 0);
776 window = XFRAME (frame)->selected_window;
777 }
dc6f92b8 778
8d2666fe 779 return window;
dc6f92b8
JB
780}
781
4a7cfafc
RS
782DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
783 Sset_frame_selected_window, 2, 2, 0,
784 "Set the selected window of frame object FRAME to WINDOW.\n\
785If FRAME is nil, the selected frame is used.\n\
786If FRAME is the selected frame, this makes WINDOW the selected window.")
787 (frame, window)
788 Lisp_Object frame, window;
789{
790 if (NILP (frame))
8d2666fe
GM
791 frame = selected_frame;
792
793 CHECK_LIVE_FRAME (frame, 0);
4a7cfafc
RS
794 CHECK_LIVE_WINDOW (window, 1);
795
796 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
797 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
798
8d2666fe 799 if (EQ (frame, selected_frame))
4a7cfafc
RS
800 return Fselect_window (window);
801
802 return XFRAME (frame)->selected_window = window;
803}
804\f
ff11dfa1 805DEFUN ("frame-list", Fframe_list, Sframe_list,
dc6f92b8 806 0, 0, 0,
ff11dfa1 807 "Return a list of all frames.")
dc6f92b8
JB
808 ()
809{
d74c1900
GM
810 Lisp_Object frames;
811 frames = Fcopy_sequence (Vframe_list);
812 if (FRAMEP (tip_frame))
813 frames = Fdelq (tip_frame, frames);
814 return frames;
dc6f92b8
JB
815}
816
ff11dfa1 817/* Return the next frame in the frame list after FRAME.
ff11dfa1 818 If MINIBUF is nil, exclude minibuffer-only frames.
a9986780
RS
819 If MINIBUF is a window, include only its own frame
820 and any frame now using that window as the minibuffer.
f7af3f7b 821 If MINIBUF is `visible', include all visible frames.
a9986780 822 If MINIBUF is 0, include all visible and iconified frames.
f7af3f7b
RS
823 Otherwise, include all frames. */
824
dc6f92b8 825Lisp_Object
ff11dfa1
JB
826next_frame (frame, minibuf)
827 Lisp_Object frame;
f9898cc6 828 Lisp_Object minibuf;
dc6f92b8
JB
829{
830 Lisp_Object tail;
831 int passed = 0;
832
ff11dfa1
JB
833 /* There must always be at least one frame in Vframe_list. */
834 if (! CONSP (Vframe_list))
f9898cc6
JB
835 abort ();
836
dbc4e1c1
JB
837 /* If this frame is dead, it won't be in Vframe_list, and we'll loop
838 forever. Forestall that. */
839 CHECK_LIVE_FRAME (frame, 0);
840
dc6f92b8 841 while (1)
7539e11f 842 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
dc6f92b8 843 {
ab9f008d 844 Lisp_Object f;
d06a8a56 845
7539e11f 846 f = XCAR (tail);
06537cc8
RS
847
848 if (passed
849 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
d5e7c279 850 {
d06a8a56
JB
851 /* Decide whether this frame is eligible to be returned. */
852
853 /* If we've looped all the way around without finding any
854 eligible frames, return the original frame. */
855 if (EQ (f, frame))
856 return f;
857
858 /* Let minibuf decide if this frame is acceptable. */
859 if (NILP (minibuf))
860 {
861 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
862 return f;
863 }
f7af3f7b
RS
864 else if (EQ (minibuf, Qvisible))
865 {
866 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
867 if (FRAME_VISIBLE_P (XFRAME (f)))
868 return f;
869 }
3780bc22 870 else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
a9986780
RS
871 {
872 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
873 if (FRAME_VISIBLE_P (XFRAME (f))
874 || FRAME_ICONIFIED_P (XFRAME (f)))
875 return f;
876 }
f7af3f7b 877 else if (WINDOWP (minibuf))
d06a8a56 878 {
a9986780 879 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
551645f8
GM
880 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
881 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
882 FRAME_FOCUS_FRAME (XFRAME (f))))
d06a8a56
JB
883 return f;
884 }
885 else
ff11dfa1 886 return f;
d5e7c279 887 }
dc6f92b8 888
d06a8a56 889 if (EQ (frame, f))
dc6f92b8
JB
890 passed++;
891 }
892}
893
ff11dfa1 894/* Return the previous frame in the frame list before FRAME.
ff11dfa1 895 If MINIBUF is nil, exclude minibuffer-only frames.
a9986780
RS
896 If MINIBUF is a window, include only its own frame
897 and any frame now using that window as the minibuffer.
f7af3f7b 898 If MINIBUF is `visible', include all visible frames.
a9986780 899 If MINIBUF is 0, include all visible and iconified frames.
f7af3f7b
RS
900 Otherwise, include all frames. */
901
dc6f92b8 902Lisp_Object
ff11dfa1
JB
903prev_frame (frame, minibuf)
904 Lisp_Object frame;
f9898cc6 905 Lisp_Object minibuf;
dc6f92b8
JB
906{
907 Lisp_Object tail;
908 Lisp_Object prev;
909
ff11dfa1
JB
910 /* There must always be at least one frame in Vframe_list. */
911 if (! CONSP (Vframe_list))
f9898cc6
JB
912 abort ();
913
dc6f92b8 914 prev = Qnil;
7539e11f 915 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
f9898cc6 916 {
ab9f008d 917 Lisp_Object f;
f9898cc6 918
7539e11f 919 f = XCAR (tail);
e35d291d 920 if (!FRAMEP (f))
d06a8a56 921 abort ();
f9898cc6 922
d06a8a56
JB
923 if (EQ (frame, f) && !NILP (prev))
924 return prev;
f9898cc6 925
06537cc8 926 if (FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
f7af3f7b 927 {
06537cc8
RS
928 /* Decide whether this frame is eligible to be returned,
929 according to minibuf. */
930 if (NILP (minibuf))
931 {
932 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
933 prev = f;
934 }
935 else if (WINDOWP (minibuf))
936 {
937 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
551645f8
GM
938 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
939 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
940 FRAME_FOCUS_FRAME (XFRAME (f))))
06537cc8
RS
941 prev = f;
942 }
943 else if (EQ (minibuf, Qvisible))
944 {
945 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
946 if (FRAME_VISIBLE_P (XFRAME (f)))
947 prev = f;
948 }
949 else if (XFASTINT (minibuf) == 0)
950 {
951 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
952 if (FRAME_VISIBLE_P (XFRAME (f))
953 || FRAME_ICONIFIED_P (XFRAME (f)))
954 prev = f;
955 }
956 else
a9986780
RS
957 prev = f;
958 }
f9898cc6 959 }
d06a8a56
JB
960
961 /* We've scanned the entire list. */
962 if (NILP (prev))
963 /* We went through the whole frame list without finding a single
964 acceptable frame. Return the original frame. */
965 return frame;
966 else
967 /* There were no acceptable frames in the list before FRAME; otherwise,
968 we would have returned directly from the loop. Since PREV is the last
969 acceptable frame in the list, return it. */
970 return prev;
dc6f92b8
JB
971}
972
ef2c57ac 973
ff11dfa1
JB
974DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
975 "Return the next frame in the frame list after FRAME.\n\
06537cc8 976It considers only frames on the same terminal as FRAME.\n\
a42e9724 977By default, skip minibuffer-only frames.\n\
d06a8a56 978If omitted, FRAME defaults to the selected frame.\n\
c08c95c7 979If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
06537cc8 980If MINIFRAME is a window, include only its own frame\n\
a9986780 981and any frame now using that window as the minibuffer.\n\
f7af3f7b 982If MINIFRAME is `visible', include all visible frames.\n\
06537cc8 983If MINIFRAME is 0, include all visible and iconified frames.\n\
f7af3f7b 984Otherwise, include all frames.")
ff11dfa1 985 (frame, miniframe)
8693ca83 986 Lisp_Object frame, miniframe;
dc6f92b8 987{
ff11dfa1 988 if (NILP (frame))
8d2666fe
GM
989 frame = selected_frame;
990
991 CHECK_LIVE_FRAME (frame, 0);
ff11dfa1 992 return next_frame (frame, miniframe);
dc6f92b8 993}
dbc4e1c1 994
ef2c57ac
RM
995DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
996 "Return the previous frame in the frame list before FRAME.\n\
06537cc8 997It considers only frames on the same terminal as FRAME.\n\
ef2c57ac
RM
998By default, skip minibuffer-only frames.\n\
999If omitted, FRAME defaults to the selected frame.\n\
1000If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
06537cc8 1001If MINIFRAME is a window, include only its own frame\n\
a9986780 1002and any frame now using that window as the minibuffer.\n\
f7af3f7b 1003If MINIFRAME is `visible', include all visible frames.\n\
06537cc8 1004If MINIFRAME is 0, include all visible and iconified frames.\n\
f7af3f7b 1005Otherwise, include all frames.")
ef2c57ac
RM
1006 (frame, miniframe)
1007 Lisp_Object frame, miniframe;
1008{
ef2c57ac 1009 if (NILP (frame))
8d2666fe
GM
1010 frame = selected_frame;
1011 CHECK_LIVE_FRAME (frame, 0);
ef2c57ac
RM
1012 return prev_frame (frame, miniframe);
1013}
dc6f92b8 1014\f
808c0f20
RS
1015/* Return 1 if it is ok to delete frame F;
1016 0 if all frames aside from F are invisible.
1017 (Exception: if F is the terminal frame, and we are using X, return 1.) */
dc6f92b8 1018
d56b45eb 1019int
808c0f20
RS
1020other_visible_frames (f)
1021 FRAME_PTR f;
1022{
1023 /* We know the selected frame is visible,
1024 so if F is some other frame, it can't be the sole visible one. */
8d2666fe 1025 if (f == SELECTED_FRAME ())
c08c95c7
RS
1026 {
1027 Lisp_Object frames;
1028 int count = 0;
1029
1030 for (frames = Vframe_list;
1031 CONSP (frames);
7539e11f 1032 frames = XCDR (frames))
c08c95c7 1033 {
ab9f008d 1034 Lisp_Object this;
c08c95c7 1035
7539e11f 1036 this = XCAR (frames);
808c0f20
RS
1037 /* Verify that the frame's window still exists
1038 and we can still talk to it. And note any recent change
1039 in visibility. */
032d78fe
GV
1040#ifdef HAVE_WINDOW_SYSTEM
1041 if (FRAME_WINDOW_P (XFRAME (this)))
5e7b7c5b 1042 {
b0509a40 1043 x_sync (XFRAME (this));
5e7b7c5b
RS
1044 FRAME_SAMPLE_VISIBILITY (XFRAME (this));
1045 }
1046#endif
1047
c08c95c7
RS
1048 if (FRAME_VISIBLE_P (XFRAME (this))
1049 || FRAME_ICONIFIED_P (XFRAME (this))
1050 /* Allow deleting the terminal frame when at least
1051 one X frame exists! */
032d78fe 1052 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
c08c95c7
RS
1053 count++;
1054 }
808c0f20 1055 return count > 1;
c08c95c7 1056 }
808c0f20
RS
1057 return 1;
1058}
1059
1060DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
1061 "Delete FRAME, permanently eliminating it from use.\n\
1062If omitted, FRAME defaults to the selected frame.\n\
1063A frame may not be deleted if its minibuffer is used by other frames.\n\
1064Normally, you may not delete a frame if all other frames are invisible,\n\
0e662342
GM
1065but if the second optional argument FORCE is non-nil, you may do so.\n\
1066\n\
1067This function runs `delete-frame-hook' before actually deleting the\n\
1068frame. The hook is called with one argument FRAME.")
808c0f20
RS
1069 (frame, force)
1070 Lisp_Object frame, force;
1071{
1072 struct frame *f;
8d2666fe 1073 struct frame *sf = SELECTED_FRAME ();
99b92e64 1074 int minibuffer_selected;
808c0f20
RS
1075
1076 if (EQ (frame, Qnil))
1077 {
8d2666fe 1078 f = sf;
2d80a27a 1079 XSETFRAME (frame, f);
808c0f20
RS
1080 }
1081 else
1082 {
1083 CHECK_FRAME (frame, 0);
1084 f = XFRAME (frame);
1085 }
1086
1087 if (! FRAME_LIVE_P (f))
1088 return Qnil;
1089
83a96b4d
AC
1090 if (NILP (force) && !other_visible_frames (f)
1091#ifdef macintosh
1092 /* Terminal frame deleted before any other visible frames are
1093 created. */
1094 && strcmp (XSTRING (f->name)->data, "F1") != 0
1095#endif
1096 )
808c0f20 1097 error ("Attempt to delete the sole visible or iconified frame");
d5e7c279 1098
00c5fd51
RS
1099#if 0
1100 /* This is a nice idea, but x_connection_closed needs to be able
1101 to delete the last frame, if it is gone. */
7539e11f 1102 if (NILP (XCDR (Vframe_list)))
e9687ee8 1103 error ("Attempt to delete the only frame");
00c5fd51 1104#endif
e9687ee8 1105
ff11dfa1
JB
1106 /* Does this frame have a minibuffer, and is it the surrogate
1107 minibuffer for any other frame? */
fd0c2bd1 1108 if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
dc6f92b8 1109 {
ff11dfa1 1110 Lisp_Object frames;
1113d9db 1111
ff11dfa1
JB
1112 for (frames = Vframe_list;
1113 CONSP (frames);
7539e11f 1114 frames = XCDR (frames))
1113d9db 1115 {
7a8cc307 1116 Lisp_Object this;
7539e11f 1117 this = XCAR (frames);
1113d9db 1118
ff11dfa1
JB
1119 if (! EQ (this, frame)
1120 && EQ (frame,
7a8cc307
RS
1121 WINDOW_FRAME (XWINDOW
1122 (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
ff11dfa1 1123 error ("Attempt to delete a surrogate minibuffer frame");
1113d9db 1124 }
dc6f92b8
JB
1125 }
1126
0e662342
GM
1127 /* Run `delete-frame-hook'. */
1128 if (!NILP (Vrun_hooks))
1129 {
1130 Lisp_Object args[2];
1131 args[0] = intern ("delete-frame-hook");
1132 args[1] = frame;
1133 Frun_hook_with_args (2, args);
1134 }
1135
99b92e64
RS
1136 minibuffer_selected = EQ (minibuf_window, selected_window);
1137
ff11dfa1 1138 /* Don't let the frame remain selected. */
8d2666fe 1139 if (f == sf)
06537cc8
RS
1140 {
1141 Lisp_Object tail, frame1;
1142
1143 /* Look for another visible frame on the same terminal. */
1144 frame1 = next_frame (frame, Qvisible);
1145
1146 /* If there is none, find *some* other frame. */
1147 if (NILP (frame1) || EQ (frame1, frame))
1148 {
1149 FOR_EACH_FRAME (tail, frame1)
1150 {
1151 if (! EQ (frame, frame1))
1152 break;
1153 }
1154 }
1155
1e8324d9 1156 do_switch_frame (frame1, 0, 1);
79a65b7f 1157 sf = SELECTED_FRAME ();
06537cc8 1158 }
dc6f92b8 1159
ff11dfa1
JB
1160 /* Don't allow minibuf_window to remain on a deleted frame. */
1161 if (EQ (f->minibuffer_window, minibuf_window))
dc6f92b8 1162 {
8d2666fe 1163 Fset_window_buffer (sf->minibuffer_window,
dc6f92b8 1164 XWINDOW (minibuf_window)->buffer);
8d2666fe 1165 minibuf_window = sf->minibuffer_window;
99b92e64
RS
1166
1167 /* If the dying minibuffer window was selected,
1168 select the new one. */
1169 if (minibuffer_selected)
1170 Fselect_window (minibuf_window);
dc6f92b8
JB
1171 }
1172
130adcb7
EZ
1173 /* Don't let echo_area_window to remain on a deleted frame. */
1174 if (EQ (f->minibuffer_window, echo_area_window))
1175 echo_area_window = sf->minibuffer_window;
1176
bb2a0a65
RS
1177 /* Clear any X selections for this frame. */
1178#ifdef HAVE_X_WINDOWS
1179 if (FRAME_X_P (f))
1180 x_clear_frame_selections (f);
1181#endif
1182
18082e2d
GM
1183 /* Free glyphs.
1184 This function must be called before the window tree of the
1185 frame is deleted because windows contain dynamically allocated
1186 memory. */
1187 free_glyphs (f);
1188
4a88b3b0
JB
1189 /* Mark all the windows that used to be on FRAME as deleted, and then
1190 remove the reference to them. */
1191 delete_all_subwindows (XWINDOW (f->root_window));
1192 f->root_window = Qnil;
1193
ff11dfa1 1194 Vframe_list = Fdelq (frame, Vframe_list);
a42e9724 1195 FRAME_SET_VISIBLE (f, 0);
dc6f92b8 1196
60a8823e 1197 if (f->namebuf)
18082e2d 1198 xfree (f->namebuf);
d2bee99e 1199 if (FRAME_INSERT_COST (f))
18082e2d 1200 xfree (FRAME_INSERT_COST (f));
d2bee99e 1201 if (FRAME_DELETEN_COST (f))
18082e2d 1202 xfree (FRAME_DELETEN_COST (f));
d2bee99e 1203 if (FRAME_INSERTN_COST (f))
18082e2d 1204 xfree (FRAME_INSERTN_COST (f));
d2bee99e 1205 if (FRAME_DELETE_COST (f))
18082e2d 1206 xfree (FRAME_DELETE_COST (f));
25734faf 1207 if (FRAME_MESSAGE_BUF (f))
18082e2d 1208 xfree (FRAME_MESSAGE_BUF (f));
d2bee99e 1209
8678b9cc
JB
1210 /* Since some events are handled at the interrupt level, we may get
1211 an event for f at any time; if we zero out the frame's display
1212 now, then we may trip up the event-handling code. Instead, we'll
1213 promise that the display of the frame must be valid until we have
1214 called the window-system-dependent frame destruction routine. */
dbc4e1c1
JB
1215
1216 /* I think this should be done with a hook. */
032d78fe
GV
1217#ifdef HAVE_WINDOW_SYSTEM
1218 if (FRAME_WINDOW_P (f))
8678b9cc 1219 x_destroy_window (f);
d5e7c279
JB
1220#endif
1221
7556890b 1222 f->output_data.nothing = 0;
8678b9cc 1223
ff11dfa1 1224 /* If we've deleted the last_nonminibuf_frame, then try to find
d5e7c279 1225 another one. */
ff11dfa1 1226 if (f == last_nonminibuf_frame)
d5e7c279 1227 {
ff11dfa1 1228 Lisp_Object frames;
1113d9db 1229
ff11dfa1 1230 last_nonminibuf_frame = 0;
d5e7c279 1231
ff11dfa1
JB
1232 for (frames = Vframe_list;
1233 CONSP (frames);
7539e11f 1234 frames = XCDR (frames))
d5e7c279 1235 {
7539e11f 1236 f = XFRAME (XCAR (frames));
ff11dfa1 1237 if (!FRAME_MINIBUF_ONLY_P (f))
d5e7c279 1238 {
ff11dfa1 1239 last_nonminibuf_frame = f;
d5e7c279
JB
1240 break;
1241 }
1242 }
1243 }
dc6f92b8 1244
c4c6d073
KH
1245 /* If we've deleted this keyboard's default_minibuffer_frame, try to
1246 find another one. Prefer minibuffer-only frames, but also notice
1247 frames with other windows. */
c60f3a6a 1248 if (EQ (frame, FRAME_KBOARD (f)->Vdefault_minibuffer_frame))
1113d9db 1249 {
ff11dfa1 1250 Lisp_Object frames;
1113d9db 1251
ff11dfa1 1252 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
ab9f008d 1253 Lisp_Object frame_with_minibuf;
32fda9ba
RS
1254 /* Some frame we found on the same kboard, or nil if there are none. */
1255 Lisp_Object frame_on_same_kboard;
1113d9db 1256
32fda9ba 1257 frame_on_same_kboard = Qnil;
ab9f008d 1258 frame_with_minibuf = Qnil;
32fda9ba 1259
ff11dfa1
JB
1260 for (frames = Vframe_list;
1261 CONSP (frames);
7539e11f 1262 frames = XCDR (frames))
1113d9db 1263 {
ab9f008d 1264 Lisp_Object this;
c4c6d073 1265 struct frame *f1;
1113d9db 1266
7539e11f 1267 this = XCAR (frames);
e35d291d 1268 if (!FRAMEP (this))
1113d9db 1269 abort ();
c4c6d073 1270 f1 = XFRAME (this);
1113d9db 1271
c4c6d073
KH
1272 /* Consider only frames on the same kboard
1273 and only those with minibuffers. */
1274 if (FRAME_KBOARD (f) == FRAME_KBOARD (f1)
1275 && FRAME_HAS_MINIBUF_P (f1))
1113d9db 1276 {
ff11dfa1 1277 frame_with_minibuf = this;
c4c6d073 1278 if (FRAME_MINIBUF_ONLY_P (f1))
1113d9db
JB
1279 break;
1280 }
32fda9ba
RS
1281
1282 if (FRAME_KBOARD (f) == FRAME_KBOARD (f1))
1283 frame_on_same_kboard = this;
1113d9db
JB
1284 }
1285
32fda9ba
RS
1286 if (!NILP (frame_on_same_kboard))
1287 {
1288 /* We know that there must be some frame with a minibuffer out
1289 there. If this were not true, all of the frames present
1290 would have to be minibufferless, which implies that at some
1291 point their minibuffer frames must have been deleted, but
1292 that is prohibited at the top; you can't delete surrogate
1293 minibuffer frames. */
1294 if (NILP (frame_with_minibuf))
1295 abort ();
1113d9db 1296
32fda9ba
RS
1297 FRAME_KBOARD (f)->Vdefault_minibuffer_frame = frame_with_minibuf;
1298 }
1299 else
1300 /* No frames left on this kboard--say no minibuffer either. */
1301 FRAME_KBOARD (f)->Vdefault_minibuffer_frame = Qnil;
1113d9db
JB
1302 }
1303
e681c92a
RS
1304 /* Cause frame titles to update--necessary if we now have just one frame. */
1305 update_mode_lines = 1;
1306
dc6f92b8
JB
1307 return Qnil;
1308}
1309\f
1310/* Return mouse position in character cell units. */
1311
f9898cc6 1312DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
ff11dfa1 1313 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
4f90516b
JB
1314The position is given in character cells, where (0, 0) is the\n\
1315upper-left corner.\n\
f9898cc6 1316If Emacs is running on a mouseless terminal or hasn't been programmed\n\
ff11dfa1 1317to read the mouse position, it returns the selected frame for FRAME\n\
beb0bc36
DL
1318and nil for X and Y.\n\
1319Runs the abnormal hook `mouse-position-function' with the normal return\n\
1320value as argument.")
f9898cc6 1321 ()
dc6f92b8 1322{
ff11dfa1 1323 FRAME_PTR f;
dbc4e1c1 1324 Lisp_Object lispy_dummy;
fd2777e0 1325 enum scroll_bar_part party_dummy;
beb0bc36 1326 Lisp_Object x, y, retval;
5384466a 1327 int col, row;
dbc4e1c1 1328 unsigned long long_dummy;
cb2255b3 1329 struct gcpro gcpro1;
dc6f92b8 1330
8d2666fe 1331 f = SELECTED_FRAME ();
c5074d8c
RS
1332 x = y = Qnil;
1333
f443c170 1334#ifdef HAVE_MOUSE
c5074d8c 1335 /* It's okay for the hook to refrain from storing anything. */
f9898cc6 1336 if (mouse_position_hook)
66e827dc 1337 (*mouse_position_hook) (&f, -1,
dbc4e1c1
JB
1338 &lispy_dummy, &party_dummy,
1339 &x, &y,
1340 &long_dummy);
76db7eb4
KH
1341 if (! NILP (x))
1342 {
1343 col = XINT (x);
1344 row = XINT (y);
8126c3b4 1345 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
76db7eb4
KH
1346 XSETINT (x, col);
1347 XSETINT (y, row);
1348 }
f443c170 1349#endif
2d80a27a 1350 XSETFRAME (lispy_dummy, f);
beb0bc36 1351 retval = Fcons (lispy_dummy, Fcons (x, y));
cb2255b3 1352 GCPRO1 (retval);
beb0bc36 1353 if (!NILP (Vmouse_position_function))
cb2255b3
GM
1354 retval = call1 (Vmouse_position_function, retval);
1355 RETURN_UNGCPRO (retval);
dc6f92b8
JB
1356}
1357
152e6c70
RS
1358DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
1359 Smouse_pixel_position, 0, 0, 0,
1360 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
1361The position is given in pixel units, where (0, 0) is the\n\
1362upper-left corner.\n\
1363If Emacs is running on a mouseless terminal or hasn't been programmed\n\
1364to read the mouse position, it returns the selected frame for FRAME\n\
1365and nil for X and Y.")
1366 ()
1367{
1368 FRAME_PTR f;
1369 Lisp_Object lispy_dummy;
1370 enum scroll_bar_part party_dummy;
1371 Lisp_Object x, y;
152e6c70
RS
1372 unsigned long long_dummy;
1373
8d2666fe 1374 f = SELECTED_FRAME ();
152e6c70
RS
1375 x = y = Qnil;
1376
0c5c1cf7 1377#ifdef HAVE_MOUSE
152e6c70
RS
1378 /* It's okay for the hook to refrain from storing anything. */
1379 if (mouse_position_hook)
66e827dc 1380 (*mouse_position_hook) (&f, -1,
152e6c70
RS
1381 &lispy_dummy, &party_dummy,
1382 &x, &y,
1383 &long_dummy);
0c5c1cf7 1384#endif
2d80a27a 1385 XSETFRAME (lispy_dummy, f);
152e6c70
RS
1386 return Fcons (lispy_dummy, Fcons (x, y));
1387}
1388
dc6f92b8 1389DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
1d7cc616 1390 "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
e84ffeec
RS
1391Coordinates are relative to the frame, not a window,\n\
1392so the coordinates of the top left character in the frame\n\
1393may be nonzero due to left-hand scroll bars or the menu bar.\n\
1394\n\
1395This function is a no-op for an X frame that is not visible.\n\
efb57f43
RS
1396If you have just created a frame, you must wait for it to become visible\n\
1397before calling this function on it, like this.\n\
1398 (while (not (frame-visible-p frame)) (sleep-for .5))")
ff11dfa1
JB
1399 (frame, x, y)
1400 Lisp_Object frame, x, y;
dc6f92b8 1401{
ff11dfa1 1402 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1403 CHECK_NUMBER (x, 2);
1404 CHECK_NUMBER (y, 1);
1405
dbc4e1c1 1406 /* I think this should be done with a hook. */
032d78fe
GV
1407#ifdef HAVE_WINDOW_SYSTEM
1408 if (FRAME_WINDOW_P (XFRAME (frame)))
dc6f92b8 1409 /* Warping the mouse will cause enternotify and focus events. */
d4d76014 1410 x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
bb221971 1411#else
be625e00 1412#if defined (MSDOS) && defined (HAVE_MOUSE)
bb221971
RS
1413 if (FRAME_MSDOS_P (XFRAME (frame)))
1414 {
1415 Fselect_frame (frame, Qnil);
1416 mouse_moveto (XINT (x), XINT (y));
1417 }
1418#endif
dc6f92b8
JB
1419#endif
1420
1421 return Qnil;
1422}
152e6c70
RS
1423
1424DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
1425 Sset_mouse_pixel_position, 3, 3, 0,
1426 "Move the mouse pointer to pixel position (X,Y) in FRAME.\n\
efb57f43
RS
1427Note, this is a no-op for an X frame that is not visible.\n\
1428If you have just created a frame, you must wait for it to become visible\n\
1429before calling this function on it, like this.\n\
1430 (while (not (frame-visible-p frame)) (sleep-for .5))")
152e6c70
RS
1431 (frame, x, y)
1432 Lisp_Object frame, x, y;
1433{
1434 CHECK_LIVE_FRAME (frame, 0);
1435 CHECK_NUMBER (x, 2);
1436 CHECK_NUMBER (y, 1);
1437
1438 /* I think this should be done with a hook. */
032d78fe
GV
1439#ifdef HAVE_WINDOW_SYSTEM
1440 if (FRAME_WINDOW_P (XFRAME (frame)))
152e6c70 1441 /* Warping the mouse will cause enternotify and focus events. */
d4d76014 1442 x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
bb221971 1443#else
be625e00 1444#if defined (MSDOS) && defined (HAVE_MOUSE)
bb221971
RS
1445 if (FRAME_MSDOS_P (XFRAME (frame)))
1446 {
1447 Fselect_frame (frame, Qnil);
1448 mouse_moveto (XINT (x), XINT (y));
1449 }
1450#endif
152e6c70
RS
1451#endif
1452
1453 return Qnil;
1454}
dc6f92b8 1455\f
98ce1622
RS
1456static void make_frame_visible_1 P_ ((Lisp_Object));
1457
ff11dfa1 1458DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
fc25d15d 1459 0, 1, "",
ff11dfa1 1460 "Make the frame FRAME visible (assuming it is an X-window).\n\
8693ca83 1461If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
1462 (frame)
1463 Lisp_Object frame;
dc6f92b8 1464{
1aa66088 1465 if (NILP (frame))
8d2666fe 1466 frame = selected_frame;
1aa66088 1467
ff11dfa1 1468 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 1469
dbc4e1c1 1470 /* I think this should be done with a hook. */
032d78fe
GV
1471#ifdef HAVE_WINDOW_SYSTEM
1472 if (FRAME_WINDOW_P (XFRAME (frame)))
02ff9dd5
RS
1473 {
1474 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1475 x_make_frame_visible (XFRAME (frame));
1476 }
fd0c2bd1 1477#endif
dc6f92b8 1478
98ce1622
RS
1479 make_frame_visible_1 (XFRAME (frame)->root_window);
1480
565620a5
RS
1481 /* Make menu bar update for the Buffers and Frams menus. */
1482 windows_or_buffers_changed++;
1483
ff11dfa1 1484 return frame;
dc6f92b8
JB
1485}
1486
98ce1622
RS
1487/* Update the display_time slot of the buffers shown in WINDOW
1488 and all its descendents. */
1489
1490static void
1491make_frame_visible_1 (window)
1492 Lisp_Object window;
1493{
1494 struct window *w;
1495
1496 for (;!NILP (window); window = w->next)
1497 {
1498 w = XWINDOW (window);
1499
1500 if (!NILP (w->buffer))
1501 XBUFFER (w->buffer)->display_time = Fcurrent_time ();
1502
1503 if (!NILP (w->vchild))
1504 make_frame_visible_1 (w->vchild);
1505 if (!NILP (w->hchild))
1506 make_frame_visible_1 (w->hchild);
1507 }
1508}
1509
ff11dfa1 1510DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
808c0f20 1511 0, 2, "",
8693ca83 1512 "Make the frame FRAME invisible (assuming it is an X-window).\n\
808c0f20
RS
1513If omitted, FRAME defaults to the currently selected frame.\n\
1514Normally you may not make FRAME invisible if all other frames are invisible,\n\
1515but if the second optional argument FORCE is non-nil, you may do so.")
1516 (frame, force)
1517 Lisp_Object frame, force;
dc6f92b8 1518{
1aa66088 1519 if (NILP (frame))
8d2666fe 1520 frame = selected_frame;
1aa66088 1521
ff11dfa1 1522 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 1523
808c0f20
RS
1524 if (NILP (force) && !other_visible_frames (XFRAME (frame)))
1525 error ("Attempt to make invisible the sole visible or iconified frame");
1526
3d378fdf 1527#if 0 /* This isn't logically necessary, and it can do GC. */
9c394f17 1528 /* Don't let the frame remain selected. */
8d2666fe 1529 if (EQ (frame, selected_frame))
1e8324d9 1530 do_switch_frame (next_frame (frame, Qt), 0, 0)
3d378fdf 1531#endif
9c394f17
RS
1532
1533 /* Don't allow minibuf_window to remain on a deleted frame. */
1534 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
1535 {
8d2666fe
GM
1536 struct frame *sf = XFRAME (selected_frame);
1537 Fset_window_buffer (sf->minibuffer_window,
9c394f17 1538 XWINDOW (minibuf_window)->buffer);
8d2666fe 1539 minibuf_window = sf->minibuffer_window;
9c394f17
RS
1540 }
1541
dbc4e1c1 1542 /* I think this should be done with a hook. */
032d78fe
GV
1543#ifdef HAVE_WINDOW_SYSTEM
1544 if (FRAME_WINDOW_P (XFRAME (frame)))
ff11dfa1 1545 x_make_frame_invisible (XFRAME (frame));
fd0c2bd1 1546#endif
dc6f92b8 1547
565620a5
RS
1548 /* Make menu bar update for the Buffers and Frams menus. */
1549 windows_or_buffers_changed++;
1550
dc6f92b8
JB
1551 return Qnil;
1552}
1553
ff11dfa1 1554DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
1aa66088 1555 0, 1, "",
8693ca83
JB
1556 "Make the frame FRAME into an icon.\n\
1557If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
1558 (frame)
1559 Lisp_Object frame;
dc6f92b8 1560{
1aa66088 1561 if (NILP (frame))
8d2666fe 1562 frame = selected_frame;
1aa66088 1563
ff11dfa1 1564 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 1565
3d378fdf 1566#if 0 /* This isn't logically necessary, and it can do GC. */
9c394f17 1567 /* Don't let the frame remain selected. */
8d2666fe 1568 if (EQ (frame, selected_frame))
9c394f17 1569 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
3d378fdf 1570#endif
9c394f17
RS
1571
1572 /* Don't allow minibuf_window to remain on a deleted frame. */
1573 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
1574 {
8d2666fe
GM
1575 struct frame *sf = XFRAME (selected_frame);
1576 Fset_window_buffer (sf->minibuffer_window,
9c394f17 1577 XWINDOW (minibuf_window)->buffer);
8d2666fe 1578 minibuf_window = sf->minibuffer_window;
9c394f17
RS
1579 }
1580
dbc4e1c1 1581 /* I think this should be done with a hook. */
032d78fe
GV
1582#ifdef HAVE_WINDOW_SYSTEM
1583 if (FRAME_WINDOW_P (XFRAME (frame)))
ff11dfa1 1584 x_iconify_frame (XFRAME (frame));
fd0c2bd1 1585#endif
dc6f92b8 1586
565620a5
RS
1587 /* Make menu bar update for the Buffers and Frams menus. */
1588 windows_or_buffers_changed++;
1589
dc6f92b8
JB
1590 return Qnil;
1591}
1592
ff11dfa1 1593DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
dc6f92b8 1594 1, 1, 0,
ff11dfa1
JB
1595 "Return t if FRAME is now \"visible\" (actually in use for display).\n\
1596A frame that is not \"visible\" is not updated and, if it works through\n\
dc6f92b8 1597a window system, it may not show at all.\n\
fd0c2bd1 1598Return the symbol `icon' if frame is visible only as an icon.")
ff11dfa1
JB
1599 (frame)
1600 Lisp_Object frame;
dc6f92b8 1601{
ff11dfa1 1602 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 1603
5c044f55
RS
1604 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1605
a42e9724 1606 if (FRAME_VISIBLE_P (XFRAME (frame)))
dc6f92b8 1607 return Qt;
a42e9724 1608 if (FRAME_ICONIFIED_P (XFRAME (frame)))
fd0c2bd1 1609 return Qicon;
dc6f92b8
JB
1610 return Qnil;
1611}
1612
ff11dfa1 1613DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
dc6f92b8 1614 0, 0, 0,
ff11dfa1 1615 "Return a list of all frames now \"visible\" (being updated).")
dc6f92b8
JB
1616 ()
1617{
ff11dfa1
JB
1618 Lisp_Object tail, frame;
1619 struct frame *f;
dc6f92b8
JB
1620 Lisp_Object value;
1621
1622 value = Qnil;
7539e11f 1623 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
dc6f92b8 1624 {
7539e11f 1625 frame = XCAR (tail);
e35d291d 1626 if (!FRAMEP (frame))
dc6f92b8 1627 continue;
ff11dfa1 1628 f = XFRAME (frame);
a42e9724 1629 if (FRAME_VISIBLE_P (f))
ff11dfa1 1630 value = Fcons (frame, value);
dc6f92b8
JB
1631 }
1632 return value;
1633}
d5e7c279
JB
1634
1635
e518d5e1 1636DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
dbc4e1c1
JB
1637 "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
1638If FRAME is invisible, make it visible.\n\
828ac693 1639If you don't specify a frame, the selected frame is used.\n\
dbc4e1c1
JB
1640If Emacs is displaying on an ordinary terminal or some other device which\n\
1641doesn't support multiple overlapping frames, this function does nothing.")
1642 (frame)
1643 Lisp_Object frame;
1644{
828ac693 1645 if (NILP (frame))
8d2666fe 1646 frame = selected_frame;
828ac693 1647
dbc4e1c1 1648 CHECK_LIVE_FRAME (frame, 0);
8a981af5
RS
1649
1650 /* Do like the documentation says. */
1651 Fmake_frame_visible (frame);
1652
dbc4e1c1
JB
1653 if (frame_raise_lower_hook)
1654 (*frame_raise_lower_hook) (XFRAME (frame), 1);
1655
1656 return Qnil;
1657}
1658
b49f5578 1659/* Should we have a corresponding function called Flower_Power? */
e518d5e1 1660DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
dbc4e1c1 1661 "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
828ac693 1662If you don't specify a frame, the selected frame is used.\n\
dbc4e1c1
JB
1663If Emacs is displaying on an ordinary terminal or some other device which\n\
1664doesn't support multiple overlapping frames, this function does nothing.")
1665 (frame)
1666 Lisp_Object frame;
1667{
828ac693 1668 if (NILP (frame))
8d2666fe 1669 frame = selected_frame;
828ac693 1670
dbc4e1c1
JB
1671 CHECK_LIVE_FRAME (frame, 0);
1672
1673 if (frame_raise_lower_hook)
1674 (*frame_raise_lower_hook) (XFRAME (frame), 0);
1675
1676 return Qnil;
1677}
1678
d5e7c279 1679\f
ff11dfa1 1680DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
d5e7c279 1681 1, 2, 0,
ff11dfa1 1682 "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
a42e9724
JB
1683In other words, switch-frame events caused by events in FRAME will\n\
1684request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
1685FOCUS-FRAME after reading an event typed at FRAME.\n\
d5e7c279 1686\n\
a42e9724 1687If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
ff11dfa1 1688cancelled, and the frame again receives its own keystrokes.\n\
d5e7c279 1689\n\
a42e9724
JB
1690Focus redirection is useful for temporarily redirecting keystrokes to\n\
1691a surrogate minibuffer frame when a frame doesn't have its own\n\
1692minibuffer window.\n\
d5e7c279 1693\n\
a42e9724
JB
1694A frame's focus redirection can be changed by select-frame. If frame\n\
1695FOO is selected, and then a different frame BAR is selected, any\n\
1696frames redirecting their focus to FOO are shifted to redirect their\n\
1697focus to BAR. This allows focus redirection to work properly when the\n\
1698user switches from one frame to another using `select-window'.\n\
1699\n\
1700This means that a frame whose focus is redirected to itself is treated\n\
1701differently from a frame whose focus is redirected to nil; the former\n\
1702is affected by select-frame, while the latter is not.\n\
1703\n\
1704The redirection lasts until `redirect-frame-focus' is called to change it.")
ff11dfa1
JB
1705 (frame, focus_frame)
1706 Lisp_Object frame, focus_frame;
d5e7c279 1707{
13144095
JB
1708 /* Note that we don't check for a live frame here. It's reasonable
1709 to redirect the focus of a frame you're about to delete, if you
1710 know what other frame should receive those keystrokes. */
1711 CHECK_FRAME (frame, 0);
f9898cc6 1712
a42e9724 1713 if (! NILP (focus_frame))
ff11dfa1 1714 CHECK_LIVE_FRAME (focus_frame, 1);
d5e7c279 1715
ff11dfa1 1716 XFRAME (frame)->focus_frame = focus_frame;
d5e7c279 1717
ff11dfa1 1718 if (frame_rehighlight_hook)
dc0700f6 1719 (*frame_rehighlight_hook) (XFRAME (frame));
d5e7c279
JB
1720
1721 return Qnil;
1722}
1723
1724
ff11dfa1
JB
1725DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
1726 "Return the frame to which FRAME's keystrokes are currently being sent.\n\
a42e9724 1727This returns nil if FRAME's focus is not redirected.\n\
ff11dfa1
JB
1728See `redirect-frame-focus'.")
1729 (frame)
1730 Lisp_Object frame;
d5e7c279 1731{
ff11dfa1 1732 CHECK_LIVE_FRAME (frame, 0);
a42e9724 1733
ff11dfa1 1734 return FRAME_FOCUS_FRAME (XFRAME (frame));
d5e7c279
JB
1735}
1736
1737
dc6f92b8 1738\f
329ca574
RS
1739/* Return the value of frame parameter PROP in frame FRAME. */
1740
dc6f92b8 1741Lisp_Object
ff11dfa1
JB
1742get_frame_param (frame, prop)
1743 register struct frame *frame;
dc6f92b8
JB
1744 Lisp_Object prop;
1745{
1746 register Lisp_Object tem;
1747
ff11dfa1 1748 tem = Fassq (prop, frame->param_alist);
dc6f92b8
JB
1749 if (EQ (tem, Qnil))
1750 return tem;
1751 return Fcdr (tem);
1752}
1753
329ca574
RS
1754/* Return the buffer-predicate of the selected frame. */
1755
1756Lisp_Object
98ce1622
RS
1757frame_buffer_predicate (frame)
1758 Lisp_Object frame;
329ca574 1759{
98ce1622 1760 return XFRAME (frame)->buffer_predicate;
329ca574
RS
1761}
1762
fa54c6ae
RS
1763/* Return the buffer-list of the selected frame. */
1764
1765Lisp_Object
98ce1622
RS
1766frame_buffer_list (frame)
1767 Lisp_Object frame;
fa54c6ae 1768{
98ce1622 1769 return XFRAME (frame)->buffer_list;
fa54c6ae
RS
1770}
1771
1772/* Set the buffer-list of the selected frame. */
1773
1774void
98ce1622
RS
1775set_frame_buffer_list (frame, list)
1776 Lisp_Object frame, list;
fa54c6ae 1777{
98ce1622 1778 XFRAME (frame)->buffer_list = list;
fa54c6ae
RS
1779}
1780
1781/* Discard BUFFER from the buffer-list of each frame. */
1782
1783void
1784frames_discard_buffer (buffer)
1785 Lisp_Object buffer;
1786{
1787 Lisp_Object frame, tail;
1788
1789 FOR_EACH_FRAME (tail, frame)
1790 {
1791 XFRAME (frame)->buffer_list
1792 = Fdelq (buffer, XFRAME (frame)->buffer_list);
1793 }
1794}
1795
214b3216
RS
1796/* Move BUFFER to the end of the buffer-list of each frame. */
1797
1798void
1799frames_bury_buffer (buffer)
1800 Lisp_Object buffer;
1801{
1802 Lisp_Object frame, tail;
1803
1804 FOR_EACH_FRAME (tail, frame)
1805 {
835c1b36
GM
1806 struct frame *f = XFRAME (frame);
1807 Lisp_Object found;
1808
1809 found = Fmemq (buffer, f->buffer_list);
1810 if (!NILP (found))
1811 f->buffer_list = nconc2 (Fdelq (buffer, f->buffer_list),
1812 Fcons (buffer, Qnil));
214b3216
RS
1813 }
1814}
1815
329ca574
RS
1816/* Modify the alist in *ALISTPTR to associate PROP with VAL.
1817 If the alist already has an element for PROP, we change it. */
1818
dc6f92b8 1819void
fd0c2bd1 1820store_in_alist (alistptr, prop, val)
dc6f92b8 1821 Lisp_Object *alistptr, val;
fd0c2bd1 1822 Lisp_Object prop;
dc6f92b8
JB
1823{
1824 register Lisp_Object tem;
dc6f92b8 1825
dc6f92b8
JB
1826 tem = Fassq (prop, *alistptr);
1827 if (EQ (tem, Qnil))
1828 *alistptr = Fcons (Fcons (prop, val), *alistptr);
1829 else
1830 Fsetcdr (tem, val);
1831}
1832
e5317d61
EZ
1833static int
1834frame_name_fnn_p (str, len)
1835 char *str;
1836 int len;
1837{
1838 if (len > 1 && str[0] == 'F')
1839 {
1840 char *end_ptr;
e5317d61 1841
48970f2f
EZ
1842 strtol (str + 1, &end_ptr, 10);
1843
e5317d61
EZ
1844 if (end_ptr == str + len)
1845 return 1;
1846 }
1847 return 0;
1848}
1849
1850/* Set the name of the terminal frame. Also used by MSDOS frames.
1851 Modeled after x_set_name which is used for WINDOW frames. */
1852
1853void
1854set_term_frame_name (f, name)
1855 struct frame *f;
1856 Lisp_Object name;
1857{
1858 f->explicit_name = ! NILP (name);
1859
1860 /* If NAME is nil, set the name to F<num>. */
1861 if (NILP (name))
1862 {
1863 char namebuf[20];
1864
1865 /* Check for no change needed in this very common case
1866 before we do any consing. */
e34c5c7d 1867 if (frame_name_fnn_p (XSTRING (f->name)->data,
fc932ac6 1868 STRING_BYTES (XSTRING (f->name))))
e5317d61
EZ
1869 return;
1870
1871 terminal_frame_count++;
1872 sprintf (namebuf, "F%d", terminal_frame_count);
1873 name = build_string (namebuf);
1874 }
1875 else
1876 {
1877 CHECK_STRING (name, 0);
1878
1879 /* Don't change the name if it's already NAME. */
1880 if (! NILP (Fstring_equal (name, f->name)))
1881 return;
1882
1883 /* Don't allow the user to set the frame name to F<num>, so it
1884 doesn't clash with the names we generate for terminal frames. */
fc932ac6 1885 if (frame_name_fnn_p (XSTRING (name)->data, STRING_BYTES (XSTRING (name))))
e5317d61
EZ
1886 error ("Frame names of the form F<num> are usurped by Emacs");
1887 }
1888
1889 f->name = name;
1890 update_mode_lines = 1;
1891}
1892
dc6f92b8 1893void
ff11dfa1
JB
1894store_frame_param (f, prop, val)
1895 struct frame *f;
dc6f92b8
JB
1896 Lisp_Object prop, val;
1897{
7eb63b72 1898 register Lisp_Object old_alist_elt;
dc6f92b8 1899
7eb63b72
GM
1900 /* The buffer-alist parameter is stored in a special place and is
1901 not in the alist. */
fa54c6ae
RS
1902 if (EQ (prop, Qbuffer_list))
1903 {
1904 f->buffer_list = val;
1905 return;
1906 }
1907
7eb63b72
GM
1908 /* If PROP is a symbol which is supposed to have frame-local values,
1909 and it is set up based on this frame, switch to the global
1910 binding. That way, we can create or alter the frame-local binding
1911 without messing up the symbol's status. */
1912 if (SYMBOLP (prop))
1913 {
1914 Lisp_Object valcontents;
1915 valcontents = XSYMBOL (prop)->value;
1916 if ((BUFFER_LOCAL_VALUEP (valcontents)
1917 || SOME_BUFFER_LOCAL_VALUEP (valcontents))
1918 && XBUFFER_LOCAL_VALUE (valcontents)->check_frame
1919 && XFRAME (XBUFFER_LOCAL_VALUE (valcontents)->frame) == f)
1920 swap_in_global_binding (prop);
1921 }
1922
1923 /* Update the frame parameter alist. */
1924 old_alist_elt = Fassq (prop, f->param_alist);
1925 if (EQ (old_alist_elt, Qnil))
ff11dfa1 1926 f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
dc6f92b8 1927 else
7eb63b72 1928 Fsetcdr (old_alist_elt, val);
bc93c097 1929
7eb63b72
GM
1930 /* Update some other special parameters in their special places
1931 in addition to the alist. */
1932
329ca574
RS
1933 if (EQ (prop, Qbuffer_predicate))
1934 f->buffer_predicate = val;
1935
032d78fe 1936 if (! FRAME_WINDOW_P (f))
e5317d61
EZ
1937 {
1938 if (EQ (prop, Qmenu_bar_lines))
1939 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
1940 else if (EQ (prop, Qname))
1941 set_term_frame_name (f, val);
1942 }
a249de79 1943
e35d291d 1944 if (EQ (prop, Qminibuffer) && WINDOWP (val))
bc93c097
JB
1945 {
1946 if (! MINI_WINDOW_P (XWINDOW (val)))
1947 error ("Surrogate minibuffer windows must be minibuffer windows.");
1948
213bac8a 1949 if ((FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
7af7ef38
KH
1950 && !EQ (val, f->minibuffer_window))
1951 error ("Can't change the surrogate minibuffer of a frame with its own minibuffer");
bc93c097
JB
1952
1953 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 1954 f->minibuffer_window = val;
bc93c097 1955 }
dc6f92b8
JB
1956}
1957
ff11dfa1
JB
1958DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
1959 "Return the parameters-alist of frame FRAME.\n\
dc6f92b8 1960It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
dc6d9681
JB
1961The meaningful PARMs depend on the kind of frame.\n\
1962If FRAME is omitted, return information on the currently selected frame.")
ff11dfa1
JB
1963 (frame)
1964 Lisp_Object frame;
dc6f92b8
JB
1965{
1966 Lisp_Object alist;
f769f1b2 1967 FRAME_PTR f;
dd10ec4f 1968 int height, width;
57629833 1969 struct gcpro gcpro1;
dc6f92b8 1970
03390a72 1971 if (NILP (frame))
8d2666fe
GM
1972 frame = selected_frame;
1973
1974 CHECK_FRAME (frame, 0);
1975 f = XFRAME (frame);
dc6f92b8 1976
f769f1b2 1977 if (!FRAME_LIVE_P (f))
dc6f92b8
JB
1978 return Qnil;
1979
ff11dfa1 1980 alist = Fcopy_alist (f->param_alist);
57629833
GM
1981 GCPRO1 (alist);
1982
2d764c78 1983 if (!FRAME_WINDOW_P (f))
bb221971 1984 {
4aec4b29
EZ
1985 int fg = FRAME_FOREGROUND_PIXEL (f);
1986 int bg = FRAME_BACKGROUND_PIXEL (f);
e1d0bbc9
EZ
1987 Lisp_Object elt;
1988
1989 /* If the frame's parameter alist says the colors are
1990 unspecified and reversed, take the frame's background pixel
1991 for foreground and vice versa. */
1992 elt = Fassq (Qforeground_color, alist);
70de9f06
EZ
1993 if (!NILP (elt) && CONSP (elt) && STRINGP (XCDR (elt)))
1994 {
1995 if (strncmp (XSTRING (XCDR (elt))->data,
1996 unspecified_bg,
1997 XSTRING (XCDR (elt))->size) == 0)
1998 store_in_alist (&alist, Qforeground_color, tty_color_name (f, bg));
1999 else if (strncmp (XSTRING (XCDR (elt))->data,
2000 unspecified_fg,
2001 XSTRING (XCDR (elt))->size) == 0)
2002 store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
2003 }
e1d0bbc9
EZ
2004 else
2005 store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
2006 elt = Fassq (Qbackground_color, alist);
70de9f06
EZ
2007 if (!NILP (elt) && CONSP (elt) && STRINGP (XCDR (elt)))
2008 {
2009 if (strncmp (XSTRING (XCDR (elt))->data,
2010 unspecified_fg,
2011 XSTRING (XCDR (elt))->size) == 0)
2012 store_in_alist (&alist, Qbackground_color, tty_color_name (f, fg));
2013 else if (strncmp (XSTRING (XCDR (elt))->data,
2014 unspecified_bg,
2015 XSTRING (XCDR (elt))->size) == 0)
2016 store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
2017 }
e1d0bbc9
EZ
2018 else
2019 store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
2d764c78
EZ
2020 store_in_alist (&alist, intern ("font"),
2021 build_string (FRAME_MSDOS_P (f)
2022 ? "ms-dos"
4ec0d3c1 2023 : FRAME_W32_P (f) ? "w32term"
4ec0d3c1 2024 :"tty"));
bb221971 2025 }
fd0c2bd1 2026 store_in_alist (&alist, Qname, f->name);
dd10ec4f
RS
2027 height = (FRAME_NEW_HEIGHT (f) ? FRAME_NEW_HEIGHT (f) : FRAME_HEIGHT (f));
2028 store_in_alist (&alist, Qheight, make_number (height));
2029 width = (FRAME_NEW_WIDTH (f) ? FRAME_NEW_WIDTH (f) : FRAME_WIDTH (f));
2030 store_in_alist (&alist, Qwidth, make_number (width));
f769f1b2 2031 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
fd0c2bd1 2032 store_in_alist (&alist, Qminibuffer,
39acc701 2033 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
f769f1b2
KH
2034 : FRAME_MINIBUF_ONLY_P (f) ? Qonly
2035 : FRAME_MINIBUF_WINDOW (f)));
2036 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
03390a72 2037 store_in_alist (&alist, Qbuffer_list, frame_buffer_list (frame));
fd0c2bd1 2038
dbc4e1c1 2039 /* I think this should be done with a hook. */
032d78fe
GV
2040#ifdef HAVE_WINDOW_SYSTEM
2041 if (FRAME_WINDOW_P (f))
ff11dfa1 2042 x_report_frame_params (f, &alist);
b6dd20ed 2043 else
fd0c2bd1 2044#endif
16a3738c
KH
2045 {
2046 /* This ought to be correct in f->param_alist for an X frame. */
2047 Lisp_Object lines;
f4e93c40 2048 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
16a3738c
KH
2049 store_in_alist (&alist, Qmenu_bar_lines, lines);
2050 }
57629833
GM
2051
2052 UNGCPRO;
dc6f92b8
JB
2053 return alist;
2054}
2055
8b60f7bc
GM
2056
2057DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
2058 "Return FRAME's value for parameter PARAMETER.\n\
2059If FRAME is nil, describe the currently selected frame.")
2060 (frame, parameter)
2061 Lisp_Object frame, parameter;
2062{
2063 struct frame *f;
2064 Lisp_Object value;
2065
2066 if (NILP (frame))
2067 frame = selected_frame;
2068 else
2069 CHECK_FRAME (frame, 0);
2070 CHECK_SYMBOL (parameter, 1);
2071
2072 f = XFRAME (frame);
2073 value = Qnil;
2074
2075 if (FRAME_LIVE_P (f))
2076 {
67d853e6
GM
2077 if (EQ (parameter, Qname))
2078 value = f->name;
6345f6aa
GM
2079#ifdef HAVE_X_WINDOWS
2080 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
2081 value = XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element);
2082#endif /* HAVE_X_WINDOWS */
8b60f7bc 2083 else
67d853e6
GM
2084 {
2085 value = Fassq (parameter, f->param_alist);
2086 if (CONSP (value))
5f65b39d 2087 {
5f65b39d
EZ
2088 value = XCDR (value);
2089 /* Fframe_parameters puts the actual fg/bg color names,
2090 even if f->param_alist says otherwise. This is
2091 important when param_alist's notion of colors is
2092 "unspecified". We need to do the same here. */
2093 if (STRINGP (value) && !FRAME_WINDOW_P (f))
2094 {
e1d0bbc9
EZ
2095 char *color_name;
2096 EMACS_INT csz;
2097
2098 if (EQ (parameter, Qbackground_color))
2099 {
2100 color_name = XSTRING (value)->data;
2101 csz = XSTRING (value)->size;
2102 if (strncmp (color_name, unspecified_bg, csz) == 0)
2103 value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
2104 else if (strncmp (color_name, unspecified_fg, csz) == 0)
2105 value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
2106 }
2107 else if (EQ (parameter, Qforeground_color))
2108 {
2109 color_name = XSTRING (value)->data;
2110 csz = XSTRING (value)->size;
2111 if (strncmp (color_name, unspecified_fg, csz) == 0)
2112 value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
2113 else if (strncmp (color_name, unspecified_bg, csz) == 0)
2114 value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
2115 }
5f65b39d
EZ
2116 }
2117 }
6345f6aa
GM
2118 else if (EQ (parameter, Qdisplay_type)
2119 || EQ (parameter, Qbackground_mode))
2120 /* Avoid consing in frequent cases. */
67d853e6
GM
2121 value = Qnil;
2122 else
2123 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2124 }
8b60f7bc
GM
2125 }
2126
2127 return value;
2128}
2129
2130
ff11dfa1
JB
2131DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
2132 Smodify_frame_parameters, 2, 2, 0,
2133 "Modify the parameters of frame FRAME according to ALIST.\n\
e86b5133 2134If FRAME is nil, it defaults to the selected frame.\n\
dc6f92b8
JB
2135ALIST is an alist of parameters to change and their new values.\n\
2136Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
e80f3932
RS
2137The meaningful PARMs depend on the kind of frame.\n\
2138Undefined PARMs are ignored, but stored in the frame's parameter list\n\
7eb63b72
GM
2139so that `frame-parameters' will return them.\n\
2140\n\
2141The value of frame parameter FOO can also be accessed\n\
2142as a frame-local binding for the variable FOO, if you have\n\
2143enabled such bindings for that variable with `make-variable-frame-local'.")
ff11dfa1
JB
2144 (frame, alist)
2145 Lisp_Object frame, alist;
dc6f92b8 2146{
fd0c2bd1 2147 FRAME_PTR f;
213bac8a 2148 register Lisp_Object tail, prop, val;
3df1fda2
GM
2149 int count = BINDING_STACK_SIZE ();
2150
2151 /* Bind this to t to inhibit initialization of the default face from
2152 X resources in face-set-after-frame-default. If we don't inhibit
2153 this, modifying the `font' frame parameter, for example, while
2154 there is a `default.attributeFont' X resource, won't work,
2155 because `default's font is reset to the value of the X resource
2156 and that resets the `font' frame parameter. */
2157 specbind (Qinhibit_default_face_x_resources, Qt);
dc6f92b8 2158
ff11dfa1 2159 if (EQ (frame, Qnil))
8d2666fe
GM
2160 frame = selected_frame;
2161 CHECK_LIVE_FRAME (frame, 0);
2162 f = XFRAME (frame);
dc6f92b8 2163
dbc4e1c1 2164 /* I think this should be done with a hook. */
032d78fe
GV
2165#ifdef HAVE_WINDOW_SYSTEM
2166 if (FRAME_WINDOW_P (f))
fd0c2bd1 2167 x_set_frame_parameters (f, alist);
329ca574 2168 else
bb221971
RS
2169#endif
2170#ifdef MSDOS
2171 if (FRAME_MSDOS_P (f))
2172 IT_set_frame_parameters (f, alist);
2173 else
329ca574 2174#endif
574a1a90 2175
41d44f1f
RS
2176 {
2177 int length = XINT (Flength (alist));
2178 int i;
2179 Lisp_Object *parms
2180 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2181 Lisp_Object *values
2182 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2183
2184 /* Extract parm names and values into those vectors. */
2185
2186 i = 0;
2187 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2188 {
213bac8a 2189 Lisp_Object elt;
41d44f1f
RS
2190
2191 elt = Fcar (tail);
2192 parms[i] = Fcar (elt);
2193 values[i] = Fcdr (elt);
2194 i++;
2195 }
2196
2197 /* Now process them in reverse of specified order. */
2198 for (i--; i >= 0; i--)
2199 {
2200 prop = parms[i];
2201 val = values[i];
2202 store_frame_param (f, prop, val);
2203 }
2204 }
dc6f92b8 2205
3df1fda2 2206 return unbind_to (count, Qnil);
dc6f92b8
JB
2207}
2208\f
a26a1f95
RS
2209DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
2210 0, 1, 0,
2211 "Height in pixels of a line in the font in frame FRAME.\n\
2212If FRAME is omitted, the selected frame is used.\n\
2213For a terminal frame, the value is always 1.")
ff11dfa1
JB
2214 (frame)
2215 Lisp_Object frame;
dc6f92b8 2216{
a26a1f95 2217 struct frame *f;
dc6f92b8 2218
a26a1f95 2219 if (NILP (frame))
8d2666fe
GM
2220 frame = selected_frame;
2221 CHECK_FRAME (frame, 0);
2222 f = XFRAME (frame);
a26a1f95 2223
032d78fe
GV
2224#ifdef HAVE_WINDOW_SYSTEM
2225 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2226 return make_number (x_char_height (f));
2227 else
dc6d9681 2228#endif
a26a1f95
RS
2229 return make_number (1);
2230}
dc6d9681 2231
dc6f92b8 2232
a26a1f95
RS
2233DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
2234 0, 1, 0,
2235 "Width in pixels of characters in the font in frame FRAME.\n\
2236If FRAME is omitted, the selected frame is used.\n\
2237The width is the same for all characters, because\n\
2238currently Emacs supports only fixed-width fonts.\n\
2239For a terminal screen, the value is always 1.")
2240 (frame)
2241 Lisp_Object frame;
dc6f92b8 2242{
a26a1f95
RS
2243 struct frame *f;
2244
2245 if (NILP (frame))
8d2666fe
GM
2246 frame = selected_frame;
2247 CHECK_FRAME (frame, 0);
2248 f = XFRAME (frame);
a26a1f95 2249
032d78fe
GV
2250#ifdef HAVE_WINDOW_SYSTEM
2251 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2252 return make_number (x_char_width (f));
2253 else
2254#endif
2255 return make_number (1);
dc6f92b8
JB
2256}
2257
a26a1f95
RS
2258DEFUN ("frame-pixel-height", Fframe_pixel_height,
2259 Sframe_pixel_height, 0, 1, 0,
164a14ef 2260 "Return a FRAME's height in pixels.\n\
07822795
RS
2261This counts only the height available for text lines,\n\
2262not menu bars on window-system Emacs frames.\n\
164a14ef 2263For a terminal frame, the result really gives the height in characters.\n\
a26a1f95
RS
2264If FRAME is omitted, the selected frame is used.")
2265 (frame)
2266 Lisp_Object frame;
dc6f92b8 2267{
a26a1f95
RS
2268 struct frame *f;
2269
2270 if (NILP (frame))
8d2666fe
GM
2271 frame = selected_frame;
2272 CHECK_FRAME (frame, 0);
2273 f = XFRAME (frame);
a26a1f95 2274
032d78fe
GV
2275#ifdef HAVE_WINDOW_SYSTEM
2276 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2277 return make_number (x_pixel_height (f));
2278 else
dc6d9681 2279#endif
a26a1f95
RS
2280 return make_number (FRAME_HEIGHT (f));
2281}
2282
2283DEFUN ("frame-pixel-width", Fframe_pixel_width,
2284 Sframe_pixel_width, 0, 1, 0,
2285 "Return FRAME's width in pixels.\n\
164a14ef 2286For a terminal frame, the result really gives the width in characters.\n\
a26a1f95
RS
2287If FRAME is omitted, the selected frame is used.")
2288 (frame)
2289 Lisp_Object frame;
2290{
2291 struct frame *f;
2292
2293 if (NILP (frame))
8d2666fe
GM
2294 frame = selected_frame;
2295 CHECK_FRAME (frame, 0);
2296 f = XFRAME (frame);
dc6f92b8 2297
032d78fe
GV
2298#ifdef HAVE_WINDOW_SYSTEM
2299 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2300 return make_number (x_pixel_width (f));
2301 else
2302#endif
2303 return make_number (FRAME_WIDTH (f));
2304}
2305\f
ff11dfa1
JB
2306DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
2307 "Specify that the frame FRAME has LINES lines.\n\
dc6f92b8 2308Optional third arg non-nil means that redisplay should use LINES lines\n\
ff11dfa1 2309but that the idea of the actual height of the frame should not be changed.")
735eeca3
EN
2310 (frame, lines, pretend)
2311 Lisp_Object frame, lines, pretend;
dc6f92b8 2312{
ff11dfa1 2313 register struct frame *f;
dc6f92b8 2314
735eeca3 2315 CHECK_NUMBER (lines, 0);
ff11dfa1 2316 if (NILP (frame))
8d2666fe
GM
2317 frame = selected_frame;
2318 CHECK_LIVE_FRAME (frame, 0);
2319 f = XFRAME (frame);
dc6f92b8 2320
dbc4e1c1 2321 /* I think this should be done with a hook. */
032d78fe
GV
2322#ifdef HAVE_WINDOW_SYSTEM
2323 if (FRAME_WINDOW_P (f))
dc6f92b8 2324 {
735eeca3
EN
2325 if (XINT (lines) != f->height)
2326 x_set_window_size (f, 1, f->width, XINT (lines));
32347cf4 2327 do_pending_window_change (0);
dc6f92b8
JB
2328 }
2329 else
fd0c2bd1 2330#endif
32347cf4 2331 change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0, 0);
dc6f92b8
JB
2332 return Qnil;
2333}
2334
ff11dfa1
JB
2335DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
2336 "Specify that the frame FRAME has COLS columns.\n\
dc6f92b8 2337Optional third arg non-nil means that redisplay should use COLS columns\n\
ff11dfa1
JB
2338but that the idea of the actual width of the frame should not be changed.")
2339 (frame, cols, pretend)
fd0c2bd1 2340 Lisp_Object frame, cols, pretend;
dc6f92b8 2341{
ff11dfa1 2342 register struct frame *f;
dc6f92b8 2343 CHECK_NUMBER (cols, 0);
ff11dfa1 2344 if (NILP (frame))
8d2666fe
GM
2345 frame = selected_frame;
2346 CHECK_LIVE_FRAME (frame, 0);
2347 f = XFRAME (frame);
dc6f92b8 2348
dbc4e1c1 2349 /* I think this should be done with a hook. */
032d78fe
GV
2350#ifdef HAVE_WINDOW_SYSTEM
2351 if (FRAME_WINDOW_P (f))
dc6f92b8 2352 {
ff11dfa1 2353 if (XINT (cols) != f->width)
808c0f20 2354 x_set_window_size (f, 1, XINT (cols), f->height);
32347cf4 2355 do_pending_window_change (0);
dc6f92b8
JB
2356 }
2357 else
fd0c2bd1 2358#endif
32347cf4 2359 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0, 0);
dc6f92b8
JB
2360 return Qnil;
2361}
2362
ff11dfa1
JB
2363DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
2364 "Sets size of FRAME to COLS by ROWS, measured in characters.")
2365 (frame, cols, rows)
2366 Lisp_Object frame, cols, rows;
dc6f92b8 2367{
ff11dfa1 2368 register struct frame *f;
dc6f92b8 2369
ff11dfa1 2370 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
2371 CHECK_NUMBER (cols, 2);
2372 CHECK_NUMBER (rows, 1);
ff11dfa1 2373 f = XFRAME (frame);
dc6f92b8 2374
dbc4e1c1 2375 /* I think this should be done with a hook. */
032d78fe
GV
2376#ifdef HAVE_WINDOW_SYSTEM
2377 if (FRAME_WINDOW_P (f))
dc6f92b8 2378 {
29824ce2
RS
2379 if (XINT (rows) != f->height || XINT (cols) != f->width
2380 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
808c0f20 2381 x_set_window_size (f, 1, XINT (cols), XINT (rows));
32347cf4 2382 do_pending_window_change (0);
dc6f92b8
JB
2383 }
2384 else
fd0c2bd1 2385#endif
32347cf4 2386 change_frame_size (f, XINT (rows), XINT (cols), 0, 0, 0);
dc6f92b8
JB
2387
2388 return Qnil;
2389}
2390
ff11dfa1
JB
2391DEFUN ("set-frame-position", Fset_frame_position,
2392 Sset_frame_position, 3, 3, 0,
2393 "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
60bf8ee4
RS
2394This is actually the position of the upper left corner of the frame.\n\
2395Negative values for XOFFSET or YOFFSET are interpreted relative to\n\
4524cb1c 2396the rightmost or bottommost possible position (that stays within the screen).")
ff11dfa1
JB
2397 (frame, xoffset, yoffset)
2398 Lisp_Object frame, xoffset, yoffset;
dc6f92b8 2399{
ff11dfa1 2400 register struct frame *f;
dc6f92b8 2401
ff11dfa1 2402 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
2403 CHECK_NUMBER (xoffset, 1);
2404 CHECK_NUMBER (yoffset, 2);
ff11dfa1 2405 f = XFRAME (frame);
dc6f92b8 2406
dbc4e1c1 2407 /* I think this should be done with a hook. */
032d78fe
GV
2408#ifdef HAVE_WINDOW_SYSTEM
2409 if (FRAME_WINDOW_P (f))
c7c70761 2410 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
fd0c2bd1 2411#endif
dc6f92b8
JB
2412
2413 return Qt;
2414}
dc6d9681 2415
dc6f92b8 2416\f
dfcf069d 2417void
ff11dfa1 2418syms_of_frame ()
dc6f92b8 2419{
3df1fda2
GM
2420 Qframep = intern ("framep");
2421 staticpro (&Qframep);
2422 Qframe_live_p = intern ("frame-live-p");
2423 staticpro (&Qframe_live_p);
2424 Qheight = intern ("height");
2425 staticpro (&Qheight);
2426 Qicon = intern ("icon");
2427 staticpro (&Qicon);
2428 Qminibuffer = intern ("minibuffer");
2429 staticpro (&Qminibuffer);
2430 Qmodeline = intern ("modeline");
2431 staticpro (&Qmodeline);
2432 Qname = intern ("name");
2433 staticpro (&Qname);
2434 Qonly = intern ("only");
2435 staticpro (&Qonly);
2436 Qunsplittable = intern ("unsplittable");
2437 staticpro (&Qunsplittable);
2438 Qmenu_bar_lines = intern ("menu-bar-lines");
2439 staticpro (&Qmenu_bar_lines);
2440 Qtool_bar_lines = intern ("tool-bar-lines");
2441 staticpro (&Qtool_bar_lines);
2442 Qwidth = intern ("width");
2443 staticpro (&Qwidth);
2444 Qx = intern ("x");
2445 staticpro (&Qx);
2446 Qw32 = intern ("w32");
2447 staticpro (&Qw32);
2448 Qpc = intern ("pc");
2449 staticpro (&Qpc);
2450 Qmac = intern ("mac");
2451 staticpro (&Qmac);
2452 Qvisible = intern ("visible");
2453 staticpro (&Qvisible);
2454 Qbuffer_predicate = intern ("buffer-predicate");
2455 staticpro (&Qbuffer_predicate);
2456 Qbuffer_list = intern ("buffer-list");
2457 staticpro (&Qbuffer_list);
2458 Qtitle = intern ("title");
2459 staticpro (&Qtitle);
2460 Qdisplay_type = intern ("display-type");
2461 staticpro (&Qdisplay_type);
2462 Qbackground_mode = intern ("background-mode");
2463 staticpro (&Qbackground_mode);
dc6f92b8 2464
3df1fda2
GM
2465 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
2466 "Alist of default values for frame creation.\n\
2467These may be set in your init file, like this:\n\
2468 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1))\n\
2469These override values given in window system configuration data,\n\
2470 including X Windows' defaults database.\n\
2471For values specific to the first Emacs frame, see `initial-frame-alist'.\n\
2472For values specific to the separate minibuffer frame, see\n\
2473 `minibuffer-frame-alist'.\n\
2474The `menu-bar-lines' element of the list controls whether new frames\n\
2475 have menu bars; `menu-bar-mode' works by altering this element.");
2476 Vdefault_frame_alist = Qnil;
2477
2478 Qinhibit_default_face_x_resources
2479 = intern ("inhibit-default-face-x-resources");
2480 staticpro (&Qinhibit_default_face_x_resources);
dc6f92b8 2481
ff11dfa1
JB
2482 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
2483 "The initial frame-object, which represents Emacs's stdout.");
dc6f92b8
JB
2484
2485 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
ff11dfa1 2486 "Non-nil if all of emacs is iconified and frame updates are not needed.");
dc6f92b8
JB
2487 Vemacs_iconified = Qnil;
2488
beb0bc36
DL
2489 DEFVAR_LISP ("mouse-position-function", &Vmouse_position_function,
2490 "If non-nil, function applied to the normal result of `mouse-position'.\n\
2491This abnormal hook exists for the benefit of packages like XTerm-mouse\n\
2492which need to do mouse handling at the Lisp level.");
2493 Vmouse_position_function = Qnil;
2494
c60f3a6a 2495 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
ff11dfa1 2496 "Minibufferless frames use this frame's minibuffer.\n\
f9898cc6 2497\n\
ff11dfa1 2498Emacs cannot create minibufferless frames unless this is set to an\n\
f9898cc6
JB
2499appropriate surrogate.\n\
2500\n\
2501Emacs consults this variable only when creating minibufferless\n\
ff11dfa1 2502frames; once the frame is created, it sticks with its assigned\n\
f9898cc6
JB
2503minibuffer, no matter what this variable is set to. This means that\n\
2504this variable doesn't necessarily say anything meaningful about the\n\
ff11dfa1 2505current set of frames, or where the minibuffer is currently being\n\
f9898cc6 2506displayed.");
dc6f92b8 2507
3df1fda2
GM
2508 staticpro (&Vframe_list);
2509
5add3885 2510 defsubr (&Sactive_minibuffer_window);
ff11dfa1 2511 defsubr (&Sframep);
dbc4e1c1 2512 defsubr (&Sframe_live_p);
bb1513c9 2513 defsubr (&Smake_terminal_frame);
0f85737c 2514 defsubr (&Shandle_switch_frame);
1c212787 2515 defsubr (&Signore_event);
ff11dfa1
JB
2516 defsubr (&Sselect_frame);
2517 defsubr (&Sselected_frame);
2518 defsubr (&Swindow_frame);
2519 defsubr (&Sframe_root_window);
d446a856 2520 defsubr (&Sframe_first_window);
ff11dfa1 2521 defsubr (&Sframe_selected_window);
4a7cfafc 2522 defsubr (&Sset_frame_selected_window);
ff11dfa1
JB
2523 defsubr (&Sframe_list);
2524 defsubr (&Snext_frame);
ef2c57ac 2525 defsubr (&Sprevious_frame);
ff11dfa1 2526 defsubr (&Sdelete_frame);
f9898cc6 2527 defsubr (&Smouse_position);
152e6c70 2528 defsubr (&Smouse_pixel_position);
dc6f92b8 2529 defsubr (&Sset_mouse_position);
152e6c70 2530 defsubr (&Sset_mouse_pixel_position);
dc6f92b8 2531#if 0
ff11dfa1
JB
2532 defsubr (&Sframe_configuration);
2533 defsubr (&Srestore_frame_configuration);
dc6f92b8 2534#endif
ff11dfa1
JB
2535 defsubr (&Smake_frame_visible);
2536 defsubr (&Smake_frame_invisible);
2537 defsubr (&Siconify_frame);
2538 defsubr (&Sframe_visible_p);
2539 defsubr (&Svisible_frame_list);
b49f5578
JB
2540 defsubr (&Sraise_frame);
2541 defsubr (&Slower_frame);
ff11dfa1
JB
2542 defsubr (&Sredirect_frame_focus);
2543 defsubr (&Sframe_focus);
2544 defsubr (&Sframe_parameters);
8b60f7bc 2545 defsubr (&Sframe_parameter);
ff11dfa1 2546 defsubr (&Smodify_frame_parameters);
a26a1f95
RS
2547 defsubr (&Sframe_char_height);
2548 defsubr (&Sframe_char_width);
2549 defsubr (&Sframe_pixel_height);
2550 defsubr (&Sframe_pixel_width);
ff11dfa1
JB
2551 defsubr (&Sset_frame_height);
2552 defsubr (&Sset_frame_width);
2553 defsubr (&Sset_frame_size);
2554 defsubr (&Sset_frame_position);
dc6f92b8 2555}
e5d77022 2556
dfcf069d 2557void
2f0b07e0
JB
2558keys_of_frame ()
2559{
0f85737c 2560 initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
d134b17b 2561 initial_define_lispy_key (global_map, "delete-frame", "handle-delete-frame");
1c212787
KH
2562 initial_define_lispy_key (global_map, "iconify-frame", "ignore-event");
2563 initial_define_lispy_key (global_map, "make-frame-visible", "ignore-event");
2f0b07e0 2564}