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