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