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