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