(make_lispy_movement, make_lispy_event):
[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
5c044f55
RS
970 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
971
a42e9724 972 if (FRAME_VISIBLE_P (XFRAME (frame)))
dc6f92b8 973 return Qt;
a42e9724 974 if (FRAME_ICONIFIED_P (XFRAME (frame)))
fd0c2bd1 975 return Qicon;
dc6f92b8
JB
976 return Qnil;
977}
978
ff11dfa1 979DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
dc6f92b8 980 0, 0, 0,
ff11dfa1 981 "Return a list of all frames now \"visible\" (being updated).")
dc6f92b8
JB
982 ()
983{
ff11dfa1
JB
984 Lisp_Object tail, frame;
985 struct frame *f;
dc6f92b8
JB
986 Lisp_Object value;
987
988 value = Qnil;
ff11dfa1 989 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
dc6f92b8 990 {
ff11dfa1
JB
991 frame = XCONS (tail)->car;
992 if (XTYPE (frame) != Lisp_Frame)
dc6f92b8 993 continue;
ff11dfa1 994 f = XFRAME (frame);
a42e9724 995 if (FRAME_VISIBLE_P (f))
ff11dfa1 996 value = Fcons (frame, value);
dc6f92b8
JB
997 }
998 return value;
999}
d5e7c279
JB
1000
1001
b49f5578 1002DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 1, 1, 0,
dbc4e1c1
JB
1003 "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
1004If FRAME is invisible, make it visible.\n\
1005If Emacs is displaying on an ordinary terminal or some other device which\n\
1006doesn't support multiple overlapping frames, this function does nothing.")
1007 (frame)
1008 Lisp_Object frame;
1009{
1010 CHECK_LIVE_FRAME (frame, 0);
8a981af5
RS
1011
1012 /* Do like the documentation says. */
1013 Fmake_frame_visible (frame);
1014
dbc4e1c1
JB
1015 if (frame_raise_lower_hook)
1016 (*frame_raise_lower_hook) (XFRAME (frame), 1);
1017
1018 return Qnil;
1019}
1020
b49f5578
JB
1021/* Should we have a corresponding function called Flower_Power? */
1022DEFUN ("lower-frame", Flower_frame, Slower_frame, 1, 1, 0,
dbc4e1c1
JB
1023 "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
1024If Emacs is displaying on an ordinary terminal or some other device which\n\
1025doesn't support multiple overlapping frames, this function does nothing.")
1026 (frame)
1027 Lisp_Object frame;
1028{
1029 CHECK_LIVE_FRAME (frame, 0);
1030
1031 if (frame_raise_lower_hook)
1032 (*frame_raise_lower_hook) (XFRAME (frame), 0);
1033
1034 return Qnil;
1035}
1036
d5e7c279 1037\f
ff11dfa1 1038DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
d5e7c279 1039 1, 2, 0,
ff11dfa1 1040 "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
a42e9724
JB
1041In other words, switch-frame events caused by events in FRAME will\n\
1042request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
1043FOCUS-FRAME after reading an event typed at FRAME.\n\
d5e7c279 1044\n\
a42e9724 1045If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
ff11dfa1 1046cancelled, and the frame again receives its own keystrokes.\n\
d5e7c279 1047\n\
a42e9724
JB
1048Focus redirection is useful for temporarily redirecting keystrokes to\n\
1049a surrogate minibuffer frame when a frame doesn't have its own\n\
1050minibuffer window.\n\
d5e7c279 1051\n\
a42e9724
JB
1052A frame's focus redirection can be changed by select-frame. If frame\n\
1053FOO is selected, and then a different frame BAR is selected, any\n\
1054frames redirecting their focus to FOO are shifted to redirect their\n\
1055focus to BAR. This allows focus redirection to work properly when the\n\
1056user switches from one frame to another using `select-window'.\n\
1057\n\
1058This means that a frame whose focus is redirected to itself is treated\n\
1059differently from a frame whose focus is redirected to nil; the former\n\
1060is affected by select-frame, while the latter is not.\n\
1061\n\
1062The redirection lasts until `redirect-frame-focus' is called to change it.")
ff11dfa1
JB
1063 (frame, focus_frame)
1064 Lisp_Object frame, focus_frame;
d5e7c279 1065{
13144095
JB
1066 /* Note that we don't check for a live frame here. It's reasonable
1067 to redirect the focus of a frame you're about to delete, if you
1068 know what other frame should receive those keystrokes. */
1069 CHECK_FRAME (frame, 0);
f9898cc6 1070
a42e9724 1071 if (! NILP (focus_frame))
ff11dfa1 1072 CHECK_LIVE_FRAME (focus_frame, 1);
d5e7c279 1073
ff11dfa1 1074 XFRAME (frame)->focus_frame = focus_frame;
d5e7c279 1075
9c394f17
RS
1076 /* I think this should be done with a hook. */
1077#ifdef HAVE_X_WINDOWS
1078 if (!NILP (focus_frame) && ! EQ (focus_frame, frame)
1079 && FRAME_X_P (XFRAME (focus_frame)))
1080 Ffocus_frame (focus_frame);
1081#endif
1082
ff11dfa1
JB
1083 if (frame_rehighlight_hook)
1084 (*frame_rehighlight_hook) ();
d5e7c279
JB
1085
1086 return Qnil;
1087}
1088
1089
ff11dfa1
JB
1090DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
1091 "Return the frame to which FRAME's keystrokes are currently being sent.\n\
a42e9724 1092This returns nil if FRAME's focus is not redirected.\n\
ff11dfa1
JB
1093See `redirect-frame-focus'.")
1094 (frame)
1095 Lisp_Object frame;
d5e7c279 1096{
ff11dfa1 1097 CHECK_LIVE_FRAME (frame, 0);
a42e9724 1098
ff11dfa1 1099 return FRAME_FOCUS_FRAME (XFRAME (frame));
d5e7c279
JB
1100}
1101
1102
dc6f92b8
JB
1103\f
1104Lisp_Object
ff11dfa1
JB
1105get_frame_param (frame, prop)
1106 register struct frame *frame;
dc6f92b8
JB
1107 Lisp_Object prop;
1108{
1109 register Lisp_Object tem;
1110
ff11dfa1 1111 tem = Fassq (prop, frame->param_alist);
dc6f92b8
JB
1112 if (EQ (tem, Qnil))
1113 return tem;
1114 return Fcdr (tem);
1115}
1116
1117void
fd0c2bd1 1118store_in_alist (alistptr, prop, val)
dc6f92b8 1119 Lisp_Object *alistptr, val;
fd0c2bd1 1120 Lisp_Object prop;
dc6f92b8
JB
1121{
1122 register Lisp_Object tem;
dc6f92b8 1123
dc6f92b8
JB
1124 tem = Fassq (prop, *alistptr);
1125 if (EQ (tem, Qnil))
1126 *alistptr = Fcons (Fcons (prop, val), *alistptr);
1127 else
1128 Fsetcdr (tem, val);
1129}
1130
1131void
ff11dfa1
JB
1132store_frame_param (f, prop, val)
1133 struct frame *f;
dc6f92b8
JB
1134 Lisp_Object prop, val;
1135{
1136 register Lisp_Object tem;
1137
ff11dfa1 1138 tem = Fassq (prop, f->param_alist);
dc6f92b8 1139 if (EQ (tem, Qnil))
ff11dfa1 1140 f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
dc6f92b8
JB
1141 else
1142 Fsetcdr (tem, val);
bc93c097
JB
1143
1144 if (EQ (prop, Qminibuffer)
1145 && XTYPE (val) == Lisp_Window)
1146 {
1147 if (! MINI_WINDOW_P (XWINDOW (val)))
1148 error ("Surrogate minibuffer windows must be minibuffer windows.");
1149
fd0c2bd1 1150 if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
1fb2d074 1151 error ("can't change the surrogate minibuffer of a frame with its own minibuffer");
bc93c097
JB
1152
1153 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 1154 f->minibuffer_window = val;
bc93c097 1155 }
dc6f92b8
JB
1156}
1157
ff11dfa1
JB
1158DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
1159 "Return the parameters-alist of frame FRAME.\n\
dc6f92b8 1160It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
dc6d9681
JB
1161The meaningful PARMs depend on the kind of frame.\n\
1162If FRAME is omitted, return information on the currently selected frame.")
ff11dfa1
JB
1163 (frame)
1164 Lisp_Object frame;
dc6f92b8
JB
1165{
1166 Lisp_Object alist;
ff11dfa1 1167 struct frame *f;
dc6f92b8 1168
ff11dfa1
JB
1169 if (EQ (frame, Qnil))
1170 f = selected_frame;
dc6f92b8
JB
1171 else
1172 {
ff11dfa1
JB
1173 CHECK_FRAME (frame, 0);
1174 f = XFRAME (frame);
dc6f92b8
JB
1175 }
1176
ff11dfa1 1177 if (f->display.nothing == 0)
dc6f92b8
JB
1178 return Qnil;
1179
ff11dfa1 1180 alist = Fcopy_alist (f->param_alist);
fd0c2bd1
JB
1181 store_in_alist (&alist, Qname, f->name);
1182 store_in_alist (&alist, Qheight, make_number (f->height));
1183 store_in_alist (&alist, Qwidth, make_number (f->width));
1184 store_in_alist (&alist, Qmodeline, (f->wants_modeline ? Qt : Qnil));
1185 store_in_alist (&alist, Qminibuffer,
39acc701 1186 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
fd0c2bd1
JB
1187 : (FRAME_MINIBUF_ONLY_P (f) ? Qonly
1188 : FRAME_MINIBUF_WINDOW (f))));
1189 store_in_alist (&alist, Qunsplittable, (f->no_split ? Qt : Qnil));
fa8fdbf9 1190 store_in_alist (&alist, Qmenu_bar_lines, (FRAME_MENU_BAR_LINES (f)));
fd0c2bd1 1191
dbc4e1c1 1192 /* I think this should be done with a hook. */
fd0c2bd1
JB
1193#ifdef HAVE_X_WINDOWS
1194 if (FRAME_X_P (f))
ff11dfa1 1195 x_report_frame_params (f, &alist);
fd0c2bd1 1196#endif
dc6f92b8
JB
1197 return alist;
1198}
1199
ff11dfa1
JB
1200DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
1201 Smodify_frame_parameters, 2, 2, 0,
1202 "Modify the parameters of frame FRAME according to ALIST.\n\
dc6f92b8
JB
1203ALIST is an alist of parameters to change and their new values.\n\
1204Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
ff11dfa1
JB
1205The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
1206 (frame, alist)
1207 Lisp_Object frame, alist;
dc6f92b8 1208{
fd0c2bd1 1209 FRAME_PTR f;
dc6f92b8
JB
1210 register Lisp_Object tail, elt, prop, val;
1211
ff11dfa1
JB
1212 if (EQ (frame, Qnil))
1213 f = selected_frame;
dc6f92b8
JB
1214 else
1215 {
ff11dfa1
JB
1216 CHECK_LIVE_FRAME (frame, 0);
1217 f = XFRAME (frame);
dc6f92b8
JB
1218 }
1219
dbc4e1c1 1220 /* I think this should be done with a hook. */
fd0c2bd1
JB
1221#ifdef HAVE_X_WINDOWS
1222 if (FRAME_X_P (f))
1223#if 1
1224 x_set_frame_parameters (f, alist);
1225#else
dc6f92b8
JB
1226 for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
1227 {
1228 elt = Fcar (tail);
1229 prop = Fcar (elt);
1230 val = Fcdr (elt);
fd0c2bd1 1231 x_set_frame_param (f, prop, val, get_frame_param (f, prop));
ff11dfa1 1232 store_frame_param (f, prop, val);
dc6f92b8 1233 }
fd0c2bd1
JB
1234#endif
1235#endif
dc6f92b8
JB
1236
1237 return Qnil;
1238}
1239\f
a26a1f95
RS
1240DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
1241 0, 1, 0,
1242 "Height in pixels of a line in the font in frame FRAME.\n\
1243If FRAME is omitted, the selected frame is used.\n\
1244For a terminal frame, the value is always 1.")
ff11dfa1
JB
1245 (frame)
1246 Lisp_Object frame;
dc6f92b8 1247{
a26a1f95 1248 struct frame *f;
dc6f92b8 1249
a26a1f95
RS
1250 if (NILP (frame))
1251 f = selected_frame;
1252 else
1253 {
1254 CHECK_FRAME (frame, 0);
1255 f = XFRAME (frame);
1256 }
1257
1258#ifdef HAVE_X_WINDOWS
1259 if (FRAME_X_P (f))
1260 return make_number (x_char_height (f));
1261 else
dc6d9681 1262#endif
a26a1f95
RS
1263 return make_number (1);
1264}
dc6d9681 1265
dc6f92b8 1266
a26a1f95
RS
1267DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
1268 0, 1, 0,
1269 "Width in pixels of characters in the font in frame FRAME.\n\
1270If FRAME is omitted, the selected frame is used.\n\
1271The width is the same for all characters, because\n\
1272currently Emacs supports only fixed-width fonts.\n\
1273For a terminal screen, the value is always 1.")
1274 (frame)
1275 Lisp_Object frame;
dc6f92b8 1276{
a26a1f95
RS
1277 struct frame *f;
1278
1279 if (NILP (frame))
1280 f = selected_frame;
1281 else
1282 {
1283 CHECK_FRAME (frame, 0);
1284 f = XFRAME (frame);
1285 }
1286
1287#ifdef HAVE_X_WINDOWS
1288 if (FRAME_X_P (f))
1289 return make_number (x_char_width (f));
1290 else
1291#endif
1292 return make_number (1);
dc6f92b8
JB
1293}
1294
a26a1f95
RS
1295DEFUN ("frame-pixel-height", Fframe_pixel_height,
1296 Sframe_pixel_height, 0, 1, 0,
164a14ef
RS
1297 "Return a FRAME's height in pixels.\n\
1298For a terminal frame, the result really gives the height in characters.\n\
a26a1f95
RS
1299If FRAME is omitted, the selected frame is used.")
1300 (frame)
1301 Lisp_Object frame;
dc6f92b8 1302{
a26a1f95
RS
1303 struct frame *f;
1304
1305 if (NILP (frame))
1306 f = selected_frame;
1307 else
1308 {
1309 CHECK_FRAME (frame, 0);
1310 f = XFRAME (frame);
1311 }
1312
1313#ifdef HAVE_X_WINDOWS
1314 if (FRAME_X_P (f))
1315 return make_number (x_pixel_height (f));
1316 else
dc6d9681 1317#endif
a26a1f95
RS
1318 return make_number (FRAME_HEIGHT (f));
1319}
1320
1321DEFUN ("frame-pixel-width", Fframe_pixel_width,
1322 Sframe_pixel_width, 0, 1, 0,
1323 "Return FRAME's width in pixels.\n\
164a14ef 1324For a terminal frame, the result really gives the width in characters.\n\
a26a1f95
RS
1325If FRAME is omitted, the selected frame is used.")
1326 (frame)
1327 Lisp_Object frame;
1328{
1329 struct frame *f;
1330
1331 if (NILP (frame))
1332 f = selected_frame;
1333 else
1334 {
1335 CHECK_FRAME (frame, 0);
1336 f = XFRAME (frame);
1337 }
dc6f92b8 1338
a26a1f95
RS
1339#ifdef HAVE_X_WINDOWS
1340 if (FRAME_X_P (f))
1341 return make_number (x_pixel_width (f));
1342 else
1343#endif
1344 return make_number (FRAME_WIDTH (f));
1345}
1346\f
ff11dfa1
JB
1347DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
1348 "Specify that the frame FRAME has LINES lines.\n\
dc6f92b8 1349Optional third arg non-nil means that redisplay should use LINES lines\n\
ff11dfa1
JB
1350but that the idea of the actual height of the frame should not be changed.")
1351 (frame, rows, pretend)
fd0c2bd1 1352 Lisp_Object frame, rows, pretend;
dc6f92b8 1353{
ff11dfa1 1354 register struct frame *f;
dc6f92b8
JB
1355
1356 CHECK_NUMBER (rows, 0);
ff11dfa1
JB
1357 if (NILP (frame))
1358 f = selected_frame;
dc6f92b8
JB
1359 else
1360 {
ff11dfa1
JB
1361 CHECK_LIVE_FRAME (frame, 0);
1362 f = XFRAME (frame);
dc6f92b8
JB
1363 }
1364
dbc4e1c1 1365 /* I think this should be done with a hook. */
fd0c2bd1
JB
1366#ifdef HAVE_X_WINDOWS
1367 if (FRAME_X_P (f))
dc6f92b8 1368 {
ff11dfa1 1369 if (XINT (rows) != f->width)
808c0f20 1370 x_set_window_size (f, 1, f->width, XINT (rows));
dc6f92b8
JB
1371 }
1372 else
fd0c2bd1
JB
1373#endif
1374 change_frame_size (f, XINT (rows), 0, !NILP (pretend), 0);
dc6f92b8
JB
1375 return Qnil;
1376}
1377
ff11dfa1
JB
1378DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
1379 "Specify that the frame FRAME has COLS columns.\n\
dc6f92b8 1380Optional third arg non-nil means that redisplay should use COLS columns\n\
ff11dfa1
JB
1381but that the idea of the actual width of the frame should not be changed.")
1382 (frame, cols, pretend)
fd0c2bd1 1383 Lisp_Object frame, cols, pretend;
dc6f92b8 1384{
ff11dfa1 1385 register struct frame *f;
dc6f92b8 1386 CHECK_NUMBER (cols, 0);
ff11dfa1
JB
1387 if (NILP (frame))
1388 f = selected_frame;
dc6f92b8
JB
1389 else
1390 {
ff11dfa1
JB
1391 CHECK_LIVE_FRAME (frame, 0);
1392 f = XFRAME (frame);
dc6f92b8
JB
1393 }
1394
dbc4e1c1 1395 /* I think this should be done with a hook. */
fd0c2bd1
JB
1396#ifdef HAVE_X_WINDOWS
1397 if (FRAME_X_P (f))
dc6f92b8 1398 {
ff11dfa1 1399 if (XINT (cols) != f->width)
808c0f20 1400 x_set_window_size (f, 1, XINT (cols), f->height);
dc6f92b8
JB
1401 }
1402 else
fd0c2bd1
JB
1403#endif
1404 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0);
dc6f92b8
JB
1405 return Qnil;
1406}
1407
ff11dfa1
JB
1408DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
1409 "Sets size of FRAME to COLS by ROWS, measured in characters.")
1410 (frame, cols, rows)
1411 Lisp_Object frame, cols, rows;
dc6f92b8 1412{
ff11dfa1 1413 register struct frame *f;
dc6f92b8
JB
1414 int mask;
1415
ff11dfa1 1416 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1417 CHECK_NUMBER (cols, 2);
1418 CHECK_NUMBER (rows, 1);
ff11dfa1 1419 f = XFRAME (frame);
dc6f92b8 1420
dbc4e1c1 1421 /* I think this should be done with a hook. */
fd0c2bd1
JB
1422#ifdef HAVE_X_WINDOWS
1423 if (FRAME_X_P (f))
dc6f92b8 1424 {
ff11dfa1 1425 if (XINT (rows) != f->height || XINT (cols) != f->width)
808c0f20 1426 x_set_window_size (f, 1, XINT (cols), XINT (rows));
dc6f92b8
JB
1427 }
1428 else
fd0c2bd1
JB
1429#endif
1430 change_frame_size (f, XINT (rows), XINT (cols), 0, 0);
dc6f92b8
JB
1431
1432 return Qnil;
1433}
1434
ff11dfa1
JB
1435DEFUN ("set-frame-position", Fset_frame_position,
1436 Sset_frame_position, 3, 3, 0,
1437 "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
60bf8ee4
RS
1438This is actually the position of the upper left corner of the frame.\n\
1439Negative values for XOFFSET or YOFFSET are interpreted relative to\n\
4524cb1c 1440the rightmost or bottommost possible position (that stays within the screen).")
ff11dfa1
JB
1441 (frame, xoffset, yoffset)
1442 Lisp_Object frame, xoffset, yoffset;
dc6f92b8 1443{
ff11dfa1 1444 register struct frame *f;
dc6f92b8
JB
1445 int mask;
1446
ff11dfa1 1447 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1448 CHECK_NUMBER (xoffset, 1);
1449 CHECK_NUMBER (yoffset, 2);
ff11dfa1 1450 f = XFRAME (frame);
dc6f92b8 1451
dbc4e1c1 1452 /* I think this should be done with a hook. */
fd0c2bd1
JB
1453#ifdef HAVE_X_WINDOWS
1454 if (FRAME_X_P (f))
ff11dfa1 1455 x_set_offset (f, XINT (xoffset), XINT (yoffset));
fd0c2bd1 1456#endif
dc6f92b8
JB
1457
1458 return Qt;
1459}
dc6d9681 1460
dc6f92b8 1461\f
ff11dfa1 1462choose_minibuf_frame ()
dc6f92b8 1463{
ff11dfa1
JB
1464 /* For lowest-level minibuf, put it on currently selected frame
1465 if frame has a minibuffer. */
d06a8a56 1466
dc6f92b8 1467 if (minibuf_level == 0
ff11dfa1 1468 && selected_frame != 0
d06a8a56 1469 && !EQ (minibuf_window, selected_frame->minibuffer_window))
dc6f92b8 1470 {
d06a8a56
JB
1471 /* I don't think that any frames may validly have a null minibuffer
1472 window anymore. */
1473 if (NILP (selected_frame->minibuffer_window))
1474 abort ();
1475
ff11dfa1 1476 Fset_window_buffer (selected_frame->minibuffer_window,
dc6f92b8 1477 XWINDOW (minibuf_window)->buffer);
ff11dfa1 1478 minibuf_window = selected_frame->minibuffer_window;
dc6f92b8
JB
1479 }
1480}
1481\f
ff11dfa1 1482syms_of_frame ()
dc6f92b8 1483{
fd0c2bd1 1484 /*&&& init symbols here &&&*/
ff11dfa1 1485 Qframep = intern ("framep");
ff11dfa1 1486 staticpro (&Qframep);
dbc4e1c1
JB
1487 Qframe_live_p = intern ("frame-live-p");
1488 staticpro (&Qframe_live_p);
fd0c2bd1
JB
1489 Qheight = intern ("height");
1490 staticpro (&Qheight);
1491 Qicon = intern ("icon");
1492 staticpro (&Qicon);
1493 Qminibuffer = intern ("minibuffer");
bc93c097 1494 staticpro (&Qminibuffer);
fd0c2bd1
JB
1495 Qmodeline = intern ("modeline");
1496 staticpro (&Qmodeline);
1497 Qname = intern ("name");
1498 staticpro (&Qname);
fd0c2bd1
JB
1499 Qonly = intern ("only");
1500 staticpro (&Qonly);
1501 Qunsplittable = intern ("unsplittable");
1502 staticpro (&Qunsplittable);
1503 Qwidth = intern ("width");
1504 staticpro (&Qwidth);
1505 Qx = intern ("x");
1506 staticpro (&Qx);
fa8fdbf9
RS
1507 Qmenu_bar_lines = intern ("menu-bar-lines");
1508 staticpro (&Qmenu_bar_lines);
dc6f92b8 1509
ff11dfa1 1510 staticpro (&Vframe_list);
dc6f92b8 1511
ff11dfa1
JB
1512 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
1513 "The initial frame-object, which represents Emacs's stdout.");
dc6f92b8
JB
1514
1515 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
ff11dfa1 1516 "Non-nil if all of emacs is iconified and frame updates are not needed.");
dc6f92b8
JB
1517 Vemacs_iconified = Qnil;
1518
ff11dfa1
JB
1519 DEFVAR_LISP ("default-minibuffer-frame", &Vdefault_minibuffer_frame,
1520 "Minibufferless frames use this frame's minibuffer.\n\
f9898cc6 1521\n\
ff11dfa1 1522Emacs cannot create minibufferless frames unless this is set to an\n\
f9898cc6
JB
1523appropriate surrogate.\n\
1524\n\
1525Emacs consults this variable only when creating minibufferless\n\
ff11dfa1 1526frames; once the frame is created, it sticks with its assigned\n\
f9898cc6
JB
1527minibuffer, no matter what this variable is set to. This means that\n\
1528this variable doesn't necessarily say anything meaningful about the\n\
ff11dfa1 1529current set of frames, or where the minibuffer is currently being\n\
f9898cc6 1530displayed.");
ff11dfa1 1531 Vdefault_minibuffer_frame = Qnil;
dc6f92b8 1532
ff11dfa1
JB
1533 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
1534 "Alist of default values for frame creation.\n\
5bce042c 1535These may be set in your init file, like this:\n\
ff11dfa1 1536 (setq default-frame-alist '((width . 80) (height . 55)))\n\
5bce042c
JB
1537These override values given in window system configuration data, like\n\
1538X Windows' defaults database.\n\
ff11dfa1
JB
1539For values specific to the first Emacs frame, see `initial-frame-alist'.\n\
1540For values specific to the separate minibuffer frame, see\n\
1541`minibuffer-frame-alist'.");
1542 Vdefault_frame_alist = Qnil;
1543
1544 defsubr (&Sframep);
dbc4e1c1 1545 defsubr (&Sframe_live_p);
0f85737c 1546 defsubr (&Shandle_switch_frame);
ff11dfa1
JB
1547 defsubr (&Sselect_frame);
1548 defsubr (&Sselected_frame);
1549 defsubr (&Swindow_frame);
1550 defsubr (&Sframe_root_window);
1551 defsubr (&Sframe_selected_window);
1552 defsubr (&Sframe_list);
1553 defsubr (&Snext_frame);
ef2c57ac 1554 defsubr (&Sprevious_frame);
ff11dfa1 1555 defsubr (&Sdelete_frame);
f9898cc6 1556 defsubr (&Smouse_position);
dc6f92b8
JB
1557 defsubr (&Sset_mouse_position);
1558#if 0
ff11dfa1
JB
1559 defsubr (&Sframe_configuration);
1560 defsubr (&Srestore_frame_configuration);
dc6f92b8 1561#endif
ff11dfa1
JB
1562 defsubr (&Smake_frame_visible);
1563 defsubr (&Smake_frame_invisible);
1564 defsubr (&Siconify_frame);
1565 defsubr (&Sframe_visible_p);
1566 defsubr (&Svisible_frame_list);
b49f5578
JB
1567 defsubr (&Sraise_frame);
1568 defsubr (&Slower_frame);
ff11dfa1
JB
1569 defsubr (&Sredirect_frame_focus);
1570 defsubr (&Sframe_focus);
1571 defsubr (&Sframe_parameters);
1572 defsubr (&Smodify_frame_parameters);
a26a1f95
RS
1573 defsubr (&Sframe_char_height);
1574 defsubr (&Sframe_char_width);
1575 defsubr (&Sframe_pixel_height);
1576 defsubr (&Sframe_pixel_width);
ff11dfa1
JB
1577 defsubr (&Sset_frame_height);
1578 defsubr (&Sset_frame_width);
1579 defsubr (&Sset_frame_size);
1580 defsubr (&Sset_frame_position);
dc6f92b8 1581}
e5d77022 1582
2f0b07e0
JB
1583keys_of_frame ()
1584{
0f85737c 1585 initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
2f0b07e0 1586}
a26a1f95 1587\f
d06a8a56 1588#else /* not MULTI_FRAME */
fd0c2bd1 1589
cc38027b
JB
1590/* If we're not using multi-frame stuff, we still need to provide some
1591 support functions. */
1592
1593/* Unless this function is defined, providing set-frame-height and
1594 set-frame-width doesn't help compatibility any, since they both
1595 want this as their first argument. */
1596DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1597 "Return the frame that is now selected.")
1598 ()
1599{
1600 Lisp_Object tem;
1601 XFASTINT (tem) = 0;
1602 return tem;
1603}
704a9b45
RS
1604DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
1605 "Return non-nil if OBJECT is a frame.\n\
1606Value is t for a termcap frame (a character-only terminal),\n\
1607`x' for an Emacs frame that is really an X window.\n\
1608Also see `live-frame-p'.")
1609 (object)
1610 Lisp_Object object;
1611{
1612 return Qnil;
1613}
fd0c2bd1
JB
1614
1615DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
1616 "Specify that the frame FRAME has LINES lines.\n\
1617Optional third arg non-nil means that redisplay should use LINES lines\n\
1618but that the idea of the actual height of the frame should not be changed.")
1619 (frame, rows, pretend)
1620 Lisp_Object frame, rows, pretend;
1621{
1622 CHECK_NUMBER (rows, 0);
1623
1624 change_frame_size (0, XINT (rows), 0, !NILP (pretend), 0);
1625 return Qnil;
1626}
1627
1628DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
1629 "Specify that the frame FRAME has COLS columns.\n\
1630Optional third arg non-nil means that redisplay should use COLS columns\n\
1631but that the idea of the actual width of the frame should not be changed.")
1632 (frame, cols, pretend)
1633 Lisp_Object frame, cols, pretend;
1634{
1635 CHECK_NUMBER (cols, 0);
1636
1637 change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
1638 return Qnil;
1639}
1640
1641DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
1642 "Sets size of FRAME to COLS by ROWS, measured in characters.")
1643 (frame, cols, rows)
1644 Lisp_Object frame, cols, rows;
1645{
1646 CHECK_NUMBER (cols, 2);
1647 CHECK_NUMBER (rows, 1);
1648
1649 change_frame_size (0, XINT (rows), XINT (cols), 0, 0);
1650
1651 return Qnil;
1652}
1653
48c9d487
JB
1654DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 1, 0,
1655 "Return number of lines available for display on FRAME.\n\
1656If FRAME is omitted, describe the currently selected frame.")
1657 (frame)
1658 Lisp_Object frame;
cc38027b
JB
1659{
1660 return make_number (FRAME_HEIGHT (selected_frame));
1661}
1662
48c9d487
JB
1663DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 1, 0,
1664 "Return number of columns available for display on FRAME.\n\
1665If FRAME is omitted, describe the currently selected frame.")
1666 (frame)
1667 Lisp_Object frame;
cc38027b
JB
1668{
1669 return make_number (FRAME_WIDTH (selected_frame));
1670}
1671
a26a1f95
RS
1672DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
1673 0, 1, 0,
1674 "Height in pixels of a line in the font in frame FRAME.\n\
1675If FRAME is omitted, the selected frame is used.\n\
1676For a terminal frame, the value is always 1.")
1677 (frame)
1678 Lisp_Object frame;
1679{
1680 return make_number (1);
1681}
1682
1683
1684DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
1685 0, 1, 0,
1686 "Width in pixels of characters in the font in frame FRAME.\n\
1687If FRAME is omitted, the selected frame is used.\n\
1688The width is the same for all characters, because\n\
1689currently Emacs supports only fixed-width fonts.\n\
1690For a terminal screen, the value is always 1.")
1691 (frame)
1692 Lisp_Object frame;
1693{
1694 return make_number (1);
1695}
1696
1697DEFUN ("frame-pixel-height", Fframe_pixel_height,
1698 Sframe_pixel_height, 0, 1, 0,
1699 "Return FRAME's height in pixels.\n\
1700For a terminal frame, the result really gives the height in characters.\n\
1701If FRAME is omitted, the selected frame is used.")
1702 (frame)
1703 Lisp_Object frame;
1704{
1705 return make_number (FRAME_HEIGHT (f));
1706}
1707
1708DEFUN ("frame-pixel-width", Fframe_pixel_width,
1709 Sframe_pixel_width, 0, 1, 0,
1710 "Return FRAME's width in pixels.\n\
1711For a terminal frame, the result really gives the width in characters.\n\
1712If FRAME is omitted, the selected frame is used.")
1713 (frame)
1714 Lisp_Object frame;
1715{
1716 return make_number (FRAME_WIDTH (f));
1717}
1718
cc38027b
JB
1719/* These are for backward compatibility with Emacs 18. */
1720
fd0c2bd1
JB
1721DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
1722 "Tell redisplay that the screen has LINES lines.\n\
1723Optional second arg non-nil means that redisplay should use LINES lines\n\
1724but that the idea of the actual height of the screen should not be changed.")
1725 (lines, pretend)
1726 Lisp_Object lines, pretend;
1727{
1728 CHECK_NUMBER (lines, 0);
1729
1730 change_frame_size (0, XINT (lines), 0, !NILP (pretend), 0);
1731 return Qnil;
1732}
1733
1734DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
1735 "Tell redisplay that the screen has COLS columns.\n\
1736Optional second arg non-nil means that redisplay should use COLS columns\n\
1737but that the idea of the actual width of the screen should not be changed.")
1738 (cols, pretend)
1739 Lisp_Object cols, pretend;
1740{
1741 CHECK_NUMBER (cols, 0);
1742
1743 change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
1744 return Qnil;
1745}
1746
bc1ed486
RS
1747DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
1748 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
1749The position is given in character cells, where (0, 0) is the\n\
1750upper-left corner.\n\
1751If Emacs is running on a mouseless terminal or hasn't been programmed\n\
1752to read the mouse position, it returns the selected frame for FRAME\n\
1753and nil for X and Y.")
1754 ()
1755{
1756 FRAME_PTR f;
1757 Lisp_Object lispy_dummy;
1758 enum scroll_bar_part party_dummy;
1759 Lisp_Object x, y;
1760 unsigned long long_dummy;
1761
1762 f = selected_frame;
1763 x = y = Qnil;
1764
1765 /* It's okay for the hook to refrain from storing anything. */
1766 if (mouse_position_hook)
1767 (*mouse_position_hook) (&f,
1768 &lispy_dummy, &party_dummy,
1769 &x, &y,
1770 &long_dummy);
1771
1772 /* Always return nil for frame. */
1773 return Fcons (Qnil, Fcons (x, y));
1774}
1775
fd0c2bd1
JB
1776syms_of_frame ()
1777{
a26a1f95 1778 defsubr (&Sselected_frame);
704a9b45 1779 defsubr (&Sframep);
a26a1f95
RS
1780 defsubr (&Sframe_char_height);
1781 defsubr (&Sframe_char_width);
1782 defsubr (&Sframe_pixel_height);
1783 defsubr (&Sframe_pixel_width);
fd0c2bd1
JB
1784 defsubr (&Sset_frame_height);
1785 defsubr (&Sset_frame_width);
1786 defsubr (&Sset_frame_size);
1787 defsubr (&Sset_screen_height);
1788 defsubr (&Sset_screen_width);
1789 defsubr (&Sframe_height);
1790 Ffset (intern ("screen-height"), intern ("frame-height"));
1791 defsubr (&Sframe_width);
1792 Ffset (intern ("screen-width"), intern ("frame-width"));
bc1ed486 1793 defsubr (&Smouse_position);
fd0c2bd1
JB
1794}
1795
2f0b07e0
JB
1796keys_of_frame ()
1797{
1798}
1799
fd0c2bd1
JB
1800#endif /* not MULTI_FRAME */
1801
1802
1803
1804