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