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