* s/darwin.h (SYSTEM_PURESIZE_EXTRA): Define here.
[bpt/emacs.git] / src / frame.c
CommitLineData
ff11dfa1 1/* Generic frame functions.
0b5538bd 2 Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003,
4e6835db 3 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
dc6f92b8
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
1113d9db 9the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
dc6f92b8 21
18160b98 22#include <config.h>
565620a5
RS
23
24#include <stdio.h>
cc38027b 25#include "lisp.h"
71025e5e 26#include "charset.h"
6d55d620 27#ifdef HAVE_X_WINDOWS
dfcf069d 28#include "xterm.h"
71025e5e 29#endif
8f23f280
AI
30#ifdef WINDOWSNT
31#include "w32term.h"
32#endif
e0f712ba 33#ifdef MAC_OS
1a578e9b
AC
34#include "macterm.h"
35#endif
2538fae4
AI
36#include "buffer.h"
37/* These help us bind and responding to switch-frame events. */
38#include "commands.h"
39#include "keyboard.h"
cc38027b 40#include "frame.h"
a1dfb88a
KH
41#ifdef HAVE_WINDOW_SYSTEM
42#include "fontset.h"
43#endif
972f4259 44#include "blockinput.h"
28d440ab 45#include "termchar.h"
bc1ed486 46#include "termhooks.h"
dfcf069d 47#include "dispextern.h"
f769f1b2 48#include "window.h"
87485d6f
MW
49#ifdef MSDOS
50#include "msdos.h"
4aec4b29 51#include "dosfns.h"
87485d6f 52#endif
e5d77022 53
972f4259 54
2731a0ad
KS
55#ifdef HAVE_WINDOW_SYSTEM
56
972f4259
KS
57/* The name we're using in resource queries. Most often "emacs". */
58
59Lisp_Object Vx_resource_name;
60
61/* The application class we're using in resource queries.
62 Normally "Emacs". */
63
64Lisp_Object Vx_resource_class;
65
2731a0ad 66#endif
972f4259
KS
67
68Lisp_Object Qframep, Qframe_live_p;
69Lisp_Object Qicon, Qmodeline;
fd0c2bd1 70Lisp_Object Qonly;
972f4259 71Lisp_Object Qx, Qw32, Qmac, Qpc;
f7af3f7b 72Lisp_Object Qvisible;
8b60f7bc 73Lisp_Object Qdisplay_type;
6345f6aa 74Lisp_Object Qbackground_mode;
972f4259
KS
75
76Lisp_Object Qx_frame_parameter;
77Lisp_Object Qx_resource_name;
6ed8eeff
KL
78Lisp_Object Qterminal;
79Lisp_Object Qterminal_live_p;
972f4259
KS
80
81/* Frame parameters (set or reported). */
82
83Lisp_Object Qauto_raise, Qauto_lower;
84Lisp_Object Qborder_color, Qborder_width;
85Lisp_Object Qcursor_color, Qcursor_type;
86Lisp_Object Qgeometry; /* Not used */
87Lisp_Object Qheight, Qwidth;
88Lisp_Object Qleft, Qright;
89Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
90Lisp_Object Qinternal_border_width;
91Lisp_Object Qmouse_color;
92Lisp_Object Qminibuffer;
93Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
94Lisp_Object Qvisibility;
95Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
96Lisp_Object Qscreen_gamma;
97Lisp_Object Qline_spacing;
98Lisp_Object Quser_position, Quser_size;
99Lisp_Object Qwait_for_wm;
100Lisp_Object Qwindow_id;
101#ifdef HAVE_X_WINDOWS
102Lisp_Object Qouter_window_id;
103#endif
104Lisp_Object Qparent_id;
105Lisp_Object Qtitle, Qname;
106Lisp_Object Qunsplittable;
107Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
108Lisp_Object Qleft_fringe, Qright_fringe;
a18b8cb5 109Lisp_Object Qbuffer_predicate, Qbuffer_list, Qburied_buffer_list;
94674d18 110Lisp_Object Qtty_color_mode;
28d440ab 111Lisp_Object Qtty, Qtty_type;
7f19e125 112Lisp_Object Qwindow_system;
da8e8fc1 113Lisp_Object Qenvironment;
dc6f92b8 114
972f4259
KS
115Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
116
26c34ec2 117Lisp_Object Qinhibit_face_set_after_frame_default;
972f4259
KS
118Lisp_Object Qface_set_after_frame_default;
119
daf01701 120Lisp_Object Vterminal_frame;
a1aaa23f 121Lisp_Object Vdefault_frame_alist;
a6e20602 122Lisp_Object Vdefault_frame_scroll_bars;
beb0bc36 123Lisp_Object Vmouse_position_function;
6018080f 124Lisp_Object Vmouse_highlight;
cd1d850f 125Lisp_Object Vdelete_frame_functions;
a249de79
RS
126\f
127static void
128set_menu_bar_lines_1 (window, n)
daf01701
KL
129 Lisp_Object window;
130 int n;
a249de79
RS
131{
132 struct window *w = XWINDOW (window);
133
57aeea1e 134 XSETFASTINT (w->last_modified, 0);
5af5757b
KS
135 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
136 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
177c0ea7 137
5af5757b
KS
138 if (INTEGERP (w->orig_top_line))
139 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
140 if (INTEGERP (w->orig_total_lines))
141 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
a249de79
RS
142
143 /* Handle just the top child in a vertical split. */
144 if (!NILP (w->vchild))
145 set_menu_bar_lines_1 (w->vchild, n);
146
147 /* Adjust all children in a horizontal split. */
148 for (window = w->hchild; !NILP (window); window = w->next)
149 {
150 w = XWINDOW (window);
151 set_menu_bar_lines_1 (window, n);
152 }
153}
154
e48f782c 155void
a249de79
RS
156set_menu_bar_lines (f, value, oldval)
157 struct frame *f;
158 Lisp_Object value, oldval;
159{
160 int nlines;
161 int olines = FRAME_MENU_BAR_LINES (f);
162
163 /* Right now, menu bars don't work properly in minibuf-only frames;
164 most of the commands try to apply themselves to the minibuffer
e3678b64 165 frame itself, and get an error because you can't switch buffers
a249de79
RS
166 in or split the minibuffer window. */
167 if (FRAME_MINIBUF_ONLY_P (f))
168 return;
169
170 if (INTEGERP (value))
171 nlines = XINT (value);
172 else
173 nlines = 0;
174
57aeea1e
RS
175 if (nlines != olines)
176 {
177 windows_or_buffers_changed++;
178 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
179 FRAME_MENU_BAR_LINES (f) = nlines;
180 set_menu_bar_lines_1 (f->root_window, nlines - olines);
18082e2d 181 adjust_glyphs (f);
57aeea1e 182 }
a249de79
RS
183}
184\f
a249de79
RS
185Lisp_Object Vemacs_iconified;
186Lisp_Object Vframe_list;
a249de79 187
dc6f92b8
JB
188extern Lisp_Object Vminibuffer_list;
189extern Lisp_Object get_minibuffer ();
84386599
RS
190extern Lisp_Object Fhandle_switch_frame ();
191extern Lisp_Object Fredirect_frame_focus ();
a54d3a73 192extern Lisp_Object x_get_focus_frame ();
dc6f92b8 193\f
ff11dfa1 194DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
14ff1ee0
PJ
195 doc: /* Return non-nil if OBJECT is a frame.
196Value is t for a termcap frame (a character-only terminal),
197`x' for an Emacs frame that is really an X window,
198`w32' for an Emacs frame that is a window on MS-Windows display,
199`mac' for an Emacs frame on a Macintosh display,
200`pc' for a direct-write MS-DOS frame.
201See also `frame-live-p'. */)
202 (object)
f9898cc6 203 Lisp_Object object;
dc6f92b8 204{
e35d291d 205 if (!FRAMEP (object))
dc6f92b8 206 return Qnil;
ff11dfa1 207 switch (XFRAME (object)->output_method)
dc6f92b8 208 {
3224dac1 209 case output_initial: /* The initial frame is like a termcap frame. */
dc6f92b8
JB
210 case output_termcap:
211 return Qt;
212 case output_x_window:
fd0c2bd1 213 return Qx;
fbd6baed
GV
214 case output_w32:
215 return Qw32;
bb221971
RS
216 case output_msdos_raw:
217 return Qpc;
574a1a90
RS
218 case output_mac:
219 return Qmac;
dc6f92b8
JB
220 default:
221 abort ();
222 }
223}
224
dbc4e1c1 225DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
14ff1ee0
PJ
226 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
227Value is nil if OBJECT is not a live frame. If object is a live
6ed8eeff 228frame, the return value indicates what sort of terminal device it is
f6fa0866 229displayed on. See the documentation of `framep' for possible
4e10df59 230return values. */)
14ff1ee0 231 (object)
f9898cc6
JB
232 Lisp_Object object;
233{
ff11dfa1
JB
234 return ((FRAMEP (object)
235 && FRAME_LIVE_P (XFRAME (object)))
236 ? Fframep (object)
f9898cc6
JB
237 : Qnil);
238}
239
428a555e
KL
240DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
241 doc: /* The name of the window system that FRAME is displaying through.
242The value is a symbol---for instance, 'x' for X windows.
243The value is nil if Emacs is using a text-only terminal.
244
245FRAME defaults to the currently selected frame. */)
246 (frame)
247 Lisp_Object frame;
248{
249 Lisp_Object type;
250 if (NILP (frame))
251 frame = selected_frame;
252
253 type = Fframep (frame);
254
255 if (NILP (type))
256 wrong_type_argument (Qframep, frame);
257
258 if (EQ (type, Qt))
259 return Qnil;
260 else
261 return type;
262}
263
ff11dfa1
JB
264struct frame *
265make_frame (mini_p)
dc6f92b8
JB
266 int mini_p;
267{
ff11dfa1
JB
268 Lisp_Object frame;
269 register struct frame *f;
dc6f92b8
JB
270 register Lisp_Object root_window;
271 register Lisp_Object mini_window;
e9c96c62
GM
272
273 f = allocate_frame ();
36af7d69 274 XSETFRAME (frame, f);
ff11dfa1 275
18082e2d
GM
276 f->desired_matrix = 0;
277 f->current_matrix = 0;
278 f->desired_pool = 0;
279 f->current_pool = 0;
280 f->glyphs_initialized_p = 0;
281 f->decode_mode_spec_buffer = 0;
ff11dfa1 282 f->visible = 0;
323405de 283 f->async_visible = 0;
7556890b 284 f->output_data.nothing = 0;
ff11dfa1 285 f->iconified = 0;
323405de 286 f->async_iconified = 0;
ff11dfa1
JB
287 f->wants_modeline = 1;
288 f->auto_raise = 0;
289 f->auto_lower = 0;
290 f->no_split = 0;
10689a01 291 f->garbaged = 1;
ff11dfa1 292 f->has_minibuffer = mini_p;
a42e9724 293 f->focus_frame = Qnil;
804518aa 294 f->explicit_name = 0;
fd2777e0 295 f->can_have_scroll_bars = 0;
3a43d2dd 296 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
ff11dfa1 297 f->param_alist = Qnil;
fd2777e0
JB
298 f->scroll_bars = Qnil;
299 f->condemned_scroll_bars = Qnil;
306cc902 300 f->face_alist = Qnil;
18082e2d 301 f->face_cache = NULL;
9dd935ee 302 f->menu_bar_items = Qnil;
c8b8e7e3
RS
303 f->menu_bar_vector = Qnil;
304 f->menu_bar_items_used = 0;
329ca574 305 f->buffer_predicate = Qnil;
fa54c6ae 306 f->buffer_list = Qnil;
a18b8cb5 307 f->buried_buffer_list = Qnil;
aec6e486 308 f->namebuf = 0;
2b1c9cfb 309 f->title = Qnil;
18082e2d 310 f->menu_bar_window = Qnil;
9ea173e8 311 f->tool_bar_window = Qnil;
61752261 312 f->tool_bar_items = Qnil;
9ea173e8 313 f->desired_tool_bar_string = f->current_tool_bar_string = Qnil;
61752261 314 f->n_tool_bar_items = 0;
5af5757b
KS
315 f->left_fringe_width = f->right_fringe_width = 0;
316 f->fringe_cols = 0;
317 f->scroll_bar_actual_width = 0;
318 f->border_width = 0;
319 f->internal_border_width = 0;
320 f->column_width = 1; /* !FRAME_WINDOW_P value */
321 f->line_height = 1; /* !FRAME_WINDOW_P value */
322 f->x_pixels_diff = f->y_pixels_diff = 0;
93421a1f 323#ifdef HAVE_WINDOW_SYSTEM
5af5757b 324 f->want_fullscreen = FULLSCREEN_NONE;
93421a1f 325#endif
5af5757b
KS
326 f->size_hint_flags = 0;
327 f->win_gravity = 0;
dc6f92b8 328
cc38027b 329 root_window = make_window ();
dc6f92b8
JB
330 if (mini_p)
331 {
cc38027b 332 mini_window = make_window ();
dc6f92b8
JB
333 XWINDOW (root_window)->next = mini_window;
334 XWINDOW (mini_window)->prev = root_window;
335 XWINDOW (mini_window)->mini_p = Qt;
ff11dfa1
JB
336 XWINDOW (mini_window)->frame = frame;
337 f->minibuffer_window = mini_window;
dc6f92b8
JB
338 }
339 else
340 {
341 mini_window = Qnil;
342 XWINDOW (root_window)->next = Qnil;
ff11dfa1 343 f->minibuffer_window = Qnil;
dc6f92b8
JB
344 }
345
ff11dfa1 346 XWINDOW (root_window)->frame = frame;
dc6f92b8
JB
347
348 /* 10 is arbitrary,
349 just so that there is "something there."
ff11dfa1 350 Correct size will be set up later with change_frame_size. */
dc6f92b8 351
5af5757b
KS
352 SET_FRAME_COLS (f, 10);
353 FRAME_LINES (f) = 10;
dc6f92b8 354
5af5757b
KS
355 XSETFASTINT (XWINDOW (root_window)->total_cols, 10);
356 XSETFASTINT (XWINDOW (root_window)->total_lines, (mini_p ? 9 : 10));
dc6f92b8
JB
357
358 if (mini_p)
359 {
5af5757b
KS
360 XSETFASTINT (XWINDOW (mini_window)->total_cols, 10);
361 XSETFASTINT (XWINDOW (mini_window)->top_line, 9);
362 XSETFASTINT (XWINDOW (mini_window)->total_lines, 1);
dc6f92b8
JB
363 }
364
ff11dfa1 365 /* Choose a buffer for the frame's root window. */
5bce042c
JB
366 {
367 Lisp_Object buf;
368
369 XWINDOW (root_window)->buffer = Qt;
370 buf = Fcurrent_buffer ();
371 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
372 a space), try to find another one. */
d5db4077 373 if (SREF (Fbuffer_name (buf), 0) == ' ')
98ce1622 374 buf = Fother_buffer (buf, Qnil, Qnil);
fa54c6ae 375
18082e2d
GM
376 /* Use set_window_buffer, not Fset_window_buffer, and don't let
377 hooks be run by it. The reason is that the whole frame/window
378 arrangement is not yet fully intialized at this point. Windows
379 don't have the right size, glyph matrices aren't initialized
380 etc. Running Lisp functions at this point surely ends in a
381 SEGV. */
5af5757b 382 set_window_buffer (root_window, buf, 0, 0);
fa54c6ae 383 f->buffer_list = Fcons (buf, Qnil);
5bce042c
JB
384 }
385
dc6f92b8
JB
386 if (mini_p)
387 {
388 XWINDOW (mini_window)->buffer = Qt;
18082e2d
GM
389 set_window_buffer (mini_window,
390 (NILP (Vminibuffer_list)
391 ? get_minibuffer (0)
392 : Fcar (Vminibuffer_list)),
5af5757b 393 0, 0);
dc6f92b8
JB
394 }
395
ff11dfa1
JB
396 f->root_window = root_window;
397 f->selected_window = root_window;
d5e7c279
JB
398 /* Make sure this window seems more recently used than
399 a newly-created, never-selected window. */
2a1893f4
SM
400 ++window_select_count;
401 XSETFASTINT (XWINDOW (f->selected_window)->use_time, window_select_count);
dc6f92b8 402
a5f696ac
JD
403 f->default_face_done_p = 0;
404
ff11dfa1 405 return f;
dc6f92b8
JB
406}
407\f
bba88bb1 408#ifdef HAVE_WINDOW_SYSTEM
ff11dfa1 409/* Make a frame using a separate minibuffer window on another frame.
dc6f92b8
JB
410 MINI_WINDOW is the minibuffer window to use. nil means use the
411 default (the global minibuffer). */
412
ff11dfa1 413struct frame *
b0660239 414make_frame_without_minibuffer (mini_window, kb, display)
dc6f92b8 415 register Lisp_Object mini_window;
662ac59a 416 KBOARD *kb;
b0660239 417 Lisp_Object display;
dc6f92b8 418{
ff11dfa1 419 register struct frame *f;
363b873b 420 struct gcpro gcpro1;
dc6f92b8 421
b0660239 422 if (!NILP (mini_window))
b7826503 423 CHECK_LIVE_WINDOW (mini_window);
dc6f92b8 424
662ac59a 425#ifdef MULTI_KBOARD
b0660239 426 if (!NILP (mini_window)
6ed8eeff
KL
427 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
428 error ("Frame and minibuffer must be on the same terminal");
662ac59a
KH
429#endif
430
ff11dfa1
JB
431 /* Make a frame containing just a root window. */
432 f = make_frame (0);
dc6f92b8 433
b0660239
KH
434 if (NILP (mini_window))
435 {
436 /* Use default-minibuffer-frame if possible. */
437 if (!FRAMEP (kb->Vdefault_minibuffer_frame)
438 || ! FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame)))
439 {
363b873b
RS
440 Lisp_Object frame_dummy;
441
442 XSETFRAME (frame_dummy, f);
443 GCPRO1 (frame_dummy);
b0660239 444 /* If there's no minibuffer frame to use, create one. */
363b873b
RS
445 kb->Vdefault_minibuffer_frame =
446 call1 (intern ("make-initial-minibuffer-frame"), display);
447 UNGCPRO;
b0660239 448 }
177c0ea7 449
b0660239
KH
450 mini_window = XFRAME (kb->Vdefault_minibuffer_frame)->minibuffer_window;
451 }
a2812a26 452
ff11dfa1 453 f->minibuffer_window = mini_window;
a2812a26
RS
454
455 /* Make the chosen minibuffer window display the proper minibuffer,
456 unless it is already showing a minibuffer. */
457 if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
458 Fset_window_buffer (mini_window,
459 (NILP (Vminibuffer_list)
460 ? get_minibuffer (0)
5af5757b 461 : Fcar (Vminibuffer_list)), Qnil);
ff11dfa1 462 return f;
dc6f92b8
JB
463}
464
ff11dfa1 465/* Make a frame containing only a minibuffer window. */
dc6f92b8 466
ff11dfa1
JB
467struct frame *
468make_minibuffer_frame ()
dc6f92b8 469{
ff11dfa1 470 /* First make a frame containing just a root window, no minibuffer. */
dc6f92b8 471
ff11dfa1 472 register struct frame *f = make_frame (0);
dc6f92b8 473 register Lisp_Object mini_window;
ff11dfa1 474 register Lisp_Object frame;
dc6f92b8 475
2d80a27a 476 XSETFRAME (frame, f);
dc6f92b8 477
804518aa 478 f->auto_raise = 0;
ff11dfa1
JB
479 f->auto_lower = 0;
480 f->no_split = 1;
481 f->wants_modeline = 0;
482 f->has_minibuffer = 1;
dc6f92b8
JB
483
484 /* Now label the root window as also being the minibuffer.
485 Avoid infinite looping on the window chain by marking next pointer
486 as nil. */
487
ff11dfa1 488 mini_window = f->minibuffer_window = f->root_window;
dc6f92b8
JB
489 XWINDOW (mini_window)->mini_p = Qt;
490 XWINDOW (mini_window)->next = Qnil;
804518aa 491 XWINDOW (mini_window)->prev = Qnil;
ff11dfa1 492 XWINDOW (mini_window)->frame = frame;
dc6f92b8
JB
493
494 /* Put the proper buffer in that window. */
495
496 Fset_window_buffer (mini_window,
265a9e55 497 (NILP (Vminibuffer_list)
dc6f92b8 498 ? get_minibuffer (0)
5af5757b 499 : Fcar (Vminibuffer_list)), Qnil);
ff11dfa1 500 return f;
dc6f92b8 501}
bba88bb1 502#endif /* HAVE_WINDOW_SYSTEM */
dc6f92b8 503\f
28d440ab 504/* Construct a frame that refers to a terminal. */
dc6f92b8 505
6ed8eeff 506static int tty_frame_count;
bb1513c9 507
ff11dfa1 508struct frame *
3224dac1 509make_initial_frame (void)
dc6f92b8 510{
3224dac1 511 struct frame *f;
6ed8eeff 512 struct terminal *terminal;
d063751a 513 Lisp_Object frame;
3224dac1 514
b4f0ee5d 515#ifdef MULTI_KBOARD
7b00d185 516 /* Create the initial keyboard. */
b4f0ee5d
KH
517 if (!initial_kboard)
518 {
519 initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
520 init_kboard (initial_kboard);
a1b658dd
KH
521 initial_kboard->next_kboard = all_kboards;
522 all_kboards = initial_kboard;
b4f0ee5d
KH
523 }
524#endif
525
bb1513c9
RS
526 /* The first call must initialize Vframe_list. */
527 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
528 Vframe_list = Qnil;
ff11dfa1 529
6ed8eeff 530 terminal = init_initial_terminal ();
3224dac1
KL
531
532 f = make_frame (1);
533 XSETFRAME (frame, f);
534
535 Vframe_list = Fcons (frame, Vframe_list);
536
6ed8eeff 537 tty_frame_count = 1;
3224dac1
KL
538 f->name = build_string ("F1");
539
540 f->visible = 1;
541 f->async_visible = 1;
542
6ed8eeff
KL
543 f->output_method = terminal->type;
544 f->terminal = terminal;
545 f->terminal->reference_count++;
3224dac1
KL
546 f->output_data.nothing = 0;
547
548 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
549 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
550
551 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
552 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
553
3224dac1
KL
554 return f;
555}
556
557
558struct frame *
6ed8eeff 559make_terminal_frame (struct terminal *terminal)
3224dac1
KL
560{
561 register struct frame *f;
3224dac1
KL
562 Lisp_Object frame;
563 char name[20];
ab797f65
KL
564
565 if (terminal->deleted)
566 error ("Terminal is being deleted, can't create new frames on it");
567
ff11dfa1 568 f = make_frame (1);
d063751a 569
2d80a27a 570 XSETFRAME (frame, f);
d063751a
RS
571 Vframe_list = Fcons (frame, Vframe_list);
572
6ed8eeff
KL
573 tty_frame_count++;
574 sprintf (name, "F%d", tty_frame_count);
0303e8da 575 f->name = build_string (name);
bb1513c9 576
bb1513c9
RS
577 f->visible = 1; /* FRAME_SET_VISIBLE wd set frame_garbaged. */
578 f->async_visible = 1; /* Don't let visible be cleared later. */
bb221971
RS
579#ifdef MSDOS
580 f->output_data.x = &the_only_x_display;
2d764c78
EZ
581 if (!inhibit_window_system
582 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
583 || XFRAME (selected_frame)->output_method == output_msdos_raw))
65606f5e
EZ
584 {
585 f->output_method = output_msdos_raw;
586 /* This initialization of foreground and background pixels is
587 only important for the initial frame created in temacs. If
588 we don't do that, we get black background and foreground in
589 the dumped Emacs because the_only_x_display is a static
590 variable, hence it is born all-zeroes, and zero is the code
591 for the black color. Other frames all inherit their pixels
592 from what's already in the_only_x_display. */
593 if ((!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
5bcee7ef
KL
594 && FRAME_BACKGROUND_PIXEL (f) == 0
595 && FRAME_FOREGROUND_PIXEL (f) == 0)
65606f5e 596 {
5bcee7ef
KL
597 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
598 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
65606f5e
EZ
599 }
600 }
2d764c78
EZ
601 else
602 f->output_method = output_termcap;
603#else
4ec0d3c1 604#ifdef WINDOWSNT
ff8d4bf4 605 f->output_method = output_termcap;
7e166218
JR
606 f->terminal = terminal;
607 f->terminal->reference_count++;
608 create_w32cons_output (f);
4ec0d3c1 609#else
e0f712ba 610#ifdef MAC_OS8
1a578e9b
AC
611 make_mac_terminal_frame (f);
612#else
0a125897 613 {
0a125897 614 f->output_method = output_termcap;
6ed8eeff
KL
615 f->terminal = terminal;
616 f->terminal->reference_count++;
428a555e
KL
617 create_tty_output (f);
618
28d7d09f
KL
619 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
620 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
0a125897 621
428a555e
KL
622 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
623 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
624
428a555e 625 /* Set the top frame to the newly created frame. */
114a8b8c
KL
626 if (FRAME_TTY (f)->top_frame
627 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
628 XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
629
428a555e 630 FRAME_TTY (f)->top_frame = frame;
0a125897
KL
631 }
632
58bd8318
KS
633#ifdef CANNOT_DUMP
634 FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR;
635 FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR;
636#endif
e0f712ba 637#endif /* MAC_OS8 */
4ec0d3c1 638#endif /* WINDOWSNT */
2d764c78 639#endif /* MSDOS */
574a1a90 640
1a6d3623
EZ
641 if (!noninteractive)
642 init_frame_faces (f);
1a578e9b 643
ff11dfa1 644 return f;
dc6f92b8 645}
bb1513c9 646
ed8dad6b
KL
647/* Get a suitable value for frame parameter PARAMETER for a newly
648 created frame, based on (1) the user-supplied frame parameter
649 alist SUPPLIED_PARMS, (2) CURRENT_VALUE, and finally, if all else
650 fails, (3) Vdefault_frame_alist. */
651
652static Lisp_Object
653get_future_frame_param (Lisp_Object parameter,
654 Lisp_Object supplied_parms,
655 char *current_value)
656{
657 Lisp_Object result;
658
659 result = Fassq (parameter, supplied_parms);
660 if (NILP (result))
661 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
662 if (NILP (result) && current_value != NULL)
663 result = build_string (current_value);
664 if (NILP (result))
665 result = Fassq (parameter, Vdefault_frame_alist);
666 if (!NILP (result) && !STRINGP (result))
667 result = XCDR (result);
668 if (NILP (result) || !STRINGP (result))
669 result = Qnil;
670
671 return result;
672}
673
bb1513c9 674DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
14ff1ee0 675 1, 1, 0,
28d440ab 676 doc: /* Create an additional terminal frame, possibly on another terminal.
14ff1ee0 677This function takes one argument, an alist specifying frame parameters.
28d440ab
KL
678
679You can create multiple frames on a single text-only terminal, but
680only one of them (the selected terminal frame) is actually displayed.
681
682In practice, generally you don't need to specify any parameters,
683except when you want to create a new frame on another terminal.
684In that case, the `tty' parameter specifies the device file to open,
685and the `tty-type' parameter specifies the terminal type. Example:
686
687 (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
688
0b0d3e0b
KL
689Note that changing the size of one terminal frame automatically
690affects all frames on the same terminal device. */)
14ff1ee0 691 (parms)
bb1513c9
RS
692 Lisp_Object parms;
693{
694 struct frame *f;
6ed8eeff 695 struct terminal *t = NULL;
574a1a90 696 Lisp_Object frame, tem;
8d2666fe 697 struct frame *sf = SELECTED_FRAME ();
bb1513c9 698
541580aa 699#ifdef MSDOS
2d764c78
EZ
700 if (sf->output_method != output_msdos_raw
701 && sf->output_method != output_termcap)
bb221971 702 abort ();
574a1a90
RS
703#else /* not MSDOS */
704
e0f712ba 705#ifdef MAC_OS
8d2666fe 706 if (sf->output_method != output_mac)
574a1a90 707 error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
bb221971 708#else
daf01701 709#if 0 /* This should work now! */
8d2666fe 710 if (sf->output_method != output_termcap)
bb1513c9 711 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
bb221971 712#endif
daf01701 713#endif
574a1a90 714#endif /* not MSDOS */
b6660415
KL
715
716 {
6ed8eeff 717 Lisp_Object terminal;
bb1513c9 718
6ed8eeff
KL
719 terminal = Fassq (Qterminal, parms);
720 if (!NILP (terminal))
28d440ab 721 {
6ed8eeff
KL
722 terminal = XCDR (terminal);
723 t = get_terminal (terminal, 1);
28d440ab 724 }
28d440ab 725 }
b6660415 726
6ed8eeff 727 if (!t)
b6660415 728 {
b6660415 729 char *name = 0, *type = 0;
ed8dad6b 730 Lisp_Object tty, tty_type;
b6660415 731
ed8dad6b
KL
732 tty = get_future_frame_param
733 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
734 ? FRAME_TTY (XFRAME (selected_frame))->name
735 : NULL));
736 if (!NILP (tty))
b6660415
KL
737 {
738 name = (char *) alloca (SBYTES (tty) + 1);
739 strncpy (name, SDATA (tty), SBYTES (tty));
740 name[SBYTES (tty)] = 0;
741 }
742
ed8dad6b
KL
743 tty_type = get_future_frame_param
744 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
745 ? FRAME_TTY (XFRAME (selected_frame))->type
746 : NULL));
747 if (!NILP (tty_type))
b6660415
KL
748 {
749 type = (char *) alloca (SBYTES (tty_type) + 1);
750 strncpy (type, SDATA (tty_type), SBYTES (tty_type));
751 type[SBYTES (tty_type)] = 0;
752 }
753
6ed8eeff 754 t = init_tty (name, type, 0); /* Errors are not fatal. */
b6660415
KL
755 }
756
6ed8eeff 757 f = make_terminal_frame (t);
574a1a90 758
9628b887
KL
759 {
760 int width, height;
0b0d3e0b 761 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
9628b887
KL
762 change_frame_size (f, height, width, 0, 0, 0);
763 }
764
18082e2d 765 adjust_glyphs (f);
bb1513c9
RS
766 calculate_costs (f);
767 XSETFRAME (frame, f);
8adfc1ec 768 Fmodify_frame_parameters (frame, Vdefault_frame_alist);
bb1513c9 769 Fmodify_frame_parameters (frame, parms);
7f19e125 770 Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qnil), Qnil));
ed8dad6b 771 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtty_type,
6ed8eeff 772 build_string (t->display_info.tty->type)),
ed8dad6b 773 Qnil));
db9d7d9a
KL
774 if (t->display_info.tty->name != NULL)
775 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtty,
776 build_string (t->display_info.tty->name)),
777 Qnil));
778 else
779 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtty, Qnil), Qnil));
5b65d888 780
87f1940e
EZ
781 /* Make the frame face alist be frame-specific, so that each
782 frame could change its face definitions independently. */
8d2666fe 783 f->face_alist = Fcopy_alist (sf->face_alist);
87f1940e
EZ
784 /* Simple Fcopy_alist isn't enough, because we need the contents of
785 the vectors which are the CDRs of associations in face_alist to
786 be copied as well. */
787 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
f3fbd155 788 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
bb1513c9
RS
789 return frame;
790}
1e8324d9 791
dc6f92b8 792\f
1e8324d9
GM
793/* Perform the switch to frame FRAME.
794
795 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
796 FRAME1 as frame.
797
798 If TRACK is non-zero and the frame that currently has the focus
799 redirects its focus to the selected frame, redirect that focused
800 frame's focus to FRAME instead.
801
802 FOR_DELETION non-zero means that the selected frame is being
6ed8eeff 803 deleted, which includes the possibility that the frame's terminal
1e8324d9
GM
804 is dead. */
805
61f94483 806Lisp_Object
1e8324d9
GM
807do_switch_frame (frame, track, for_deletion)
808 Lisp_Object frame;
809 int track, for_deletion;
dc6f92b8 810{
8d2666fe 811 struct frame *sf = SELECTED_FRAME ();
177c0ea7 812
2f0b07e0
JB
813 /* If FRAME is a switch-frame event, extract the frame we should
814 switch to. */
815 if (CONSP (frame)
7539e11f
KR
816 && EQ (XCAR (frame), Qswitch_frame)
817 && CONSP (XCDR (frame)))
818 frame = XCAR (XCDR (frame));
2f0b07e0 819
09907c3a
KH
820 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
821 a switch-frame event to arrive after a frame is no longer live,
822 especially when deleting the initial frame during startup. */
b7826503 823 CHECK_FRAME (frame);
09907c3a
KH
824 if (! FRAME_LIVE_P (XFRAME (frame)))
825 return Qnil;
dc6f92b8 826
8d2666fe 827 if (sf == XFRAME (frame))
ff11dfa1 828 return frame;
dc6f92b8 829
0aed85f4
KH
830 /* This is too greedy; it causes inappropriate focus redirection
831 that's hard to get rid of. */
832#if 0
a42e9724
JB
833 /* If a frame's focus has been redirected toward the currently
834 selected frame, we should change the redirection to point to the
835 newly selected frame. This means that if the focus is redirected
836 from a minibufferless frame to a surrogate minibuffer frame, we
837 can use `other-window' to switch between all the frames using
838 that minibuffer frame, and the focus redirection will follow us
839 around. */
0aed85f4
KH
840 if (track)
841 {
842 Lisp_Object tail;
a42e9724 843
7539e11f 844 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
0aed85f4
KH
845 {
846 Lisp_Object focus;
a42e9724 847
7539e11f 848 if (!FRAMEP (XCAR (tail)))
0aed85f4 849 abort ();
a42e9724 850
7539e11f 851 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
a42e9724 852
8d2666fe 853 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
7539e11f 854 Fredirect_frame_focus (XCAR (tail), frame);
0aed85f4
KH
855 }
856 }
857#else /* ! 0 */
858 /* Instead, apply it only to the frame we're pointing to. */
032d78fe 859#ifdef HAVE_WINDOW_SYSTEM
1e8324d9 860 if (track && FRAME_WINDOW_P (XFRAME (frame)))
0aed85f4
KH
861 {
862 Lisp_Object focus, xfocus;
863
d7266360 864 xfocus = x_get_focus_frame (XFRAME (frame));
0aed85f4
KH
865 if (FRAMEP (xfocus))
866 {
867 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
8d2666fe 868 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
0aed85f4
KH
869 Fredirect_frame_focus (xfocus, frame);
870 }
871 }
872#endif /* HAVE_X_WINDOWS */
873#endif /* ! 0 */
a42e9724 874
1e8324d9 875 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
550f0e6a
GM
876 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
877
9628b887
KL
878 if (FRAME_TERMCAP_P (XFRAME (selected_frame))
879 && FRAME_TERMCAP_P (XFRAME (frame))
880 && FRAME_TTY (XFRAME (selected_frame)) == FRAME_TTY (XFRAME (frame)))
881 {
6548cf00 882 XFRAME (selected_frame)->async_visible = 2; /* obscured */
9628b887
KL
883 XFRAME (frame)->async_visible = 1;
884 FRAME_TTY (XFRAME (frame))->top_frame = frame;
885 }
886
8d2666fe
GM
887 selected_frame = frame;
888 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
889 last_nonminibuf_frame = XFRAME (selected_frame);
d5e7c279 890
f1321dc3 891 Fselect_window (XFRAME (frame)->selected_window, Qnil);
dc6f92b8 892
94674d18
EZ
893#ifndef WINDOWSNT
894 /* Make sure to switch the tty color mode to that of the newly
895 selected frame. */
896 sf = SELECTED_FRAME ();
897 if (FRAME_TERMCAP_P (sf))
898 {
899 Lisp_Object color_mode_spec, color_mode;
900
901 color_mode_spec = assq_no_quit (Qtty_color_mode, sf->param_alist);
902 if (CONSP (color_mode_spec))
903 color_mode = XCDR (color_mode_spec);
904 else
905 color_mode = make_number (0);
906 set_tty_color_mode (sf, color_mode);
907 }
908#endif /* !WINDOWSNT */
909
074577b8 910 /* We want to make sure that the next event generates a frame-switch
eb8c3be9 911 event to the appropriate frame. This seems kludgy to me, but
074577b8
JB
912 before you take it out, make sure that evaluating something like
913 (select-window (frame-root-window (new-frame))) doesn't end up
914 with your typing being interpreted in the new frame instead of
915 the one you're actually typing in. */
ef352596 916 internal_last_event_frame = Qnil;
074577b8 917
ff11dfa1 918 return frame;
dc6f92b8
JB
919}
920
20dc6fbb 921DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 1, "e",
14ff1ee0
PJ
922 doc: /* Select the frame FRAME.
923Subsequent editing commands apply to its selected window.
924The selection of FRAME lasts until the next time the user does
925something to select a different frame, or until the next time this
e4ed805e
LT
926function is called. If you are using a window system, the previously
927selected frame may be restored as the selected frame after return to
928the command loop, because it still may have the window system's input
929focus. On a text-only terminal, the next redisplay will display FRAME.
930
931This function returns FRAME, or nil if FRAME has been deleted. */)
20dc6fbb
LT
932 (frame)
933 Lisp_Object frame;
0aed85f4 934{
1e8324d9 935 return do_switch_frame (frame, 1, 0);
0aed85f4
KH
936}
937
938
20dc6fbb 939DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "e",
14ff1ee0
PJ
940 doc: /* Handle a switch-frame event EVENT.
941Switch-frame events are usually bound to this function.
942A switch-frame event tells Emacs that the window manager has requested
943that the user's events be directed to the frame mentioned in the event.
944This function selects the selected window of the frame of EVENT.
945
946If EVENT is frame object, handle it as if it were a switch-frame event
947to that frame. */)
20dc6fbb
LT
948 (event)
949 Lisp_Object event;
0aed85f4 950{
6951cd71
KH
951 /* Preserve prefix arg that the command loop just cleared. */
952 current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
e05169e2 953 call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
1e8324d9 954 return do_switch_frame (event, 0, 0);
0aed85f4
KH
955}
956
ff11dfa1 957DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
14ff1ee0
PJ
958 doc: /* Return the frame that is now selected. */)
959 ()
dc6f92b8 960{
8d2666fe 961 return selected_frame;
dc6f92b8 962}
4a7cfafc 963\f
ff11dfa1 964DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
14ff1ee0
PJ
965 doc: /* Return the frame object that window WINDOW is on. */)
966 (window)
dc6f92b8
JB
967 Lisp_Object window;
968{
b7826503 969 CHECK_LIVE_WINDOW (window);
ff11dfa1 970 return XWINDOW (window)->frame;
dc6f92b8
JB
971}
972
ba32f2db 973DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
14ff1ee0
PJ
974 doc: /* Returns the topmost, leftmost window of FRAME.
975If omitted, FRAME defaults to the currently selected frame. */)
976 (frame)
ba32f2db
KH
977 Lisp_Object frame;
978{
979 Lisp_Object w;
980
981 if (NILP (frame))
8d2666fe 982 w = SELECTED_FRAME ()->root_window;
ba32f2db
KH
983 else
984 {
b7826503 985 CHECK_LIVE_FRAME (frame);
ba32f2db
KH
986 w = XFRAME (frame)->root_window;
987 }
988 while (NILP (XWINDOW (w)->buffer))
989 {
990 if (! NILP (XWINDOW (w)->hchild))
991 w = XWINDOW (w)->hchild;
992 else if (! NILP (XWINDOW (w)->vchild))
993 w = XWINDOW (w)->vchild;
994 else
995 abort ();
996 }
997 return w;
998}
999
5add3885
RS
1000DEFUN ("active-minibuffer-window", Factive_minibuffer_window,
1001 Sactive_minibuffer_window, 0, 0, 0,
14ff1ee0
PJ
1002 doc: /* Return the currently active minibuffer window, or nil if none. */)
1003 ()
5add3885
RS
1004{
1005 return minibuf_level ? minibuf_window : Qnil;
1006}
1007
ff11dfa1 1008DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
14ff1ee0
PJ
1009 doc: /* Returns the root-window of FRAME.
1010If omitted, FRAME defaults to the currently selected frame. */)
1011 (frame)
ff11dfa1 1012 Lisp_Object frame;
dc6f92b8 1013{
8d2666fe 1014 Lisp_Object window;
177c0ea7 1015
ff11dfa1 1016 if (NILP (frame))
8d2666fe 1017 window = SELECTED_FRAME ()->root_window;
f9898cc6 1018 else
8d2666fe 1019 {
b7826503 1020 CHECK_LIVE_FRAME (frame);
8d2666fe
GM
1021 window = XFRAME (frame)->root_window;
1022 }
177c0ea7 1023
8d2666fe 1024 return window;
dc6f92b8
JB
1025}
1026
ff11dfa1
JB
1027DEFUN ("frame-selected-window", Fframe_selected_window,
1028 Sframe_selected_window, 0, 1, 0,
14ff1ee0
PJ
1029 doc: /* Return the selected window of frame object FRAME.
1030If omitted, FRAME defaults to the currently selected frame. */)
1031 (frame)
ff11dfa1 1032 Lisp_Object frame;
dc6f92b8 1033{
8d2666fe 1034 Lisp_Object window;
177c0ea7 1035
ff11dfa1 1036 if (NILP (frame))
8d2666fe 1037 window = SELECTED_FRAME ()->selected_window;
f9898cc6 1038 else
8d2666fe 1039 {
b7826503 1040 CHECK_LIVE_FRAME (frame);
8d2666fe
GM
1041 window = XFRAME (frame)->selected_window;
1042 }
dc6f92b8 1043
8d2666fe 1044 return window;
dc6f92b8
JB
1045}
1046
4a7cfafc
RS
1047DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
1048 Sset_frame_selected_window, 2, 2, 0,
14ff1ee0 1049 doc: /* Set the selected window of frame object FRAME to WINDOW.
e4ed805e 1050Return WINDOW.
14ff1ee0
PJ
1051If FRAME is nil, the selected frame is used.
1052If FRAME is the selected frame, this makes WINDOW the selected window. */)
1053 (frame, window)
4a7cfafc
RS
1054 Lisp_Object frame, window;
1055{
1056 if (NILP (frame))
8d2666fe 1057 frame = selected_frame;
177c0ea7 1058
b7826503
PJ
1059 CHECK_LIVE_FRAME (frame);
1060 CHECK_LIVE_WINDOW (window);
4a7cfafc
RS
1061
1062 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
1063 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
1064
8d2666fe 1065 if (EQ (frame, selected_frame))
f1321dc3 1066 return Fselect_window (window, Qnil);
4a7cfafc
RS
1067
1068 return XFRAME (frame)->selected_window = window;
1069}
b6660415
KL
1070
1071\f
ff11dfa1 1072DEFUN ("frame-list", Fframe_list, Sframe_list,
dc6f92b8 1073 0, 0, 0,
14ff1ee0
PJ
1074 doc: /* Return a list of all frames. */)
1075 ()
dc6f92b8 1076{
d74c1900
GM
1077 Lisp_Object frames;
1078 frames = Fcopy_sequence (Vframe_list);
6a65b1b5 1079#ifdef HAVE_WINDOW_SYSTEM
d74c1900
GM
1080 if (FRAMEP (tip_frame))
1081 frames = Fdelq (tip_frame, frames);
6a65b1b5 1082#endif
d74c1900 1083 return frames;
dc6f92b8
JB
1084}
1085
ff11dfa1 1086/* Return the next frame in the frame list after FRAME.
ff11dfa1 1087 If MINIBUF is nil, exclude minibuffer-only frames.
a9986780
RS
1088 If MINIBUF is a window, include only its own frame
1089 and any frame now using that window as the minibuffer.
f7af3f7b 1090 If MINIBUF is `visible', include all visible frames.
a9986780 1091 If MINIBUF is 0, include all visible and iconified frames.
f7af3f7b
RS
1092 Otherwise, include all frames. */
1093
66a9dbbe 1094static Lisp_Object
ff11dfa1
JB
1095next_frame (frame, minibuf)
1096 Lisp_Object frame;
f9898cc6 1097 Lisp_Object minibuf;
dc6f92b8
JB
1098{
1099 Lisp_Object tail;
1100 int passed = 0;
1101
ff11dfa1
JB
1102 /* There must always be at least one frame in Vframe_list. */
1103 if (! CONSP (Vframe_list))
f9898cc6
JB
1104 abort ();
1105
dbc4e1c1
JB
1106 /* If this frame is dead, it won't be in Vframe_list, and we'll loop
1107 forever. Forestall that. */
b7826503 1108 CHECK_LIVE_FRAME (frame);
dbc4e1c1 1109
dc6f92b8 1110 while (1)
7539e11f 1111 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
dc6f92b8 1112 {
ab9f008d 1113 Lisp_Object f;
d06a8a56 1114
7539e11f 1115 f = XCAR (tail);
06537cc8
RS
1116
1117 if (passed
9628b887
KL
1118 && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
1119 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
1120 || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
1121 && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))))
d5e7c279 1122 {
d06a8a56
JB
1123 /* Decide whether this frame is eligible to be returned. */
1124
1125 /* If we've looped all the way around without finding any
1126 eligible frames, return the original frame. */
1127 if (EQ (f, frame))
1128 return f;
1129
1130 /* Let minibuf decide if this frame is acceptable. */
1131 if (NILP (minibuf))
1132 {
1133 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
1134 return f;
1135 }
f7af3f7b
RS
1136 else if (EQ (minibuf, Qvisible))
1137 {
1138 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
1139 if (FRAME_VISIBLE_P (XFRAME (f)))
1140 return f;
1141 }
3780bc22 1142 else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
a9986780
RS
1143 {
1144 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
1145 if (FRAME_VISIBLE_P (XFRAME (f))
1146 || FRAME_ICONIFIED_P (XFRAME (f)))
1147 return f;
1148 }
f7af3f7b 1149 else if (WINDOWP (minibuf))
d06a8a56 1150 {
a9986780 1151 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
551645f8
GM
1152 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
1153 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1154 FRAME_FOCUS_FRAME (XFRAME (f))))
d06a8a56
JB
1155 return f;
1156 }
1157 else
ff11dfa1 1158 return f;
d5e7c279 1159 }
dc6f92b8 1160
d06a8a56 1161 if (EQ (frame, f))
dc6f92b8
JB
1162 passed++;
1163 }
1164}
1165
ff11dfa1 1166/* Return the previous frame in the frame list before FRAME.
ff11dfa1 1167 If MINIBUF is nil, exclude minibuffer-only frames.
a9986780
RS
1168 If MINIBUF is a window, include only its own frame
1169 and any frame now using that window as the minibuffer.
f7af3f7b 1170 If MINIBUF is `visible', include all visible frames.
a9986780 1171 If MINIBUF is 0, include all visible and iconified frames.
f7af3f7b
RS
1172 Otherwise, include all frames. */
1173
66a9dbbe 1174static Lisp_Object
ff11dfa1
JB
1175prev_frame (frame, minibuf)
1176 Lisp_Object frame;
f9898cc6 1177 Lisp_Object minibuf;
dc6f92b8
JB
1178{
1179 Lisp_Object tail;
1180 Lisp_Object prev;
1181
ff11dfa1
JB
1182 /* There must always be at least one frame in Vframe_list. */
1183 if (! CONSP (Vframe_list))
f9898cc6
JB
1184 abort ();
1185
dc6f92b8 1186 prev = Qnil;
7539e11f 1187 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
f9898cc6 1188 {
ab9f008d 1189 Lisp_Object f;
f9898cc6 1190
7539e11f 1191 f = XCAR (tail);
e35d291d 1192 if (!FRAMEP (f))
d06a8a56 1193 abort ();
f9898cc6 1194
d06a8a56
JB
1195 if (EQ (frame, f) && !NILP (prev))
1196 return prev;
f9898cc6 1197
9628b887
KL
1198 if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
1199 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
1200 || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
1201 && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))
f7af3f7b 1202 {
06537cc8
RS
1203 /* Decide whether this frame is eligible to be returned,
1204 according to minibuf. */
1205 if (NILP (minibuf))
1206 {
1207 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
1208 prev = f;
1209 }
1210 else if (WINDOWP (minibuf))
1211 {
1212 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
551645f8
GM
1213 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
1214 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1215 FRAME_FOCUS_FRAME (XFRAME (f))))
06537cc8
RS
1216 prev = f;
1217 }
1218 else if (EQ (minibuf, Qvisible))
1219 {
1220 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
1221 if (FRAME_VISIBLE_P (XFRAME (f)))
1222 prev = f;
1223 }
1224 else if (XFASTINT (minibuf) == 0)
1225 {
1226 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
1227 if (FRAME_VISIBLE_P (XFRAME (f))
1228 || FRAME_ICONIFIED_P (XFRAME (f)))
1229 prev = f;
1230 }
1231 else
a9986780
RS
1232 prev = f;
1233 }
f9898cc6 1234 }
d06a8a56
JB
1235
1236 /* We've scanned the entire list. */
1237 if (NILP (prev))
1238 /* We went through the whole frame list without finding a single
1239 acceptable frame. Return the original frame. */
1240 return frame;
1241 else
1242 /* There were no acceptable frames in the list before FRAME; otherwise,
1243 we would have returned directly from the loop. Since PREV is the last
1244 acceptable frame in the list, return it. */
1245 return prev;
dc6f92b8
JB
1246}
1247
ef2c57ac 1248
ff11dfa1 1249DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
14ff1ee0
PJ
1250 doc: /* Return the next frame in the frame list after FRAME.
1251It considers only frames on the same terminal as FRAME.
1252By default, skip minibuffer-only frames.
1253If omitted, FRAME defaults to the selected frame.
1254If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1255If MINIFRAME is a window, include only its own frame
1256and any frame now using that window as the minibuffer.
1257If MINIFRAME is `visible', include all visible frames.
1258If MINIFRAME is 0, include all visible and iconified frames.
1259Otherwise, include all frames. */)
1260 (frame, miniframe)
8693ca83 1261 Lisp_Object frame, miniframe;
dc6f92b8 1262{
ff11dfa1 1263 if (NILP (frame))
8d2666fe 1264 frame = selected_frame;
177c0ea7 1265
b7826503 1266 CHECK_LIVE_FRAME (frame);
ff11dfa1 1267 return next_frame (frame, miniframe);
dc6f92b8 1268}
dbc4e1c1 1269
ef2c57ac 1270DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
14ff1ee0
PJ
1271 doc: /* Return the previous frame in the frame list before FRAME.
1272It considers only frames on the same terminal as FRAME.
1273By default, skip minibuffer-only frames.
1274If omitted, FRAME defaults to the selected frame.
1275If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1276If MINIFRAME is a window, include only its own frame
1277and any frame now using that window as the minibuffer.
1278If MINIFRAME is `visible', include all visible frames.
1279If MINIFRAME is 0, include all visible and iconified frames.
1280Otherwise, include all frames. */)
1281 (frame, miniframe)
ef2c57ac
RM
1282 Lisp_Object frame, miniframe;
1283{
ef2c57ac 1284 if (NILP (frame))
8d2666fe 1285 frame = selected_frame;
b7826503 1286 CHECK_LIVE_FRAME (frame);
ef2c57ac
RM
1287 return prev_frame (frame, miniframe);
1288}
dc6f92b8 1289\f
808c0f20
RS
1290/* Return 1 if it is ok to delete frame F;
1291 0 if all frames aside from F are invisible.
1292 (Exception: if F is the terminal frame, and we are using X, return 1.) */
dc6f92b8 1293
d56b45eb 1294int
808c0f20
RS
1295other_visible_frames (f)
1296 FRAME_PTR f;
1297{
1298 /* We know the selected frame is visible,
1299 so if F is some other frame, it can't be the sole visible one. */
8d2666fe 1300 if (f == SELECTED_FRAME ())
c08c95c7
RS
1301 {
1302 Lisp_Object frames;
1303 int count = 0;
1304
1305 for (frames = Vframe_list;
1306 CONSP (frames);
7539e11f 1307 frames = XCDR (frames))
c08c95c7 1308 {
ab9f008d 1309 Lisp_Object this;
c08c95c7 1310
7539e11f 1311 this = XCAR (frames);
808c0f20
RS
1312 /* Verify that the frame's window still exists
1313 and we can still talk to it. And note any recent change
1314 in visibility. */
032d78fe
GV
1315#ifdef HAVE_WINDOW_SYSTEM
1316 if (FRAME_WINDOW_P (XFRAME (this)))
5e7b7c5b 1317 {
b0509a40 1318 x_sync (XFRAME (this));
5e7b7c5b
RS
1319 FRAME_SAMPLE_VISIBILITY (XFRAME (this));
1320 }
1321#endif
1322
c08c95c7
RS
1323 if (FRAME_VISIBLE_P (XFRAME (this))
1324 || FRAME_ICONIFIED_P (XFRAME (this))
1325 /* Allow deleting the terminal frame when at least
1326 one X frame exists! */
032d78fe 1327 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
c08c95c7
RS
1328 count++;
1329 }
808c0f20 1330 return count > 1;
c08c95c7 1331 }
808c0f20
RS
1332 return 1;
1333}
1334
ea161626
KL
1335/* Error handler for `delete-frame-functions'. */
1336static Lisp_Object
1337delete_frame_handler (Lisp_Object arg)
1338{
1339 add_to_log ("Error during `delete-frame': %s", arg, Qnil);
1340 return Qnil;
1341}
1342
808c0f20 1343DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
14ff1ee0
PJ
1344 doc: /* Delete FRAME, permanently eliminating it from use.
1345If omitted, FRAME defaults to the selected frame.
1346A frame may not be deleted if its minibuffer is used by other frames.
1347Normally, you may not delete a frame if all other frames are invisible,
1348but if the second optional argument FORCE is non-nil, you may do so.
1349
cd1d850f
JPW
1350This function runs `delete-frame-functions' before actually deleting the
1351frame, unless the frame is a tooltip.
1352The functions are run with one arg, the frame to be deleted. */)
14ff1ee0 1353 (frame, force)
808c0f20
RS
1354 Lisp_Object frame, force;
1355{
1356 struct frame *f;
8d2666fe 1357 struct frame *sf = SELECTED_FRAME ();
bedb9c0e
KL
1358 struct kboard *kb;
1359
99b92e64 1360 int minibuffer_selected;
808c0f20
RS
1361
1362 if (EQ (frame, Qnil))
1363 {
8d2666fe 1364 f = sf;
2d80a27a 1365 XSETFRAME (frame, f);
808c0f20
RS
1366 }
1367 else
1368 {
b7826503 1369 CHECK_FRAME (frame);
808c0f20
RS
1370 f = XFRAME (frame);
1371 }
1372
1373 if (! FRAME_LIVE_P (f))
1374 return Qnil;
1375
83a96b4d 1376 if (NILP (force) && !other_visible_frames (f)
e0f712ba 1377#ifdef MAC_OS8
83a96b4d
AC
1378 /* Terminal frame deleted before any other visible frames are
1379 created. */
d5db4077 1380 && strcmp (SDATA (f->name), "F1") != 0
83a96b4d
AC
1381#endif
1382 )
808c0f20 1383 error ("Attempt to delete the sole visible or iconified frame");
d5e7c279 1384
00c5fd51
RS
1385#if 0
1386 /* This is a nice idea, but x_connection_closed needs to be able
1387 to delete the last frame, if it is gone. */
7539e11f 1388 if (NILP (XCDR (Vframe_list)))
e9687ee8 1389 error ("Attempt to delete the only frame");
00c5fd51 1390#endif
e9687ee8 1391
ff11dfa1
JB
1392 /* Does this frame have a minibuffer, and is it the surrogate
1393 minibuffer for any other frame? */
fd0c2bd1 1394 if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
dc6f92b8 1395 {
ff11dfa1 1396 Lisp_Object frames;
1113d9db 1397
ff11dfa1
JB
1398 for (frames = Vframe_list;
1399 CONSP (frames);
7539e11f 1400 frames = XCDR (frames))
1113d9db 1401 {
7a8cc307 1402 Lisp_Object this;
7539e11f 1403 this = XCAR (frames);
1113d9db 1404
ff11dfa1
JB
1405 if (! EQ (this, frame)
1406 && EQ (frame,
7a8cc307
RS
1407 WINDOW_FRAME (XWINDOW
1408 (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
ff11dfa1 1409 error ("Attempt to delete a surrogate minibuffer frame");
1113d9db 1410 }
dc6f92b8
JB
1411 }
1412
cd1d850f
JPW
1413 /* Run `delete-frame-functions' unless frame is a tooltip. */
1414 if (!NILP (Vrun_hooks)
1415 && NILP (Fframe_parameter (frame, intern ("tooltip"))))
0e662342
GM
1416 {
1417 Lisp_Object args[2];
ea161626
KL
1418 struct gcpro gcpro1, gcpro2;
1419
1420 /* Don't let a rogue function in `delete-frame-functions'
1421 prevent the frame deletion. */
1422 GCPRO2 (args[0], args[1]);
cd1d850f 1423 args[0] = intern ("delete-frame-functions");
0e662342 1424 args[1] = frame;
ea161626
KL
1425 internal_condition_case_2 (Frun_hook_with_args, 2, args,
1426 Qt, delete_frame_handler);
1427 UNGCPRO;
0e662342
GM
1428 }
1429
b6660415
KL
1430 /* The hook may sometimes (indirectly) cause the frame to be deleted. */
1431 if (! FRAME_LIVE_P (f))
1432 return Qnil;
1433
99b92e64
RS
1434 minibuffer_selected = EQ (minibuf_window, selected_window);
1435
ff11dfa1 1436 /* Don't let the frame remain selected. */
8d2666fe 1437 if (f == sf)
06537cc8
RS
1438 {
1439 Lisp_Object tail, frame1;
1440
1441 /* Look for another visible frame on the same terminal. */
1442 frame1 = next_frame (frame, Qvisible);
1443
1444 /* If there is none, find *some* other frame. */
1445 if (NILP (frame1) || EQ (frame1, frame))
1446 {
1447 FOR_EACH_FRAME (tail, frame1)
1448 {
fca177d4 1449 if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
06537cc8
RS
1450 break;
1451 }
1452 }
1453
1e8324d9 1454 do_switch_frame (frame1, 0, 1);
79a65b7f 1455 sf = SELECTED_FRAME ();
06537cc8 1456 }
dc6f92b8 1457
ff11dfa1
JB
1458 /* Don't allow minibuf_window to remain on a deleted frame. */
1459 if (EQ (f->minibuffer_window, minibuf_window))
dc6f92b8 1460 {
8d2666fe 1461 Fset_window_buffer (sf->minibuffer_window,
5af5757b 1462 XWINDOW (minibuf_window)->buffer, Qnil);
8d2666fe 1463 minibuf_window = sf->minibuffer_window;
99b92e64
RS
1464
1465 /* If the dying minibuffer window was selected,
1466 select the new one. */
1467 if (minibuffer_selected)
f1321dc3 1468 Fselect_window (minibuf_window, Qnil);
dc6f92b8
JB
1469 }
1470
130adcb7
EZ
1471 /* Don't let echo_area_window to remain on a deleted frame. */
1472 if (EQ (f->minibuffer_window, echo_area_window))
1473 echo_area_window = sf->minibuffer_window;
1474
da8e8fc1
KL
1475 /* Don't allow other frames to refer to a deleted frame in their
1476 'environment parameter. */
1477 {
1478 Lisp_Object tail, frame1;
1479 Lisp_Object env = get_frame_param (XFRAME (frame), Qenvironment);
1480 FOR_EACH_FRAME (tail, frame1)
1481 {
1482 if (EQ (frame, frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
1483 continue;
1484 if (EQ (frame, get_frame_param (XFRAME (frame1), Qenvironment)))
1485 {
1486 store_frame_param (XFRAME (frame1), Qenvironment, env);
1487 if (!FRAMEP (env))
1488 env = frame1;
1489 }
1490 }
1491 }
1492
bb2a0a65
RS
1493 /* Clear any X selections for this frame. */
1494#ifdef HAVE_X_WINDOWS
1495 if (FRAME_X_P (f))
1496 x_clear_frame_selections (f);
1497#endif
f706a7b2
YM
1498#ifdef MAC_OS
1499 if (FRAME_MAC_P (f))
1500 x_clear_frame_selections (f);
1501#endif
bb2a0a65 1502
177c0ea7
JB
1503 /* Free glyphs.
1504 This function must be called before the window tree of the
18082e2d
GM
1505 frame is deleted because windows contain dynamically allocated
1506 memory. */
1507 free_glyphs (f);
1508
4a88b3b0
JB
1509 /* Mark all the windows that used to be on FRAME as deleted, and then
1510 remove the reference to them. */
1511 delete_all_subwindows (XWINDOW (f->root_window));
1512 f->root_window = Qnil;
1513
ff11dfa1 1514 Vframe_list = Fdelq (frame, Vframe_list);
a42e9724 1515 FRAME_SET_VISIBLE (f, 0);
dc6f92b8 1516
60a8823e 1517 if (f->namebuf)
18082e2d 1518 xfree (f->namebuf);
96f09305
JD
1519 if (f->decode_mode_spec_buffer)
1520 xfree (f->decode_mode_spec_buffer);
d2bee99e 1521 if (FRAME_INSERT_COST (f))
18082e2d 1522 xfree (FRAME_INSERT_COST (f));
d2bee99e 1523 if (FRAME_DELETEN_COST (f))
18082e2d 1524 xfree (FRAME_DELETEN_COST (f));
d2bee99e 1525 if (FRAME_INSERTN_COST (f))
18082e2d 1526 xfree (FRAME_INSERTN_COST (f));
d2bee99e 1527 if (FRAME_DELETE_COST (f))
18082e2d 1528 xfree (FRAME_DELETE_COST (f));
25734faf 1529 if (FRAME_MESSAGE_BUF (f))
18082e2d 1530 xfree (FRAME_MESSAGE_BUF (f));
d2bee99e 1531
8678b9cc 1532 /* Since some events are handled at the interrupt level, we may get
6ed8eeff 1533 an event for f at any time; if we zero out the frame's terminal
8678b9cc 1534 now, then we may trip up the event-handling code. Instead, we'll
6ed8eeff
KL
1535 promise that the terminal of the frame must be valid until we
1536 have called the window-system-dependent frame destruction
1537 routine. */
dbc4e1c1 1538
6ed8eeff
KL
1539 if (FRAME_TERMINAL (f)->delete_frame_hook)
1540 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
bedb9c0e 1541
428a555e 1542 {
6ed8eeff 1543 struct terminal *terminal = FRAME_TERMINAL (f);
428a555e 1544 f->output_data.nothing = 0;
6ed8eeff 1545 f->terminal = 0; /* Now the frame is dead. */
428a555e 1546
6ed8eeff 1547 /* If needed, delete the terminal that this frame was on.
bedb9c0e 1548 (This must be done after the frame is killed.) */
6ed8eeff
KL
1549 terminal->reference_count--;
1550 if (terminal->reference_count == 0)
bedb9c0e
KL
1551 {
1552 kb = NULL;
6ed8eeff
KL
1553 if (terminal->delete_terminal_hook)
1554 (*terminal->delete_terminal_hook) (terminal);
bedb9c0e 1555 else
6ed8eeff 1556 delete_terminal (terminal);
bedb9c0e 1557 }
7e166218 1558#ifdef MULTI_KBOARD
bedb9c0e 1559 else
6ed8eeff 1560 kb = terminal->kboard;
7e166218 1561#endif
428a555e 1562 }
8678b9cc 1563
ff11dfa1 1564 /* If we've deleted the last_nonminibuf_frame, then try to find
d5e7c279 1565 another one. */
ff11dfa1 1566 if (f == last_nonminibuf_frame)
d5e7c279 1567 {
ff11dfa1 1568 Lisp_Object frames;
1113d9db 1569
ff11dfa1 1570 last_nonminibuf_frame = 0;
d5e7c279 1571
ff11dfa1
JB
1572 for (frames = Vframe_list;
1573 CONSP (frames);
7539e11f 1574 frames = XCDR (frames))
d5e7c279 1575 {
7539e11f 1576 f = XFRAME (XCAR (frames));
ff11dfa1 1577 if (!FRAME_MINIBUF_ONLY_P (f))
d5e7c279 1578 {
ff11dfa1 1579 last_nonminibuf_frame = f;
d5e7c279
JB
1580 break;
1581 }
1582 }
1583 }
dc6f92b8 1584
8ceb7434
RS
1585 /* If there's no other frame on the same kboard, get out of
1586 single-kboard state if we're in it for this kboard. */
bedb9c0e
KL
1587 if (kb != NULL)
1588 {
1589 Lisp_Object frames;
1590 /* Some frame we found on the same kboard, or nil if there are none. */
1591 Lisp_Object frame_on_same_kboard;
8ceb7434 1592
bedb9c0e 1593 frame_on_same_kboard = Qnil;
8ceb7434 1594
bedb9c0e
KL
1595 for (frames = Vframe_list;
1596 CONSP (frames);
1597 frames = XCDR (frames))
1598 {
1599 Lisp_Object this;
1600 struct frame *f1;
8ceb7434 1601
bedb9c0e
KL
1602 this = XCAR (frames);
1603 if (!FRAMEP (this))
1604 abort ();
1605 f1 = XFRAME (this);
8ceb7434 1606
bedb9c0e
KL
1607 if (kb == FRAME_KBOARD (f1))
1608 frame_on_same_kboard = this;
1609 }
8ceb7434 1610
bedb9c0e
KL
1611 if (NILP (frame_on_same_kboard))
1612 not_single_kboard_state (kb);
1613 }
8ceb7434
RS
1614
1615
c4c6d073
KH
1616 /* If we've deleted this keyboard's default_minibuffer_frame, try to
1617 find another one. Prefer minibuffer-only frames, but also notice
1618 frames with other windows. */
bedb9c0e 1619 if (kb != NULL && EQ (frame, kb->Vdefault_minibuffer_frame))
1113d9db 1620 {
ff11dfa1 1621 Lisp_Object frames;
1113d9db 1622
ff11dfa1 1623 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
ab9f008d 1624 Lisp_Object frame_with_minibuf;
32fda9ba
RS
1625 /* Some frame we found on the same kboard, or nil if there are none. */
1626 Lisp_Object frame_on_same_kboard;
1113d9db 1627
32fda9ba 1628 frame_on_same_kboard = Qnil;
ab9f008d 1629 frame_with_minibuf = Qnil;
32fda9ba 1630
ff11dfa1
JB
1631 for (frames = Vframe_list;
1632 CONSP (frames);
7539e11f 1633 frames = XCDR (frames))
1113d9db 1634 {
ab9f008d 1635 Lisp_Object this;
c4c6d073 1636 struct frame *f1;
1113d9db 1637
7539e11f 1638 this = XCAR (frames);
e35d291d 1639 if (!FRAMEP (this))
1113d9db 1640 abort ();
c4c6d073 1641 f1 = XFRAME (this);
1113d9db 1642
c4c6d073
KH
1643 /* Consider only frames on the same kboard
1644 and only those with minibuffers. */
bedb9c0e 1645 if (kb == FRAME_KBOARD (f1)
c4c6d073 1646 && FRAME_HAS_MINIBUF_P (f1))
1113d9db 1647 {
ff11dfa1 1648 frame_with_minibuf = this;
c4c6d073 1649 if (FRAME_MINIBUF_ONLY_P (f1))
1113d9db
JB
1650 break;
1651 }
32fda9ba 1652
bedb9c0e 1653 if (kb == FRAME_KBOARD (f1))
32fda9ba 1654 frame_on_same_kboard = this;
1113d9db
JB
1655 }
1656
32fda9ba
RS
1657 if (!NILP (frame_on_same_kboard))
1658 {
1659 /* We know that there must be some frame with a minibuffer out
1660 there. If this were not true, all of the frames present
1661 would have to be minibufferless, which implies that at some
1662 point their minibuffer frames must have been deleted, but
1663 that is prohibited at the top; you can't delete surrogate
1664 minibuffer frames. */
1665 if (NILP (frame_with_minibuf))
1666 abort ();
1113d9db 1667
bedb9c0e 1668 kb->Vdefault_minibuffer_frame = frame_with_minibuf;
32fda9ba
RS
1669 }
1670 else
1671 /* No frames left on this kboard--say no minibuffer either. */
bedb9c0e 1672 kb->Vdefault_minibuffer_frame = Qnil;
1113d9db
JB
1673 }
1674
e681c92a
RS
1675 /* Cause frame titles to update--necessary if we now have just one frame. */
1676 update_mode_lines = 1;
1677
dc6f92b8
JB
1678 return Qnil;
1679}
1680\f
1681/* Return mouse position in character cell units. */
1682
f9898cc6 1683DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
14ff1ee0
PJ
1684 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1685The position is given in character cells, where (0, 0) is the
d0cd961e
EZ
1686upper-left corner of the frame, X is the horizontal offset, and Y is
1687the vertical offset.
14ff1ee0
PJ
1688If Emacs is running on a mouseless terminal or hasn't been programmed
1689to read the mouse position, it returns the selected frame for FRAME
1690and nil for X and Y.
1691If `mouse-position-function' is non-nil, `mouse-position' calls it,
1692passing the normal return value to that function as an argument,
1693and returns whatever that function returns. */)
1694 ()
dc6f92b8 1695{
ff11dfa1 1696 FRAME_PTR f;
dbc4e1c1 1697 Lisp_Object lispy_dummy;
fd2777e0 1698 enum scroll_bar_part party_dummy;
beb0bc36 1699 Lisp_Object x, y, retval;
5384466a 1700 int col, row;
dbc4e1c1 1701 unsigned long long_dummy;
cb2255b3 1702 struct gcpro gcpro1;
dc6f92b8 1703
8d2666fe 1704 f = SELECTED_FRAME ();
c5074d8c
RS
1705 x = y = Qnil;
1706
f443c170 1707#ifdef HAVE_MOUSE
c5074d8c 1708 /* It's okay for the hook to refrain from storing anything. */
6ed8eeff
KL
1709 if (FRAME_TERMINAL (f)->mouse_position_hook)
1710 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1711 &lispy_dummy, &party_dummy,
1712 &x, &y,
1713 &long_dummy);
76db7eb4
KH
1714 if (! NILP (x))
1715 {
1716 col = XINT (x);
1717 row = XINT (y);
8126c3b4 1718 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
76db7eb4
KH
1719 XSETINT (x, col);
1720 XSETINT (y, row);
1721 }
f443c170 1722#endif
2d80a27a 1723 XSETFRAME (lispy_dummy, f);
beb0bc36 1724 retval = Fcons (lispy_dummy, Fcons (x, y));
cb2255b3 1725 GCPRO1 (retval);
beb0bc36 1726 if (!NILP (Vmouse_position_function))
cb2255b3
GM
1727 retval = call1 (Vmouse_position_function, retval);
1728 RETURN_UNGCPRO (retval);
dc6f92b8
JB
1729}
1730
152e6c70
RS
1731DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
1732 Smouse_pixel_position, 0, 0, 0,
14ff1ee0
PJ
1733 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1734The position is given in pixel units, where (0, 0) is the
d0cd961e
EZ
1735upper-left corner of the frame, X is the horizontal offset, and Y is
1736the vertical offset.
14ff1ee0
PJ
1737If Emacs is running on a mouseless terminal or hasn't been programmed
1738to read the mouse position, it returns the selected frame for FRAME
1739and nil for X and Y. */)
1740 ()
152e6c70
RS
1741{
1742 FRAME_PTR f;
1743 Lisp_Object lispy_dummy;
1744 enum scroll_bar_part party_dummy;
1745 Lisp_Object x, y;
152e6c70
RS
1746 unsigned long long_dummy;
1747
8d2666fe 1748 f = SELECTED_FRAME ();
152e6c70
RS
1749 x = y = Qnil;
1750
0c5c1cf7 1751#ifdef HAVE_MOUSE
152e6c70 1752 /* It's okay for the hook to refrain from storing anything. */
6ed8eeff
KL
1753 if (FRAME_TERMINAL (f)->mouse_position_hook)
1754 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1755 &lispy_dummy, &party_dummy,
1756 &x, &y,
1757 &long_dummy);
0c5c1cf7 1758#endif
2d80a27a 1759 XSETFRAME (lispy_dummy, f);
152e6c70
RS
1760 return Fcons (lispy_dummy, Fcons (x, y));
1761}
1762
dc6f92b8 1763DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
14ff1ee0
PJ
1764 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
1765Coordinates are relative to the frame, not a window,
1766so the coordinates of the top left character in the frame
1767may be nonzero due to left-hand scroll bars or the menu bar.
1768
d0cd961e
EZ
1769The position is given in character cells, where (0, 0) is the
1770upper-left corner of the frame, X is the horizontal offset, and Y is
1771the vertical offset.
1772
14ff1ee0
PJ
1773This function is a no-op for an X frame that is not visible.
1774If you have just created a frame, you must wait for it to become visible
1775before calling this function on it, like this.
1776 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
ff11dfa1
JB
1777 (frame, x, y)
1778 Lisp_Object frame, x, y;
dc6f92b8 1779{
b7826503
PJ
1780 CHECK_LIVE_FRAME (frame);
1781 CHECK_NUMBER (x);
1782 CHECK_NUMBER (y);
dc6f92b8 1783
dbc4e1c1 1784 /* I think this should be done with a hook. */
032d78fe
GV
1785#ifdef HAVE_WINDOW_SYSTEM
1786 if (FRAME_WINDOW_P (XFRAME (frame)))
d19be8a9 1787 /* Warping the mouse will cause enternotify and focus events. */
d4d76014 1788 x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
bb221971 1789#else
be625e00 1790#if defined (MSDOS) && defined (HAVE_MOUSE)
bb221971
RS
1791 if (FRAME_MSDOS_P (XFRAME (frame)))
1792 {
20dc6fbb 1793 Fselect_frame (frame);
bb221971
RS
1794 mouse_moveto (XINT (x), XINT (y));
1795 }
1796#endif
dc6f92b8
JB
1797#endif
1798
1799 return Qnil;
1800}
152e6c70
RS
1801
1802DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
1803 Sset_mouse_pixel_position, 3, 3, 0,
14ff1ee0 1804 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
d0cd961e
EZ
1805The position is given in pixels, where (0, 0) is the upper-left corner
1806of the frame, X is the horizontal offset, and Y is the vertical offset.
1807
14ff1ee0
PJ
1808Note, this is a no-op for an X frame that is not visible.
1809If you have just created a frame, you must wait for it to become visible
1810before calling this function on it, like this.
1811 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
152e6c70
RS
1812 (frame, x, y)
1813 Lisp_Object frame, x, y;
1814{
b7826503
PJ
1815 CHECK_LIVE_FRAME (frame);
1816 CHECK_NUMBER (x);
1817 CHECK_NUMBER (y);
152e6c70
RS
1818
1819 /* I think this should be done with a hook. */
032d78fe
GV
1820#ifdef HAVE_WINDOW_SYSTEM
1821 if (FRAME_WINDOW_P (XFRAME (frame)))
d19be8a9 1822 /* Warping the mouse will cause enternotify and focus events. */
d4d76014 1823 x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
bb221971 1824#else
be625e00 1825#if defined (MSDOS) && defined (HAVE_MOUSE)
bb221971
RS
1826 if (FRAME_MSDOS_P (XFRAME (frame)))
1827 {
20dc6fbb 1828 Fselect_frame (frame);
bb221971
RS
1829 mouse_moveto (XINT (x), XINT (y));
1830 }
1831#endif
152e6c70
RS
1832#endif
1833
1834 return Qnil;
1835}
dc6f92b8 1836\f
98ce1622
RS
1837static void make_frame_visible_1 P_ ((Lisp_Object));
1838
ff11dfa1 1839DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
fc25d15d 1840 0, 1, "",
14ff1ee0
PJ
1841 doc: /* Make the frame FRAME visible (assuming it is an X window).
1842If omitted, FRAME defaults to the currently selected frame. */)
1843 (frame)
ff11dfa1 1844 Lisp_Object frame;
dc6f92b8 1845{
1aa66088 1846 if (NILP (frame))
8d2666fe 1847 frame = selected_frame;
1aa66088 1848
b7826503 1849 CHECK_LIVE_FRAME (frame);
dc6f92b8 1850
dbc4e1c1 1851 /* I think this should be done with a hook. */
032d78fe
GV
1852#ifdef HAVE_WINDOW_SYSTEM
1853 if (FRAME_WINDOW_P (XFRAME (frame)))
02ff9dd5
RS
1854 {
1855 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1856 x_make_frame_visible (XFRAME (frame));
1857 }
fd0c2bd1 1858#endif
dc6f92b8 1859
98ce1622
RS
1860 make_frame_visible_1 (XFRAME (frame)->root_window);
1861
d19be8a9 1862 /* Make menu bar update for the Buffers and Frames menus. */
565620a5
RS
1863 windows_or_buffers_changed++;
1864
ff11dfa1 1865 return frame;
dc6f92b8
JB
1866}
1867
98ce1622
RS
1868/* Update the display_time slot of the buffers shown in WINDOW
1869 and all its descendents. */
1870
1871static void
1872make_frame_visible_1 (window)
1873 Lisp_Object window;
1874{
1875 struct window *w;
1876
1877 for (;!NILP (window); window = w->next)
1878 {
1879 w = XWINDOW (window);
1880
1881 if (!NILP (w->buffer))
1882 XBUFFER (w->buffer)->display_time = Fcurrent_time ();
1883
1884 if (!NILP (w->vchild))
1885 make_frame_visible_1 (w->vchild);
1886 if (!NILP (w->hchild))
1887 make_frame_visible_1 (w->hchild);
1888 }
1889}
1890
ff11dfa1 1891DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
808c0f20 1892 0, 2, "",
14ff1ee0
PJ
1893 doc: /* Make the frame FRAME invisible (assuming it is an X window).
1894If omitted, FRAME defaults to the currently selected frame.
1895Normally you may not make FRAME invisible if all other frames are invisible,
1896but if the second optional argument FORCE is non-nil, you may do so. */)
808c0f20
RS
1897 (frame, force)
1898 Lisp_Object frame, force;
dc6f92b8 1899{
1aa66088 1900 if (NILP (frame))
8d2666fe 1901 frame = selected_frame;
1aa66088 1902
b7826503 1903 CHECK_LIVE_FRAME (frame);
dc6f92b8 1904
808c0f20
RS
1905 if (NILP (force) && !other_visible_frames (XFRAME (frame)))
1906 error ("Attempt to make invisible the sole visible or iconified frame");
1907
3d378fdf 1908#if 0 /* This isn't logically necessary, and it can do GC. */
9c394f17 1909 /* Don't let the frame remain selected. */
8d2666fe 1910 if (EQ (frame, selected_frame))
1e8324d9 1911 do_switch_frame (next_frame (frame, Qt), 0, 0)
3d378fdf 1912#endif
9c394f17
RS
1913
1914 /* Don't allow minibuf_window to remain on a deleted frame. */
1915 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
1916 {
8d2666fe
GM
1917 struct frame *sf = XFRAME (selected_frame);
1918 Fset_window_buffer (sf->minibuffer_window,
5af5757b 1919 XWINDOW (minibuf_window)->buffer, Qnil);
8d2666fe 1920 minibuf_window = sf->minibuffer_window;
9c394f17
RS
1921 }
1922
dbc4e1c1 1923 /* I think this should be done with a hook. */
032d78fe
GV
1924#ifdef HAVE_WINDOW_SYSTEM
1925 if (FRAME_WINDOW_P (XFRAME (frame)))
ff11dfa1 1926 x_make_frame_invisible (XFRAME (frame));
fd0c2bd1 1927#endif
dc6f92b8 1928
d19be8a9 1929 /* Make menu bar update for the Buffers and Frames menus. */
565620a5
RS
1930 windows_or_buffers_changed++;
1931
dc6f92b8
JB
1932 return Qnil;
1933}
1934
ff11dfa1 1935DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
1aa66088 1936 0, 1, "",
14ff1ee0
PJ
1937 doc: /* Make the frame FRAME into an icon.
1938If omitted, FRAME defaults to the currently selected frame. */)
ff11dfa1
JB
1939 (frame)
1940 Lisp_Object frame;
dc6f92b8 1941{
1aa66088 1942 if (NILP (frame))
8d2666fe 1943 frame = selected_frame;
177c0ea7 1944
b7826503 1945 CHECK_LIVE_FRAME (frame);
dc6f92b8 1946
3d378fdf 1947#if 0 /* This isn't logically necessary, and it can do GC. */
9c394f17 1948 /* Don't let the frame remain selected. */
8d2666fe 1949 if (EQ (frame, selected_frame))
20dc6fbb 1950 Fhandle_switch_frame (next_frame (frame, Qt));
3d378fdf 1951#endif
9c394f17
RS
1952
1953 /* Don't allow minibuf_window to remain on a deleted frame. */
1954 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
1955 {
8d2666fe
GM
1956 struct frame *sf = XFRAME (selected_frame);
1957 Fset_window_buffer (sf->minibuffer_window,
5af5757b 1958 XWINDOW (minibuf_window)->buffer, Qnil);
8d2666fe 1959 minibuf_window = sf->minibuffer_window;
9c394f17
RS
1960 }
1961
dbc4e1c1 1962 /* I think this should be done with a hook. */
032d78fe
GV
1963#ifdef HAVE_WINDOW_SYSTEM
1964 if (FRAME_WINDOW_P (XFRAME (frame)))
ff11dfa1 1965 x_iconify_frame (XFRAME (frame));
fd0c2bd1 1966#endif
dc6f92b8 1967
d19be8a9 1968 /* Make menu bar update for the Buffers and Frames menus. */
565620a5
RS
1969 windows_or_buffers_changed++;
1970
dc6f92b8
JB
1971 return Qnil;
1972}
1973
ff11dfa1 1974DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
dc6f92b8 1975 1, 1, 0,
14ff1ee0
PJ
1976 doc: /* Return t if FRAME is now \"visible\" (actually in use for display).
1977A frame that is not \"visible\" is not updated and, if it works through
1978a window system, it may not show at all.
e4ed805e
LT
1979Return the symbol `icon' if frame is visible only as an icon.
1980
1981On a text-only terminal, all frames are considered visible, whether
1982they are currently being displayed or not, and this function returns t
1983for all frames. */)
14ff1ee0 1984 (frame)
ff11dfa1 1985 Lisp_Object frame;
dc6f92b8 1986{
b7826503 1987 CHECK_LIVE_FRAME (frame);
dc6f92b8 1988
5c044f55
RS
1989 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1990
a42e9724 1991 if (FRAME_VISIBLE_P (XFRAME (frame)))
dc6f92b8 1992 return Qt;
a42e9724 1993 if (FRAME_ICONIFIED_P (XFRAME (frame)))
fd0c2bd1 1994 return Qicon;
dc6f92b8
JB
1995 return Qnil;
1996}
1997
ff11dfa1 1998DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
dc6f92b8 1999 0, 0, 0,
14ff1ee0 2000 doc: /* Return a list of all frames now \"visible\" (being updated). */)
dc6f92b8
JB
2001 ()
2002{
ff11dfa1
JB
2003 Lisp_Object tail, frame;
2004 struct frame *f;
dc6f92b8
JB
2005 Lisp_Object value;
2006
2007 value = Qnil;
7539e11f 2008 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
dc6f92b8 2009 {
7539e11f 2010 frame = XCAR (tail);
e35d291d 2011 if (!FRAMEP (frame))
dc6f92b8 2012 continue;
ff11dfa1 2013 f = XFRAME (frame);
a42e9724 2014 if (FRAME_VISIBLE_P (f))
ff11dfa1 2015 value = Fcons (frame, value);
dc6f92b8
JB
2016 }
2017 return value;
2018}
d5e7c279
JB
2019
2020
e518d5e1 2021DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
14ff1ee0 2022 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
e4ed805e 2023If FRAME is invisible or iconified, make it visible.
14ff1ee0
PJ
2024If you don't specify a frame, the selected frame is used.
2025If Emacs is displaying on an ordinary terminal or some other device which
2026doesn't support multiple overlapping frames, this function does nothing. */)
2027 (frame)
dbc4e1c1
JB
2028 Lisp_Object frame;
2029{
428a555e 2030 struct frame *f;
828ac693 2031 if (NILP (frame))
8d2666fe 2032 frame = selected_frame;
828ac693 2033
b7826503 2034 CHECK_LIVE_FRAME (frame);
8a981af5 2035
428a555e
KL
2036 f = XFRAME (frame);
2037
8a981af5
RS
2038 /* Do like the documentation says. */
2039 Fmake_frame_visible (frame);
2040
6ed8eeff
KL
2041 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2042 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
dbc4e1c1
JB
2043
2044 return Qnil;
2045}
2046
b49f5578 2047/* Should we have a corresponding function called Flower_Power? */
e518d5e1 2048DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
14ff1ee0
PJ
2049 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2050If you don't specify a frame, the selected frame is used.
2051If Emacs is displaying on an ordinary terminal or some other device which
2052doesn't support multiple overlapping frames, this function does nothing. */)
2053 (frame)
dbc4e1c1
JB
2054 Lisp_Object frame;
2055{
428a555e
KL
2056 struct frame *f;
2057
828ac693 2058 if (NILP (frame))
8d2666fe 2059 frame = selected_frame;
828ac693 2060
b7826503 2061 CHECK_LIVE_FRAME (frame);
177c0ea7 2062
428a555e
KL
2063 f = XFRAME (frame);
2064
6ed8eeff
KL
2065 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2066 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
dbc4e1c1
JB
2067
2068 return Qnil;
2069}
2070
d5e7c279 2071\f
ff11dfa1 2072DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
d5e7c279 2073 1, 2, 0,
14ff1ee0
PJ
2074 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2075In other words, switch-frame events caused by events in FRAME will
2076request a switch to FOCUS-FRAME, and `last-event-frame' will be
2077FOCUS-FRAME after reading an event typed at FRAME.
2078
2079If FOCUS-FRAME is omitted or nil, any existing redirection is
2080cancelled, and the frame again receives its own keystrokes.
2081
2082Focus redirection is useful for temporarily redirecting keystrokes to
2083a surrogate minibuffer frame when a frame doesn't have its own
2084minibuffer window.
2085
66a9dbbe 2086A frame's focus redirection can be changed by `select-frame'. If frame
14ff1ee0
PJ
2087FOO is selected, and then a different frame BAR is selected, any
2088frames redirecting their focus to FOO are shifted to redirect their
2089focus to BAR. This allows focus redirection to work properly when the
2090user switches from one frame to another using `select-window'.
2091
2092This means that a frame whose focus is redirected to itself is treated
2093differently from a frame whose focus is redirected to nil; the former
66a9dbbe 2094is affected by `select-frame', while the latter is not.
14ff1ee0
PJ
2095
2096The redirection lasts until `redirect-frame-focus' is called to change it. */)
2097 (frame, focus_frame)
2098 Lisp_Object frame, focus_frame;
d5e7c279 2099{
428a555e
KL
2100 struct frame *f;
2101
13144095
JB
2102 /* Note that we don't check for a live frame here. It's reasonable
2103 to redirect the focus of a frame you're about to delete, if you
2104 know what other frame should receive those keystrokes. */
b7826503 2105 CHECK_FRAME (frame);
f9898cc6 2106
a42e9724 2107 if (! NILP (focus_frame))
b7826503 2108 CHECK_LIVE_FRAME (focus_frame);
d5e7c279 2109
428a555e
KL
2110 f = XFRAME (frame);
2111
2112 f->focus_frame = focus_frame;
d5e7c279 2113
6ed8eeff
KL
2114 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2115 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
177c0ea7 2116
d5e7c279
JB
2117 return Qnil;
2118}
2119
2120
ff11dfa1 2121DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
14ff1ee0
PJ
2122 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2123This returns nil if FRAME's focus is not redirected.
2124See `redirect-frame-focus'. */)
2125 (frame)
2126 Lisp_Object frame;
d5e7c279 2127{
b7826503 2128 CHECK_LIVE_FRAME (frame);
a42e9724 2129
ff11dfa1 2130 return FRAME_FOCUS_FRAME (XFRAME (frame));
d5e7c279
JB
2131}
2132
2133
dc6f92b8 2134\f
329ca574
RS
2135/* Return the value of frame parameter PROP in frame FRAME. */
2136
dc6f92b8 2137Lisp_Object
ff11dfa1
JB
2138get_frame_param (frame, prop)
2139 register struct frame *frame;
dc6f92b8
JB
2140 Lisp_Object prop;
2141{
2142 register Lisp_Object tem;
2143
ff11dfa1 2144 tem = Fassq (prop, frame->param_alist);
dc6f92b8
JB
2145 if (EQ (tem, Qnil))
2146 return tem;
2147 return Fcdr (tem);
2148}
2149
329ca574
RS
2150/* Return the buffer-predicate of the selected frame. */
2151
2152Lisp_Object
98ce1622
RS
2153frame_buffer_predicate (frame)
2154 Lisp_Object frame;
329ca574 2155{
98ce1622 2156 return XFRAME (frame)->buffer_predicate;
329ca574
RS
2157}
2158
fa54c6ae
RS
2159/* Return the buffer-list of the selected frame. */
2160
2161Lisp_Object
98ce1622
RS
2162frame_buffer_list (frame)
2163 Lisp_Object frame;
fa54c6ae 2164{
98ce1622 2165 return XFRAME (frame)->buffer_list;
fa54c6ae
RS
2166}
2167
2168/* Set the buffer-list of the selected frame. */
2169
2170void
98ce1622
RS
2171set_frame_buffer_list (frame, list)
2172 Lisp_Object frame, list;
fa54c6ae 2173{
98ce1622 2174 XFRAME (frame)->buffer_list = list;
fa54c6ae
RS
2175}
2176
a18b8cb5 2177/* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
fa54c6ae
RS
2178
2179void
2180frames_discard_buffer (buffer)
2181 Lisp_Object buffer;
2182{
2183 Lisp_Object frame, tail;
2184
2185 FOR_EACH_FRAME (tail, frame)
2186 {
2187 XFRAME (frame)->buffer_list
2188 = Fdelq (buffer, XFRAME (frame)->buffer_list);
a18b8cb5
KL
2189 XFRAME (frame)->buried_buffer_list
2190 = Fdelq (buffer, XFRAME (frame)->buried_buffer_list);
fa54c6ae
RS
2191 }
2192}
2193
329ca574
RS
2194/* Modify the alist in *ALISTPTR to associate PROP with VAL.
2195 If the alist already has an element for PROP, we change it. */
2196
dc6f92b8 2197void
fd0c2bd1 2198store_in_alist (alistptr, prop, val)
dc6f92b8 2199 Lisp_Object *alistptr, val;
fd0c2bd1 2200 Lisp_Object prop;
dc6f92b8
JB
2201{
2202 register Lisp_Object tem;
dc6f92b8 2203
dc6f92b8
JB
2204 tem = Fassq (prop, *alistptr);
2205 if (EQ (tem, Qnil))
2206 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2207 else
2208 Fsetcdr (tem, val);
2209}
2210
e5317d61
EZ
2211static int
2212frame_name_fnn_p (str, len)
2213 char *str;
2214 int len;
2215{
2216 if (len > 1 && str[0] == 'F')
2217 {
2218 char *end_ptr;
e5317d61 2219
48970f2f
EZ
2220 strtol (str + 1, &end_ptr, 10);
2221
e5317d61
EZ
2222 if (end_ptr == str + len)
2223 return 1;
2224 }
2225 return 0;
2226}
2227
2228/* Set the name of the terminal frame. Also used by MSDOS frames.
2229 Modeled after x_set_name which is used for WINDOW frames. */
2230
66a9dbbe 2231static void
e5317d61
EZ
2232set_term_frame_name (f, name)
2233 struct frame *f;
2234 Lisp_Object name;
2235{
2236 f->explicit_name = ! NILP (name);
2237
2238 /* If NAME is nil, set the name to F<num>. */
2239 if (NILP (name))
2240 {
2241 char namebuf[20];
2242
2243 /* Check for no change needed in this very common case
2244 before we do any consing. */
d5db4077
KR
2245 if (frame_name_fnn_p (SDATA (f->name),
2246 SBYTES (f->name)))
e5317d61
EZ
2247 return;
2248
6ed8eeff
KL
2249 tty_frame_count++;
2250 sprintf (namebuf, "F%d", tty_frame_count);
e5317d61
EZ
2251 name = build_string (namebuf);
2252 }
2253 else
2254 {
b7826503 2255 CHECK_STRING (name);
e5317d61
EZ
2256
2257 /* Don't change the name if it's already NAME. */
2258 if (! NILP (Fstring_equal (name, f->name)))
2259 return;
2260
2261 /* Don't allow the user to set the frame name to F<num>, so it
2262 doesn't clash with the names we generate for terminal frames. */
d5db4077 2263 if (frame_name_fnn_p (SDATA (name), SBYTES (name)))
e5317d61
EZ
2264 error ("Frame names of the form F<num> are usurped by Emacs");
2265 }
2266
2267 f->name = name;
2268 update_mode_lines = 1;
2269}
2270
dc6f92b8 2271void
ff11dfa1
JB
2272store_frame_param (f, prop, val)
2273 struct frame *f;
dc6f92b8
JB
2274 Lisp_Object prop, val;
2275{
7eb63b72 2276 register Lisp_Object old_alist_elt;
dc6f92b8 2277
a18b8cb5
KL
2278 /* The buffer-list parameters are stored in a special place and not
2279 in the alist. */
fa54c6ae
RS
2280 if (EQ (prop, Qbuffer_list))
2281 {
2282 f->buffer_list = val;
2283 return;
2284 }
a18b8cb5
KL
2285 if (EQ (prop, Qburied_buffer_list))
2286 {
2287 f->buried_buffer_list = val;
2288 return;
2289 }
fa54c6ae 2290
7eb63b72
GM
2291 /* If PROP is a symbol which is supposed to have frame-local values,
2292 and it is set up based on this frame, switch to the global
2293 binding. That way, we can create or alter the frame-local binding
2294 without messing up the symbol's status. */
2295 if (SYMBOLP (prop))
2296 {
2297 Lisp_Object valcontents;
f5c1dd0d 2298 valcontents = SYMBOL_VALUE (prop);
7eb63b72
GM
2299 if ((BUFFER_LOCAL_VALUEP (valcontents)
2300 || SOME_BUFFER_LOCAL_VALUEP (valcontents))
2301 && XBUFFER_LOCAL_VALUE (valcontents)->check_frame
486420a9 2302 && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame
7eb63b72
GM
2303 && XFRAME (XBUFFER_LOCAL_VALUE (valcontents)->frame) == f)
2304 swap_in_global_binding (prop);
2305 }
2306
94674d18
EZ
2307#ifndef WINDOWSNT
2308 /* The tty color mode needs to be set before the frame's parameter
2309 alist is updated with the new value, because set_tty_color_mode
2310 wants to look at the old mode. */
2311 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode))
2312 set_tty_color_mode (f, val);
2313#endif
2314
7eb63b72
GM
2315 /* Update the frame parameter alist. */
2316 old_alist_elt = Fassq (prop, f->param_alist);
2317 if (EQ (old_alist_elt, Qnil))
ff11dfa1 2318 f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
dc6f92b8 2319 else
7eb63b72 2320 Fsetcdr (old_alist_elt, val);
bc93c097 2321
7eb63b72
GM
2322 /* Update some other special parameters in their special places
2323 in addition to the alist. */
177c0ea7 2324
329ca574
RS
2325 if (EQ (prop, Qbuffer_predicate))
2326 f->buffer_predicate = val;
2327
032d78fe 2328 if (! FRAME_WINDOW_P (f))
e5317d61
EZ
2329 {
2330 if (EQ (prop, Qmenu_bar_lines))
2331 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2332 else if (EQ (prop, Qname))
2333 set_term_frame_name (f, val);
2334 }
a249de79 2335
e35d291d 2336 if (EQ (prop, Qminibuffer) && WINDOWP (val))
bc93c097
JB
2337 {
2338 if (! MINI_WINDOW_P (XWINDOW (val)))
7c402969 2339 error ("Surrogate minibuffer windows must be minibuffer windows");
bc93c097 2340
213bac8a 2341 if ((FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
7af7ef38
KH
2342 && !EQ (val, f->minibuffer_window))
2343 error ("Can't change the surrogate minibuffer of a frame with its own minibuffer");
bc93c097
JB
2344
2345 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 2346 f->minibuffer_window = val;
bc93c097 2347 }
dc6f92b8
JB
2348}
2349
ff11dfa1 2350DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
14ff1ee0
PJ
2351 doc: /* Return the parameters-alist of frame FRAME.
2352It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2353The meaningful PARMs depend on the kind of frame.
2354If FRAME is omitted, return information on the currently selected frame. */)
2355 (frame)
ff11dfa1 2356 Lisp_Object frame;
dc6f92b8
JB
2357{
2358 Lisp_Object alist;
f769f1b2 2359 FRAME_PTR f;
dd10ec4f 2360 int height, width;
57629833 2361 struct gcpro gcpro1;
dc6f92b8 2362
03390a72 2363 if (NILP (frame))
8d2666fe
GM
2364 frame = selected_frame;
2365
b7826503 2366 CHECK_FRAME (frame);
8d2666fe 2367 f = XFRAME (frame);
dc6f92b8 2368
f769f1b2 2369 if (!FRAME_LIVE_P (f))
dc6f92b8
JB
2370 return Qnil;
2371
ff11dfa1 2372 alist = Fcopy_alist (f->param_alist);
57629833 2373 GCPRO1 (alist);
177c0ea7 2374
2d764c78 2375 if (!FRAME_WINDOW_P (f))
bb221971 2376 {
4aec4b29
EZ
2377 int fg = FRAME_FOREGROUND_PIXEL (f);
2378 int bg = FRAME_BACKGROUND_PIXEL (f);
e1d0bbc9
EZ
2379 Lisp_Object elt;
2380
2381 /* If the frame's parameter alist says the colors are
2382 unspecified and reversed, take the frame's background pixel
2383 for foreground and vice versa. */
2384 elt = Fassq (Qforeground_color, alist);
70de9f06
EZ
2385 if (!NILP (elt) && CONSP (elt) && STRINGP (XCDR (elt)))
2386 {
d5db4077 2387 if (strncmp (SDATA (XCDR (elt)),
70de9f06 2388 unspecified_bg,
d5db4077 2389 SCHARS (XCDR (elt))) == 0)
70de9f06 2390 store_in_alist (&alist, Qforeground_color, tty_color_name (f, bg));
d5db4077 2391 else if (strncmp (SDATA (XCDR (elt)),
70de9f06 2392 unspecified_fg,
d5db4077 2393 SCHARS (XCDR (elt))) == 0)
70de9f06
EZ
2394 store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
2395 }
e1d0bbc9
EZ
2396 else
2397 store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
2398 elt = Fassq (Qbackground_color, alist);
70de9f06
EZ
2399 if (!NILP (elt) && CONSP (elt) && STRINGP (XCDR (elt)))
2400 {
d5db4077 2401 if (strncmp (SDATA (XCDR (elt)),
70de9f06 2402 unspecified_fg,
d5db4077 2403 SCHARS (XCDR (elt))) == 0)
70de9f06 2404 store_in_alist (&alist, Qbackground_color, tty_color_name (f, fg));
d5db4077 2405 else if (strncmp (SDATA (XCDR (elt)),
70de9f06 2406 unspecified_bg,
d5db4077 2407 SCHARS (XCDR (elt))) == 0)
70de9f06
EZ
2408 store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
2409 }
e1d0bbc9
EZ
2410 else
2411 store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
2d764c78
EZ
2412 store_in_alist (&alist, intern ("font"),
2413 build_string (FRAME_MSDOS_P (f)
2414 ? "ms-dos"
4ec0d3c1 2415 : FRAME_W32_P (f) ? "w32term"
4ec0d3c1 2416 :"tty"));
bb221971 2417 }
fd0c2bd1 2418 store_in_alist (&alist, Qname, f->name);
5af5757b 2419 height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
dd10ec4f 2420 store_in_alist (&alist, Qheight, make_number (height));
5af5757b 2421 width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
dd10ec4f 2422 store_in_alist (&alist, Qwidth, make_number (width));
f769f1b2 2423 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
fd0c2bd1 2424 store_in_alist (&alist, Qminibuffer,
39acc701 2425 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
f769f1b2
KH
2426 : FRAME_MINIBUF_ONLY_P (f) ? Qonly
2427 : FRAME_MINIBUF_WINDOW (f)));
2428 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
03390a72 2429 store_in_alist (&alist, Qbuffer_list, frame_buffer_list (frame));
a18b8cb5 2430 store_in_alist (&alist, Qburied_buffer_list, XFRAME (frame)->buried_buffer_list);
fd0c2bd1 2431
dbc4e1c1 2432 /* I think this should be done with a hook. */
032d78fe
GV
2433#ifdef HAVE_WINDOW_SYSTEM
2434 if (FRAME_WINDOW_P (f))
ff11dfa1 2435 x_report_frame_params (f, &alist);
b6dd20ed 2436 else
fd0c2bd1 2437#endif
16a3738c
KH
2438 {
2439 /* This ought to be correct in f->param_alist for an X frame. */
2440 Lisp_Object lines;
f4e93c40 2441 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
16a3738c
KH
2442 store_in_alist (&alist, Qmenu_bar_lines, lines);
2443 }
57629833
GM
2444
2445 UNGCPRO;
dc6f92b8
JB
2446 return alist;
2447}
2448
8b60f7bc
GM
2449
2450DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
14ff1ee0
PJ
2451 doc: /* Return FRAME's value for parameter PARAMETER.
2452If FRAME is nil, describe the currently selected frame. */)
2453 (frame, parameter)
2454 Lisp_Object frame, parameter;
8b60f7bc
GM
2455{
2456 struct frame *f;
2457 Lisp_Object value;
2458
2459 if (NILP (frame))
2460 frame = selected_frame;
2461 else
b7826503
PJ
2462 CHECK_FRAME (frame);
2463 CHECK_SYMBOL (parameter);
177c0ea7 2464
8b60f7bc
GM
2465 f = XFRAME (frame);
2466 value = Qnil;
177c0ea7 2467
8b60f7bc
GM
2468 if (FRAME_LIVE_P (f))
2469 {
5cd62b8c 2470 /* Avoid consing in frequent cases. */
67d853e6
GM
2471 if (EQ (parameter, Qname))
2472 value = f->name;
6345f6aa
GM
2473#ifdef HAVE_X_WINDOWS
2474 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
2475 value = XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element);
2476#endif /* HAVE_X_WINDOWS */
75700ff2
GM
2477 else if (EQ (parameter, Qbackground_color)
2478 || EQ (parameter, Qforeground_color))
67d853e6
GM
2479 {
2480 value = Fassq (parameter, f->param_alist);
2481 if (CONSP (value))
5f65b39d 2482 {
5f65b39d
EZ
2483 value = XCDR (value);
2484 /* Fframe_parameters puts the actual fg/bg color names,
2485 even if f->param_alist says otherwise. This is
2486 important when param_alist's notion of colors is
2487 "unspecified". We need to do the same here. */
2488 if (STRINGP (value) && !FRAME_WINDOW_P (f))
2489 {
c9b08ba8 2490 const char *color_name;
e1d0bbc9
EZ
2491 EMACS_INT csz;
2492
2493 if (EQ (parameter, Qbackground_color))
2494 {
d5db4077
KR
2495 color_name = SDATA (value);
2496 csz = SCHARS (value);
e1d0bbc9
EZ
2497 if (strncmp (color_name, unspecified_bg, csz) == 0)
2498 value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
2499 else if (strncmp (color_name, unspecified_fg, csz) == 0)
2500 value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
2501 }
2502 else if (EQ (parameter, Qforeground_color))
2503 {
d5db4077
KR
2504 color_name = SDATA (value);
2505 csz = SCHARS (value);
e1d0bbc9
EZ
2506 if (strncmp (color_name, unspecified_fg, csz) == 0)
2507 value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
2508 else if (strncmp (color_name, unspecified_bg, csz) == 0)
2509 value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
2510 }
5f65b39d
EZ
2511 }
2512 }
b23236fb
EZ
2513 else
2514 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
67d853e6 2515 }
75700ff2
GM
2516 else if (EQ (parameter, Qdisplay_type)
2517 || EQ (parameter, Qbackground_mode))
75700ff2
GM
2518 value = Fcdr (Fassq (parameter, f->param_alist));
2519 else
2520 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
8b60f7bc 2521 }
177c0ea7 2522
8b60f7bc
GM
2523 return value;
2524}
2525
2526
177c0ea7 2527DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
ff11dfa1 2528 Smodify_frame_parameters, 2, 2, 0,
14ff1ee0
PJ
2529 doc: /* Modify the parameters of frame FRAME according to ALIST.
2530If FRAME is nil, it defaults to the selected frame.
2531ALIST is an alist of parameters to change and their new values.
2532Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
2533The meaningful PARMs depend on the kind of frame.
2534Undefined PARMs are ignored, but stored in the frame's parameter list
2535so that `frame-parameters' will return them.
2536
2537The value of frame parameter FOO can also be accessed
2538as a frame-local binding for the variable FOO, if you have
2539enabled such bindings for that variable with `make-variable-frame-local'. */)
2540 (frame, alist)
ff11dfa1 2541 Lisp_Object frame, alist;
dc6f92b8 2542{
fd0c2bd1 2543 FRAME_PTR f;
213bac8a 2544 register Lisp_Object tail, prop, val;
dc6f92b8 2545
ff11dfa1 2546 if (EQ (frame, Qnil))
8d2666fe 2547 frame = selected_frame;
b7826503 2548 CHECK_LIVE_FRAME (frame);
8d2666fe 2549 f = XFRAME (frame);
dc6f92b8 2550
dbc4e1c1 2551 /* I think this should be done with a hook. */
032d78fe
GV
2552#ifdef HAVE_WINDOW_SYSTEM
2553 if (FRAME_WINDOW_P (f))
fd0c2bd1 2554 x_set_frame_parameters (f, alist);
329ca574 2555 else
bb221971
RS
2556#endif
2557#ifdef MSDOS
2558 if (FRAME_MSDOS_P (f))
2559 IT_set_frame_parameters (f, alist);
2560 else
329ca574 2561#endif
574a1a90 2562
41d44f1f
RS
2563 {
2564 int length = XINT (Flength (alist));
2565 int i;
2566 Lisp_Object *parms
2567 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2568 Lisp_Object *values
2569 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2570
2571 /* Extract parm names and values into those vectors. */
2572
2573 i = 0;
2574 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2575 {
213bac8a 2576 Lisp_Object elt;
41d44f1f
RS
2577
2578 elt = Fcar (tail);
2579 parms[i] = Fcar (elt);
2580 values[i] = Fcdr (elt);
2581 i++;
2582 }
2583
2584 /* Now process them in reverse of specified order. */
2585 for (i--; i >= 0; i--)
2586 {
2587 prop = parms[i];
2588 val = values[i];
2589 store_frame_param (f, prop, val);
33d537f0
JL
2590
2591 /* Changing the background color might change the background
2592 mode, so that we have to load new defface specs.
2593 Call frame-set-background-mode to do that. */
2594 if (EQ (prop, Qbackground_color))
2595 call1 (Qframe_set_background_mode, frame);
41d44f1f
RS
2596 }
2597 }
dc6f92b8 2598}
da8e8fc1
KL
2599
2600DEFUN ("frame-with-environment", Fframe_with_environment, Sframe_with_environment, 0, 1, 0,
2601 doc: /* Return the frame that has the environment variable list for FRAME.
2602
2603The frame-local environment variable list is normally shared between
2604frames that were created in the same Emacsclient session. The
2605environment list is stored in a single frame's 'environment parameter;
2606the other frames' 'environment parameter is set to this frame. This
6d8299f6 2607function follows the chain of 'environment references to reach the
da8e8fc1
KL
2608frame that stores the actual local environment list, and returns that
2609frame. */)
2610 (frame)
2611 Lisp_Object frame;
2612{
2613 Lisp_Object hare, tortoise;
2614
2615 if (NILP (frame))
2616 frame = selected_frame;
2617 CHECK_FRAME (frame);
2618
2619 hare = tortoise = get_frame_param (XFRAME (frame), Qenvironment);
2620 while (!NILP (hare) && FRAMEP (hare))
2621 {
2622 frame = hare;
2623 hare = get_frame_param (XFRAME (hare), Qenvironment);
2624 if (NILP (hare) || !FRAMEP (hare))
2625 break;
2626 frame = hare;
2627 hare = get_frame_param (XFRAME (hare), Qenvironment);
2628 tortoise = get_frame_param (XFRAME (tortoise), Qenvironment);
2629 if (EQ (hare, tortoise))
2630 error ("Cyclic frame-local environment indirection");
2631 }
2632
2633 return frame;
2634}
2635
dc6f92b8 2636\f
a26a1f95 2637DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
14ff1ee0
PJ
2638 0, 1, 0,
2639 doc: /* Height in pixels of a line in the font in frame FRAME.
2640If FRAME is omitted, the selected frame is used.
2641For a terminal frame, the value is always 1. */)
ff11dfa1
JB
2642 (frame)
2643 Lisp_Object frame;
dc6f92b8 2644{
a26a1f95 2645 struct frame *f;
dc6f92b8 2646
a26a1f95 2647 if (NILP (frame))
8d2666fe 2648 frame = selected_frame;
b7826503 2649 CHECK_FRAME (frame);
8d2666fe 2650 f = XFRAME (frame);
a26a1f95 2651
032d78fe
GV
2652#ifdef HAVE_WINDOW_SYSTEM
2653 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2654 return make_number (x_char_height (f));
2655 else
dc6d9681 2656#endif
a26a1f95
RS
2657 return make_number (1);
2658}
dc6d9681 2659
dc6f92b8 2660
a26a1f95 2661DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
14ff1ee0
PJ
2662 0, 1, 0,
2663 doc: /* Width in pixels of characters in the font in frame FRAME.
2664If FRAME is omitted, the selected frame is used.
31b7cc74 2665On a graphical screen, the width is the standard width of the default font.
14ff1ee0
PJ
2666For a terminal screen, the value is always 1. */)
2667 (frame)
a26a1f95 2668 Lisp_Object frame;
dc6f92b8 2669{
a26a1f95
RS
2670 struct frame *f;
2671
2672 if (NILP (frame))
8d2666fe 2673 frame = selected_frame;
b7826503 2674 CHECK_FRAME (frame);
8d2666fe 2675 f = XFRAME (frame);
a26a1f95 2676
032d78fe
GV
2677#ifdef HAVE_WINDOW_SYSTEM
2678 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2679 return make_number (x_char_width (f));
2680 else
2681#endif
2682 return make_number (1);
dc6f92b8
JB
2683}
2684
177c0ea7 2685DEFUN ("frame-pixel-height", Fframe_pixel_height,
a26a1f95 2686 Sframe_pixel_height, 0, 1, 0,
14ff1ee0
PJ
2687 doc: /* Return a FRAME's height in pixels.
2688This counts only the height available for text lines,
2689not menu bars on window-system Emacs frames.
2690For a terminal frame, the result really gives the height in characters.
2691If FRAME is omitted, the selected frame is used. */)
2692 (frame)
a26a1f95 2693 Lisp_Object frame;
dc6f92b8 2694{
a26a1f95
RS
2695 struct frame *f;
2696
2697 if (NILP (frame))
8d2666fe 2698 frame = selected_frame;
b7826503 2699 CHECK_FRAME (frame);
8d2666fe 2700 f = XFRAME (frame);
a26a1f95 2701
032d78fe
GV
2702#ifdef HAVE_WINDOW_SYSTEM
2703 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2704 return make_number (x_pixel_height (f));
2705 else
dc6d9681 2706#endif
5af5757b 2707 return make_number (FRAME_LINES (f));
a26a1f95
RS
2708}
2709
177c0ea7 2710DEFUN ("frame-pixel-width", Fframe_pixel_width,
a26a1f95 2711 Sframe_pixel_width, 0, 1, 0,
14ff1ee0
PJ
2712 doc: /* Return FRAME's width in pixels.
2713For a terminal frame, the result really gives the width in characters.
2714If FRAME is omitted, the selected frame is used. */)
2715 (frame)
a26a1f95
RS
2716 Lisp_Object frame;
2717{
2718 struct frame *f;
2719
2720 if (NILP (frame))
8d2666fe 2721 frame = selected_frame;
b7826503 2722 CHECK_FRAME (frame);
8d2666fe 2723 f = XFRAME (frame);
dc6f92b8 2724
032d78fe
GV
2725#ifdef HAVE_WINDOW_SYSTEM
2726 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2727 return make_number (x_pixel_width (f));
2728 else
2729#endif
5af5757b 2730 return make_number (FRAME_COLS (f));
a26a1f95
RS
2731}
2732\f
ff11dfa1 2733DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
14ff1ee0
PJ
2734 doc: /* Specify that the frame FRAME has LINES lines.
2735Optional third arg non-nil means that redisplay should use LINES lines
2736but that the idea of the actual height of the frame should not be changed. */)
2737 (frame, lines, pretend)
735eeca3 2738 Lisp_Object frame, lines, pretend;
dc6f92b8 2739{
ff11dfa1 2740 register struct frame *f;
dc6f92b8 2741
b7826503 2742 CHECK_NUMBER (lines);
ff11dfa1 2743 if (NILP (frame))
8d2666fe 2744 frame = selected_frame;
b7826503 2745 CHECK_LIVE_FRAME (frame);
8d2666fe 2746 f = XFRAME (frame);
dc6f92b8 2747
dbc4e1c1 2748 /* I think this should be done with a hook. */
032d78fe
GV
2749#ifdef HAVE_WINDOW_SYSTEM
2750 if (FRAME_WINDOW_P (f))
dc6f92b8 2751 {
5af5757b
KS
2752 if (XINT (lines) != FRAME_LINES (f))
2753 x_set_window_size (f, 1, FRAME_COLS (f), XINT (lines));
32347cf4 2754 do_pending_window_change (0);
dc6f92b8
JB
2755 }
2756 else
fd0c2bd1 2757#endif
32347cf4 2758 change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0, 0);
dc6f92b8
JB
2759 return Qnil;
2760}
2761
ff11dfa1 2762DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
14ff1ee0
PJ
2763 doc: /* Specify that the frame FRAME has COLS columns.
2764Optional third arg non-nil means that redisplay should use COLS columns
2765but that the idea of the actual width of the frame should not be changed. */)
2766 (frame, cols, pretend)
fd0c2bd1 2767 Lisp_Object frame, cols, pretend;
dc6f92b8 2768{
ff11dfa1 2769 register struct frame *f;
b7826503 2770 CHECK_NUMBER (cols);
ff11dfa1 2771 if (NILP (frame))
8d2666fe 2772 frame = selected_frame;
b7826503 2773 CHECK_LIVE_FRAME (frame);
8d2666fe 2774 f = XFRAME (frame);
dc6f92b8 2775
dbc4e1c1 2776 /* I think this should be done with a hook. */
032d78fe
GV
2777#ifdef HAVE_WINDOW_SYSTEM
2778 if (FRAME_WINDOW_P (f))
dc6f92b8 2779 {
5af5757b
KS
2780 if (XINT (cols) != FRAME_COLS (f))
2781 x_set_window_size (f, 1, XINT (cols), FRAME_LINES (f));
32347cf4 2782 do_pending_window_change (0);
dc6f92b8
JB
2783 }
2784 else
fd0c2bd1 2785#endif
32347cf4 2786 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0, 0);
dc6f92b8
JB
2787 return Qnil;
2788}
2789
ff11dfa1 2790DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
14ff1ee0
PJ
2791 doc: /* Sets size of FRAME to COLS by ROWS, measured in characters. */)
2792 (frame, cols, rows)
ff11dfa1 2793 Lisp_Object frame, cols, rows;
dc6f92b8 2794{
ff11dfa1 2795 register struct frame *f;
dc6f92b8 2796
b7826503
PJ
2797 CHECK_LIVE_FRAME (frame);
2798 CHECK_NUMBER (cols);
2799 CHECK_NUMBER (rows);
ff11dfa1 2800 f = XFRAME (frame);
dc6f92b8 2801
dbc4e1c1 2802 /* I think this should be done with a hook. */
032d78fe
GV
2803#ifdef HAVE_WINDOW_SYSTEM
2804 if (FRAME_WINDOW_P (f))
dc6f92b8 2805 {
5af5757b
KS
2806 if (XINT (rows) != FRAME_LINES (f)
2807 || XINT (cols) != FRAME_COLS (f)
2808 || f->new_text_lines || f->new_text_cols)
808c0f20 2809 x_set_window_size (f, 1, XINT (cols), XINT (rows));
32347cf4 2810 do_pending_window_change (0);
dc6f92b8
JB
2811 }
2812 else
fd0c2bd1 2813#endif
32347cf4 2814 change_frame_size (f, XINT (rows), XINT (cols), 0, 0, 0);
dc6f92b8
JB
2815
2816 return Qnil;
2817}
2818
177c0ea7 2819DEFUN ("set-frame-position", Fset_frame_position,
ff11dfa1 2820 Sset_frame_position, 3, 3, 0,
14ff1ee0
PJ
2821 doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
2822This is actually the position of the upper left corner of the frame.
2823Negative values for XOFFSET or YOFFSET are interpreted relative to
2824the rightmost or bottommost possible position (that stays within the screen). */)
2825 (frame, xoffset, yoffset)
ff11dfa1 2826 Lisp_Object frame, xoffset, yoffset;
dc6f92b8 2827{
ff11dfa1 2828 register struct frame *f;
dc6f92b8 2829
b7826503
PJ
2830 CHECK_LIVE_FRAME (frame);
2831 CHECK_NUMBER (xoffset);
2832 CHECK_NUMBER (yoffset);
ff11dfa1 2833 f = XFRAME (frame);
dc6f92b8 2834
dbc4e1c1 2835 /* I think this should be done with a hook. */
032d78fe
GV
2836#ifdef HAVE_WINDOW_SYSTEM
2837 if (FRAME_WINDOW_P (f))
c7c70761 2838 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
fd0c2bd1 2839#endif
dc6f92b8
JB
2840
2841 return Qt;
2842}
dc6d9681 2843
dc6f92b8 2844\f
972f4259
KS
2845/***********************************************************************
2846 Frame Parameters
2847 ***********************************************************************/
2848
2849/* Connect the frame-parameter names for X frames
2850 to the ways of passing the parameter values to the window system.
2851
2852 The name of a parameter, as a Lisp symbol,
2853 has an `x-frame-parameter' property which is an integer in Lisp
2854 that is an index in this table. */
2855
2856struct frame_parm_table {
2857 char *name;
2858 Lisp_Object *variable;
2859};
2860
2861static struct frame_parm_table frame_parms[] =
2862{
2863 {"auto-raise", &Qauto_raise},
2864 {"auto-lower", &Qauto_lower},
2865 {"background-color", 0},
2866 {"border-color", &Qborder_color},
2867 {"border-width", &Qborder_width},
2868 {"cursor-color", &Qcursor_color},
2869 {"cursor-type", &Qcursor_type},
2870 {"font", 0},
2871 {"foreground-color", 0},
2872 {"icon-name", &Qicon_name},
2873 {"icon-type", &Qicon_type},
2874 {"internal-border-width", &Qinternal_border_width},
2875 {"menu-bar-lines", &Qmenu_bar_lines},
2876 {"mouse-color", &Qmouse_color},
2877 {"name", &Qname},
2878 {"scroll-bar-width", &Qscroll_bar_width},
2879 {"title", &Qtitle},
2880 {"unsplittable", &Qunsplittable},
2881 {"vertical-scroll-bars", &Qvertical_scroll_bars},
2882 {"visibility", &Qvisibility},
2883 {"tool-bar-lines", &Qtool_bar_lines},
2884 {"scroll-bar-foreground", &Qscroll_bar_foreground},
2885 {"scroll-bar-background", &Qscroll_bar_background},
2886 {"screen-gamma", &Qscreen_gamma},
2887 {"line-spacing", &Qline_spacing},
2888 {"left-fringe", &Qleft_fringe},
2889 {"right-fringe", &Qright_fringe},
2890 {"wait-for-wm", &Qwait_for_wm},
2891 {"fullscreen", &Qfullscreen},
2892};
2893
2894#ifdef HAVE_WINDOW_SYSTEM
2895
2896extern Lisp_Object Qbox;
2897extern Lisp_Object Qtop;
2898
2899/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
bd45aef7 2900 wanted positions of the WM window (not Emacs window).
972f4259
KS
2901 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
2902 window (FRAME_X_WINDOW).
2903 */
2904
dfcf069d 2905void
972f4259
KS
2906x_fullscreen_adjust (f, width, height, top_pos, left_pos)
2907 struct frame *f;
2908 int *width;
2909 int *height;
2910 int *top_pos;
2911 int *left_pos;
dc6f92b8 2912{
5af5757b
KS
2913 int newwidth = FRAME_COLS (f);
2914 int newheight = FRAME_LINES (f);
dc6f92b8 2915
5af5757b
KS
2916 *top_pos = f->top_pos;
2917 *left_pos = f->left_pos;
3df1fda2 2918
5af5757b 2919 if (f->want_fullscreen & FULLSCREEN_HEIGHT)
972f4259
KS
2920 {
2921 int ph;
2922
2923 ph = FRAME_X_DISPLAY_INFO (f)->height;
5af5757b
KS
2924 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
2925 ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
2926 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
972f4259
KS
2927 *top_pos = 0;
2928 }
dc6f92b8 2929
5af5757b 2930 if (f->want_fullscreen & FULLSCREEN_WIDTH)
972f4259
KS
2931 {
2932 int pw;
2933
2934 pw = FRAME_X_DISPLAY_INFO (f)->width;
5af5757b
KS
2935 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
2936 pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
2937 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
972f4259
KS
2938 *left_pos = 0;
2939 }
dc6f92b8 2940
972f4259
KS
2941 *width = newwidth;
2942 *height = newheight;
2943}
dc6f92b8 2944
beb0bc36 2945
972f4259
KS
2946/* Change the parameters of frame F as specified by ALIST.
2947 If a parameter is not specially recognized, do nothing special;
2948 otherwise call the `x_set_...' function for that parameter.
2949 Except for certain geometry properties, always call store_frame_param
2950 to store the new value in the parameter alist. */
14ff1ee0 2951
972f4259
KS
2952void
2953x_set_frame_parameters (f, alist)
2954 FRAME_PTR f;
2955 Lisp_Object alist;
2956{
2957 Lisp_Object tail;
dc6f92b8 2958
972f4259
KS
2959 /* If both of these parameters are present, it's more efficient to
2960 set them both at once. So we wait until we've looked at the
2961 entire list before we set them. */
2962 int width, height;
3df1fda2 2963
972f4259
KS
2964 /* Same here. */
2965 Lisp_Object left, top;
2966
2967 /* Same with these. */
2968 Lisp_Object icon_left, icon_top;
2969
2970 /* Record in these vectors all the parms specified. */
2971 Lisp_Object *parms;
2972 Lisp_Object *values;
2973 int i, p;
2974 int left_no_change = 0, top_no_change = 0;
2975 int icon_left_no_change = 0, icon_top_no_change = 0;
2976 int fullscreen_is_being_set = 0;
2977
2978 struct gcpro gcpro1, gcpro2;
2979
2980 i = 0;
2981 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2982 i++;
2983
2984 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
2985 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
2986
2987 /* Extract parm names and values into those vectors. */
2988
2989 i = 0;
2990 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2991 {
2992 Lisp_Object elt;
2993
2994 elt = Fcar (tail);
2995 parms[i] = Fcar (elt);
2996 values[i] = Fcdr (elt);
2997 i++;
2998 }
2999 /* TAIL and ALIST are not used again below here. */
3000 alist = tail = Qnil;
3001
3002 GCPRO2 (*parms, *values);
3003 gcpro1.nvars = i;
3004 gcpro2.nvars = i;
3005
3006 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
3007 because their values appear in VALUES and strings are not valid. */
3008 top = left = Qunbound;
3009 icon_left = icon_top = Qunbound;
3010
3011 /* Provide default values for HEIGHT and WIDTH. */
5af5757b
KS
3012 width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
3013 height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
972f4259
KS
3014
3015 /* Process foreground_color and background_color before anything else.
3016 They are independent of other properties, but other properties (e.g.,
3017 cursor_color) are dependent upon them. */
3018 /* Process default font as well, since fringe widths depends on it. */
3019 /* Also, process fullscreen, width and height depend upon that */
3020 for (p = 0; p < i; p++)
3021 {
3022 Lisp_Object prop, val;
3023
3024 prop = parms[p];
3025 val = values[p];
3026 if (EQ (prop, Qforeground_color)
3027 || EQ (prop, Qbackground_color)
3028 || EQ (prop, Qfont)
3029 || EQ (prop, Qfullscreen))
3030 {
3031 register Lisp_Object param_index, old_value;
26c34ec2 3032 int count = SPECPDL_INDEX ();
972f4259
KS
3033
3034 old_value = get_frame_param (f, prop);
3035 fullscreen_is_being_set |= EQ (prop, Qfullscreen);
3036
3037 if (NILP (Fequal (val, old_value)))
3038 {
26c34ec2
CY
3039 /* For :font attributes, the frame_parm_handler
3040 x_set_font calls `face-set-after-frame-default'.
3041 Unless we bind inhibit-face-set-after-frame-default
3042 here, this would reset the :font attribute that we
3043 just applied to the default value for new faces. */
3044 specbind (Qinhibit_face_set_after_frame_default, Qt);
3045
972f4259
KS
3046 store_frame_param (f, prop, val);
3047
3048 param_index = Fget (prop, Qx_frame_parameter);
3049 if (NATNUMP (param_index)
3050 && (XFASTINT (param_index)
3051 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
3052 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3053 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
26c34ec2 3054 unbind_to (count, Qnil);
972f4259
KS
3055 }
3056 }
3057 }
3058
3059 /* Now process them in reverse of specified order. */
3060 for (i--; i >= 0; i--)
3061 {
3062 Lisp_Object prop, val;
3063
3064 prop = parms[i];
3065 val = values[i];
3066
3067 if (EQ (prop, Qwidth) && NUMBERP (val))
3068 width = XFASTINT (val);
3069 else if (EQ (prop, Qheight) && NUMBERP (val))
3070 height = XFASTINT (val);
3071 else if (EQ (prop, Qtop))
3072 top = val;
3073 else if (EQ (prop, Qleft))
3074 left = val;
3075 else if (EQ (prop, Qicon_top))
3076 icon_top = val;
3077 else if (EQ (prop, Qicon_left))
3078 icon_left = val;
3079 else if (EQ (prop, Qforeground_color)
3080 || EQ (prop, Qbackground_color)
3081 || EQ (prop, Qfont)
3082 || EQ (prop, Qfullscreen))
3083 /* Processed above. */
3084 continue;
3085 else
3086 {
3087 register Lisp_Object param_index, old_value;
3088
3089 old_value = get_frame_param (f, prop);
3090
3091 store_frame_param (f, prop, val);
3092
3093 param_index = Fget (prop, Qx_frame_parameter);
3094 if (NATNUMP (param_index)
3095 && (XFASTINT (param_index)
3096 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
3097 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3098 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
972f4259
KS
3099 }
3100 }
3101
3102 /* Don't die if just one of these was set. */
3103 if (EQ (left, Qunbound))
3104 {
3105 left_no_change = 1;
5af5757b
KS
3106 if (f->left_pos < 0)
3107 left = Fcons (Qplus, Fcons (make_number (f->left_pos), Qnil));
972f4259 3108 else
5af5757b 3109 XSETINT (left, f->left_pos);
972f4259
KS
3110 }
3111 if (EQ (top, Qunbound))
3112 {
3113 top_no_change = 1;
5af5757b
KS
3114 if (f->top_pos < 0)
3115 top = Fcons (Qplus, Fcons (make_number (f->top_pos), Qnil));
972f4259 3116 else
5af5757b 3117 XSETINT (top, f->top_pos);
972f4259
KS
3118 }
3119
3120 /* If one of the icon positions was not set, preserve or default it. */
3121 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
3122 {
3123 icon_left_no_change = 1;
3124 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3125 if (NILP (icon_left))
3126 XSETINT (icon_left, 0);
3127 }
3128 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
3129 {
3130 icon_top_no_change = 1;
3131 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3132 if (NILP (icon_top))
3133 XSETINT (icon_top, 0);
3134 }
3135
972f4259
KS
3136 if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set)
3137 {
3138 /* If the frame is visible already and the fullscreen parameter is
3139 being set, it is too late to set WM manager hints to specify
3140 size and position.
3141 Here we first get the width, height and position that applies to
3142 fullscreen. We then move the frame to the appropriate
3143 position. Resize of the frame is taken care of in the code after
3144 this if-statement. */
3145 int new_left, new_top;
3146
3147 x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
068ae0fd
JD
3148 if (new_top != f->top_pos || new_left != f->left_pos)
3149 x_set_offset (f, new_left, new_top, 1);
972f4259 3150 }
972f4259
KS
3151
3152 /* Don't set these parameters unless they've been explicitly
3153 specified. The window might be mapped or resized while we're in
3154 this function, and we don't want to override that unless the lisp
3155 code has asked for it.
3156
3157 Don't set these parameters unless they actually differ from the
3158 window's current parameters; the window may not actually exist
3159 yet. */
3160 {
3161 Lisp_Object frame;
3162
3163 check_frame_size (f, &height, &width);
3164
3165 XSETFRAME (frame, f);
3166
5af5757b
KS
3167 if (width != FRAME_COLS (f)
3168 || height != FRAME_LINES (f)
3169 || f->new_text_lines || f->new_text_cols)
972f4259
KS
3170 Fset_frame_size (frame, make_number (width), make_number (height));
3171
3172 if ((!NILP (left) || !NILP (top))
3173 && ! (left_no_change && top_no_change)
5af5757b
KS
3174 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3175 && NUMBERP (top) && XINT (top) == f->top_pos))
972f4259
KS
3176 {
3177 int leftpos = 0;
3178 int toppos = 0;
3179
3180 /* Record the signs. */
5af5757b 3181 f->size_hint_flags &= ~ (XNegative | YNegative);
972f4259 3182 if (EQ (left, Qminus))
5af5757b 3183 f->size_hint_flags |= XNegative;
972f4259
KS
3184 else if (INTEGERP (left))
3185 {
3186 leftpos = XINT (left);
3187 if (leftpos < 0)
5af5757b 3188 f->size_hint_flags |= XNegative;
972f4259
KS
3189 }
3190 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3191 && CONSP (XCDR (left))
3192 && INTEGERP (XCAR (XCDR (left))))
3193 {
3194 leftpos = - XINT (XCAR (XCDR (left)));
5af5757b 3195 f->size_hint_flags |= XNegative;
972f4259
KS
3196 }
3197 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3198 && CONSP (XCDR (left))
3199 && INTEGERP (XCAR (XCDR (left))))
3200 {
3201 leftpos = XINT (XCAR (XCDR (left)));
3202 }
3203
3204 if (EQ (top, Qminus))
5af5757b 3205 f->size_hint_flags |= YNegative;
972f4259
KS
3206 else if (INTEGERP (top))
3207 {
3208 toppos = XINT (top);
3209 if (toppos < 0)
5af5757b 3210 f->size_hint_flags |= YNegative;
972f4259
KS
3211 }
3212 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3213 && CONSP (XCDR (top))
3214 && INTEGERP (XCAR (XCDR (top))))
3215 {
3216 toppos = - XINT (XCAR (XCDR (top)));
5af5757b 3217 f->size_hint_flags |= YNegative;
972f4259
KS
3218 }
3219 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3220 && CONSP (XCDR (top))
3221 && INTEGERP (XCAR (XCDR (top))))
3222 {
3223 toppos = XINT (XCAR (XCDR (top)));
3224 }
3225
3226
3227 /* Store the numeric value of the position. */
5af5757b
KS
3228 f->top_pos = toppos;
3229 f->left_pos = leftpos;
972f4259 3230
5af5757b 3231 f->win_gravity = NorthWestGravity;
972f4259
KS
3232
3233 /* Actually set that position, and convert to absolute. */
3234 x_set_offset (f, leftpos, toppos, -1);
3235 }
3236
3237 if ((!NILP (icon_left) || !NILP (icon_top))
3238 && ! (icon_left_no_change && icon_top_no_change))
3239 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3240 }
3241
3242 UNGCPRO;
3243}
3244
3245
3246/* Insert a description of internally-recorded parameters of frame X
3247 into the parameter alist *ALISTPTR that is to be given to the user.
3248 Only parameters that are specific to the X window system
3249 and whose values are not correctly recorded in the frame's
3250 param_alist need to be considered here. */
3251
3252void
3253x_report_frame_params (f, alistptr)
3254 struct frame *f;
3255 Lisp_Object *alistptr;
3256{
3257 char buf[16];
3258 Lisp_Object tem;
3259
3260 /* Represent negative positions (off the top or left screen edge)
3261 in a way that Fmodify_frame_parameters will understand correctly. */
5af5757b
KS
3262 XSETINT (tem, f->left_pos);
3263 if (f->left_pos >= 0)
972f4259
KS
3264 store_in_alist (alistptr, Qleft, tem);
3265 else
3266 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
3267
5af5757b
KS
3268 XSETINT (tem, f->top_pos);
3269 if (f->top_pos >= 0)
972f4259
KS
3270 store_in_alist (alistptr, Qtop, tem);
3271 else
3272 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
3273
3274 store_in_alist (alistptr, Qborder_width,
5af5757b 3275 make_number (f->border_width));
972f4259 3276 store_in_alist (alistptr, Qinternal_border_width,
5af5757b 3277 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
972f4259 3278 store_in_alist (alistptr, Qleft_fringe,
5af5757b 3279 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
972f4259 3280 store_in_alist (alistptr, Qright_fringe,
5af5757b 3281 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
972f4259
KS
3282 store_in_alist (alistptr, Qscroll_bar_width,
3283 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3284 ? make_number (0)
5af5757b
KS
3285 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
3286 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3287 /* nil means "use default width"
3288 for non-toolkit scroll bar.
3289 ruler-mode.el depends on this. */
3290 : Qnil));
3291 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
3292 store_in_alist (alistptr, Qwindow_id,
3293 build_string (buf));
3294#ifdef HAVE_X_WINDOWS
3295#ifdef USE_X_TOOLKIT
3296 /* Tooltip frame may not have this widget. */
3297 if (FRAME_X_OUTPUT (f)->widget)
3298#endif
3299 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
3300 store_in_alist (alistptr, Qouter_window_id,
3301 build_string (buf));
3302#endif
3303 store_in_alist (alistptr, Qicon_name, f->icon_name);
3304 FRAME_SAMPLE_VISIBILITY (f);
3305 store_in_alist (alistptr, Qvisibility,
3306 (FRAME_VISIBLE_P (f) ? Qt
3307 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
3308 store_in_alist (alistptr, Qdisplay,
3309 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
3310
3311 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
3312 tem = Qnil;
3313 else
3314 XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
3315 store_in_alist (alistptr, Qparent_id, tem);
3316}
3317
3318
3319/* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
3320 the previous value of that parameter, NEW_VALUE is the new value. */
3321
3322void
3323x_set_fullscreen (f, new_value, old_value)
3324 struct frame *f;
3325 Lisp_Object new_value, old_value;
3326{
972f4259 3327 if (NILP (new_value))
5af5757b 3328 f->want_fullscreen = FULLSCREEN_NONE;
972f4259 3329 else if (EQ (new_value, Qfullboth))
5af5757b 3330 f->want_fullscreen = FULLSCREEN_BOTH;
972f4259 3331 else if (EQ (new_value, Qfullwidth))
5af5757b 3332 f->want_fullscreen = FULLSCREEN_WIDTH;
972f4259 3333 else if (EQ (new_value, Qfullheight))
5af5757b 3334 f->want_fullscreen = FULLSCREEN_HEIGHT;
d761dd42 3335
974b73e8
KL
3336 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
3337 FRAME_TERMINAL (f)->fullscreen_hook (f);
972f4259
KS
3338}
3339
3340
3341/* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
3342 the previous value of that parameter, NEW_VALUE is the new value. */
3343
3344void
3345x_set_line_spacing (f, new_value, old_value)
3346 struct frame *f;
3347 Lisp_Object new_value, old_value;
3348{
3349 if (NILP (new_value))
3350 f->extra_line_spacing = 0;
3351 else if (NATNUMP (new_value))
3352 f->extra_line_spacing = XFASTINT (new_value);
3353 else
9dc95187 3354 signal_error ("Invalid line-spacing", new_value);
972f4259
KS
3355 if (FRAME_VISIBLE_P (f))
3356 redraw_frame (f);
3357}
3358
3359
3360/* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
3361 the previous value of that parameter, NEW_VALUE is the new value. */
3362
3363void
3364x_set_screen_gamma (f, new_value, old_value)
3365 struct frame *f;
3366 Lisp_Object new_value, old_value;
3367{
05fc2ef7
CY
3368 Lisp_Object bgcolor;
3369
972f4259
KS
3370 if (NILP (new_value))
3371 f->gamma = 0;
3372 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
3373 /* The value 0.4545 is the normal viewing gamma. */
3374 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
3375 else
9dc95187 3376 signal_error ("Invalid screen-gamma", new_value);
972f4259 3377
05fc2ef7
CY
3378 /* Apply the new gamma value to the frame background. */
3379 bgcolor = Fassq (Qbackground_color, f->param_alist);
3380 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
3381 {
3382 Lisp_Object index = Fget (Qbackground_color, Qx_frame_parameter);
3383 if (NATNUMP (index)
3384 && (XFASTINT (index)
3385 < sizeof (frame_parms)/sizeof (frame_parms[0]))
6baa22c1
KL
3386 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (index)])
3387 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (index)])
3388 (f, bgcolor, Qnil);
05fc2ef7
CY
3389 }
3390
3391 Fclear_face_cache (Qnil);
972f4259
KS
3392}
3393
3394
3395void
3396x_set_font (f, arg, oldval)
3397 struct frame *f;
3398 Lisp_Object arg, oldval;
3399{
3400 Lisp_Object result;
3401 Lisp_Object fontset_name;
3402 Lisp_Object frame;
3403 int old_fontset = FRAME_FONTSET(f);
3404
3405 CHECK_STRING (arg);
3406
3407 fontset_name = Fquery_fontset (arg, Qnil);
3408
3409 BLOCK_INPUT;
3410 result = (STRINGP (fontset_name)
3411 ? x_new_fontset (f, SDATA (fontset_name))
3412 : x_new_font (f, SDATA (arg)));
3413 UNBLOCK_INPUT;
3414
3415 if (EQ (result, Qnil))
3416 error ("Font `%s' is not defined", SDATA (arg));
3417 else if (EQ (result, Qt))
3418 error ("The characters of the given font have varying widths");
3419 else if (STRINGP (result))
3420 {
ee5d57b0 3421 set_default_ascii_font (result);
972f4259
KS
3422 if (STRINGP (fontset_name))
3423 {
3424 /* Fontset names are built from ASCII font names, so the
3425 names may be equal despite there was a change. */
3426 if (old_fontset == FRAME_FONTSET (f))
3427 return;
3428 }
3429 else if (!NILP (Fequal (result, oldval)))
3430 return;
3431
ca03f883
KS
3432 /* Recalculate toolbar height. */
3433 f->n_tool_bar_rows = 0;
3434 /* Ensure we redraw it. */
3435 clear_current_matrices (f);
3436
972f4259
KS
3437 store_frame_param (f, Qfont, result);
3438 recompute_basic_faces (f);
3439 }
3440 else
3441 abort ();
3442
3443 do_pending_window_change (0);
3444
3445 /* Don't call `face-set-after-frame-default' when faces haven't been
3446 initialized yet. This is the case when called from
3447 Fx_create_frame. In that case, the X widget or window doesn't
3448 exist either, and we can end up in x_report_frame_params with a
3449 null widget which gives a segfault. */
3450 if (FRAME_FACE_CACHE (f))
3451 {
3452 XSETFRAME (frame, f);
3453 call1 (Qface_set_after_frame_default, frame);
3454 }
3455}
3456
3457
3458void
3459x_set_fringe_width (f, new_value, old_value)
3460 struct frame *f;
3461 Lisp_Object new_value, old_value;
3462{
3463 compute_fringe_widths (f, 1);
3464}
3465
3466void
3467x_set_border_width (f, arg, oldval)
3468 struct frame *f;
3469 Lisp_Object arg, oldval;
3470{
3471 CHECK_NUMBER (arg);
3472
5af5757b 3473 if (XINT (arg) == f->border_width)
972f4259
KS
3474 return;
3475
972f4259 3476 if (FRAME_X_WINDOW (f) != 0)
dac85f4b 3477 error ("Cannot change the border width of a frame");
972f4259 3478
5af5757b 3479 f->border_width = XINT (arg);
972f4259
KS
3480}
3481
3482void
3483x_set_internal_border_width (f, arg, oldval)
3484 struct frame *f;
3485 Lisp_Object arg, oldval;
3486{
5af5757b 3487 int old = FRAME_INTERNAL_BORDER_WIDTH (f);
972f4259
KS
3488
3489 CHECK_NUMBER (arg);
5af5757b
KS
3490 FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
3491 if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
3492 FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
972f4259
KS
3493
3494#ifdef USE_X_TOOLKIT
3495 if (FRAME_X_OUTPUT (f)->edit_widget)
3496 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
3497#endif
3498
5af5757b 3499 if (FRAME_INTERNAL_BORDER_WIDTH (f) == old)
972f4259
KS
3500 return;
3501
3502 if (FRAME_X_WINDOW (f) != 0)
3503 {
5af5757b 3504 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3505 SET_FRAME_GARBAGED (f);
3506 do_pending_window_change (0);
3507 }
3508 else
3509 SET_FRAME_GARBAGED (f);
3510}
3511
3512void
3513x_set_visibility (f, value, oldval)
3514 struct frame *f;
3515 Lisp_Object value, oldval;
3516{
3517 Lisp_Object frame;
3518 XSETFRAME (frame, f);
3519
3520 if (NILP (value))
3521 Fmake_frame_invisible (frame, Qt);
3522 else if (EQ (value, Qicon))
3523 Ficonify_frame (frame);
3524 else
3525 Fmake_frame_visible (frame);
3526}
3527
3528void
3529x_set_autoraise (f, arg, oldval)
3530 struct frame *f;
3531 Lisp_Object arg, oldval;
3532{
3533 f->auto_raise = !EQ (Qnil, arg);
3534}
3535
3536void
3537x_set_autolower (f, arg, oldval)
3538 struct frame *f;
3539 Lisp_Object arg, oldval;
3540{
3541 f->auto_lower = !EQ (Qnil, arg);
3542}
3543
3544void
3545x_set_unsplittable (f, arg, oldval)
3546 struct frame *f;
3547 Lisp_Object arg, oldval;
3548{
3549 f->no_split = !NILP (arg);
3550}
3551
3552void
3553x_set_vertical_scroll_bars (f, arg, oldval)
3554 struct frame *f;
3555 Lisp_Object arg, oldval;
3556{
3557 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3558 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
3559 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3560 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
3561 {
3562 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
3563 = (NILP (arg)
3564 ? vertical_scroll_bar_none
3565 : EQ (Qleft, arg)
3566 ? vertical_scroll_bar_left
3567 : EQ (Qright, arg)
3568 ? vertical_scroll_bar_right
a6e20602
KS
3569 : EQ (Qleft, Vdefault_frame_scroll_bars)
3570 ? vertical_scroll_bar_left
3571 : EQ (Qright, Vdefault_frame_scroll_bars)
3572 ? vertical_scroll_bar_right
3573 : vertical_scroll_bar_none);
972f4259
KS
3574
3575 /* We set this parameter before creating the X window for the
3576 frame, so we can get the geometry right from the start.
3577 However, if the window hasn't been created yet, we shouldn't
3578 call x_set_window_size. */
3579 if (FRAME_X_WINDOW (f))
5af5757b 3580 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3581 do_pending_window_change (0);
3582 }
3583}
3584
3585void
3586x_set_scroll_bar_width (f, arg, oldval)
3587 struct frame *f;
3588 Lisp_Object arg, oldval;
3589{
5af5757b 3590 int wid = FRAME_COLUMN_WIDTH (f);
972f4259
KS
3591
3592 if (NILP (arg))
3593 {
3594 x_set_scroll_bar_default_width (f);
3595
3596 if (FRAME_X_WINDOW (f))
5af5757b 3597 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3598 do_pending_window_change (0);
3599 }
3600 else if (INTEGERP (arg) && XINT (arg) > 0
5af5757b 3601 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3602 {
3603 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
3604 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
3605
5af5757b
KS
3606 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
3607 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
972f4259 3608 if (FRAME_X_WINDOW (f))
5af5757b 3609 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3610 do_pending_window_change (0);
3611 }
3612
5af5757b 3613 change_frame_size (f, 0, FRAME_COLS (f), 0, 0, 0);
972f4259
KS
3614 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3615 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3616}
3617
3618
3619
3620/* Return non-nil if frame F wants a bitmap icon. */
3621
3622Lisp_Object
3623x_icon_type (f)
3624 FRAME_PTR f;
3625{
3626 Lisp_Object tem;
3627
3628 tem = assq_no_quit (Qicon_type, f->param_alist);
3629 if (CONSP (tem))
3630 return XCDR (tem);
3631 else
3632 return Qnil;
3633}
3634
3635\f
3636/* Subroutines of creating an X frame. */
3637
3638/* Make sure that Vx_resource_name is set to a reasonable value.
3639 Fix it up, or set it to `emacs' if it is too hopeless. */
3640
3641void
3642validate_x_resource_name ()
3643{
3644 int len = 0;
3645 /* Number of valid characters in the resource name. */
3646 int good_count = 0;
3647 /* Number of invalid characters in the resource name. */
3648 int bad_count = 0;
3649 Lisp_Object new;
3650 int i;
3651
3652 if (!STRINGP (Vx_resource_class))
3653 Vx_resource_class = build_string (EMACS_CLASS);
3654
3655 if (STRINGP (Vx_resource_name))
3656 {
3657 unsigned char *p = SDATA (Vx_resource_name);
3658 int i;
3659
3660 len = SBYTES (Vx_resource_name);
3661
3662 /* Only letters, digits, - and _ are valid in resource names.
3663 Count the valid characters and count the invalid ones. */
3664 for (i = 0; i < len; i++)
3665 {
3666 int c = p[i];
3667 if (! ((c >= 'a' && c <= 'z')
3668 || (c >= 'A' && c <= 'Z')
3669 || (c >= '0' && c <= '9')
3670 || c == '-' || c == '_'))
3671 bad_count++;
3672 else
3673 good_count++;
3674 }
3675 }
3676 else
3677 /* Not a string => completely invalid. */
3678 bad_count = 5, good_count = 0;
3679
3680 /* If name is valid already, return. */
3681 if (bad_count == 0)
3682 return;
3683
3684 /* If name is entirely invalid, or nearly so, use `emacs'. */
3685 if (good_count == 0
3686 || (good_count == 1 && bad_count > 0))
3687 {
3688 Vx_resource_name = build_string ("emacs");
3689 return;
3690 }
3691
3692 /* Name is partly valid. Copy it and replace the invalid characters
3693 with underscores. */
3694
3695 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3696
3697 for (i = 0; i < len; i++)
3698 {
3699 int c = SREF (new, i);
3700 if (! ((c >= 'a' && c <= 'z')
3701 || (c >= 'A' && c <= 'Z')
3702 || (c >= '0' && c <= '9')
3703 || c == '-' || c == '_'))
3704 SSET (new, i, '_');
3705 }
3706}
3707
3708
3709extern char *x_get_string_resource P_ ((XrmDatabase, char *, char *));
3710extern Display_Info *check_x_display_info P_ ((Lisp_Object));
3711
3712
b5251fe7 3713/* Get specified attribute from resource database RDB.
972f4259
KS
3714 See Fx_get_resource below for other parameters. */
3715
3716static Lisp_Object
3717xrdb_get_resource (rdb, attribute, class, component, subclass)
3718 XrmDatabase rdb;
3719 Lisp_Object attribute, class, component, subclass;
3720{
3721 register char *value;
3722 char *name_key;
3723 char *class_key;
3724
3725 CHECK_STRING (attribute);
3726 CHECK_STRING (class);
3727
3728 if (!NILP (component))
3729 CHECK_STRING (component);
3730 if (!NILP (subclass))
3731 CHECK_STRING (subclass);
3732 if (NILP (component) != NILP (subclass))
3733 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3734
3735 validate_x_resource_name ();
3736
3737 /* Allocate space for the components, the dots which separate them,
3738 and the final '\0'. Make them big enough for the worst case. */
3739 name_key = (char *) alloca (SBYTES (Vx_resource_name)
3740 + (STRINGP (component)
3741 ? SBYTES (component) : 0)
3742 + SBYTES (attribute)
3743 + 3);
3744
3745 class_key = (char *) alloca (SBYTES (Vx_resource_class)
3746 + SBYTES (class)
3747 + (STRINGP (subclass)
3748 ? SBYTES (subclass) : 0)
3749 + 3);
3750
3751 /* Start with emacs.FRAMENAME for the name (the specific one)
3752 and with `Emacs' for the class key (the general one). */
3753 strcpy (name_key, SDATA (Vx_resource_name));
3754 strcpy (class_key, SDATA (Vx_resource_class));
3755
3756 strcat (class_key, ".");
3757 strcat (class_key, SDATA (class));
3758
3759 if (!NILP (component))
3760 {
3761 strcat (class_key, ".");
3762 strcat (class_key, SDATA (subclass));
3763
3764 strcat (name_key, ".");
3765 strcat (name_key, SDATA (component));
3766 }
3767
3768 strcat (name_key, ".");
3769 strcat (name_key, SDATA (attribute));
3770
3771 value = x_get_string_resource (rdb, name_key, class_key);
3772
3773 if (value != (char *) 0)
3774 return build_string (value);
3775 else
3776 return Qnil;
3777}
3778
3779
3780DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
3781 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
3782This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
3783class, where INSTANCE is the name under which Emacs was invoked, or
3784the name specified by the `-name' or `-rn' command-line arguments.
3785
3786The optional arguments COMPONENT and SUBCLASS add to the key and the
3787class, respectively. You must specify both of them or neither.
3788If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
3789and the class is `Emacs.CLASS.SUBCLASS'. */)
3790 (attribute, class, component, subclass)
3791 Lisp_Object attribute, class, component, subclass;
3792{
3793#ifdef HAVE_X_WINDOWS
3794 check_x ();
3795#endif
3796
3797 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
3798 attribute, class, component, subclass);
3799}
3800
3801/* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
3802
3803Lisp_Object
3804display_x_get_resource (dpyinfo, attribute, class, component, subclass)
a1702920 3805 Display_Info *dpyinfo;
972f4259
KS
3806 Lisp_Object attribute, class, component, subclass;
3807{
3808 return xrdb_get_resource (dpyinfo->xrdb,
3809 attribute, class, component, subclass);
3810}
3811
3812/* Used when C code wants a resource value. */
3813
3814char *
3815x_get_resource_string (attribute, class)
3816 char *attribute, *class;
3817{
3818 char *name_key;
3819 char *class_key;
3820 struct frame *sf = SELECTED_FRAME ();
3821
3822 /* Allocate space for the components, the dots which separate them,
3823 and the final '\0'. */
3824 name_key = (char *) alloca (SBYTES (Vinvocation_name)
3825 + strlen (attribute) + 2);
3826 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3827 + strlen (class) + 2);
3828
3829 sprintf (name_key, "%s.%s", SDATA (Vinvocation_name), attribute);
3830 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3831
3832 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
3833 name_key, class_key);
3834}
3835
3836
3837/* Return the value of parameter PARAM.
3838
3839 First search ALIST, then Vdefault_frame_alist, then the X defaults
3840 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3841
3842 Convert the resource to the type specified by desired_type.
3843
3844 If no default is specified, return Qunbound. If you call
3845 x_get_arg, make sure you deal with Qunbound in a reasonable way,
3846 and don't let it get stored in any Lisp-visible variables! */
3847
3848Lisp_Object
3849x_get_arg (dpyinfo, alist, param, attribute, class, type)
b5251fe7 3850 Display_Info *dpyinfo;
972f4259
KS
3851 Lisp_Object alist, param;
3852 char *attribute;
3853 char *class;
3854 enum resource_types type;
3855{
3856 register Lisp_Object tem;
3857
3858 tem = Fassq (param, alist);
d00368cf
RS
3859
3860 if (!NILP (tem))
3861 {
3862 /* If we find this parm in ALIST, clear it out
3863 so that it won't be "left over" at the end. */
58ec2913 3864#ifndef WINDOWSNT /* w32fns.c has not yet been changed to cope with this. */
5f694926 3865 Lisp_Object tail;
d00368cf 3866 XSETCAR (tem, Qnil);
5f694926
RS
3867 /* In case the parameter appears more than once in the alist,
3868 clear it out. */
3869 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3870 if (CONSP (XCAR (tail))
3871 && EQ (XCAR (XCAR (tail)), param))
3872 XSETCAR (XCAR (tail), Qnil);
d00368cf
RS
3873#endif
3874 }
3875 else
972f4259 3876 tem = Fassq (param, Vdefault_frame_alist);
d00368cf
RS
3877
3878 /* If it wasn't specified in ALIST or the Lisp-level defaults,
3879 look in the X resources. */
972f4259
KS
3880 if (EQ (tem, Qnil))
3881 {
3882 if (attribute)
3883 {
3884 tem = display_x_get_resource (dpyinfo,
3885 build_string (attribute),
3886 build_string (class),
3887 Qnil, Qnil);
3888
3889 if (NILP (tem))
3890 return Qunbound;
3891
3892 switch (type)
3893 {
3894 case RES_TYPE_NUMBER:
3895 return make_number (atoi (SDATA (tem)));
3896
3897 case RES_TYPE_FLOAT:
3898 return make_float (atof (SDATA (tem)));
3899
3900 case RES_TYPE_BOOLEAN:
3901 tem = Fdowncase (tem);
3902 if (!strcmp (SDATA (tem), "on")
3903 || !strcmp (SDATA (tem), "true"))
3904 return Qt;
3905 else
3906 return Qnil;
3907
3908 case RES_TYPE_STRING:
3909 return tem;
3910
3911 case RES_TYPE_SYMBOL:
3912 /* As a special case, we map the values `true' and `on'
3913 to Qt, and `false' and `off' to Qnil. */
3914 {
3915 Lisp_Object lower;
3916 lower = Fdowncase (tem);
3917 if (!strcmp (SDATA (lower), "on")
3918 || !strcmp (SDATA (lower), "true"))
3919 return Qt;
3920 else if (!strcmp (SDATA (lower), "off")
3921 || !strcmp (SDATA (lower), "false"))
3922 return Qnil;
3923 else
3924 return Fintern (tem, Qnil);
3925 }
3926
3927 default:
3928 abort ();
3929 }
3930 }
3931 else
3932 return Qunbound;
3933 }
3934 return Fcdr (tem);
3935}
3936
3937Lisp_Object
3938x_frame_get_arg (f, alist, param, attribute, class, type)
3939 struct frame *f;
3940 Lisp_Object alist, param;
3941 char *attribute;
3942 char *class;
3943 enum resource_types type;
3944{
3945 return x_get_arg (FRAME_X_DISPLAY_INFO (f),
3946 alist, param, attribute, class, type);
3947}
3948
3949/* Like x_frame_get_arg, but also record the value in f->param_alist. */
3950
3951Lisp_Object
3952x_frame_get_and_record_arg (f, alist, param, attribute, class, type)
3953 struct frame *f;
3954 Lisp_Object alist, param;
3955 char *attribute;
3956 char *class;
3957 enum resource_types type;
3958{
3959 Lisp_Object value;
3960
3961 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
3962 attribute, class, type);
edd1c685 3963 if (! NILP (value) && ! EQ (value, Qunbound))
972f4259
KS
3964 store_frame_param (f, param, value);
3965
3966 return value;
3967}
3968
3969
3970/* Record in frame F the specified or default value according to ALIST
3971 of the parameter named PROP (a Lisp symbol).
3972 If no value is specified for PROP, look for an X default for XPROP
3973 on the frame named NAME.
3974 If that is not found either, use the value DEFLT. */
3975
3976Lisp_Object
3977x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3978 struct frame *f;
3979 Lisp_Object alist;
3980 Lisp_Object prop;
3981 Lisp_Object deflt;
3982 char *xprop;
3983 char *xclass;
3984 enum resource_types type;
3985{
3986 Lisp_Object tem;
3987
3988 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
3989 if (EQ (tem, Qunbound))
3990 tem = deflt;
3991 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3992 return tem;
3993}
3994
3995
3996
3997\f
3998DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3999 doc: /* Parse an X-style geometry string STRING.
4000Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
4001The properties returned may include `top', `left', `height', and `width'.
4002The value of `left' or `top' may be an integer,
4003or a list (+ N) meaning N pixels relative to top/left corner,
4004or a list (- N) meaning -N pixels relative to bottom/right corner. */)
4005 (string)
4006 Lisp_Object string;
4007{
4008 int geometry, x, y;
4009 unsigned int width, height;
4010 Lisp_Object result;
4011
4012 CHECK_STRING (string);
4013
4014 geometry = XParseGeometry ((char *) SDATA (string),
4015 &x, &y, &width, &height);
4016
4017#if 0
4018 if (!!(geometry & XValue) != !!(geometry & YValue))
4019 error ("Must specify both x and y position, or neither");
4020#endif
4021
4022 result = Qnil;
4023 if (geometry & XValue)
4024 {
4025 Lisp_Object element;
4026
4027 if (x >= 0 && (geometry & XNegative))
4028 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
4029 else if (x < 0 && ! (geometry & XNegative))
4030 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
4031 else
4032 element = Fcons (Qleft, make_number (x));
4033 result = Fcons (element, result);
4034 }
4035
4036 if (geometry & YValue)
4037 {
4038 Lisp_Object element;
4039
4040 if (y >= 0 && (geometry & YNegative))
4041 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
4042 else if (y < 0 && ! (geometry & YNegative))
4043 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
4044 else
4045 element = Fcons (Qtop, make_number (y));
4046 result = Fcons (element, result);
4047 }
4048
4049 if (geometry & WidthValue)
4050 result = Fcons (Fcons (Qwidth, make_number (width)), result);
4051 if (geometry & HeightValue)
4052 result = Fcons (Fcons (Qheight, make_number (height)), result);
4053
4054 return result;
4055}
4056
4057/* Calculate the desired size and position of frame F.
4058 Return the flags saying which aspects were specified.
4059
4060 Also set the win_gravity and size_hint_flags of F.
4061
4062 Adjust height for toolbar if TOOLBAR_P is 1.
4063
4064 This function does not make the coordinates positive. */
4065
4066#define DEFAULT_ROWS 40
4067#define DEFAULT_COLS 80
4068
4069int
4070x_figure_window_size (f, parms, toolbar_p)
4071 struct frame *f;
4072 Lisp_Object parms;
4073 int toolbar_p;
4074{
4075 register Lisp_Object tem0, tem1, tem2;
4076 long window_prompting = 0;
4077 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4078
4079 /* Default values if we fall through.
4080 Actually, if that happens we should get
4081 window manager prompting. */
5af5757b
KS
4082 SET_FRAME_COLS (f, DEFAULT_COLS);
4083 FRAME_LINES (f) = DEFAULT_ROWS;
972f4259
KS
4084 /* Window managers expect that if program-specified
4085 positions are not (0,0), they're intentional, not defaults. */
5af5757b
KS
4086 f->top_pos = 0;
4087 f->left_pos = 0;
972f4259 4088
5af5757b 4089 /* Ensure that old new_text_cols and new_text_lines will not override the
972f4259
KS
4090 values set here. */
4091 /* ++KFS: This was specific to W32, but seems ok for all platforms */
5af5757b 4092 f->new_text_cols = f->new_text_lines = 0;
972f4259
KS
4093
4094 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
4095 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
4096 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
4097 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
4098 {
4099 if (!EQ (tem0, Qunbound))
4100 {
4101 CHECK_NUMBER (tem0);
5af5757b 4102 FRAME_LINES (f) = XINT (tem0);
972f4259
KS
4103 }
4104 if (!EQ (tem1, Qunbound))
4105 {
4106 CHECK_NUMBER (tem1);
5af5757b 4107 SET_FRAME_COLS (f, XINT (tem1));
972f4259
KS
4108 }
4109 if (!NILP (tem2) && !EQ (tem2, Qunbound))
4110 window_prompting |= USSize;
4111 else
4112 window_prompting |= PSize;
4113 }
4114
5af5757b
KS
4115 f->scroll_bar_actual_width
4116 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
972f4259
KS
4117
4118 /* This used to be done _before_ calling x_figure_window_size, but
4119 since the height is reset here, this was really a no-op. I
4120 assume that moving it here does what Gerd intended (although he
4121 no longer can remember what that was... ++KFS, 2003-03-25. */
4122
4123 /* Add the tool-bar height to the initial frame height so that the
4124 user gets a text display area of the size he specified with -g or
4125 via .Xdefaults. Later changes of the tool-bar height don't
4126 change the frame size. This is done so that users can create
4127 tall Emacs frames without having to guess how tall the tool-bar
4128 will get. */
4129 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
4130 {
4131 int margin, relief, bar_height;
4132
4133 relief = (tool_bar_button_relief >= 0
4134 ? tool_bar_button_relief
4135 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4136
4137 if (INTEGERP (Vtool_bar_button_margin)
4138 && XINT (Vtool_bar_button_margin) > 0)
4139 margin = XFASTINT (Vtool_bar_button_margin);
4140 else if (CONSP (Vtool_bar_button_margin)
4141 && INTEGERP (XCDR (Vtool_bar_button_margin))
4142 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4143 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4144 else
4145 margin = 0;
4146
4147 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5af5757b 4148 FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
972f4259
KS
4149 }
4150
4151 compute_fringe_widths (f, 0);
4152
5af5757b
KS
4153 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, FRAME_COLS (f));
4154 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
972f4259
KS
4155
4156 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
4157 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
4158 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
4159 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
4160 {
4161 if (EQ (tem0, Qminus))
4162 {
5af5757b 4163 f->top_pos = 0;
972f4259
KS
4164 window_prompting |= YNegative;
4165 }
4166 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
4167 && CONSP (XCDR (tem0))
4168 && INTEGERP (XCAR (XCDR (tem0))))
4169 {
5af5757b 4170 f->top_pos = - XINT (XCAR (XCDR (tem0)));
972f4259
KS
4171 window_prompting |= YNegative;
4172 }
4173 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
4174 && CONSP (XCDR (tem0))
4175 && INTEGERP (XCAR (XCDR (tem0))))
4176 {
5af5757b 4177 f->top_pos = XINT (XCAR (XCDR (tem0)));
972f4259
KS
4178 }
4179 else if (EQ (tem0, Qunbound))
5af5757b 4180 f->top_pos = 0;
972f4259
KS
4181 else
4182 {
4183 CHECK_NUMBER (tem0);
5af5757b
KS
4184 f->top_pos = XINT (tem0);
4185 if (f->top_pos < 0)
972f4259
KS
4186 window_prompting |= YNegative;
4187 }
4188
4189 if (EQ (tem1, Qminus))
4190 {
5af5757b 4191 f->left_pos = 0;
972f4259
KS
4192 window_prompting |= XNegative;
4193 }
4194 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
4195 && CONSP (XCDR (tem1))
4196 && INTEGERP (XCAR (XCDR (tem1))))
4197 {
5af5757b 4198 f->left_pos = - XINT (XCAR (XCDR (tem1)));
972f4259
KS
4199 window_prompting |= XNegative;
4200 }
4201 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
4202 && CONSP (XCDR (tem1))
4203 && INTEGERP (XCAR (XCDR (tem1))))
4204 {
5af5757b 4205 f->left_pos = XINT (XCAR (XCDR (tem1)));
972f4259
KS
4206 }
4207 else if (EQ (tem1, Qunbound))
5af5757b 4208 f->left_pos = 0;
972f4259
KS
4209 else
4210 {
4211 CHECK_NUMBER (tem1);
5af5757b
KS
4212 f->left_pos = XINT (tem1);
4213 if (f->left_pos < 0)
972f4259
KS
4214 window_prompting |= XNegative;
4215 }
4216
4217 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
4218 window_prompting |= USPosition;
4219 else
4220 window_prompting |= PPosition;
4221 }
4222
5af5757b 4223 if (f->want_fullscreen != FULLSCREEN_NONE)
972f4259
KS
4224 {
4225 int left, top;
4226 int width, height;
4227
4228 /* It takes both for some WM:s to place it where we want */
4229 window_prompting = USPosition | PPosition;
4230 x_fullscreen_adjust (f, &width, &height, &top, &left);
5af5757b
KS
4231 FRAME_COLS (f) = width;
4232 FRAME_LINES (f) = height;
4233 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
4234 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
4235 f->left_pos = left;
4236 f->top_pos = top;
972f4259
KS
4237 }
4238
4239 if (window_prompting & XNegative)
4240 {
4241 if (window_prompting & YNegative)
5af5757b 4242 f->win_gravity = SouthEastGravity;
972f4259 4243 else
5af5757b 4244 f->win_gravity = NorthEastGravity;
972f4259
KS
4245 }
4246 else
4247 {
4248 if (window_prompting & YNegative)
5af5757b 4249 f->win_gravity = SouthWestGravity;
972f4259 4250 else
5af5757b 4251 f->win_gravity = NorthWestGravity;
972f4259
KS
4252 }
4253
5af5757b 4254 f->size_hint_flags = window_prompting;
972f4259
KS
4255
4256 return window_prompting;
4257}
4258
4259
4260
4261#endif /* HAVE_WINDOW_SYSTEM */
4262
4263
4264\f
4265/***********************************************************************
4266 Initialization
4267 ***********************************************************************/
4268
4269void
4270syms_of_frame ()
4271{
4272 Qframep = intern ("framep");
4273 staticpro (&Qframep);
4274 Qframe_live_p = intern ("frame-live-p");
4275 staticpro (&Qframe_live_p);
4276 Qheight = intern ("height");
4277 staticpro (&Qheight);
4278 Qicon = intern ("icon");
4279 staticpro (&Qicon);
4280 Qminibuffer = intern ("minibuffer");
4281 staticpro (&Qminibuffer);
4282 Qmodeline = intern ("modeline");
4283 staticpro (&Qmodeline);
4284 Qonly = intern ("only");
4285 staticpro (&Qonly);
4286 Qwidth = intern ("width");
4287 staticpro (&Qwidth);
4288 Qgeometry = intern ("geometry");
4289 staticpro (&Qgeometry);
4290 Qicon_left = intern ("icon-left");
4291 staticpro (&Qicon_left);
4292 Qicon_top = intern ("icon-top");
4293 staticpro (&Qicon_top);
4294 Qleft = intern ("left");
4295 staticpro (&Qleft);
4296 Qright = intern ("right");
4297 staticpro (&Qright);
4298 Quser_position = intern ("user-position");
4299 staticpro (&Quser_position);
4300 Quser_size = intern ("user-size");
4301 staticpro (&Quser_size);
4302 Qwindow_id = intern ("window-id");
4303 staticpro (&Qwindow_id);
4304#ifdef HAVE_X_WINDOWS
4305 Qouter_window_id = intern ("outer-window-id");
4306 staticpro (&Qouter_window_id);
4307#endif
4308 Qparent_id = intern ("parent-id");
4309 staticpro (&Qparent_id);
4310 Qx = intern ("x");
4311 staticpro (&Qx);
4312 Qw32 = intern ("w32");
4313 staticpro (&Qw32);
4314 Qpc = intern ("pc");
4315 staticpro (&Qpc);
4316 Qmac = intern ("mac");
4317 staticpro (&Qmac);
4318 Qvisible = intern ("visible");
4319 staticpro (&Qvisible);
4320 Qbuffer_predicate = intern ("buffer-predicate");
4321 staticpro (&Qbuffer_predicate);
4322 Qbuffer_list = intern ("buffer-list");
4323 staticpro (&Qbuffer_list);
a18b8cb5
KL
4324 Qburied_buffer_list = intern ("buried-buffer-list");
4325 staticpro (&Qburied_buffer_list);
972f4259
KS
4326 Qdisplay_type = intern ("display-type");
4327 staticpro (&Qdisplay_type);
4328 Qbackground_mode = intern ("background-mode");
4329 staticpro (&Qbackground_mode);
4330 Qtty_color_mode = intern ("tty-color-mode");
4331 staticpro (&Qtty_color_mode);
28d440ab
KL
4332 Qtty = intern ("tty");
4333 staticpro (&Qtty);
4334 Qtty_type = intern ("tty-type");
4335 staticpro (&Qtty_type);
7f19e125
KL
4336 Qwindow_system = intern ("window-system");
4337 staticpro (&Qwindow_system);
da8e8fc1
KL
4338 Qenvironment = intern ("environment");
4339 staticpro (&Qenvironment);
7f19e125 4340
972f4259
KS
4341 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
4342 staticpro (&Qface_set_after_frame_default);
4343
26c34ec2
CY
4344 Qinhibit_face_set_after_frame_default
4345 = intern ("inhibit-face-set-after-frame-default");
4346 staticpro (&Qinhibit_face_set_after_frame_default);
4347
972f4259
KS
4348 Qfullwidth = intern ("fullwidth");
4349 staticpro (&Qfullwidth);
4350 Qfullheight = intern ("fullheight");
4351 staticpro (&Qfullheight);
4352 Qfullboth = intern ("fullboth");
4353 staticpro (&Qfullboth);
4354 Qx_resource_name = intern ("x-resource-name");
4355 staticpro (&Qx_resource_name);
4356
4357 Qx_frame_parameter = intern ("x-frame-parameter");
4358 staticpro (&Qx_frame_parameter);
4359
6ed8eeff
KL
4360 Qterminal = intern ("terminal");
4361 staticpro (&Qterminal);
4362 Qterminal_live_p = intern ("terminal-live-p");
4363 staticpro (&Qterminal_live_p);
b6660415 4364
972f4259
KS
4365 {
4366 int i;
4367
4368 for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++)
4369 {
4370 Lisp_Object v = intern (frame_parms[i].name);
4371 if (frame_parms[i].variable)
4372 {
4373 *frame_parms[i].variable = v;
4374 staticpro (frame_parms[i].variable);
4375 }
4376 Fput (v, Qx_frame_parameter, make_number (i));
4377 }
4378 }
4379
2731a0ad 4380#ifdef HAVE_WINDOW_SYSTEM
972f4259
KS
4381 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
4382 doc: /* The name Emacs uses to look up X resources.
4383`x-get-resource' uses this as the first component of the instance name
4384when requesting resource values.
4385Emacs initially sets `x-resource-name' to the name under which Emacs
4386was invoked, or to the value specified with the `-name' or `-rn'
4387switches, if present.
4388
4389It may be useful to bind this variable locally around a call
4390to `x-get-resource'. See also the variable `x-resource-class'. */);
4391 Vx_resource_name = Qnil;
4392
4393 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
4394 doc: /* The class Emacs uses to look up X resources.
4395`x-get-resource' uses this as the first component of the instance class
4396when requesting resource values.
4397
4398Emacs initially sets `x-resource-class' to "Emacs".
4399
4400Setting this variable permanently is not a reasonable thing to do,
4401but binding this variable locally around a call to `x-get-resource'
4402is a reasonable practice. See also the variable `x-resource-name'. */);
4403 Vx_resource_class = build_string (EMACS_CLASS);
2731a0ad 4404#endif
972f4259
KS
4405
4406 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
4407 doc: /* Alist of default values for frame creation.
4408These may be set in your init file, like this:
5ff00c42 4409 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
972f4259
KS
4410These override values given in window system configuration data,
4411 including X Windows' defaults database.
4412For values specific to the first Emacs frame, see `initial-frame-alist'.
095fe281 4413For window-system specific values, see `window-system-default-frame-alist'.
972f4259
KS
4414For values specific to the separate minibuffer frame, see
4415 `minibuffer-frame-alist'.
4416The `menu-bar-lines' element of the list controls whether new frames
4417 have menu bars; `menu-bar-mode' works by altering this element.
4418Setting this variable does not affect existing frames, only new ones. */);
4419 Vdefault_frame_alist = Qnil;
4420
a6e20602
KS
4421 DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
4422 doc: /* Default position of scroll bars on this window-system. */);
4423#ifdef HAVE_WINDOW_SYSTEM
b15325b2 4424#if defined(HAVE_NTGUI) || defined(MAC_OS)
a6e20602
KS
4425 /* MS-Windows has scroll bars on the right by default. */
4426 Vdefault_frame_scroll_bars = Qright;
4427#else
4428 Vdefault_frame_scroll_bars = Qleft;
4429#endif
4430#else
4431 Vdefault_frame_scroll_bars = Qnil;
4432#endif
4433
daf01701
KL
4434 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
4435 doc: /* The initial frame-object, which represents Emacs's stdout. */);
4436
972f4259 4437 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
bd45aef7 4438 doc: /* Non-nil if all of Emacs is iconified and frame updates are not needed. */);
972f4259
KS
4439 Vemacs_iconified = Qnil;
4440
4441 DEFVAR_LISP ("mouse-position-function", &Vmouse_position_function,
4442 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4443`mouse-position' calls this function, passing its usual return value as
4444argument, and returns whatever this function returns.
4445This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4446which need to do mouse handling at the Lisp level. */);
4447 Vmouse_position_function = Qnil;
4448
4449 DEFVAR_LISP ("mouse-highlight", &Vmouse_highlight,
4450 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4451If the value is an integer, highlighting is only shown after moving the
4452mouse, while keyboard input turns off the highlight even when the mouse
4453is over the clickable text. However, the mouse shape still indicates
4454when the mouse is over clickable text. */);
4455 Vmouse_highlight = Qt;
4456
4457 DEFVAR_LISP ("delete-frame-functions", &Vdelete_frame_functions,
4458 doc: /* Functions to be run before deleting a frame.
4459The functions are run with one arg, the frame to be deleted.
e519a50b
KL
4460See `delete-frame'.
4461
4462Note that functions in this list may be called twice on the same
4463frame. In the second invocation, the frame is already deleted, and
4464the function should do nothing. (You can use `frame-live-p' to check
4465for this.) This wrinkle happens when an earlier function in
4466`delete-frame-functions' (indirectly) calls delete-frame
4467recursively. */);
972f4259
KS
4468 Vdelete_frame_functions = Qnil;
4469
4470 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
4471 doc: /* Minibufferless frames use this frame's minibuffer.
4472
4473Emacs cannot create minibufferless frames unless this is set to an
4474appropriate surrogate.
4475
4476Emacs consults this variable only when creating minibufferless
4477frames; once the frame is created, it sticks with its assigned
4478minibuffer, no matter what this variable is set to. This means that
4479this variable doesn't necessarily say anything meaningful about the
4480current set of frames, or where the minibuffer is currently being
4481displayed.
4482
4483This variable is local to the current terminal and cannot be buffer-local. */);
4484
4485 staticpro (&Vframe_list);
4486
4487 defsubr (&Sactive_minibuffer_window);
4488 defsubr (&Sframep);
4489 defsubr (&Sframe_live_p);
428a555e 4490 defsubr (&Swindow_system);
972f4259
KS
4491 defsubr (&Smake_terminal_frame);
4492 defsubr (&Shandle_switch_frame);
972f4259
KS
4493 defsubr (&Sselect_frame);
4494 defsubr (&Sselected_frame);
4495 defsubr (&Swindow_frame);
4496 defsubr (&Sframe_root_window);
4497 defsubr (&Sframe_first_window);
4498 defsubr (&Sframe_selected_window);
4499 defsubr (&Sset_frame_selected_window);
4500 defsubr (&Sframe_list);
4501 defsubr (&Snext_frame);
4502 defsubr (&Sprevious_frame);
4503 defsubr (&Sdelete_frame);
4504 defsubr (&Smouse_position);
4505 defsubr (&Smouse_pixel_position);
4506 defsubr (&Sset_mouse_position);
4507 defsubr (&Sset_mouse_pixel_position);
4508#if 0
4509 defsubr (&Sframe_configuration);
4510 defsubr (&Srestore_frame_configuration);
4511#endif
4512 defsubr (&Smake_frame_visible);
4513 defsubr (&Smake_frame_invisible);
4514 defsubr (&Siconify_frame);
4515 defsubr (&Sframe_visible_p);
4516 defsubr (&Svisible_frame_list);
4517 defsubr (&Sraise_frame);
4518 defsubr (&Slower_frame);
4519 defsubr (&Sredirect_frame_focus);
4520 defsubr (&Sframe_focus);
4521 defsubr (&Sframe_parameters);
4522 defsubr (&Sframe_parameter);
4523 defsubr (&Smodify_frame_parameters);
da8e8fc1 4524 defsubr (&Sframe_with_environment);
972f4259
KS
4525 defsubr (&Sframe_char_height);
4526 defsubr (&Sframe_char_width);
4527 defsubr (&Sframe_pixel_height);
4528 defsubr (&Sframe_pixel_width);
4529 defsubr (&Sset_frame_height);
4530 defsubr (&Sset_frame_width);
4531 defsubr (&Sset_frame_size);
4532 defsubr (&Sset_frame_position);
4533
4534#ifdef HAVE_WINDOW_SYSTEM
4535 defsubr (&Sx_get_resource);
4536 defsubr (&Sx_parse_geometry);
4537#endif
4538
dc6f92b8 4539}
ab5796a9
MB
4540
4541/* arch-tag: 7dbf2c69-9aad-45f8-8296-db893d6dd039
4542 (do not change this comment) */