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