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