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