(x_window_to_frame): Add parens for clarity.
[bpt/emacs.git] / src / frame.c
CommitLineData
ff11dfa1 1/* Generic frame functions.
c6c5df7f 2 Copyright (C) 1993 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
d5e7c279
JB
20#include <stdio.h>
21
18160b98 22#include <config.h>
cc38027b
JB
23#include "lisp.h"
24#include "frame.h"
bc1ed486 25#include "termhooks.h"
e5d77022 26
ff11dfa1 27#ifdef MULTI_FRAME
e5d77022 28
bff19c8d 29#include "buffer.h"
dc6f92b8
JB
30#include "window.h"
31
2f0b07e0
JB
32/* These help us bind and responding to switch-frame events. */
33#include "commands.h"
34#include "keyboard.h"
35
dc6f92b8 36Lisp_Object Vemacs_iconified;
ff11dfa1
JB
37Lisp_Object Vframe_list;
38Lisp_Object Vterminal_frame;
39Lisp_Object Vdefault_minibuffer_frame;
40Lisp_Object Vdefault_frame_alist;
fd0c2bd1
JB
41
42/* Evaluate this expression to rebuild the section of syms_of_frame
43 that initializes and staticpros the symbols declared below. Note
44 that Emacs 18 has a bug that keeps C-x C-e from being able to
45 evaluate this expression.
46
47(progn
48 ;; Accumulate a list of the symbols we want to initialize from the
49 ;; declarations at the top of the file.
50 (goto-char (point-min))
51 (search-forward "/\*&&& symbols declared here &&&*\/\n")
52 (let (symbol-list)
53 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
54 (setq symbol-list
55 (cons (buffer-substring (match-beginning 1) (match-end 1))
56 symbol-list))
57 (forward-line 1))
58 (setq symbol-list (nreverse symbol-list))
59 ;; Delete the section of syms_of_... where we initialize the symbols.
60 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
61 (let ((start (point)))
62 (while (looking-at "^ Q")
63 (forward-line 2))
64 (kill-region start (point)))
65 ;; Write a new symbol initialization section.
66 (while symbol-list
67 (insert (format " %s = intern (\"" (car symbol-list)))
68 (let ((start (point)))
69 (insert (substring (car symbol-list) 1))
70 (subst-char-in-region start (point) ?_ ?-))
71 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
72 (setq symbol-list (cdr symbol-list)))))
73 */
74
75/*&&& symbols declared here &&&*/
76Lisp_Object Qframep;
dbc4e1c1 77Lisp_Object Qframe_live_p;
fd0c2bd1
JB
78Lisp_Object Qheight;
79Lisp_Object Qicon;
bc93c097 80Lisp_Object Qminibuffer;
fd0c2bd1
JB
81Lisp_Object Qmodeline;
82Lisp_Object Qname;
fd0c2bd1
JB
83Lisp_Object Qonly;
84Lisp_Object Qunsplittable;
fa8fdbf9 85Lisp_Object Qmenu_bar_lines;
fd0c2bd1
JB
86Lisp_Object Qwidth;
87Lisp_Object Qx;
dc6f92b8
JB
88
89extern Lisp_Object Vminibuffer_list;
90extern Lisp_Object get_minibuffer ();
84386599
RS
91extern Lisp_Object Fhandle_switch_frame ();
92extern Lisp_Object Fredirect_frame_focus ();
dc6f92b8 93\f
ff11dfa1
JB
94DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
95 "Return non-nil if OBJECT is a frame.\n\
96Value is t for a termcap frame (a character-only terminal),\n\
97`x' for an Emacs frame that is really an X window.\n\
98Also see `live-frame-p'.")
f9898cc6
JB
99 (object)
100 Lisp_Object object;
dc6f92b8 101{
ff11dfa1 102 if (XTYPE (object) != Lisp_Frame)
dc6f92b8 103 return Qnil;
ff11dfa1 104 switch (XFRAME (object)->output_method)
dc6f92b8
JB
105 {
106 case output_termcap:
107 return Qt;
108 case output_x_window:
fd0c2bd1 109 return Qx;
dc6f92b8
JB
110 default:
111 abort ();
112 }
113}
114
dbc4e1c1 115DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
ff11dfa1
JB
116 "Return non-nil if OBJECT is a frame which has not been deleted.\n\
117Value is nil if OBJECT is not a live frame. If object is a live\n\
118frame, the return value indicates what sort of output device it is\n\
119displayed on. Value is t for a termcap frame (a character-only\n\
120terminal), `x' for an Emacs frame being displayed in an X window.")
f9898cc6
JB
121 (object)
122 Lisp_Object object;
123{
ff11dfa1
JB
124 return ((FRAMEP (object)
125 && FRAME_LIVE_P (XFRAME (object)))
126 ? Fframep (object)
f9898cc6
JB
127 : Qnil);
128}
129
ff11dfa1
JB
130struct frame *
131make_frame (mini_p)
dc6f92b8
JB
132 int mini_p;
133{
ff11dfa1
JB
134 Lisp_Object frame;
135 register struct frame *f;
dc6f92b8
JB
136 register Lisp_Object root_window;
137 register Lisp_Object mini_window;
138
ff11dfa1 139 frame = Fmake_vector (((sizeof (struct frame) - (sizeof (Lisp_Vector)
d5e7c279
JB
140 - sizeof (Lisp_Object)))
141 / sizeof (Lisp_Object)),
dc6f92b8 142 make_number (0));
ff11dfa1
JB
143 XSETTYPE (frame, Lisp_Frame);
144 f = XFRAME (frame);
145
146 f->cursor_x = 0;
147 f->cursor_y = 0;
148 f->current_glyphs = 0;
149 f->desired_glyphs = 0;
150 f->visible = 0;
323405de 151 f->async_visible = 0;
ff11dfa1
JB
152 f->display.nothing = 0;
153 f->iconified = 0;
323405de 154 f->async_iconified = 0;
ff11dfa1
JB
155 f->wants_modeline = 1;
156 f->auto_raise = 0;
157 f->auto_lower = 0;
158 f->no_split = 0;
159 f->garbaged = 0;
160 f->has_minibuffer = mini_p;
a42e9724 161 f->focus_frame = Qnil;
804518aa 162 f->explicit_name = 0;
fd2777e0
JB
163 f->can_have_scroll_bars = 0;
164 f->has_vertical_scroll_bars = 0;
ff11dfa1 165 f->param_alist = Qnil;
fd2777e0
JB
166 f->scroll_bars = Qnil;
167 f->condemned_scroll_bars = Qnil;
306cc902 168 f->face_alist = Qnil;
dc6f92b8 169
cc38027b 170 root_window = make_window ();
dc6f92b8
JB
171 if (mini_p)
172 {
cc38027b 173 mini_window = make_window ();
dc6f92b8
JB
174 XWINDOW (root_window)->next = mini_window;
175 XWINDOW (mini_window)->prev = root_window;
176 XWINDOW (mini_window)->mini_p = Qt;
ff11dfa1
JB
177 XWINDOW (mini_window)->frame = frame;
178 f->minibuffer_window = mini_window;
dc6f92b8
JB
179 }
180 else
181 {
182 mini_window = Qnil;
183 XWINDOW (root_window)->next = Qnil;
ff11dfa1 184 f->minibuffer_window = Qnil;
dc6f92b8
JB
185 }
186
ff11dfa1 187 XWINDOW (root_window)->frame = frame;
dc6f92b8
JB
188
189 /* 10 is arbitrary,
190 just so that there is "something there."
ff11dfa1 191 Correct size will be set up later with change_frame_size. */
dc6f92b8 192
ff11dfa1
JB
193 f->width = 10;
194 f->height = 10;
dc6f92b8
JB
195
196 XFASTINT (XWINDOW (root_window)->width) = 10;
197 XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
198
199 if (mini_p)
200 {
201 XFASTINT (XWINDOW (mini_window)->width) = 10;
202 XFASTINT (XWINDOW (mini_window)->top) = 9;
203 XFASTINT (XWINDOW (mini_window)->height) = 1;
204 }
205
ff11dfa1 206 /* Choose a buffer for the frame's root window. */
5bce042c
JB
207 {
208 Lisp_Object buf;
209
210 XWINDOW (root_window)->buffer = Qt;
211 buf = Fcurrent_buffer ();
212 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
213 a space), try to find another one. */
214 if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
c3c73481 215 buf = Fother_buffer (buf, Qnil);
5bce042c
JB
216 Fset_window_buffer (root_window, buf);
217 }
218
dc6f92b8
JB
219 if (mini_p)
220 {
221 XWINDOW (mini_window)->buffer = Qt;
222 Fset_window_buffer (mini_window,
265a9e55 223 (NILP (Vminibuffer_list)
dc6f92b8
JB
224 ? get_minibuffer (0)
225 : Fcar (Vminibuffer_list)));
226 }
227
ff11dfa1
JB
228 f->root_window = root_window;
229 f->selected_window = root_window;
d5e7c279
JB
230 /* Make sure this window seems more recently used than
231 a newly-created, never-selected window. */
ff11dfa1 232 XFASTINT (XWINDOW (f->selected_window)->use_time) = ++window_select_count;
dc6f92b8 233
ff11dfa1 234 return f;
dc6f92b8
JB
235}
236\f
ff11dfa1 237/* Make a frame using a separate minibuffer window on another frame.
dc6f92b8
JB
238 MINI_WINDOW is the minibuffer window to use. nil means use the
239 default (the global minibuffer). */
240
ff11dfa1
JB
241struct frame *
242make_frame_without_minibuffer (mini_window)
dc6f92b8
JB
243 register Lisp_Object mini_window;
244{
ff11dfa1 245 register struct frame *f;
dc6f92b8
JB
246
247 /* Choose the minibuffer window to use. */
265a9e55 248 if (NILP (mini_window))
dc6f92b8 249 {
ff11dfa1
JB
250 if (XTYPE (Vdefault_minibuffer_frame) != Lisp_Frame)
251 error ("default-minibuffer-frame must be set when creating minibufferless frames");
252 if (! FRAME_LIVE_P (XFRAME (Vdefault_minibuffer_frame)))
253 error ("default-minibuffer-frame must be a live frame");
254 mini_window = XFRAME (Vdefault_minibuffer_frame)->minibuffer_window;
dc6f92b8
JB
255 }
256 else
257 {
774910eb 258 CHECK_LIVE_WINDOW (mini_window, 0);
dc6f92b8
JB
259 }
260
ff11dfa1
JB
261 /* Make a frame containing just a root window. */
262 f = make_frame (0);
dc6f92b8
JB
263
264 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 265 f->minibuffer_window = mini_window;
dc6f92b8 266 Fset_window_buffer (mini_window,
265a9e55 267 (NILP (Vminibuffer_list)
dc6f92b8
JB
268 ? get_minibuffer (0)
269 : Fcar (Vminibuffer_list)));
ff11dfa1 270 return f;
dc6f92b8
JB
271}
272
ff11dfa1 273/* Make a frame containing only a minibuffer window. */
dc6f92b8 274
ff11dfa1
JB
275struct frame *
276make_minibuffer_frame ()
dc6f92b8 277{
ff11dfa1 278 /* First make a frame containing just a root window, no minibuffer. */
dc6f92b8 279
ff11dfa1 280 register struct frame *f = make_frame (0);
dc6f92b8 281 register Lisp_Object mini_window;
ff11dfa1 282 register Lisp_Object frame;
dc6f92b8 283
ff11dfa1 284 XSET (frame, Lisp_Frame, f);
dc6f92b8 285
804518aa 286 f->auto_raise = 0;
ff11dfa1
JB
287 f->auto_lower = 0;
288 f->no_split = 1;
289 f->wants_modeline = 0;
290 f->has_minibuffer = 1;
dc6f92b8
JB
291
292 /* Now label the root window as also being the minibuffer.
293 Avoid infinite looping on the window chain by marking next pointer
294 as nil. */
295
ff11dfa1 296 mini_window = f->minibuffer_window = f->root_window;
dc6f92b8
JB
297 XWINDOW (mini_window)->mini_p = Qt;
298 XWINDOW (mini_window)->next = Qnil;
804518aa 299 XWINDOW (mini_window)->prev = Qnil;
ff11dfa1 300 XWINDOW (mini_window)->frame = frame;
dc6f92b8
JB
301
302 /* Put the proper buffer in that window. */
303
304 Fset_window_buffer (mini_window,
265a9e55 305 (NILP (Vminibuffer_list)
dc6f92b8
JB
306 ? get_minibuffer (0)
307 : Fcar (Vminibuffer_list)));
ff11dfa1 308 return f;
dc6f92b8
JB
309}
310\f
ff11dfa1 311/* Construct a frame that refers to the terminal (stdin and stdout). */
dc6f92b8 312
ff11dfa1
JB
313struct frame *
314make_terminal_frame ()
dc6f92b8 315{
ff11dfa1 316 register struct frame *f;
d063751a 317 Lisp_Object frame;
ff11dfa1
JB
318
319 Vframe_list = Qnil;
320 f = make_frame (1);
d063751a
RS
321
322 XSET (frame, Lisp_Frame, f);
323 Vframe_list = Fcons (frame, Vframe_list);
324
ff11dfa1 325 f->name = build_string ("terminal");
a42e9724 326 FRAME_SET_VISIBLE (f, 1);
ff11dfa1
JB
327 f->display.nothing = 1; /* Nonzero means frame isn't deleted. */
328 XSET (Vterminal_frame, Lisp_Frame, f);
329 return f;
dc6f92b8
JB
330}
331\f
2f0b07e0 332DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
0f85737c 333 "Select the frame FRAME.\n\
eb8c3be9 334Subsequent editing commands apply to its selected window.\n\
0f85737c
JB
335The selection of FRAME lasts until the next time the user does\n\
336something to select a different frame, or until the next time this\n\
337function is called.")
338 (frame, no_enter)
339 Lisp_Object frame, no_enter;
340{
341 return Fhandle_switch_frame (frame, no_enter);
342}
343
344
345DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
346 "Handle a switch-frame event EVENT.\n\
a375dcc0 347Switch-frame events are usually bound to this function.\n\
0f85737c
JB
348A switch-frame event tells Emacs that the window manager has requested\n\
349that the user's events be directed to the frame mentioned in the event.\n\
350This function selects the selected window of the frame of EVENT.\n\
a42e9724 351\n\
0f85737c
JB
352If EVENT is frame object, handle it as if it were a switch-frame event\n\
353to that frame.")
ff11dfa1
JB
354 (frame, no_enter)
355 Lisp_Object frame, no_enter;
dc6f92b8 356{
2f0b07e0
JB
357 /* If FRAME is a switch-frame event, extract the frame we should
358 switch to. */
359 if (CONSP (frame)
360 && EQ (XCONS (frame)->car, Qswitch_frame)
361 && CONSP (XCONS (frame)->cdr))
362 frame = XCONS (XCONS (frame)->cdr)->car;
363
ff11dfa1 364 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 365
ff11dfa1
JB
366 if (selected_frame == XFRAME (frame))
367 return frame;
dc6f92b8 368
a42e9724
JB
369 /* If a frame's focus has been redirected toward the currently
370 selected frame, we should change the redirection to point to the
371 newly selected frame. This means that if the focus is redirected
372 from a minibufferless frame to a surrogate minibuffer frame, we
373 can use `other-window' to switch between all the frames using
374 that minibuffer frame, and the focus redirection will follow us
375 around. */
376 {
377 Lisp_Object tail;
378
379 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
380 {
381 Lisp_Object focus;
382
383 if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
384 abort ();
385
386 focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
387
388 if (XTYPE (focus) == Lisp_Frame
389 && XFRAME (focus) == selected_frame)
390 Fredirect_frame_focus (XCONS (tail)->car, frame);
391 }
392 }
393
ff11dfa1
JB
394 selected_frame = XFRAME (frame);
395 if (! FRAME_MINIBUF_ONLY_P (selected_frame))
396 last_nonminibuf_frame = selected_frame;
d5e7c279 397
ff11dfa1 398 Fselect_window (XFRAME (frame)->selected_window);
ff11dfa1 399 choose_minibuf_frame ();
dc6f92b8 400
074577b8 401 /* We want to make sure that the next event generates a frame-switch
eb8c3be9 402 event to the appropriate frame. This seems kludgy to me, but
074577b8
JB
403 before you take it out, make sure that evaluating something like
404 (select-window (frame-root-window (new-frame))) doesn't end up
405 with your typing being interpreted in the new frame instead of
406 the one you're actually typing in. */
fd2777e0 407 internal_last_event_frame = Qnil;
074577b8 408
ff11dfa1 409 return frame;
dc6f92b8
JB
410}
411
ff11dfa1
JB
412DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
413 "Return the frame that is now selected.")
dc6f92b8
JB
414 ()
415{
416 Lisp_Object tem;
ff11dfa1 417 XSET (tem, Lisp_Frame, selected_frame);
dc6f92b8
JB
418 return tem;
419}
420
ff11dfa1
JB
421DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
422 "Return the frame object that window WINDOW is on.")
dc6f92b8
JB
423 (window)
424 Lisp_Object window;
425{
774910eb 426 CHECK_LIVE_WINDOW (window, 0);
ff11dfa1 427 return XWINDOW (window)->frame;
dc6f92b8
JB
428}
429
ff11dfa1 430DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
8693ca83
JB
431 "Returns the root-window of FRAME.\n\
432If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
433 (frame)
434 Lisp_Object frame;
dc6f92b8 435{
ff11dfa1
JB
436 if (NILP (frame))
437 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 438 else
ff11dfa1 439 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 440
ff11dfa1 441 return XFRAME (frame)->root_window;
dc6f92b8
JB
442}
443
ff11dfa1
JB
444DEFUN ("frame-selected-window", Fframe_selected_window,
445 Sframe_selected_window, 0, 1, 0,
8693ca83
JB
446 "Return the selected window of frame object FRAME.\n\
447If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
448 (frame)
449 Lisp_Object frame;
dc6f92b8 450{
ff11dfa1
JB
451 if (NILP (frame))
452 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 453 else
ff11dfa1 454 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 455
ff11dfa1 456 return XFRAME (frame)->selected_window;
dc6f92b8
JB
457}
458
ff11dfa1 459DEFUN ("frame-list", Fframe_list, Sframe_list,
dc6f92b8 460 0, 0, 0,
ff11dfa1 461 "Return a list of all frames.")
dc6f92b8
JB
462 ()
463{
ff11dfa1 464 return Fcopy_sequence (Vframe_list);
dc6f92b8
JB
465}
466
ff11dfa1 467/* Return the next frame in the frame list after FRAME.
ff11dfa1
JB
468 If MINIBUF is nil, exclude minibuffer-only frames.
469 If MINIBUF is a window, include only frames using that window for
d06a8a56
JB
470 their minibuffer.
471 If MINIBUF is non-nil, and not a window, include all frames. */
dc6f92b8 472Lisp_Object
ff11dfa1
JB
473next_frame (frame, minibuf)
474 Lisp_Object frame;
f9898cc6 475 Lisp_Object minibuf;
dc6f92b8
JB
476{
477 Lisp_Object tail;
478 int passed = 0;
479
ff11dfa1
JB
480 /* There must always be at least one frame in Vframe_list. */
481 if (! CONSP (Vframe_list))
f9898cc6
JB
482 abort ();
483
dbc4e1c1
JB
484 /* If this frame is dead, it won't be in Vframe_list, and we'll loop
485 forever. Forestall that. */
486 CHECK_LIVE_FRAME (frame, 0);
487
dc6f92b8 488 while (1)
ff11dfa1 489 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
dc6f92b8 490 {
d06a8a56
JB
491 Lisp_Object f = XCONS (tail)->car;
492
dc6f92b8 493 if (passed)
d5e7c279 494 {
d06a8a56
JB
495 /* Decide whether this frame is eligible to be returned. */
496
497 /* If we've looped all the way around without finding any
498 eligible frames, return the original frame. */
499 if (EQ (f, frame))
500 return f;
501
502 /* Let minibuf decide if this frame is acceptable. */
503 if (NILP (minibuf))
504 {
505 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
506 return f;
507 }
508 else if (XTYPE (minibuf) == Lisp_Window)
509 {
510 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
511 return f;
512 }
513 else
ff11dfa1 514 return f;
d5e7c279 515 }
dc6f92b8 516
d06a8a56 517 if (EQ (frame, f))
dc6f92b8
JB
518 passed++;
519 }
520}
521
ff11dfa1 522/* Return the previous frame in the frame list before FRAME.
ff11dfa1
JB
523 If MINIBUF is nil, exclude minibuffer-only frames.
524 If MINIBUF is a window, include only frames using that window for
d06a8a56
JB
525 their minibuffer.
526 If MINIBUF is non-nil and not a window, include all frames. */
dc6f92b8 527Lisp_Object
ff11dfa1
JB
528prev_frame (frame, minibuf)
529 Lisp_Object frame;
f9898cc6 530 Lisp_Object minibuf;
dc6f92b8
JB
531{
532 Lisp_Object tail;
533 Lisp_Object prev;
534
ff11dfa1
JB
535 /* There must always be at least one frame in Vframe_list. */
536 if (! CONSP (Vframe_list))
f9898cc6
JB
537 abort ();
538
dc6f92b8 539 prev = Qnil;
d06a8a56 540 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
f9898cc6 541 {
d06a8a56 542 Lisp_Object f = XCONS (tail)->car;
f9898cc6 543
d06a8a56
JB
544 if (XTYPE (f) != Lisp_Frame)
545 abort ();
f9898cc6 546
d06a8a56
JB
547 if (EQ (frame, f) && !NILP (prev))
548 return prev;
f9898cc6 549
d06a8a56
JB
550 /* Decide whether this frame is eligible to be returned,
551 according to minibuf. */
552 if (NILP (minibuf))
553 {
554 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
555 prev = f;
f9898cc6 556 }
d06a8a56
JB
557 else if (XTYPE (minibuf) == Lisp_Window)
558 {
559 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
560 prev = f;
561 }
562 else
563 prev = f;
f9898cc6 564 }
d06a8a56
JB
565
566 /* We've scanned the entire list. */
567 if (NILP (prev))
568 /* We went through the whole frame list without finding a single
569 acceptable frame. Return the original frame. */
570 return frame;
571 else
572 /* There were no acceptable frames in the list before FRAME; otherwise,
573 we would have returned directly from the loop. Since PREV is the last
574 acceptable frame in the list, return it. */
575 return prev;
dc6f92b8
JB
576}
577
ef2c57ac 578
ff11dfa1
JB
579DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
580 "Return the next frame in the frame list after FRAME.\n\
a42e9724 581By default, skip minibuffer-only frames.\n\
d06a8a56 582If omitted, FRAME defaults to the selected frame.\n\
c08c95c7 583If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
8693ca83 584If MINIFRAME is a window, include only frames using that window for their\n\
d06a8a56 585minibuffer.\n\
8693ca83 586If MINIFRAME is non-nil and not a window, include all frames.")
ff11dfa1 587 (frame, miniframe)
8693ca83 588 Lisp_Object frame, miniframe;
dc6f92b8
JB
589{
590 Lisp_Object tail;
591
ff11dfa1
JB
592 if (NILP (frame))
593 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 594 else
ff11dfa1 595 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 596
ff11dfa1 597 return next_frame (frame, miniframe);
dc6f92b8 598}
dbc4e1c1 599
ef2c57ac
RM
600DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
601 "Return the previous frame in the frame list before FRAME.\n\
602By default, skip minibuffer-only frames.\n\
603If omitted, FRAME defaults to the selected frame.\n\
604If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
605If MINIFRAME is a window, include only frames using that window for their\n\
606minibuffer.\n\
607If MINIFRAME is non-nil and not a window, include all frames.")
608 (frame, miniframe)
609 Lisp_Object frame, miniframe;
610{
611 Lisp_Object tail;
612
613 if (NILP (frame))
614 XSET (frame, Lisp_Frame, selected_frame);
615 else
616 CHECK_LIVE_FRAME (frame, 0);
617
618 return prev_frame (frame, miniframe);
619}
dc6f92b8 620\f
808c0f20
RS
621/* Return 1 if it is ok to delete frame F;
622 0 if all frames aside from F are invisible.
623 (Exception: if F is the terminal frame, and we are using X, return 1.) */
dc6f92b8 624
808c0f20
RS
625static int
626other_visible_frames (f)
627 FRAME_PTR f;
628{
629 /* We know the selected frame is visible,
630 so if F is some other frame, it can't be the sole visible one. */
631 if (f == selected_frame)
c08c95c7
RS
632 {
633 Lisp_Object frames;
634 int count = 0;
635
636 for (frames = Vframe_list;
637 CONSP (frames);
638 frames = XCONS (frames)->cdr)
639 {
640 Lisp_Object this = XCONS (frames)->car;
641
808c0f20
RS
642 /* Verify that the frame's window still exists
643 and we can still talk to it. And note any recent change
644 in visibility. */
5e7b7c5b
RS
645#ifdef HAVE_X_WINDOWS
646 if (FRAME_X_P (XFRAME (this)))
647 {
648 x_sync (this);
649 FRAME_SAMPLE_VISIBILITY (XFRAME (this));
650 }
651#endif
652
c08c95c7
RS
653 if (FRAME_VISIBLE_P (XFRAME (this))
654 || FRAME_ICONIFIED_P (XFRAME (this))
655 /* Allow deleting the terminal frame when at least
656 one X frame exists! */
9fbb139c 657 || (FRAME_X_P (XFRAME (this)) && !FRAME_X_P (f)))
c08c95c7
RS
658 count++;
659 }
808c0f20 660 return count > 1;
c08c95c7 661 }
808c0f20
RS
662 return 1;
663}
664
665DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
666 "Delete FRAME, permanently eliminating it from use.\n\
667If omitted, FRAME defaults to the selected frame.\n\
668A frame may not be deleted if its minibuffer is used by other frames.\n\
669Normally, you may not delete a frame if all other frames are invisible,\n\
670but if the second optional argument FORCE is non-nil, you may do so.")
671 (frame, force)
672 Lisp_Object frame, force;
673{
674 struct frame *f;
675
676 if (EQ (frame, Qnil))
677 {
678 f = selected_frame;
679 XSET (frame, Lisp_Frame, f);
680 }
681 else
682 {
683 CHECK_FRAME (frame, 0);
684 f = XFRAME (frame);
685 }
686
687 if (! FRAME_LIVE_P (f))
688 return Qnil;
689
690 if (NILP (force) && !other_visible_frames (f))
691 error ("Attempt to delete the sole visible or iconified frame");
d5e7c279 692
ff11dfa1
JB
693 /* Does this frame have a minibuffer, and is it the surrogate
694 minibuffer for any other frame? */
fd0c2bd1 695 if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
dc6f92b8 696 {
ff11dfa1 697 Lisp_Object frames;
1113d9db 698
ff11dfa1
JB
699 for (frames = Vframe_list;
700 CONSP (frames);
701 frames = XCONS (frames)->cdr)
1113d9db 702 {
ff11dfa1 703 Lisp_Object this = XCONS (frames)->car;
1113d9db 704
ff11dfa1
JB
705 if (! EQ (this, frame)
706 && EQ (frame,
707 (WINDOW_FRAME
1113d9db 708 (XWINDOW
ff11dfa1
JB
709 (FRAME_MINIBUF_WINDOW
710 (XFRAME (this)))))))
711 error ("Attempt to delete a surrogate minibuffer frame");
1113d9db 712 }
dc6f92b8
JB
713 }
714
ff11dfa1
JB
715 /* Don't let the frame remain selected. */
716 if (f == selected_frame)
0f85737c 717 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
dc6f92b8 718
ff11dfa1
JB
719 /* Don't allow minibuf_window to remain on a deleted frame. */
720 if (EQ (f->minibuffer_window, minibuf_window))
dc6f92b8 721 {
ff11dfa1 722 Fset_window_buffer (selected_frame->minibuffer_window,
dc6f92b8 723 XWINDOW (minibuf_window)->buffer);
ff11dfa1 724 minibuf_window = selected_frame->minibuffer_window;
dc6f92b8
JB
725 }
726
4a88b3b0
JB
727 /* Mark all the windows that used to be on FRAME as deleted, and then
728 remove the reference to them. */
729 delete_all_subwindows (XWINDOW (f->root_window));
730 f->root_window = Qnil;
731
ff11dfa1 732 Vframe_list = Fdelq (frame, Vframe_list);
a42e9724 733 FRAME_SET_VISIBLE (f, 0);
dc6f92b8 734
8678b9cc
JB
735 /* Since some events are handled at the interrupt level, we may get
736 an event for f at any time; if we zero out the frame's display
737 now, then we may trip up the event-handling code. Instead, we'll
738 promise that the display of the frame must be valid until we have
739 called the window-system-dependent frame destruction routine. */
dbc4e1c1
JB
740
741 /* I think this should be done with a hook. */
d5e7c279 742#ifdef HAVE_X_WINDOWS
fd0c2bd1 743 if (FRAME_X_P (f))
8678b9cc 744 x_destroy_window (f);
d5e7c279
JB
745#endif
746
8678b9cc
JB
747 f->display.nothing = 0;
748
ff11dfa1 749 /* If we've deleted the last_nonminibuf_frame, then try to find
d5e7c279 750 another one. */
ff11dfa1 751 if (f == last_nonminibuf_frame)
d5e7c279 752 {
ff11dfa1 753 Lisp_Object frames;
1113d9db 754
ff11dfa1 755 last_nonminibuf_frame = 0;
d5e7c279 756
ff11dfa1
JB
757 for (frames = Vframe_list;
758 CONSP (frames);
759 frames = XCONS (frames)->cdr)
d5e7c279 760 {
ff11dfa1
JB
761 f = XFRAME (XCONS (frames)->car);
762 if (!FRAME_MINIBUF_ONLY_P (f))
d5e7c279 763 {
ff11dfa1 764 last_nonminibuf_frame = f;
d5e7c279
JB
765 break;
766 }
767 }
768 }
dc6f92b8 769
ff11dfa1
JB
770 /* If we've deleted Vdefault_minibuffer_frame, try to find another
771 one. Prefer minibuffer-only frames, but also notice frames
1113d9db 772 with other windows. */
ff11dfa1 773 if (EQ (frame, Vdefault_minibuffer_frame))
1113d9db 774 {
ff11dfa1 775 Lisp_Object frames;
1113d9db 776
ff11dfa1
JB
777 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
778 Lisp_Object frame_with_minibuf = Qnil;
1113d9db 779
ff11dfa1
JB
780 for (frames = Vframe_list;
781 CONSP (frames);
782 frames = XCONS (frames)->cdr)
1113d9db 783 {
ff11dfa1 784 Lisp_Object this = XCONS (frames)->car;
1113d9db 785
ff11dfa1 786 if (XTYPE (this) != Lisp_Frame)
1113d9db 787 abort ();
ff11dfa1 788 f = XFRAME (this);
1113d9db 789
fd0c2bd1 790 if (FRAME_HAS_MINIBUF_P (f))
1113d9db 791 {
ff11dfa1
JB
792 frame_with_minibuf = this;
793 if (FRAME_MINIBUF_ONLY_P (f))
1113d9db
JB
794 break;
795 }
796 }
797
ff11dfa1
JB
798 /* We know that there must be some frame with a minibuffer out
799 there. If this were not true, all of the frames present
1113d9db 800 would have to be minibufferless, which implies that at some
ff11dfa1 801 point their minibuffer frames must have been deleted, but
1113d9db 802 that is prohibited at the top; you can't delete surrogate
ff11dfa1
JB
803 minibuffer frames. */
804 if (NILP (frame_with_minibuf))
1113d9db
JB
805 abort ();
806
ff11dfa1 807 Vdefault_minibuffer_frame = frame_with_minibuf;
1113d9db
JB
808 }
809
dc6f92b8
JB
810 return Qnil;
811}
812\f
813/* Return mouse position in character cell units. */
814
f9898cc6 815DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
ff11dfa1 816 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
4f90516b
JB
817The position is given in character cells, where (0, 0) is the\n\
818upper-left corner.\n\
f9898cc6 819If Emacs is running on a mouseless terminal or hasn't been programmed\n\
ff11dfa1 820to read the mouse position, it returns the selected frame for FRAME\n\
f9898cc6
JB
821and nil for X and Y.")
822 ()
dc6f92b8 823{
ff11dfa1 824 FRAME_PTR f;
dbc4e1c1 825 Lisp_Object lispy_dummy;
fd2777e0 826 enum scroll_bar_part party_dummy;
dbc4e1c1
JB
827 Lisp_Object x, y;
828 unsigned long long_dummy;
dc6f92b8 829
c5074d8c
RS
830 f = selected_frame;
831 x = y = Qnil;
832
833 /* It's okay for the hook to refrain from storing anything. */
f9898cc6 834 if (mouse_position_hook)
dbc4e1c1
JB
835 (*mouse_position_hook) (&f,
836 &lispy_dummy, &party_dummy,
837 &x, &y,
838 &long_dummy);
dc6f92b8 839
dbc4e1c1 840 XSET (lispy_dummy, Lisp_Frame, f);
c5074d8c 841 return Fcons (lispy_dummy, Fcons (x, y));
dc6f92b8
JB
842}
843
844DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
1d7cc616 845 "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
ff11dfa1
JB
846WARNING: If you use this under X, you should do `unfocus-frame' afterwards.")
847 (frame, x, y)
848 Lisp_Object frame, x, y;
dc6f92b8 849{
ff11dfa1 850 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
851 CHECK_NUMBER (x, 2);
852 CHECK_NUMBER (y, 1);
853
dbc4e1c1 854 /* I think this should be done with a hook. */
dc6f92b8 855#ifdef HAVE_X_WINDOWS
fd0c2bd1 856 if (FRAME_X_P (XFRAME (frame)))
dc6f92b8 857 /* Warping the mouse will cause enternotify and focus events. */
ff11dfa1 858 x_set_mouse_position (XFRAME (frame), x, y);
dc6f92b8
JB
859#endif
860
861 return Qnil;
862}
863\f
ff11dfa1 864DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
fc25d15d 865 0, 1, "",
ff11dfa1 866 "Make the frame FRAME visible (assuming it is an X-window).\n\
8693ca83 867If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
868 (frame)
869 Lisp_Object frame;
dc6f92b8 870{
1aa66088 871 if (NILP (frame))
7500877e 872 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 873
ff11dfa1 874 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 875
dbc4e1c1 876 /* I think this should be done with a hook. */
fd0c2bd1
JB
877#ifdef HAVE_X_WINDOWS
878 if (FRAME_X_P (XFRAME (frame)))
02ff9dd5
RS
879 {
880 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
881 x_make_frame_visible (XFRAME (frame));
882 }
fd0c2bd1 883#endif
dc6f92b8 884
ff11dfa1 885 return frame;
dc6f92b8
JB
886}
887
ff11dfa1 888DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
808c0f20 889 0, 2, "",
8693ca83 890 "Make the frame FRAME invisible (assuming it is an X-window).\n\
808c0f20
RS
891If omitted, FRAME defaults to the currently selected frame.\n\
892Normally you may not make FRAME invisible if all other frames are invisible,\n\
893but if the second optional argument FORCE is non-nil, you may do so.")
894 (frame, force)
895 Lisp_Object frame, force;
dc6f92b8 896{
1aa66088 897 if (NILP (frame))
7500877e 898 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 899
ff11dfa1 900 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 901
808c0f20
RS
902 if (NILP (force) && !other_visible_frames (XFRAME (frame)))
903 error ("Attempt to make invisible the sole visible or iconified frame");
904
9c394f17
RS
905 /* Don't let the frame remain selected. */
906 if (XFRAME (frame) == selected_frame)
907 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
908
909 /* Don't allow minibuf_window to remain on a deleted frame. */
910 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
911 {
912 Fset_window_buffer (selected_frame->minibuffer_window,
913 XWINDOW (minibuf_window)->buffer);
914 minibuf_window = selected_frame->minibuffer_window;
915 }
916
dbc4e1c1 917 /* I think this should be done with a hook. */
fd0c2bd1
JB
918#ifdef HAVE_X_WINDOWS
919 if (FRAME_X_P (XFRAME (frame)))
ff11dfa1 920 x_make_frame_invisible (XFRAME (frame));
fd0c2bd1 921#endif
dc6f92b8
JB
922
923 return Qnil;
924}
925
ff11dfa1 926DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
1aa66088 927 0, 1, "",
8693ca83
JB
928 "Make the frame FRAME into an icon.\n\
929If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
930 (frame)
931 Lisp_Object frame;
dc6f92b8 932{
1aa66088 933 if (NILP (frame))
7500877e 934 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 935
ff11dfa1 936 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 937
9c394f17
RS
938 /* Don't let the frame remain selected. */
939 if (XFRAME (frame) == selected_frame)
940 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
941
942 /* Don't allow minibuf_window to remain on a deleted frame. */
943 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
944 {
945 Fset_window_buffer (selected_frame->minibuffer_window,
946 XWINDOW (minibuf_window)->buffer);
947 minibuf_window = selected_frame->minibuffer_window;
948 }
949
dbc4e1c1 950 /* I think this should be done with a hook. */
fd0c2bd1
JB
951#ifdef HAVE_X_WINDOWS
952 if (FRAME_X_P (XFRAME (frame)))
ff11dfa1 953 x_iconify_frame (XFRAME (frame));
fd0c2bd1 954#endif
dc6f92b8
JB
955
956 return Qnil;
957}
958
ff11dfa1 959DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
dc6f92b8 960 1, 1, 0,
ff11dfa1
JB
961 "Return t if FRAME is now \"visible\" (actually in use for display).\n\
962A frame that is not \"visible\" is not updated and, if it works through\n\
dc6f92b8 963a window system, it may not show at all.\n\
fd0c2bd1 964Return the symbol `icon' if frame is visible only as an icon.")
ff11dfa1
JB
965 (frame)
966 Lisp_Object frame;
dc6f92b8 967{
ff11dfa1 968 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 969
a42e9724 970 if (FRAME_VISIBLE_P (XFRAME (frame)))
dc6f92b8 971 return Qt;
a42e9724 972 if (FRAME_ICONIFIED_P (XFRAME (frame)))
fd0c2bd1 973 return Qicon;
dc6f92b8
JB
974 return Qnil;
975}
976
ff11dfa1 977DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
dc6f92b8 978 0, 0, 0,
ff11dfa1 979 "Return a list of all frames now \"visible\" (being updated).")
dc6f92b8
JB
980 ()
981{
ff11dfa1
JB
982 Lisp_Object tail, frame;
983 struct frame *f;
dc6f92b8
JB
984 Lisp_Object value;
985
986 value = Qnil;
ff11dfa1 987 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
dc6f92b8 988 {
ff11dfa1
JB
989 frame = XCONS (tail)->car;
990 if (XTYPE (frame) != Lisp_Frame)
dc6f92b8 991 continue;
ff11dfa1 992 f = XFRAME (frame);
a42e9724 993 if (FRAME_VISIBLE_P (f))
ff11dfa1 994 value = Fcons (frame, value);
dc6f92b8
JB
995 }
996 return value;
997}
d5e7c279
JB
998
999
b49f5578 1000DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 1, 1, 0,
dbc4e1c1
JB
1001 "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
1002If FRAME is invisible, make it visible.\n\
1003If Emacs is displaying on an ordinary terminal or some other device which\n\
1004doesn't support multiple overlapping frames, this function does nothing.")
1005 (frame)
1006 Lisp_Object frame;
1007{
1008 CHECK_LIVE_FRAME (frame, 0);
8a981af5
RS
1009
1010 /* Do like the documentation says. */
1011 Fmake_frame_visible (frame);
1012
dbc4e1c1
JB
1013 if (frame_raise_lower_hook)
1014 (*frame_raise_lower_hook) (XFRAME (frame), 1);
1015
1016 return Qnil;
1017}
1018
b49f5578
JB
1019/* Should we have a corresponding function called Flower_Power? */
1020DEFUN ("lower-frame", Flower_frame, Slower_frame, 1, 1, 0,
dbc4e1c1
JB
1021 "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
1022If Emacs is displaying on an ordinary terminal or some other device which\n\
1023doesn't support multiple overlapping frames, this function does nothing.")
1024 (frame)
1025 Lisp_Object frame;
1026{
1027 CHECK_LIVE_FRAME (frame, 0);
1028
1029 if (frame_raise_lower_hook)
1030 (*frame_raise_lower_hook) (XFRAME (frame), 0);
1031
1032 return Qnil;
1033}
1034
d5e7c279 1035\f
ff11dfa1 1036DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
d5e7c279 1037 1, 2, 0,
ff11dfa1 1038 "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
a42e9724
JB
1039In other words, switch-frame events caused by events in FRAME will\n\
1040request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
1041FOCUS-FRAME after reading an event typed at FRAME.\n\
d5e7c279 1042\n\
a42e9724 1043If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
ff11dfa1 1044cancelled, and the frame again receives its own keystrokes.\n\
d5e7c279 1045\n\
a42e9724
JB
1046Focus redirection is useful for temporarily redirecting keystrokes to\n\
1047a surrogate minibuffer frame when a frame doesn't have its own\n\
1048minibuffer window.\n\
d5e7c279 1049\n\
a42e9724
JB
1050A frame's focus redirection can be changed by select-frame. If frame\n\
1051FOO is selected, and then a different frame BAR is selected, any\n\
1052frames redirecting their focus to FOO are shifted to redirect their\n\
1053focus to BAR. This allows focus redirection to work properly when the\n\
1054user switches from one frame to another using `select-window'.\n\
1055\n\
1056This means that a frame whose focus is redirected to itself is treated\n\
1057differently from a frame whose focus is redirected to nil; the former\n\
1058is affected by select-frame, while the latter is not.\n\
1059\n\
1060The redirection lasts until `redirect-frame-focus' is called to change it.")
ff11dfa1
JB
1061 (frame, focus_frame)
1062 Lisp_Object frame, focus_frame;
d5e7c279 1063{
13144095
JB
1064 /* Note that we don't check for a live frame here. It's reasonable
1065 to redirect the focus of a frame you're about to delete, if you
1066 know what other frame should receive those keystrokes. */
1067 CHECK_FRAME (frame, 0);
f9898cc6 1068
a42e9724 1069 if (! NILP (focus_frame))
ff11dfa1 1070 CHECK_LIVE_FRAME (focus_frame, 1);
d5e7c279 1071
ff11dfa1 1072 XFRAME (frame)->focus_frame = focus_frame;
d5e7c279 1073
9c394f17
RS
1074 /* I think this should be done with a hook. */
1075#ifdef HAVE_X_WINDOWS
1076 if (!NILP (focus_frame) && ! EQ (focus_frame, frame)
1077 && FRAME_X_P (XFRAME (focus_frame)))
1078 Ffocus_frame (focus_frame);
1079#endif
1080
ff11dfa1
JB
1081 if (frame_rehighlight_hook)
1082 (*frame_rehighlight_hook) ();
d5e7c279
JB
1083
1084 return Qnil;
1085}
1086
1087
ff11dfa1
JB
1088DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
1089 "Return the frame to which FRAME's keystrokes are currently being sent.\n\
a42e9724 1090This returns nil if FRAME's focus is not redirected.\n\
ff11dfa1
JB
1091See `redirect-frame-focus'.")
1092 (frame)
1093 Lisp_Object frame;
d5e7c279 1094{
ff11dfa1 1095 CHECK_LIVE_FRAME (frame, 0);
a42e9724 1096
ff11dfa1 1097 return FRAME_FOCUS_FRAME (XFRAME (frame));
d5e7c279
JB
1098}
1099
1100
dc6f92b8
JB
1101\f
1102Lisp_Object
ff11dfa1
JB
1103get_frame_param (frame, prop)
1104 register struct frame *frame;
dc6f92b8
JB
1105 Lisp_Object prop;
1106{
1107 register Lisp_Object tem;
1108
ff11dfa1 1109 tem = Fassq (prop, frame->param_alist);
dc6f92b8
JB
1110 if (EQ (tem, Qnil))
1111 return tem;
1112 return Fcdr (tem);
1113}
1114
1115void
fd0c2bd1 1116store_in_alist (alistptr, prop, val)
dc6f92b8 1117 Lisp_Object *alistptr, val;
fd0c2bd1 1118 Lisp_Object prop;
dc6f92b8
JB
1119{
1120 register Lisp_Object tem;
dc6f92b8 1121
dc6f92b8
JB
1122 tem = Fassq (prop, *alistptr);
1123 if (EQ (tem, Qnil))
1124 *alistptr = Fcons (Fcons (prop, val), *alistptr);
1125 else
1126 Fsetcdr (tem, val);
1127}
1128
1129void
ff11dfa1
JB
1130store_frame_param (f, prop, val)
1131 struct frame *f;
dc6f92b8
JB
1132 Lisp_Object prop, val;
1133{
1134 register Lisp_Object tem;
1135
ff11dfa1 1136 tem = Fassq (prop, f->param_alist);
dc6f92b8 1137 if (EQ (tem, Qnil))
ff11dfa1 1138 f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
dc6f92b8
JB
1139 else
1140 Fsetcdr (tem, val);
bc93c097
JB
1141
1142 if (EQ (prop, Qminibuffer)
1143 && XTYPE (val) == Lisp_Window)
1144 {
1145 if (! MINI_WINDOW_P (XWINDOW (val)))
1146 error ("Surrogate minibuffer windows must be minibuffer windows.");
1147
fd0c2bd1 1148 if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
1fb2d074 1149 error ("can't change the surrogate minibuffer of a frame with its own minibuffer");
bc93c097
JB
1150
1151 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 1152 f->minibuffer_window = val;
bc93c097 1153 }
dc6f92b8
JB
1154}
1155
ff11dfa1
JB
1156DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
1157 "Return the parameters-alist of frame FRAME.\n\
dc6f92b8 1158It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
dc6d9681
JB
1159The meaningful PARMs depend on the kind of frame.\n\
1160If FRAME is omitted, return information on the currently selected frame.")
ff11dfa1
JB
1161 (frame)
1162 Lisp_Object frame;
dc6f92b8
JB
1163{
1164 Lisp_Object alist;
ff11dfa1 1165 struct frame *f;
dc6f92b8 1166
ff11dfa1
JB
1167 if (EQ (frame, Qnil))
1168 f = selected_frame;
dc6f92b8
JB
1169 else
1170 {
ff11dfa1
JB
1171 CHECK_FRAME (frame, 0);
1172 f = XFRAME (frame);
dc6f92b8
JB
1173 }
1174
ff11dfa1 1175 if (f->display.nothing == 0)
dc6f92b8
JB
1176 return Qnil;
1177
ff11dfa1 1178 alist = Fcopy_alist (f->param_alist);
fd0c2bd1
JB
1179 store_in_alist (&alist, Qname, f->name);
1180 store_in_alist (&alist, Qheight, make_number (f->height));
1181 store_in_alist (&alist, Qwidth, make_number (f->width));
1182 store_in_alist (&alist, Qmodeline, (f->wants_modeline ? Qt : Qnil));
1183 store_in_alist (&alist, Qminibuffer,
39acc701 1184 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
fd0c2bd1
JB
1185 : (FRAME_MINIBUF_ONLY_P (f) ? Qonly
1186 : FRAME_MINIBUF_WINDOW (f))));
1187 store_in_alist (&alist, Qunsplittable, (f->no_split ? Qt : Qnil));
fa8fdbf9 1188 store_in_alist (&alist, Qmenu_bar_lines, (FRAME_MENU_BAR_LINES (f)));
fd0c2bd1 1189
dbc4e1c1 1190 /* I think this should be done with a hook. */
fd0c2bd1
JB
1191#ifdef HAVE_X_WINDOWS
1192 if (FRAME_X_P (f))
ff11dfa1 1193 x_report_frame_params (f, &alist);
fd0c2bd1 1194#endif
dc6f92b8
JB
1195 return alist;
1196}
1197
ff11dfa1
JB
1198DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
1199 Smodify_frame_parameters, 2, 2, 0,
1200 "Modify the parameters of frame FRAME according to ALIST.\n\
dc6f92b8
JB
1201ALIST is an alist of parameters to change and their new values.\n\
1202Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
ff11dfa1
JB
1203The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
1204 (frame, alist)
1205 Lisp_Object frame, alist;
dc6f92b8 1206{
fd0c2bd1 1207 FRAME_PTR f;
dc6f92b8
JB
1208 register Lisp_Object tail, elt, prop, val;
1209
ff11dfa1
JB
1210 if (EQ (frame, Qnil))
1211 f = selected_frame;
dc6f92b8
JB
1212 else
1213 {
ff11dfa1
JB
1214 CHECK_LIVE_FRAME (frame, 0);
1215 f = XFRAME (frame);
dc6f92b8
JB
1216 }
1217
dbc4e1c1 1218 /* I think this should be done with a hook. */
fd0c2bd1
JB
1219#ifdef HAVE_X_WINDOWS
1220 if (FRAME_X_P (f))
1221#if 1
1222 x_set_frame_parameters (f, alist);
1223#else
dc6f92b8
JB
1224 for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
1225 {
1226 elt = Fcar (tail);
1227 prop = Fcar (elt);
1228 val = Fcdr (elt);
fd0c2bd1 1229 x_set_frame_param (f, prop, val, get_frame_param (f, prop));
ff11dfa1 1230 store_frame_param (f, prop, val);
dc6f92b8 1231 }
fd0c2bd1
JB
1232#endif
1233#endif
dc6f92b8
JB
1234
1235 return Qnil;
1236}
1237\f
a26a1f95
RS
1238DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
1239 0, 1, 0,
1240 "Height in pixels of a line in the font in frame FRAME.\n\
1241If FRAME is omitted, the selected frame is used.\n\
1242For a terminal frame, the value is always 1.")
ff11dfa1
JB
1243 (frame)
1244 Lisp_Object frame;
dc6f92b8 1245{
a26a1f95 1246 struct frame *f;
dc6f92b8 1247
a26a1f95
RS
1248 if (NILP (frame))
1249 f = selected_frame;
1250 else
1251 {
1252 CHECK_FRAME (frame, 0);
1253 f = XFRAME (frame);
1254 }
1255
1256#ifdef HAVE_X_WINDOWS
1257 if (FRAME_X_P (f))
1258 return make_number (x_char_height (f));
1259 else
dc6d9681 1260#endif
a26a1f95
RS
1261 return make_number (1);
1262}
dc6d9681 1263
dc6f92b8 1264
a26a1f95
RS
1265DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
1266 0, 1, 0,
1267 "Width in pixels of characters in the font in frame FRAME.\n\
1268If FRAME is omitted, the selected frame is used.\n\
1269The width is the same for all characters, because\n\
1270currently Emacs supports only fixed-width fonts.\n\
1271For a terminal screen, the value is always 1.")
1272 (frame)
1273 Lisp_Object frame;
dc6f92b8 1274{
a26a1f95
RS
1275 struct frame *f;
1276
1277 if (NILP (frame))
1278 f = selected_frame;
1279 else
1280 {
1281 CHECK_FRAME (frame, 0);
1282 f = XFRAME (frame);
1283 }
1284
1285#ifdef HAVE_X_WINDOWS
1286 if (FRAME_X_P (f))
1287 return make_number (x_char_width (f));
1288 else
1289#endif
1290 return make_number (1);
dc6f92b8
JB
1291}
1292
a26a1f95
RS
1293DEFUN ("frame-pixel-height", Fframe_pixel_height,
1294 Sframe_pixel_height, 0, 1, 0,
164a14ef
RS
1295 "Return a FRAME's height in pixels.\n\
1296For a terminal frame, the result really gives the height in characters.\n\
a26a1f95
RS
1297If FRAME is omitted, the selected frame is used.")
1298 (frame)
1299 Lisp_Object frame;
dc6f92b8 1300{
a26a1f95
RS
1301 struct frame *f;
1302
1303 if (NILP (frame))
1304 f = selected_frame;
1305 else
1306 {
1307 CHECK_FRAME (frame, 0);
1308 f = XFRAME (frame);
1309 }
1310
1311#ifdef HAVE_X_WINDOWS
1312 if (FRAME_X_P (f))
1313 return make_number (x_pixel_height (f));
1314 else
dc6d9681 1315#endif
a26a1f95
RS
1316 return make_number (FRAME_HEIGHT (f));
1317}
1318
1319DEFUN ("frame-pixel-width", Fframe_pixel_width,
1320 Sframe_pixel_width, 0, 1, 0,
1321 "Return FRAME's width in pixels.\n\
164a14ef 1322For a terminal frame, the result really gives the width in characters.\n\
a26a1f95
RS
1323If FRAME is omitted, the selected frame is used.")
1324 (frame)
1325 Lisp_Object frame;
1326{
1327 struct frame *f;
1328
1329 if (NILP (frame))
1330 f = selected_frame;
1331 else
1332 {
1333 CHECK_FRAME (frame, 0);
1334 f = XFRAME (frame);
1335 }
dc6f92b8 1336
a26a1f95
RS
1337#ifdef HAVE_X_WINDOWS
1338 if (FRAME_X_P (f))
1339 return make_number (x_pixel_width (f));
1340 else
1341#endif
1342 return make_number (FRAME_WIDTH (f));
1343}
1344\f
ff11dfa1
JB
1345DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
1346 "Specify that the frame FRAME has LINES lines.\n\
dc6f92b8 1347Optional third arg non-nil means that redisplay should use LINES lines\n\
ff11dfa1
JB
1348but that the idea of the actual height of the frame should not be changed.")
1349 (frame, rows, pretend)
fd0c2bd1 1350 Lisp_Object frame, rows, pretend;
dc6f92b8 1351{
ff11dfa1 1352 register struct frame *f;
dc6f92b8
JB
1353
1354 CHECK_NUMBER (rows, 0);
ff11dfa1
JB
1355 if (NILP (frame))
1356 f = selected_frame;
dc6f92b8
JB
1357 else
1358 {
ff11dfa1
JB
1359 CHECK_LIVE_FRAME (frame, 0);
1360 f = XFRAME (frame);
dc6f92b8
JB
1361 }
1362
dbc4e1c1 1363 /* I think this should be done with a hook. */
fd0c2bd1
JB
1364#ifdef HAVE_X_WINDOWS
1365 if (FRAME_X_P (f))
dc6f92b8 1366 {
ff11dfa1 1367 if (XINT (rows) != f->width)
808c0f20 1368 x_set_window_size (f, 1, f->width, XINT (rows));
dc6f92b8
JB
1369 }
1370 else
fd0c2bd1
JB
1371#endif
1372 change_frame_size (f, XINT (rows), 0, !NILP (pretend), 0);
dc6f92b8
JB
1373 return Qnil;
1374}
1375
ff11dfa1
JB
1376DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
1377 "Specify that the frame FRAME has COLS columns.\n\
dc6f92b8 1378Optional third arg non-nil means that redisplay should use COLS columns\n\
ff11dfa1
JB
1379but that the idea of the actual width of the frame should not be changed.")
1380 (frame, cols, pretend)
fd0c2bd1 1381 Lisp_Object frame, cols, pretend;
dc6f92b8 1382{
ff11dfa1 1383 register struct frame *f;
dc6f92b8 1384 CHECK_NUMBER (cols, 0);
ff11dfa1
JB
1385 if (NILP (frame))
1386 f = selected_frame;
dc6f92b8
JB
1387 else
1388 {
ff11dfa1
JB
1389 CHECK_LIVE_FRAME (frame, 0);
1390 f = XFRAME (frame);
dc6f92b8
JB
1391 }
1392
dbc4e1c1 1393 /* I think this should be done with a hook. */
fd0c2bd1
JB
1394#ifdef HAVE_X_WINDOWS
1395 if (FRAME_X_P (f))
dc6f92b8 1396 {
ff11dfa1 1397 if (XINT (cols) != f->width)
808c0f20 1398 x_set_window_size (f, 1, XINT (cols), f->height);
dc6f92b8
JB
1399 }
1400 else
fd0c2bd1
JB
1401#endif
1402 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0);
dc6f92b8
JB
1403 return Qnil;
1404}
1405
ff11dfa1
JB
1406DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
1407 "Sets size of FRAME to COLS by ROWS, measured in characters.")
1408 (frame, cols, rows)
1409 Lisp_Object frame, cols, rows;
dc6f92b8 1410{
ff11dfa1 1411 register struct frame *f;
dc6f92b8
JB
1412 int mask;
1413
ff11dfa1 1414 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1415 CHECK_NUMBER (cols, 2);
1416 CHECK_NUMBER (rows, 1);
ff11dfa1 1417 f = XFRAME (frame);
dc6f92b8 1418
dbc4e1c1 1419 /* I think this should be done with a hook. */
fd0c2bd1
JB
1420#ifdef HAVE_X_WINDOWS
1421 if (FRAME_X_P (f))
dc6f92b8 1422 {
ff11dfa1 1423 if (XINT (rows) != f->height || XINT (cols) != f->width)
808c0f20 1424 x_set_window_size (f, 1, XINT (cols), XINT (rows));
dc6f92b8
JB
1425 }
1426 else
fd0c2bd1
JB
1427#endif
1428 change_frame_size (f, XINT (rows), XINT (cols), 0, 0);
dc6f92b8
JB
1429
1430 return Qnil;
1431}
1432
ff11dfa1
JB
1433DEFUN ("set-frame-position", Fset_frame_position,
1434 Sset_frame_position, 3, 3, 0,
1435 "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
60bf8ee4
RS
1436This is actually the position of the upper left corner of the frame.\n\
1437Negative values for XOFFSET or YOFFSET are interpreted relative to\n\
4524cb1c 1438the rightmost or bottommost possible position (that stays within the screen).")
ff11dfa1
JB
1439 (frame, xoffset, yoffset)
1440 Lisp_Object frame, xoffset, yoffset;
dc6f92b8 1441{
ff11dfa1 1442 register struct frame *f;
dc6f92b8
JB
1443 int mask;
1444
ff11dfa1 1445 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1446 CHECK_NUMBER (xoffset, 1);
1447 CHECK_NUMBER (yoffset, 2);
ff11dfa1 1448 f = XFRAME (frame);
dc6f92b8 1449
dbc4e1c1 1450 /* I think this should be done with a hook. */
fd0c2bd1
JB
1451#ifdef HAVE_X_WINDOWS
1452 if (FRAME_X_P (f))
ff11dfa1 1453 x_set_offset (f, XINT (xoffset), XINT (yoffset));
fd0c2bd1 1454#endif
dc6f92b8
JB
1455
1456 return Qt;
1457}
dc6d9681 1458
dc6f92b8 1459\f
ff11dfa1 1460choose_minibuf_frame ()
dc6f92b8 1461{
ff11dfa1
JB
1462 /* For lowest-level minibuf, put it on currently selected frame
1463 if frame has a minibuffer. */
d06a8a56 1464
dc6f92b8 1465 if (minibuf_level == 0
ff11dfa1 1466 && selected_frame != 0
d06a8a56 1467 && !EQ (minibuf_window, selected_frame->minibuffer_window))
dc6f92b8 1468 {
d06a8a56
JB
1469 /* I don't think that any frames may validly have a null minibuffer
1470 window anymore. */
1471 if (NILP (selected_frame->minibuffer_window))
1472 abort ();
1473
ff11dfa1 1474 Fset_window_buffer (selected_frame->minibuffer_window,
dc6f92b8 1475 XWINDOW (minibuf_window)->buffer);
ff11dfa1 1476 minibuf_window = selected_frame->minibuffer_window;
dc6f92b8
JB
1477 }
1478}
1479\f
ff11dfa1 1480syms_of_frame ()
dc6f92b8 1481{
fd0c2bd1 1482 /*&&& init symbols here &&&*/
ff11dfa1 1483 Qframep = intern ("framep");
ff11dfa1 1484 staticpro (&Qframep);
dbc4e1c1
JB
1485 Qframe_live_p = intern ("frame-live-p");
1486 staticpro (&Qframe_live_p);
fd0c2bd1
JB
1487 Qheight = intern ("height");
1488 staticpro (&Qheight);
1489 Qicon = intern ("icon");
1490 staticpro (&Qicon);
1491 Qminibuffer = intern ("minibuffer");
bc93c097 1492 staticpro (&Qminibuffer);
fd0c2bd1
JB
1493 Qmodeline = intern ("modeline");
1494 staticpro (&Qmodeline);
1495 Qname = intern ("name");
1496 staticpro (&Qname);
fd0c2bd1
JB
1497 Qonly = intern ("only");
1498 staticpro (&Qonly);
1499 Qunsplittable = intern ("unsplittable");
1500 staticpro (&Qunsplittable);
1501 Qwidth = intern ("width");
1502 staticpro (&Qwidth);
1503 Qx = intern ("x");
1504 staticpro (&Qx);
fa8fdbf9
RS
1505 Qmenu_bar_lines = intern ("menu-bar-lines");
1506 staticpro (&Qmenu_bar_lines);
dc6f92b8 1507
ff11dfa1 1508 staticpro (&Vframe_list);
dc6f92b8 1509
ff11dfa1
JB
1510 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
1511 "The initial frame-object, which represents Emacs's stdout.");
dc6f92b8
JB
1512
1513 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
ff11dfa1 1514 "Non-nil if all of emacs is iconified and frame updates are not needed.");
dc6f92b8
JB
1515 Vemacs_iconified = Qnil;
1516
ff11dfa1
JB
1517 DEFVAR_LISP ("default-minibuffer-frame", &Vdefault_minibuffer_frame,
1518 "Minibufferless frames use this frame's minibuffer.\n\
f9898cc6 1519\n\
ff11dfa1 1520Emacs cannot create minibufferless frames unless this is set to an\n\
f9898cc6
JB
1521appropriate surrogate.\n\
1522\n\
1523Emacs consults this variable only when creating minibufferless\n\
ff11dfa1 1524frames; once the frame is created, it sticks with its assigned\n\
f9898cc6
JB
1525minibuffer, no matter what this variable is set to. This means that\n\
1526this variable doesn't necessarily say anything meaningful about the\n\
ff11dfa1 1527current set of frames, or where the minibuffer is currently being\n\
f9898cc6 1528displayed.");
ff11dfa1 1529 Vdefault_minibuffer_frame = Qnil;
dc6f92b8 1530
ff11dfa1
JB
1531 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
1532 "Alist of default values for frame creation.\n\
5bce042c 1533These may be set in your init file, like this:\n\
ff11dfa1 1534 (setq default-frame-alist '((width . 80) (height . 55)))\n\
5bce042c
JB
1535These override values given in window system configuration data, like\n\
1536X Windows' defaults database.\n\
ff11dfa1
JB
1537For values specific to the first Emacs frame, see `initial-frame-alist'.\n\
1538For values specific to the separate minibuffer frame, see\n\
1539`minibuffer-frame-alist'.");
1540 Vdefault_frame_alist = Qnil;
1541
1542 defsubr (&Sframep);
dbc4e1c1 1543 defsubr (&Sframe_live_p);
0f85737c 1544 defsubr (&Shandle_switch_frame);
ff11dfa1
JB
1545 defsubr (&Sselect_frame);
1546 defsubr (&Sselected_frame);
1547 defsubr (&Swindow_frame);
1548 defsubr (&Sframe_root_window);
1549 defsubr (&Sframe_selected_window);
1550 defsubr (&Sframe_list);
1551 defsubr (&Snext_frame);
ef2c57ac 1552 defsubr (&Sprevious_frame);
ff11dfa1 1553 defsubr (&Sdelete_frame);
f9898cc6 1554 defsubr (&Smouse_position);
dc6f92b8
JB
1555 defsubr (&Sset_mouse_position);
1556#if 0
ff11dfa1
JB
1557 defsubr (&Sframe_configuration);
1558 defsubr (&Srestore_frame_configuration);
dc6f92b8 1559#endif
ff11dfa1
JB
1560 defsubr (&Smake_frame_visible);
1561 defsubr (&Smake_frame_invisible);
1562 defsubr (&Siconify_frame);
1563 defsubr (&Sframe_visible_p);
1564 defsubr (&Svisible_frame_list);
b49f5578
JB
1565 defsubr (&Sraise_frame);
1566 defsubr (&Slower_frame);
ff11dfa1
JB
1567 defsubr (&Sredirect_frame_focus);
1568 defsubr (&Sframe_focus);
1569 defsubr (&Sframe_parameters);
1570 defsubr (&Smodify_frame_parameters);
a26a1f95
RS
1571 defsubr (&Sframe_char_height);
1572 defsubr (&Sframe_char_width);
1573 defsubr (&Sframe_pixel_height);
1574 defsubr (&Sframe_pixel_width);
ff11dfa1
JB
1575 defsubr (&Sset_frame_height);
1576 defsubr (&Sset_frame_width);
1577 defsubr (&Sset_frame_size);
1578 defsubr (&Sset_frame_position);
dc6f92b8 1579}
e5d77022 1580
2f0b07e0
JB
1581keys_of_frame ()
1582{
0f85737c 1583 initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
2f0b07e0 1584}
a26a1f95 1585\f
d06a8a56 1586#else /* not MULTI_FRAME */
fd0c2bd1 1587
cc38027b
JB
1588/* If we're not using multi-frame stuff, we still need to provide some
1589 support functions. */
1590
1591/* Unless this function is defined, providing set-frame-height and
1592 set-frame-width doesn't help compatibility any, since they both
1593 want this as their first argument. */
1594DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1595 "Return the frame that is now selected.")
1596 ()
1597{
1598 Lisp_Object tem;
1599 XFASTINT (tem) = 0;
1600 return tem;
1601}
704a9b45
RS
1602DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
1603 "Return non-nil if OBJECT is a frame.\n\
1604Value is t for a termcap frame (a character-only terminal),\n\
1605`x' for an Emacs frame that is really an X window.\n\
1606Also see `live-frame-p'.")
1607 (object)
1608 Lisp_Object object;
1609{
1610 return Qnil;
1611}
fd0c2bd1
JB
1612
1613DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
1614 "Specify that the frame FRAME has LINES lines.\n\
1615Optional third arg non-nil means that redisplay should use LINES lines\n\
1616but that the idea of the actual height of the frame should not be changed.")
1617 (frame, rows, pretend)
1618 Lisp_Object frame, rows, pretend;
1619{
1620 CHECK_NUMBER (rows, 0);
1621
1622 change_frame_size (0, XINT (rows), 0, !NILP (pretend), 0);
1623 return Qnil;
1624}
1625
1626DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
1627 "Specify that the frame FRAME has COLS columns.\n\
1628Optional third arg non-nil means that redisplay should use COLS columns\n\
1629but that the idea of the actual width of the frame should not be changed.")
1630 (frame, cols, pretend)
1631 Lisp_Object frame, cols, pretend;
1632{
1633 CHECK_NUMBER (cols, 0);
1634
1635 change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
1636 return Qnil;
1637}
1638
1639DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
1640 "Sets size of FRAME to COLS by ROWS, measured in characters.")
1641 (frame, cols, rows)
1642 Lisp_Object frame, cols, rows;
1643{
1644 CHECK_NUMBER (cols, 2);
1645 CHECK_NUMBER (rows, 1);
1646
1647 change_frame_size (0, XINT (rows), XINT (cols), 0, 0);
1648
1649 return Qnil;
1650}
1651
48c9d487
JB
1652DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 1, 0,
1653 "Return number of lines available for display on FRAME.\n\
1654If FRAME is omitted, describe the currently selected frame.")
1655 (frame)
1656 Lisp_Object frame;
cc38027b
JB
1657{
1658 return make_number (FRAME_HEIGHT (selected_frame));
1659}
1660
48c9d487
JB
1661DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 1, 0,
1662 "Return number of columns available for display on FRAME.\n\
1663If FRAME is omitted, describe the currently selected frame.")
1664 (frame)
1665 Lisp_Object frame;
cc38027b
JB
1666{
1667 return make_number (FRAME_WIDTH (selected_frame));
1668}
1669
a26a1f95
RS
1670DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
1671 0, 1, 0,
1672 "Height in pixels of a line in the font in frame FRAME.\n\
1673If FRAME is omitted, the selected frame is used.\n\
1674For a terminal frame, the value is always 1.")
1675 (frame)
1676 Lisp_Object frame;
1677{
1678 return make_number (1);
1679}
1680
1681
1682DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
1683 0, 1, 0,
1684 "Width in pixels of characters in the font in frame FRAME.\n\
1685If FRAME is omitted, the selected frame is used.\n\
1686The width is the same for all characters, because\n\
1687currently Emacs supports only fixed-width fonts.\n\
1688For a terminal screen, the value is always 1.")
1689 (frame)
1690 Lisp_Object frame;
1691{
1692 return make_number (1);
1693}
1694
1695DEFUN ("frame-pixel-height", Fframe_pixel_height,
1696 Sframe_pixel_height, 0, 1, 0,
1697 "Return FRAME's height in pixels.\n\
1698For a terminal frame, the result really gives the height in characters.\n\
1699If FRAME is omitted, the selected frame is used.")
1700 (frame)
1701 Lisp_Object frame;
1702{
1703 return make_number (FRAME_HEIGHT (f));
1704}
1705
1706DEFUN ("frame-pixel-width", Fframe_pixel_width,
1707 Sframe_pixel_width, 0, 1, 0,
1708 "Return FRAME's width in pixels.\n\
1709For a terminal frame, the result really gives the width in characters.\n\
1710If FRAME is omitted, the selected frame is used.")
1711 (frame)
1712 Lisp_Object frame;
1713{
1714 return make_number (FRAME_WIDTH (f));
1715}
1716
cc38027b
JB
1717/* These are for backward compatibility with Emacs 18. */
1718
fd0c2bd1
JB
1719DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
1720 "Tell redisplay that the screen has LINES lines.\n\
1721Optional second arg non-nil means that redisplay should use LINES lines\n\
1722but that the idea of the actual height of the screen should not be changed.")
1723 (lines, pretend)
1724 Lisp_Object lines, pretend;
1725{
1726 CHECK_NUMBER (lines, 0);
1727
1728 change_frame_size (0, XINT (lines), 0, !NILP (pretend), 0);
1729 return Qnil;
1730}
1731
1732DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
1733 "Tell redisplay that the screen has COLS columns.\n\
1734Optional second arg non-nil means that redisplay should use COLS columns\n\
1735but that the idea of the actual width of the screen should not be changed.")
1736 (cols, pretend)
1737 Lisp_Object cols, pretend;
1738{
1739 CHECK_NUMBER (cols, 0);
1740
1741 change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
1742 return Qnil;
1743}
1744
bc1ed486
RS
1745DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
1746 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
1747The position is given in character cells, where (0, 0) is the\n\
1748upper-left corner.\n\
1749If Emacs is running on a mouseless terminal or hasn't been programmed\n\
1750to read the mouse position, it returns the selected frame for FRAME\n\
1751and nil for X and Y.")
1752 ()
1753{
1754 FRAME_PTR f;
1755 Lisp_Object lispy_dummy;
1756 enum scroll_bar_part party_dummy;
1757 Lisp_Object x, y;
1758 unsigned long long_dummy;
1759
1760 f = selected_frame;
1761 x = y = Qnil;
1762
1763 /* It's okay for the hook to refrain from storing anything. */
1764 if (mouse_position_hook)
1765 (*mouse_position_hook) (&f,
1766 &lispy_dummy, &party_dummy,
1767 &x, &y,
1768 &long_dummy);
1769
1770 /* Always return nil for frame. */
1771 return Fcons (Qnil, Fcons (x, y));
1772}
1773
fd0c2bd1
JB
1774syms_of_frame ()
1775{
a26a1f95 1776 defsubr (&Sselected_frame);
704a9b45 1777 defsubr (&Sframep);
a26a1f95
RS
1778 defsubr (&Sframe_char_height);
1779 defsubr (&Sframe_char_width);
1780 defsubr (&Sframe_pixel_height);
1781 defsubr (&Sframe_pixel_width);
fd0c2bd1
JB
1782 defsubr (&Sset_frame_height);
1783 defsubr (&Sset_frame_width);
1784 defsubr (&Sset_frame_size);
1785 defsubr (&Sset_screen_height);
1786 defsubr (&Sset_screen_width);
1787 defsubr (&Sframe_height);
1788 Ffset (intern ("screen-height"), intern ("frame-height"));
1789 defsubr (&Sframe_width);
1790 Ffset (intern ("screen-width"), intern ("frame-width"));
bc1ed486 1791 defsubr (&Smouse_position);
fd0c2bd1
JB
1792}
1793
2f0b07e0
JB
1794keys_of_frame ()
1795{
1796}
1797
fd0c2bd1
JB
1798#endif /* not MULTI_FRAME */
1799
1800
1801
1802