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