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