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