New s-file for rs60000-ibm-aix3.2.5.
[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 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