Merged from emacs@sv.gnu.org
[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 }
f65f7603
KL
2344
2345 return Qnil;
dc6f92b8
JB
2346}
2347
ff11dfa1 2348DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
14ff1ee0
PJ
2349 doc: /* Return the parameters-alist of frame FRAME.
2350It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2351The meaningful PARMs depend on the kind of frame.
2352If FRAME is omitted, return information on the currently selected frame. */)
2353 (frame)
ff11dfa1 2354 Lisp_Object frame;
dc6f92b8
JB
2355{
2356 Lisp_Object alist;
f769f1b2 2357 FRAME_PTR f;
dd10ec4f 2358 int height, width;
57629833 2359 struct gcpro gcpro1;
dc6f92b8 2360
03390a72 2361 if (NILP (frame))
8d2666fe
GM
2362 frame = selected_frame;
2363
b7826503 2364 CHECK_FRAME (frame);
8d2666fe 2365 f = XFRAME (frame);
dc6f92b8 2366
f769f1b2 2367 if (!FRAME_LIVE_P (f))
dc6f92b8
JB
2368 return Qnil;
2369
ff11dfa1 2370 alist = Fcopy_alist (f->param_alist);
57629833 2371 GCPRO1 (alist);
177c0ea7 2372
2d764c78 2373 if (!FRAME_WINDOW_P (f))
bb221971 2374 {
4aec4b29
EZ
2375 int fg = FRAME_FOREGROUND_PIXEL (f);
2376 int bg = FRAME_BACKGROUND_PIXEL (f);
e1d0bbc9
EZ
2377 Lisp_Object elt;
2378
2379 /* If the frame's parameter alist says the colors are
2380 unspecified and reversed, take the frame's background pixel
2381 for foreground and vice versa. */
2382 elt = Fassq (Qforeground_color, alist);
70de9f06
EZ
2383 if (!NILP (elt) && CONSP (elt) && STRINGP (XCDR (elt)))
2384 {
d5db4077 2385 if (strncmp (SDATA (XCDR (elt)),
70de9f06 2386 unspecified_bg,
d5db4077 2387 SCHARS (XCDR (elt))) == 0)
70de9f06 2388 store_in_alist (&alist, Qforeground_color, tty_color_name (f, bg));
d5db4077 2389 else if (strncmp (SDATA (XCDR (elt)),
70de9f06 2390 unspecified_fg,
d5db4077 2391 SCHARS (XCDR (elt))) == 0)
70de9f06
EZ
2392 store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
2393 }
e1d0bbc9
EZ
2394 else
2395 store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
2396 elt = Fassq (Qbackground_color, alist);
70de9f06
EZ
2397 if (!NILP (elt) && CONSP (elt) && STRINGP (XCDR (elt)))
2398 {
d5db4077 2399 if (strncmp (SDATA (XCDR (elt)),
70de9f06 2400 unspecified_fg,
d5db4077 2401 SCHARS (XCDR (elt))) == 0)
70de9f06 2402 store_in_alist (&alist, Qbackground_color, tty_color_name (f, fg));
d5db4077 2403 else if (strncmp (SDATA (XCDR (elt)),
70de9f06 2404 unspecified_bg,
d5db4077 2405 SCHARS (XCDR (elt))) == 0)
70de9f06
EZ
2406 store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
2407 }
e1d0bbc9
EZ
2408 else
2409 store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
2d764c78
EZ
2410 store_in_alist (&alist, intern ("font"),
2411 build_string (FRAME_MSDOS_P (f)
2412 ? "ms-dos"
4ec0d3c1 2413 : FRAME_W32_P (f) ? "w32term"
4ec0d3c1 2414 :"tty"));
bb221971 2415 }
fd0c2bd1 2416 store_in_alist (&alist, Qname, f->name);
5af5757b 2417 height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
dd10ec4f 2418 store_in_alist (&alist, Qheight, make_number (height));
5af5757b 2419 width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
dd10ec4f 2420 store_in_alist (&alist, Qwidth, make_number (width));
f769f1b2 2421 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
fd0c2bd1 2422 store_in_alist (&alist, Qminibuffer,
39acc701 2423 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
f769f1b2
KH
2424 : FRAME_MINIBUF_ONLY_P (f) ? Qonly
2425 : FRAME_MINIBUF_WINDOW (f)));
2426 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
03390a72 2427 store_in_alist (&alist, Qbuffer_list, frame_buffer_list (frame));
a18b8cb5 2428 store_in_alist (&alist, Qburied_buffer_list, XFRAME (frame)->buried_buffer_list);
fd0c2bd1 2429
dbc4e1c1 2430 /* I think this should be done with a hook. */
032d78fe
GV
2431#ifdef HAVE_WINDOW_SYSTEM
2432 if (FRAME_WINDOW_P (f))
ff11dfa1 2433 x_report_frame_params (f, &alist);
b6dd20ed 2434 else
fd0c2bd1 2435#endif
16a3738c
KH
2436 {
2437 /* This ought to be correct in f->param_alist for an X frame. */
2438 Lisp_Object lines;
f4e93c40 2439 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
16a3738c
KH
2440 store_in_alist (&alist, Qmenu_bar_lines, lines);
2441 }
57629833
GM
2442
2443 UNGCPRO;
dc6f92b8
JB
2444 return alist;
2445}
2446
8b60f7bc
GM
2447
2448DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
14ff1ee0
PJ
2449 doc: /* Return FRAME's value for parameter PARAMETER.
2450If FRAME is nil, describe the currently selected frame. */)
2451 (frame, parameter)
2452 Lisp_Object frame, parameter;
8b60f7bc
GM
2453{
2454 struct frame *f;
2455 Lisp_Object value;
2456
2457 if (NILP (frame))
2458 frame = selected_frame;
2459 else
b7826503
PJ
2460 CHECK_FRAME (frame);
2461 CHECK_SYMBOL (parameter);
177c0ea7 2462
8b60f7bc
GM
2463 f = XFRAME (frame);
2464 value = Qnil;
177c0ea7 2465
8b60f7bc
GM
2466 if (FRAME_LIVE_P (f))
2467 {
5cd62b8c 2468 /* Avoid consing in frequent cases. */
67d853e6
GM
2469 if (EQ (parameter, Qname))
2470 value = f->name;
6345f6aa
GM
2471#ifdef HAVE_X_WINDOWS
2472 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
2473 value = XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element);
2474#endif /* HAVE_X_WINDOWS */
75700ff2
GM
2475 else if (EQ (parameter, Qbackground_color)
2476 || EQ (parameter, Qforeground_color))
67d853e6
GM
2477 {
2478 value = Fassq (parameter, f->param_alist);
2479 if (CONSP (value))
5f65b39d 2480 {
5f65b39d
EZ
2481 value = XCDR (value);
2482 /* Fframe_parameters puts the actual fg/bg color names,
2483 even if f->param_alist says otherwise. This is
2484 important when param_alist's notion of colors is
2485 "unspecified". We need to do the same here. */
2486 if (STRINGP (value) && !FRAME_WINDOW_P (f))
2487 {
c9b08ba8 2488 const char *color_name;
e1d0bbc9
EZ
2489 EMACS_INT csz;
2490
2491 if (EQ (parameter, Qbackground_color))
2492 {
d5db4077
KR
2493 color_name = SDATA (value);
2494 csz = SCHARS (value);
e1d0bbc9
EZ
2495 if (strncmp (color_name, unspecified_bg, csz) == 0)
2496 value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
2497 else if (strncmp (color_name, unspecified_fg, csz) == 0)
2498 value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
2499 }
2500 else if (EQ (parameter, Qforeground_color))
2501 {
d5db4077
KR
2502 color_name = SDATA (value);
2503 csz = SCHARS (value);
e1d0bbc9
EZ
2504 if (strncmp (color_name, unspecified_fg, csz) == 0)
2505 value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
2506 else if (strncmp (color_name, unspecified_bg, csz) == 0)
2507 value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
2508 }
5f65b39d
EZ
2509 }
2510 }
b23236fb
EZ
2511 else
2512 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
67d853e6 2513 }
75700ff2
GM
2514 else if (EQ (parameter, Qdisplay_type)
2515 || EQ (parameter, Qbackground_mode))
75700ff2
GM
2516 value = Fcdr (Fassq (parameter, f->param_alist));
2517 else
2518 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
8b60f7bc 2519 }
177c0ea7 2520
8b60f7bc
GM
2521 return value;
2522}
2523
2524
177c0ea7 2525DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
ff11dfa1 2526 Smodify_frame_parameters, 2, 2, 0,
14ff1ee0
PJ
2527 doc: /* Modify the parameters of frame FRAME according to ALIST.
2528If FRAME is nil, it defaults to the selected frame.
2529ALIST is an alist of parameters to change and their new values.
2530Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
2531The meaningful PARMs depend on the kind of frame.
2532Undefined PARMs are ignored, but stored in the frame's parameter list
2533so that `frame-parameters' will return them.
2534
2535The value of frame parameter FOO can also be accessed
2536as a frame-local binding for the variable FOO, if you have
2537enabled such bindings for that variable with `make-variable-frame-local'. */)
2538 (frame, alist)
ff11dfa1 2539 Lisp_Object frame, alist;
dc6f92b8 2540{
fd0c2bd1 2541 FRAME_PTR f;
213bac8a 2542 register Lisp_Object tail, prop, val;
dc6f92b8 2543
ff11dfa1 2544 if (EQ (frame, Qnil))
8d2666fe 2545 frame = selected_frame;
b7826503 2546 CHECK_LIVE_FRAME (frame);
8d2666fe 2547 f = XFRAME (frame);
dc6f92b8 2548
dbc4e1c1 2549 /* I think this should be done with a hook. */
032d78fe
GV
2550#ifdef HAVE_WINDOW_SYSTEM
2551 if (FRAME_WINDOW_P (f))
fd0c2bd1 2552 x_set_frame_parameters (f, alist);
329ca574 2553 else
bb221971
RS
2554#endif
2555#ifdef MSDOS
2556 if (FRAME_MSDOS_P (f))
2557 IT_set_frame_parameters (f, alist);
2558 else
329ca574 2559#endif
574a1a90 2560
41d44f1f
RS
2561 {
2562 int length = XINT (Flength (alist));
2563 int i;
2564 Lisp_Object *parms
2565 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2566 Lisp_Object *values
2567 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2568
2569 /* Extract parm names and values into those vectors. */
2570
2571 i = 0;
2572 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2573 {
213bac8a 2574 Lisp_Object elt;
41d44f1f
RS
2575
2576 elt = Fcar (tail);
2577 parms[i] = Fcar (elt);
2578 values[i] = Fcdr (elt);
2579 i++;
2580 }
2581
2582 /* Now process them in reverse of specified order. */
2583 for (i--; i >= 0; i--)
2584 {
2585 prop = parms[i];
2586 val = values[i];
2587 store_frame_param (f, prop, val);
33d537f0
JL
2588
2589 /* Changing the background color might change the background
2590 mode, so that we have to load new defface specs.
2591 Call frame-set-background-mode to do that. */
2592 if (EQ (prop, Qbackground_color))
2593 call1 (Qframe_set_background_mode, frame);
41d44f1f
RS
2594 }
2595 }
dc6f92b8 2596}
da8e8fc1
KL
2597
2598DEFUN ("frame-with-environment", Fframe_with_environment, Sframe_with_environment, 0, 1, 0,
2599 doc: /* Return the frame that has the environment variable list for FRAME.
2600
2601The frame-local environment variable list is normally shared between
2602frames that were created in the same Emacsclient session. The
2603environment list is stored in a single frame's 'environment parameter;
2604the other frames' 'environment parameter is set to this frame. This
6d8299f6 2605function follows the chain of 'environment references to reach the
da8e8fc1
KL
2606frame that stores the actual local environment list, and returns that
2607frame. */)
2608 (frame)
2609 Lisp_Object frame;
2610{
2611 Lisp_Object hare, tortoise;
2612
2613 if (NILP (frame))
2614 frame = selected_frame;
2615 CHECK_FRAME (frame);
2616
2617 hare = tortoise = get_frame_param (XFRAME (frame), Qenvironment);
2618 while (!NILP (hare) && FRAMEP (hare))
2619 {
2620 frame = hare;
2621 hare = get_frame_param (XFRAME (hare), Qenvironment);
2622 if (NILP (hare) || !FRAMEP (hare))
2623 break;
2624 frame = hare;
2625 hare = get_frame_param (XFRAME (hare), Qenvironment);
2626 tortoise = get_frame_param (XFRAME (tortoise), Qenvironment);
2627 if (EQ (hare, tortoise))
2628 error ("Cyclic frame-local environment indirection");
2629 }
2630
2631 return frame;
2632}
2633
dc6f92b8 2634\f
a26a1f95 2635DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
14ff1ee0
PJ
2636 0, 1, 0,
2637 doc: /* Height in pixels of a line in the font in frame FRAME.
2638If FRAME is omitted, the selected frame is used.
2639For a terminal frame, the value is always 1. */)
ff11dfa1
JB
2640 (frame)
2641 Lisp_Object frame;
dc6f92b8 2642{
a26a1f95 2643 struct frame *f;
dc6f92b8 2644
a26a1f95 2645 if (NILP (frame))
8d2666fe 2646 frame = selected_frame;
b7826503 2647 CHECK_FRAME (frame);
8d2666fe 2648 f = XFRAME (frame);
a26a1f95 2649
032d78fe
GV
2650#ifdef HAVE_WINDOW_SYSTEM
2651 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2652 return make_number (x_char_height (f));
2653 else
dc6d9681 2654#endif
a26a1f95
RS
2655 return make_number (1);
2656}
dc6d9681 2657
dc6f92b8 2658
a26a1f95 2659DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
14ff1ee0
PJ
2660 0, 1, 0,
2661 doc: /* Width in pixels of characters in the font in frame FRAME.
2662If FRAME is omitted, the selected frame is used.
31b7cc74 2663On a graphical screen, the width is the standard width of the default font.
14ff1ee0
PJ
2664For a terminal screen, the value is always 1. */)
2665 (frame)
a26a1f95 2666 Lisp_Object frame;
dc6f92b8 2667{
a26a1f95
RS
2668 struct frame *f;
2669
2670 if (NILP (frame))
8d2666fe 2671 frame = selected_frame;
b7826503 2672 CHECK_FRAME (frame);
8d2666fe 2673 f = XFRAME (frame);
a26a1f95 2674
032d78fe
GV
2675#ifdef HAVE_WINDOW_SYSTEM
2676 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2677 return make_number (x_char_width (f));
2678 else
2679#endif
2680 return make_number (1);
dc6f92b8
JB
2681}
2682
177c0ea7 2683DEFUN ("frame-pixel-height", Fframe_pixel_height,
a26a1f95 2684 Sframe_pixel_height, 0, 1, 0,
14ff1ee0
PJ
2685 doc: /* Return a FRAME's height in pixels.
2686This counts only the height available for text lines,
2687not menu bars on window-system Emacs frames.
2688For a terminal frame, the result really gives the height in characters.
2689If FRAME is omitted, the selected frame is used. */)
2690 (frame)
a26a1f95 2691 Lisp_Object frame;
dc6f92b8 2692{
a26a1f95
RS
2693 struct frame *f;
2694
2695 if (NILP (frame))
8d2666fe 2696 frame = selected_frame;
b7826503 2697 CHECK_FRAME (frame);
8d2666fe 2698 f = XFRAME (frame);
a26a1f95 2699
032d78fe
GV
2700#ifdef HAVE_WINDOW_SYSTEM
2701 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2702 return make_number (x_pixel_height (f));
2703 else
dc6d9681 2704#endif
5af5757b 2705 return make_number (FRAME_LINES (f));
a26a1f95
RS
2706}
2707
177c0ea7 2708DEFUN ("frame-pixel-width", Fframe_pixel_width,
a26a1f95 2709 Sframe_pixel_width, 0, 1, 0,
14ff1ee0
PJ
2710 doc: /* Return FRAME's width in pixels.
2711For a terminal frame, the result really gives the width in characters.
2712If FRAME is omitted, the selected frame is used. */)
2713 (frame)
a26a1f95
RS
2714 Lisp_Object frame;
2715{
2716 struct frame *f;
2717
2718 if (NILP (frame))
8d2666fe 2719 frame = selected_frame;
b7826503 2720 CHECK_FRAME (frame);
8d2666fe 2721 f = XFRAME (frame);
dc6f92b8 2722
032d78fe
GV
2723#ifdef HAVE_WINDOW_SYSTEM
2724 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2725 return make_number (x_pixel_width (f));
2726 else
2727#endif
5af5757b 2728 return make_number (FRAME_COLS (f));
a26a1f95
RS
2729}
2730\f
ff11dfa1 2731DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
14ff1ee0
PJ
2732 doc: /* Specify that the frame FRAME has LINES lines.
2733Optional third arg non-nil means that redisplay should use LINES lines
2734but that the idea of the actual height of the frame should not be changed. */)
2735 (frame, lines, pretend)
735eeca3 2736 Lisp_Object frame, lines, pretend;
dc6f92b8 2737{
ff11dfa1 2738 register struct frame *f;
dc6f92b8 2739
b7826503 2740 CHECK_NUMBER (lines);
ff11dfa1 2741 if (NILP (frame))
8d2666fe 2742 frame = selected_frame;
b7826503 2743 CHECK_LIVE_FRAME (frame);
8d2666fe 2744 f = XFRAME (frame);
dc6f92b8 2745
dbc4e1c1 2746 /* I think this should be done with a hook. */
032d78fe
GV
2747#ifdef HAVE_WINDOW_SYSTEM
2748 if (FRAME_WINDOW_P (f))
dc6f92b8 2749 {
5af5757b
KS
2750 if (XINT (lines) != FRAME_LINES (f))
2751 x_set_window_size (f, 1, FRAME_COLS (f), XINT (lines));
32347cf4 2752 do_pending_window_change (0);
dc6f92b8
JB
2753 }
2754 else
fd0c2bd1 2755#endif
32347cf4 2756 change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0, 0);
dc6f92b8
JB
2757 return Qnil;
2758}
2759
ff11dfa1 2760DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
14ff1ee0
PJ
2761 doc: /* Specify that the frame FRAME has COLS columns.
2762Optional third arg non-nil means that redisplay should use COLS columns
2763but that the idea of the actual width of the frame should not be changed. */)
2764 (frame, cols, pretend)
fd0c2bd1 2765 Lisp_Object frame, cols, pretend;
dc6f92b8 2766{
ff11dfa1 2767 register struct frame *f;
b7826503 2768 CHECK_NUMBER (cols);
ff11dfa1 2769 if (NILP (frame))
8d2666fe 2770 frame = selected_frame;
b7826503 2771 CHECK_LIVE_FRAME (frame);
8d2666fe 2772 f = XFRAME (frame);
dc6f92b8 2773
dbc4e1c1 2774 /* I think this should be done with a hook. */
032d78fe
GV
2775#ifdef HAVE_WINDOW_SYSTEM
2776 if (FRAME_WINDOW_P (f))
dc6f92b8 2777 {
5af5757b
KS
2778 if (XINT (cols) != FRAME_COLS (f))
2779 x_set_window_size (f, 1, XINT (cols), FRAME_LINES (f));
32347cf4 2780 do_pending_window_change (0);
dc6f92b8
JB
2781 }
2782 else
fd0c2bd1 2783#endif
32347cf4 2784 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0, 0);
dc6f92b8
JB
2785 return Qnil;
2786}
2787
ff11dfa1 2788DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
14ff1ee0
PJ
2789 doc: /* Sets size of FRAME to COLS by ROWS, measured in characters. */)
2790 (frame, cols, rows)
ff11dfa1 2791 Lisp_Object frame, cols, rows;
dc6f92b8 2792{
ff11dfa1 2793 register struct frame *f;
dc6f92b8 2794
b7826503
PJ
2795 CHECK_LIVE_FRAME (frame);
2796 CHECK_NUMBER (cols);
2797 CHECK_NUMBER (rows);
ff11dfa1 2798 f = XFRAME (frame);
dc6f92b8 2799
dbc4e1c1 2800 /* I think this should be done with a hook. */
032d78fe
GV
2801#ifdef HAVE_WINDOW_SYSTEM
2802 if (FRAME_WINDOW_P (f))
dc6f92b8 2803 {
5af5757b
KS
2804 if (XINT (rows) != FRAME_LINES (f)
2805 || XINT (cols) != FRAME_COLS (f)
2806 || f->new_text_lines || f->new_text_cols)
808c0f20 2807 x_set_window_size (f, 1, XINT (cols), XINT (rows));
32347cf4 2808 do_pending_window_change (0);
dc6f92b8
JB
2809 }
2810 else
fd0c2bd1 2811#endif
32347cf4 2812 change_frame_size (f, XINT (rows), XINT (cols), 0, 0, 0);
dc6f92b8
JB
2813
2814 return Qnil;
2815}
2816
177c0ea7 2817DEFUN ("set-frame-position", Fset_frame_position,
ff11dfa1 2818 Sset_frame_position, 3, 3, 0,
14ff1ee0
PJ
2819 doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
2820This is actually the position of the upper left corner of the frame.
2821Negative values for XOFFSET or YOFFSET are interpreted relative to
2822the rightmost or bottommost possible position (that stays within the screen). */)
2823 (frame, xoffset, yoffset)
ff11dfa1 2824 Lisp_Object frame, xoffset, yoffset;
dc6f92b8 2825{
ff11dfa1 2826 register struct frame *f;
dc6f92b8 2827
b7826503
PJ
2828 CHECK_LIVE_FRAME (frame);
2829 CHECK_NUMBER (xoffset);
2830 CHECK_NUMBER (yoffset);
ff11dfa1 2831 f = XFRAME (frame);
dc6f92b8 2832
dbc4e1c1 2833 /* I think this should be done with a hook. */
032d78fe
GV
2834#ifdef HAVE_WINDOW_SYSTEM
2835 if (FRAME_WINDOW_P (f))
c7c70761 2836 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
fd0c2bd1 2837#endif
dc6f92b8
JB
2838
2839 return Qt;
2840}
dc6d9681 2841
dc6f92b8 2842\f
972f4259
KS
2843/***********************************************************************
2844 Frame Parameters
2845 ***********************************************************************/
2846
2847/* Connect the frame-parameter names for X frames
2848 to the ways of passing the parameter values to the window system.
2849
2850 The name of a parameter, as a Lisp symbol,
2851 has an `x-frame-parameter' property which is an integer in Lisp
2852 that is an index in this table. */
2853
2854struct frame_parm_table {
2855 char *name;
2856 Lisp_Object *variable;
2857};
2858
2859static struct frame_parm_table frame_parms[] =
2860{
2861 {"auto-raise", &Qauto_raise},
2862 {"auto-lower", &Qauto_lower},
2863 {"background-color", 0},
2864 {"border-color", &Qborder_color},
2865 {"border-width", &Qborder_width},
2866 {"cursor-color", &Qcursor_color},
2867 {"cursor-type", &Qcursor_type},
2868 {"font", 0},
2869 {"foreground-color", 0},
2870 {"icon-name", &Qicon_name},
2871 {"icon-type", &Qicon_type},
2872 {"internal-border-width", &Qinternal_border_width},
2873 {"menu-bar-lines", &Qmenu_bar_lines},
2874 {"mouse-color", &Qmouse_color},
2875 {"name", &Qname},
2876 {"scroll-bar-width", &Qscroll_bar_width},
2877 {"title", &Qtitle},
2878 {"unsplittable", &Qunsplittable},
2879 {"vertical-scroll-bars", &Qvertical_scroll_bars},
2880 {"visibility", &Qvisibility},
2881 {"tool-bar-lines", &Qtool_bar_lines},
2882 {"scroll-bar-foreground", &Qscroll_bar_foreground},
2883 {"scroll-bar-background", &Qscroll_bar_background},
2884 {"screen-gamma", &Qscreen_gamma},
2885 {"line-spacing", &Qline_spacing},
2886 {"left-fringe", &Qleft_fringe},
2887 {"right-fringe", &Qright_fringe},
2888 {"wait-for-wm", &Qwait_for_wm},
2889 {"fullscreen", &Qfullscreen},
2890};
2891
2892#ifdef HAVE_WINDOW_SYSTEM
2893
2894extern Lisp_Object Qbox;
2895extern Lisp_Object Qtop;
2896
2897/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
bd45aef7 2898 wanted positions of the WM window (not Emacs window).
972f4259
KS
2899 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
2900 window (FRAME_X_WINDOW).
2901 */
2902
dfcf069d 2903void
972f4259
KS
2904x_fullscreen_adjust (f, width, height, top_pos, left_pos)
2905 struct frame *f;
2906 int *width;
2907 int *height;
2908 int *top_pos;
2909 int *left_pos;
dc6f92b8 2910{
5af5757b
KS
2911 int newwidth = FRAME_COLS (f);
2912 int newheight = FRAME_LINES (f);
dc6f92b8 2913
5af5757b
KS
2914 *top_pos = f->top_pos;
2915 *left_pos = f->left_pos;
3df1fda2 2916
5af5757b 2917 if (f->want_fullscreen & FULLSCREEN_HEIGHT)
972f4259
KS
2918 {
2919 int ph;
2920
2921 ph = FRAME_X_DISPLAY_INFO (f)->height;
5af5757b
KS
2922 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
2923 ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
2924 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
972f4259
KS
2925 *top_pos = 0;
2926 }
dc6f92b8 2927
5af5757b 2928 if (f->want_fullscreen & FULLSCREEN_WIDTH)
972f4259
KS
2929 {
2930 int pw;
2931
2932 pw = FRAME_X_DISPLAY_INFO (f)->width;
5af5757b
KS
2933 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
2934 pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
2935 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
972f4259
KS
2936 *left_pos = 0;
2937 }
dc6f92b8 2938
972f4259
KS
2939 *width = newwidth;
2940 *height = newheight;
2941}
dc6f92b8 2942
beb0bc36 2943
972f4259
KS
2944/* Change the parameters of frame F as specified by ALIST.
2945 If a parameter is not specially recognized, do nothing special;
2946 otherwise call the `x_set_...' function for that parameter.
2947 Except for certain geometry properties, always call store_frame_param
2948 to store the new value in the parameter alist. */
14ff1ee0 2949
972f4259
KS
2950void
2951x_set_frame_parameters (f, alist)
2952 FRAME_PTR f;
2953 Lisp_Object alist;
2954{
2955 Lisp_Object tail;
dc6f92b8 2956
972f4259
KS
2957 /* If both of these parameters are present, it's more efficient to
2958 set them both at once. So we wait until we've looked at the
2959 entire list before we set them. */
2960 int width, height;
3df1fda2 2961
972f4259
KS
2962 /* Same here. */
2963 Lisp_Object left, top;
2964
2965 /* Same with these. */
2966 Lisp_Object icon_left, icon_top;
2967
2968 /* Record in these vectors all the parms specified. */
2969 Lisp_Object *parms;
2970 Lisp_Object *values;
2971 int i, p;
2972 int left_no_change = 0, top_no_change = 0;
2973 int icon_left_no_change = 0, icon_top_no_change = 0;
2974 int fullscreen_is_being_set = 0;
2975
2976 struct gcpro gcpro1, gcpro2;
2977
2978 i = 0;
2979 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2980 i++;
2981
2982 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
2983 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
2984
2985 /* Extract parm names and values into those vectors. */
2986
2987 i = 0;
2988 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2989 {
2990 Lisp_Object elt;
2991
2992 elt = Fcar (tail);
2993 parms[i] = Fcar (elt);
2994 values[i] = Fcdr (elt);
2995 i++;
2996 }
2997 /* TAIL and ALIST are not used again below here. */
2998 alist = tail = Qnil;
2999
3000 GCPRO2 (*parms, *values);
3001 gcpro1.nvars = i;
3002 gcpro2.nvars = i;
3003
3004 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
3005 because their values appear in VALUES and strings are not valid. */
3006 top = left = Qunbound;
3007 icon_left = icon_top = Qunbound;
3008
3009 /* Provide default values for HEIGHT and WIDTH. */
5af5757b
KS
3010 width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
3011 height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
972f4259
KS
3012
3013 /* Process foreground_color and background_color before anything else.
3014 They are independent of other properties, but other properties (e.g.,
3015 cursor_color) are dependent upon them. */
3016 /* Process default font as well, since fringe widths depends on it. */
3017 /* Also, process fullscreen, width and height depend upon that */
3018 for (p = 0; p < i; p++)
3019 {
3020 Lisp_Object prop, val;
3021
3022 prop = parms[p];
3023 val = values[p];
3024 if (EQ (prop, Qforeground_color)
3025 || EQ (prop, Qbackground_color)
3026 || EQ (prop, Qfont)
3027 || EQ (prop, Qfullscreen))
3028 {
3029 register Lisp_Object param_index, old_value;
26c34ec2 3030 int count = SPECPDL_INDEX ();
972f4259
KS
3031
3032 old_value = get_frame_param (f, prop);
3033 fullscreen_is_being_set |= EQ (prop, Qfullscreen);
3034
3035 if (NILP (Fequal (val, old_value)))
3036 {
26c34ec2
CY
3037 /* For :font attributes, the frame_parm_handler
3038 x_set_font calls `face-set-after-frame-default'.
3039 Unless we bind inhibit-face-set-after-frame-default
3040 here, this would reset the :font attribute that we
3041 just applied to the default value for new faces. */
3042 specbind (Qinhibit_face_set_after_frame_default, Qt);
3043
972f4259
KS
3044 store_frame_param (f, prop, val);
3045
3046 param_index = Fget (prop, Qx_frame_parameter);
3047 if (NATNUMP (param_index)
3048 && (XFASTINT (param_index)
3049 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
3050 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3051 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
26c34ec2 3052 unbind_to (count, Qnil);
972f4259
KS
3053 }
3054 }
3055 }
3056
3057 /* Now process them in reverse of specified order. */
3058 for (i--; i >= 0; i--)
3059 {
3060 Lisp_Object prop, val;
3061
3062 prop = parms[i];
3063 val = values[i];
3064
3065 if (EQ (prop, Qwidth) && NUMBERP (val))
3066 width = XFASTINT (val);
3067 else if (EQ (prop, Qheight) && NUMBERP (val))
3068 height = XFASTINT (val);
3069 else if (EQ (prop, Qtop))
3070 top = val;
3071 else if (EQ (prop, Qleft))
3072 left = val;
3073 else if (EQ (prop, Qicon_top))
3074 icon_top = val;
3075 else if (EQ (prop, Qicon_left))
3076 icon_left = val;
3077 else if (EQ (prop, Qforeground_color)
3078 || EQ (prop, Qbackground_color)
3079 || EQ (prop, Qfont)
3080 || EQ (prop, Qfullscreen))
3081 /* Processed above. */
3082 continue;
3083 else
3084 {
3085 register Lisp_Object param_index, old_value;
3086
3087 old_value = get_frame_param (f, prop);
3088
3089 store_frame_param (f, prop, val);
3090
3091 param_index = Fget (prop, Qx_frame_parameter);
3092 if (NATNUMP (param_index)
3093 && (XFASTINT (param_index)
3094 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
3095 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3096 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
972f4259
KS
3097 }
3098 }
3099
3100 /* Don't die if just one of these was set. */
3101 if (EQ (left, Qunbound))
3102 {
3103 left_no_change = 1;
5af5757b
KS
3104 if (f->left_pos < 0)
3105 left = Fcons (Qplus, Fcons (make_number (f->left_pos), Qnil));
972f4259 3106 else
5af5757b 3107 XSETINT (left, f->left_pos);
972f4259
KS
3108 }
3109 if (EQ (top, Qunbound))
3110 {
3111 top_no_change = 1;
5af5757b
KS
3112 if (f->top_pos < 0)
3113 top = Fcons (Qplus, Fcons (make_number (f->top_pos), Qnil));
972f4259 3114 else
5af5757b 3115 XSETINT (top, f->top_pos);
972f4259
KS
3116 }
3117
3118 /* If one of the icon positions was not set, preserve or default it. */
3119 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
3120 {
3121 icon_left_no_change = 1;
3122 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3123 if (NILP (icon_left))
3124 XSETINT (icon_left, 0);
3125 }
3126 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
3127 {
3128 icon_top_no_change = 1;
3129 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3130 if (NILP (icon_top))
3131 XSETINT (icon_top, 0);
3132 }
3133
972f4259
KS
3134 if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set)
3135 {
3136 /* If the frame is visible already and the fullscreen parameter is
3137 being set, it is too late to set WM manager hints to specify
3138 size and position.
3139 Here we first get the width, height and position that applies to
3140 fullscreen. We then move the frame to the appropriate
3141 position. Resize of the frame is taken care of in the code after
3142 this if-statement. */
3143 int new_left, new_top;
3144
3145 x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
068ae0fd
JD
3146 if (new_top != f->top_pos || new_left != f->left_pos)
3147 x_set_offset (f, new_left, new_top, 1);
972f4259 3148 }
972f4259
KS
3149
3150 /* Don't set these parameters unless they've been explicitly
3151 specified. The window might be mapped or resized while we're in
3152 this function, and we don't want to override that unless the lisp
3153 code has asked for it.
3154
3155 Don't set these parameters unless they actually differ from the
3156 window's current parameters; the window may not actually exist
3157 yet. */
3158 {
3159 Lisp_Object frame;
3160
3161 check_frame_size (f, &height, &width);
3162
3163 XSETFRAME (frame, f);
3164
5af5757b
KS
3165 if (width != FRAME_COLS (f)
3166 || height != FRAME_LINES (f)
3167 || f->new_text_lines || f->new_text_cols)
972f4259
KS
3168 Fset_frame_size (frame, make_number (width), make_number (height));
3169
3170 if ((!NILP (left) || !NILP (top))
3171 && ! (left_no_change && top_no_change)
5af5757b
KS
3172 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3173 && NUMBERP (top) && XINT (top) == f->top_pos))
972f4259
KS
3174 {
3175 int leftpos = 0;
3176 int toppos = 0;
3177
3178 /* Record the signs. */
5af5757b 3179 f->size_hint_flags &= ~ (XNegative | YNegative);
972f4259 3180 if (EQ (left, Qminus))
5af5757b 3181 f->size_hint_flags |= XNegative;
972f4259
KS
3182 else if (INTEGERP (left))
3183 {
3184 leftpos = XINT (left);
3185 if (leftpos < 0)
5af5757b 3186 f->size_hint_flags |= XNegative;
972f4259
KS
3187 }
3188 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3189 && CONSP (XCDR (left))
3190 && INTEGERP (XCAR (XCDR (left))))
3191 {
3192 leftpos = - XINT (XCAR (XCDR (left)));
5af5757b 3193 f->size_hint_flags |= XNegative;
972f4259
KS
3194 }
3195 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3196 && CONSP (XCDR (left))
3197 && INTEGERP (XCAR (XCDR (left))))
3198 {
3199 leftpos = XINT (XCAR (XCDR (left)));
3200 }
3201
3202 if (EQ (top, Qminus))
5af5757b 3203 f->size_hint_flags |= YNegative;
972f4259
KS
3204 else if (INTEGERP (top))
3205 {
3206 toppos = XINT (top);
3207 if (toppos < 0)
5af5757b 3208 f->size_hint_flags |= YNegative;
972f4259
KS
3209 }
3210 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3211 && CONSP (XCDR (top))
3212 && INTEGERP (XCAR (XCDR (top))))
3213 {
3214 toppos = - XINT (XCAR (XCDR (top)));
5af5757b 3215 f->size_hint_flags |= YNegative;
972f4259
KS
3216 }
3217 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3218 && CONSP (XCDR (top))
3219 && INTEGERP (XCAR (XCDR (top))))
3220 {
3221 toppos = XINT (XCAR (XCDR (top)));
3222 }
3223
3224
3225 /* Store the numeric value of the position. */
5af5757b
KS
3226 f->top_pos = toppos;
3227 f->left_pos = leftpos;
972f4259 3228
5af5757b 3229 f->win_gravity = NorthWestGravity;
972f4259
KS
3230
3231 /* Actually set that position, and convert to absolute. */
3232 x_set_offset (f, leftpos, toppos, -1);
3233 }
3234
3235 if ((!NILP (icon_left) || !NILP (icon_top))
3236 && ! (icon_left_no_change && icon_top_no_change))
3237 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3238 }
3239
3240 UNGCPRO;
3241}
3242
3243
3244/* Insert a description of internally-recorded parameters of frame X
3245 into the parameter alist *ALISTPTR that is to be given to the user.
3246 Only parameters that are specific to the X window system
3247 and whose values are not correctly recorded in the frame's
3248 param_alist need to be considered here. */
3249
3250void
3251x_report_frame_params (f, alistptr)
3252 struct frame *f;
3253 Lisp_Object *alistptr;
3254{
3255 char buf[16];
3256 Lisp_Object tem;
3257
3258 /* Represent negative positions (off the top or left screen edge)
3259 in a way that Fmodify_frame_parameters will understand correctly. */
5af5757b
KS
3260 XSETINT (tem, f->left_pos);
3261 if (f->left_pos >= 0)
972f4259
KS
3262 store_in_alist (alistptr, Qleft, tem);
3263 else
3264 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
3265
5af5757b
KS
3266 XSETINT (tem, f->top_pos);
3267 if (f->top_pos >= 0)
972f4259
KS
3268 store_in_alist (alistptr, Qtop, tem);
3269 else
3270 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
3271
3272 store_in_alist (alistptr, Qborder_width,
5af5757b 3273 make_number (f->border_width));
972f4259 3274 store_in_alist (alistptr, Qinternal_border_width,
5af5757b 3275 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
972f4259 3276 store_in_alist (alistptr, Qleft_fringe,
5af5757b 3277 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
972f4259 3278 store_in_alist (alistptr, Qright_fringe,
5af5757b 3279 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
972f4259
KS
3280 store_in_alist (alistptr, Qscroll_bar_width,
3281 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3282 ? make_number (0)
5af5757b
KS
3283 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
3284 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3285 /* nil means "use default width"
3286 for non-toolkit scroll bar.
3287 ruler-mode.el depends on this. */
3288 : Qnil));
3289 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
3290 store_in_alist (alistptr, Qwindow_id,
3291 build_string (buf));
3292#ifdef HAVE_X_WINDOWS
3293#ifdef USE_X_TOOLKIT
3294 /* Tooltip frame may not have this widget. */
3295 if (FRAME_X_OUTPUT (f)->widget)
3296#endif
3297 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
3298 store_in_alist (alistptr, Qouter_window_id,
3299 build_string (buf));
3300#endif
3301 store_in_alist (alistptr, Qicon_name, f->icon_name);
3302 FRAME_SAMPLE_VISIBILITY (f);
3303 store_in_alist (alistptr, Qvisibility,
3304 (FRAME_VISIBLE_P (f) ? Qt
3305 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
3306 store_in_alist (alistptr, Qdisplay,
3307 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
3308
3309 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
3310 tem = Qnil;
3311 else
3312 XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
3313 store_in_alist (alistptr, Qparent_id, tem);
3314}
3315
3316
3317/* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
3318 the previous value of that parameter, NEW_VALUE is the new value. */
3319
3320void
3321x_set_fullscreen (f, new_value, old_value)
3322 struct frame *f;
3323 Lisp_Object new_value, old_value;
3324{
972f4259 3325 if (NILP (new_value))
5af5757b 3326 f->want_fullscreen = FULLSCREEN_NONE;
972f4259 3327 else if (EQ (new_value, Qfullboth))
5af5757b 3328 f->want_fullscreen = FULLSCREEN_BOTH;
972f4259 3329 else if (EQ (new_value, Qfullwidth))
5af5757b 3330 f->want_fullscreen = FULLSCREEN_WIDTH;
972f4259 3331 else if (EQ (new_value, Qfullheight))
5af5757b 3332 f->want_fullscreen = FULLSCREEN_HEIGHT;
d761dd42 3333
974b73e8
KL
3334 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
3335 FRAME_TERMINAL (f)->fullscreen_hook (f);
972f4259
KS
3336}
3337
3338
3339/* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
3340 the previous value of that parameter, NEW_VALUE is the new value. */
3341
3342void
3343x_set_line_spacing (f, new_value, old_value)
3344 struct frame *f;
3345 Lisp_Object new_value, old_value;
3346{
3347 if (NILP (new_value))
3348 f->extra_line_spacing = 0;
3349 else if (NATNUMP (new_value))
3350 f->extra_line_spacing = XFASTINT (new_value);
3351 else
9dc95187 3352 signal_error ("Invalid line-spacing", new_value);
972f4259
KS
3353 if (FRAME_VISIBLE_P (f))
3354 redraw_frame (f);
3355}
3356
3357
3358/* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
3359 the previous value of that parameter, NEW_VALUE is the new value. */
3360
3361void
3362x_set_screen_gamma (f, new_value, old_value)
3363 struct frame *f;
3364 Lisp_Object new_value, old_value;
3365{
05fc2ef7
CY
3366 Lisp_Object bgcolor;
3367
972f4259
KS
3368 if (NILP (new_value))
3369 f->gamma = 0;
3370 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
3371 /* The value 0.4545 is the normal viewing gamma. */
3372 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
3373 else
9dc95187 3374 signal_error ("Invalid screen-gamma", new_value);
972f4259 3375
05fc2ef7
CY
3376 /* Apply the new gamma value to the frame background. */
3377 bgcolor = Fassq (Qbackground_color, f->param_alist);
3378 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
3379 {
3380 Lisp_Object index = Fget (Qbackground_color, Qx_frame_parameter);
3381 if (NATNUMP (index)
3382 && (XFASTINT (index)
3383 < sizeof (frame_parms)/sizeof (frame_parms[0]))
3384 && rif->frame_parm_handlers[XFASTINT (index)])
3385 (*(rif->frame_parm_handlers[XFASTINT (index)]))
3386 (f, bgcolor, Qnil);
3387 }
3388
3389 Fclear_face_cache (Qnil);
972f4259
KS
3390}
3391
3392
3393void
3394x_set_font (f, arg, oldval)
3395 struct frame *f;
3396 Lisp_Object arg, oldval;
3397{
3398 Lisp_Object result;
3399 Lisp_Object fontset_name;
3400 Lisp_Object frame;
3401 int old_fontset = FRAME_FONTSET(f);
3402
3403 CHECK_STRING (arg);
3404
3405 fontset_name = Fquery_fontset (arg, Qnil);
3406
3407 BLOCK_INPUT;
3408 result = (STRINGP (fontset_name)
3409 ? x_new_fontset (f, SDATA (fontset_name))
3410 : x_new_font (f, SDATA (arg)));
3411 UNBLOCK_INPUT;
3412
3413 if (EQ (result, Qnil))
3414 error ("Font `%s' is not defined", SDATA (arg));
3415 else if (EQ (result, Qt))
3416 error ("The characters of the given font have varying widths");
3417 else if (STRINGP (result))
3418 {
ee5d57b0 3419 set_default_ascii_font (result);
972f4259
KS
3420 if (STRINGP (fontset_name))
3421 {
3422 /* Fontset names are built from ASCII font names, so the
3423 names may be equal despite there was a change. */
3424 if (old_fontset == FRAME_FONTSET (f))
3425 return;
3426 }
3427 else if (!NILP (Fequal (result, oldval)))
3428 return;
3429
ca03f883
KS
3430 /* Recalculate toolbar height. */
3431 f->n_tool_bar_rows = 0;
3432 /* Ensure we redraw it. */
3433 clear_current_matrices (f);
3434
972f4259
KS
3435 store_frame_param (f, Qfont, result);
3436 recompute_basic_faces (f);
3437 }
3438 else
3439 abort ();
3440
3441 do_pending_window_change (0);
3442
3443 /* Don't call `face-set-after-frame-default' when faces haven't been
3444 initialized yet. This is the case when called from
3445 Fx_create_frame. In that case, the X widget or window doesn't
3446 exist either, and we can end up in x_report_frame_params with a
3447 null widget which gives a segfault. */
3448 if (FRAME_FACE_CACHE (f))
3449 {
3450 XSETFRAME (frame, f);
3451 call1 (Qface_set_after_frame_default, frame);
3452 }
3453}
3454
3455
3456void
3457x_set_fringe_width (f, new_value, old_value)
3458 struct frame *f;
3459 Lisp_Object new_value, old_value;
3460{
3461 compute_fringe_widths (f, 1);
3462}
3463
3464void
3465x_set_border_width (f, arg, oldval)
3466 struct frame *f;
3467 Lisp_Object arg, oldval;
3468{
3469 CHECK_NUMBER (arg);
3470
5af5757b 3471 if (XINT (arg) == f->border_width)
972f4259
KS
3472 return;
3473
972f4259 3474 if (FRAME_X_WINDOW (f) != 0)
dac85f4b 3475 error ("Cannot change the border width of a frame");
972f4259 3476
5af5757b 3477 f->border_width = XINT (arg);
972f4259
KS
3478}
3479
3480void
3481x_set_internal_border_width (f, arg, oldval)
3482 struct frame *f;
3483 Lisp_Object arg, oldval;
3484{
5af5757b 3485 int old = FRAME_INTERNAL_BORDER_WIDTH (f);
972f4259
KS
3486
3487 CHECK_NUMBER (arg);
5af5757b
KS
3488 FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
3489 if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
3490 FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
972f4259
KS
3491
3492#ifdef USE_X_TOOLKIT
3493 if (FRAME_X_OUTPUT (f)->edit_widget)
3494 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
3495#endif
3496
5af5757b 3497 if (FRAME_INTERNAL_BORDER_WIDTH (f) == old)
972f4259
KS
3498 return;
3499
3500 if (FRAME_X_WINDOW (f) != 0)
3501 {
5af5757b 3502 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3503 SET_FRAME_GARBAGED (f);
3504 do_pending_window_change (0);
3505 }
3506 else
3507 SET_FRAME_GARBAGED (f);
3508}
3509
3510void
3511x_set_visibility (f, value, oldval)
3512 struct frame *f;
3513 Lisp_Object value, oldval;
3514{
3515 Lisp_Object frame;
3516 XSETFRAME (frame, f);
3517
3518 if (NILP (value))
3519 Fmake_frame_invisible (frame, Qt);
3520 else if (EQ (value, Qicon))
3521 Ficonify_frame (frame);
3522 else
3523 Fmake_frame_visible (frame);
3524}
3525
3526void
3527x_set_autoraise (f, arg, oldval)
3528 struct frame *f;
3529 Lisp_Object arg, oldval;
3530{
3531 f->auto_raise = !EQ (Qnil, arg);
3532}
3533
3534void
3535x_set_autolower (f, arg, oldval)
3536 struct frame *f;
3537 Lisp_Object arg, oldval;
3538{
3539 f->auto_lower = !EQ (Qnil, arg);
3540}
3541
3542void
3543x_set_unsplittable (f, arg, oldval)
3544 struct frame *f;
3545 Lisp_Object arg, oldval;
3546{
3547 f->no_split = !NILP (arg);
3548}
3549
3550void
3551x_set_vertical_scroll_bars (f, arg, oldval)
3552 struct frame *f;
3553 Lisp_Object arg, oldval;
3554{
3555 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3556 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
3557 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3558 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
3559 {
3560 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
3561 = (NILP (arg)
3562 ? vertical_scroll_bar_none
3563 : EQ (Qleft, arg)
3564 ? vertical_scroll_bar_left
3565 : EQ (Qright, arg)
3566 ? vertical_scroll_bar_right
a6e20602
KS
3567 : EQ (Qleft, Vdefault_frame_scroll_bars)
3568 ? vertical_scroll_bar_left
3569 : EQ (Qright, Vdefault_frame_scroll_bars)
3570 ? vertical_scroll_bar_right
3571 : vertical_scroll_bar_none);
972f4259
KS
3572
3573 /* We set this parameter before creating the X window for the
3574 frame, so we can get the geometry right from the start.
3575 However, if the window hasn't been created yet, we shouldn't
3576 call x_set_window_size. */
3577 if (FRAME_X_WINDOW (f))
5af5757b 3578 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3579 do_pending_window_change (0);
3580 }
3581}
3582
3583void
3584x_set_scroll_bar_width (f, arg, oldval)
3585 struct frame *f;
3586 Lisp_Object arg, oldval;
3587{
5af5757b 3588 int wid = FRAME_COLUMN_WIDTH (f);
972f4259
KS
3589
3590 if (NILP (arg))
3591 {
3592 x_set_scroll_bar_default_width (f);
3593
3594 if (FRAME_X_WINDOW (f))
5af5757b 3595 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3596 do_pending_window_change (0);
3597 }
3598 else if (INTEGERP (arg) && XINT (arg) > 0
5af5757b 3599 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3600 {
3601 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
3602 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
3603
5af5757b
KS
3604 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
3605 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
972f4259 3606 if (FRAME_X_WINDOW (f))
5af5757b 3607 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3608 do_pending_window_change (0);
3609 }
3610
5af5757b 3611 change_frame_size (f, 0, FRAME_COLS (f), 0, 0, 0);
972f4259
KS
3612 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3613 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3614}
3615
3616
3617
3618/* Return non-nil if frame F wants a bitmap icon. */
3619
3620Lisp_Object
3621x_icon_type (f)
3622 FRAME_PTR f;
3623{
3624 Lisp_Object tem;
3625
3626 tem = assq_no_quit (Qicon_type, f->param_alist);
3627 if (CONSP (tem))
3628 return XCDR (tem);
3629 else
3630 return Qnil;
3631}
3632
3633\f
3634/* Subroutines of creating an X frame. */
3635
3636/* Make sure that Vx_resource_name is set to a reasonable value.
3637 Fix it up, or set it to `emacs' if it is too hopeless. */
3638
3639void
3640validate_x_resource_name ()
3641{
3642 int len = 0;
3643 /* Number of valid characters in the resource name. */
3644 int good_count = 0;
3645 /* Number of invalid characters in the resource name. */
3646 int bad_count = 0;
3647 Lisp_Object new;
3648 int i;
3649
3650 if (!STRINGP (Vx_resource_class))
3651 Vx_resource_class = build_string (EMACS_CLASS);
3652
3653 if (STRINGP (Vx_resource_name))
3654 {
3655 unsigned char *p = SDATA (Vx_resource_name);
3656 int i;
3657
3658 len = SBYTES (Vx_resource_name);
3659
3660 /* Only letters, digits, - and _ are valid in resource names.
3661 Count the valid characters and count the invalid ones. */
3662 for (i = 0; i < len; i++)
3663 {
3664 int c = p[i];
3665 if (! ((c >= 'a' && c <= 'z')
3666 || (c >= 'A' && c <= 'Z')
3667 || (c >= '0' && c <= '9')
3668 || c == '-' || c == '_'))
3669 bad_count++;
3670 else
3671 good_count++;
3672 }
3673 }
3674 else
3675 /* Not a string => completely invalid. */
3676 bad_count = 5, good_count = 0;
3677
3678 /* If name is valid already, return. */
3679 if (bad_count == 0)
3680 return;
3681
3682 /* If name is entirely invalid, or nearly so, use `emacs'. */
3683 if (good_count == 0
3684 || (good_count == 1 && bad_count > 0))
3685 {
3686 Vx_resource_name = build_string ("emacs");
3687 return;
3688 }
3689
3690 /* Name is partly valid. Copy it and replace the invalid characters
3691 with underscores. */
3692
3693 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3694
3695 for (i = 0; i < len; i++)
3696 {
3697 int c = SREF (new, i);
3698 if (! ((c >= 'a' && c <= 'z')
3699 || (c >= 'A' && c <= 'Z')
3700 || (c >= '0' && c <= '9')
3701 || c == '-' || c == '_'))
3702 SSET (new, i, '_');
3703 }
3704}
3705
3706
3707extern char *x_get_string_resource P_ ((XrmDatabase, char *, char *));
3708extern Display_Info *check_x_display_info P_ ((Lisp_Object));
3709
3710
b5251fe7 3711/* Get specified attribute from resource database RDB.
972f4259
KS
3712 See Fx_get_resource below for other parameters. */
3713
3714static Lisp_Object
3715xrdb_get_resource (rdb, attribute, class, component, subclass)
3716 XrmDatabase rdb;
3717 Lisp_Object attribute, class, component, subclass;
3718{
3719 register char *value;
3720 char *name_key;
3721 char *class_key;
3722
3723 CHECK_STRING (attribute);
3724 CHECK_STRING (class);
3725
3726 if (!NILP (component))
3727 CHECK_STRING (component);
3728 if (!NILP (subclass))
3729 CHECK_STRING (subclass);
3730 if (NILP (component) != NILP (subclass))
3731 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3732
3733 validate_x_resource_name ();
3734
3735 /* Allocate space for the components, the dots which separate them,
3736 and the final '\0'. Make them big enough for the worst case. */
3737 name_key = (char *) alloca (SBYTES (Vx_resource_name)
3738 + (STRINGP (component)
3739 ? SBYTES (component) : 0)
3740 + SBYTES (attribute)
3741 + 3);
3742
3743 class_key = (char *) alloca (SBYTES (Vx_resource_class)
3744 + SBYTES (class)
3745 + (STRINGP (subclass)
3746 ? SBYTES (subclass) : 0)
3747 + 3);
3748
3749 /* Start with emacs.FRAMENAME for the name (the specific one)
3750 and with `Emacs' for the class key (the general one). */
3751 strcpy (name_key, SDATA (Vx_resource_name));
3752 strcpy (class_key, SDATA (Vx_resource_class));
3753
3754 strcat (class_key, ".");
3755 strcat (class_key, SDATA (class));
3756
3757 if (!NILP (component))
3758 {
3759 strcat (class_key, ".");
3760 strcat (class_key, SDATA (subclass));
3761
3762 strcat (name_key, ".");
3763 strcat (name_key, SDATA (component));
3764 }
3765
3766 strcat (name_key, ".");
3767 strcat (name_key, SDATA (attribute));
3768
3769 value = x_get_string_resource (rdb, name_key, class_key);
3770
3771 if (value != (char *) 0)
3772 return build_string (value);
3773 else
3774 return Qnil;
3775}
3776
3777
3778DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
3779 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
3780This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
3781class, where INSTANCE is the name under which Emacs was invoked, or
3782the name specified by the `-name' or `-rn' command-line arguments.
3783
3784The optional arguments COMPONENT and SUBCLASS add to the key and the
3785class, respectively. You must specify both of them or neither.
3786If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
3787and the class is `Emacs.CLASS.SUBCLASS'. */)
3788 (attribute, class, component, subclass)
3789 Lisp_Object attribute, class, component, subclass;
3790{
3791#ifdef HAVE_X_WINDOWS
3792 check_x ();
3793#endif
3794
3795 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
3796 attribute, class, component, subclass);
3797}
3798
3799/* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
3800
3801Lisp_Object
3802display_x_get_resource (dpyinfo, attribute, class, component, subclass)
a1702920 3803 Display_Info *dpyinfo;
972f4259
KS
3804 Lisp_Object attribute, class, component, subclass;
3805{
3806 return xrdb_get_resource (dpyinfo->xrdb,
3807 attribute, class, component, subclass);
3808}
3809
3810/* Used when C code wants a resource value. */
3811
3812char *
3813x_get_resource_string (attribute, class)
3814 char *attribute, *class;
3815{
3816 char *name_key;
3817 char *class_key;
3818 struct frame *sf = SELECTED_FRAME ();
3819
3820 /* Allocate space for the components, the dots which separate them,
3821 and the final '\0'. */
3822 name_key = (char *) alloca (SBYTES (Vinvocation_name)
3823 + strlen (attribute) + 2);
3824 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3825 + strlen (class) + 2);
3826
3827 sprintf (name_key, "%s.%s", SDATA (Vinvocation_name), attribute);
3828 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3829
3830 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
3831 name_key, class_key);
3832}
3833
3834
3835/* Return the value of parameter PARAM.
3836
3837 First search ALIST, then Vdefault_frame_alist, then the X defaults
3838 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3839
3840 Convert the resource to the type specified by desired_type.
3841
3842 If no default is specified, return Qunbound. If you call
3843 x_get_arg, make sure you deal with Qunbound in a reasonable way,
3844 and don't let it get stored in any Lisp-visible variables! */
3845
3846Lisp_Object
3847x_get_arg (dpyinfo, alist, param, attribute, class, type)
b5251fe7 3848 Display_Info *dpyinfo;
972f4259
KS
3849 Lisp_Object alist, param;
3850 char *attribute;
3851 char *class;
3852 enum resource_types type;
3853{
3854 register Lisp_Object tem;
3855
3856 tem = Fassq (param, alist);
d00368cf
RS
3857
3858 if (!NILP (tem))
3859 {
3860 /* If we find this parm in ALIST, clear it out
3861 so that it won't be "left over" at the end. */
58ec2913 3862#ifndef WINDOWSNT /* w32fns.c has not yet been changed to cope with this. */
5f694926 3863 Lisp_Object tail;
d00368cf 3864 XSETCAR (tem, Qnil);
5f694926
RS
3865 /* In case the parameter appears more than once in the alist,
3866 clear it out. */
3867 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3868 if (CONSP (XCAR (tail))
3869 && EQ (XCAR (XCAR (tail)), param))
3870 XSETCAR (XCAR (tail), Qnil);
d00368cf
RS
3871#endif
3872 }
3873 else
972f4259 3874 tem = Fassq (param, Vdefault_frame_alist);
d00368cf
RS
3875
3876 /* If it wasn't specified in ALIST or the Lisp-level defaults,
3877 look in the X resources. */
972f4259
KS
3878 if (EQ (tem, Qnil))
3879 {
3880 if (attribute)
3881 {
3882 tem = display_x_get_resource (dpyinfo,
3883 build_string (attribute),
3884 build_string (class),
3885 Qnil, Qnil);
3886
3887 if (NILP (tem))
3888 return Qunbound;
3889
3890 switch (type)
3891 {
3892 case RES_TYPE_NUMBER:
3893 return make_number (atoi (SDATA (tem)));
3894
3895 case RES_TYPE_FLOAT:
3896 return make_float (atof (SDATA (tem)));
3897
3898 case RES_TYPE_BOOLEAN:
3899 tem = Fdowncase (tem);
3900 if (!strcmp (SDATA (tem), "on")
3901 || !strcmp (SDATA (tem), "true"))
3902 return Qt;
3903 else
3904 return Qnil;
3905
3906 case RES_TYPE_STRING:
3907 return tem;
3908
3909 case RES_TYPE_SYMBOL:
3910 /* As a special case, we map the values `true' and `on'
3911 to Qt, and `false' and `off' to Qnil. */
3912 {
3913 Lisp_Object lower;
3914 lower = Fdowncase (tem);
3915 if (!strcmp (SDATA (lower), "on")
3916 || !strcmp (SDATA (lower), "true"))
3917 return Qt;
3918 else if (!strcmp (SDATA (lower), "off")
3919 || !strcmp (SDATA (lower), "false"))
3920 return Qnil;
3921 else
3922 return Fintern (tem, Qnil);
3923 }
3924
3925 default:
3926 abort ();
3927 }
3928 }
3929 else
3930 return Qunbound;
3931 }
3932 return Fcdr (tem);
3933}
3934
3935Lisp_Object
3936x_frame_get_arg (f, alist, param, attribute, class, type)
3937 struct frame *f;
3938 Lisp_Object alist, param;
3939 char *attribute;
3940 char *class;
3941 enum resource_types type;
3942{
3943 return x_get_arg (FRAME_X_DISPLAY_INFO (f),
3944 alist, param, attribute, class, type);
3945}
3946
3947/* Like x_frame_get_arg, but also record the value in f->param_alist. */
3948
3949Lisp_Object
3950x_frame_get_and_record_arg (f, alist, param, attribute, class, type)
3951 struct frame *f;
3952 Lisp_Object alist, param;
3953 char *attribute;
3954 char *class;
3955 enum resource_types type;
3956{
3957 Lisp_Object value;
3958
3959 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
3960 attribute, class, type);
edd1c685 3961 if (! NILP (value) && ! EQ (value, Qunbound))
972f4259
KS
3962 store_frame_param (f, param, value);
3963
3964 return value;
3965}
3966
3967
3968/* Record in frame F the specified or default value according to ALIST
3969 of the parameter named PROP (a Lisp symbol).
3970 If no value is specified for PROP, look for an X default for XPROP
3971 on the frame named NAME.
3972 If that is not found either, use the value DEFLT. */
3973
3974Lisp_Object
3975x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3976 struct frame *f;
3977 Lisp_Object alist;
3978 Lisp_Object prop;
3979 Lisp_Object deflt;
3980 char *xprop;
3981 char *xclass;
3982 enum resource_types type;
3983{
3984 Lisp_Object tem;
3985
3986 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
3987 if (EQ (tem, Qunbound))
3988 tem = deflt;
3989 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3990 return tem;
3991}
3992
3993
3994
3995\f
3996DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3997 doc: /* Parse an X-style geometry string STRING.
3998Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3999The properties returned may include `top', `left', `height', and `width'.
4000The value of `left' or `top' may be an integer,
4001or a list (+ N) meaning N pixels relative to top/left corner,
4002or a list (- N) meaning -N pixels relative to bottom/right corner. */)
4003 (string)
4004 Lisp_Object string;
4005{
4006 int geometry, x, y;
4007 unsigned int width, height;
4008 Lisp_Object result;
4009
4010 CHECK_STRING (string);
4011
4012 geometry = XParseGeometry ((char *) SDATA (string),
4013 &x, &y, &width, &height);
4014
4015#if 0
4016 if (!!(geometry & XValue) != !!(geometry & YValue))
4017 error ("Must specify both x and y position, or neither");
4018#endif
4019
4020 result = Qnil;
4021 if (geometry & XValue)
4022 {
4023 Lisp_Object element;
4024
4025 if (x >= 0 && (geometry & XNegative))
4026 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
4027 else if (x < 0 && ! (geometry & XNegative))
4028 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
4029 else
4030 element = Fcons (Qleft, make_number (x));
4031 result = Fcons (element, result);
4032 }
4033
4034 if (geometry & YValue)
4035 {
4036 Lisp_Object element;
4037
4038 if (y >= 0 && (geometry & YNegative))
4039 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
4040 else if (y < 0 && ! (geometry & YNegative))
4041 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
4042 else
4043 element = Fcons (Qtop, make_number (y));
4044 result = Fcons (element, result);
4045 }
4046
4047 if (geometry & WidthValue)
4048 result = Fcons (Fcons (Qwidth, make_number (width)), result);
4049 if (geometry & HeightValue)
4050 result = Fcons (Fcons (Qheight, make_number (height)), result);
4051
4052 return result;
4053}
4054
4055/* Calculate the desired size and position of frame F.
4056 Return the flags saying which aspects were specified.
4057
4058 Also set the win_gravity and size_hint_flags of F.
4059
4060 Adjust height for toolbar if TOOLBAR_P is 1.
4061
4062 This function does not make the coordinates positive. */
4063
4064#define DEFAULT_ROWS 40
4065#define DEFAULT_COLS 80
4066
4067int
4068x_figure_window_size (f, parms, toolbar_p)
4069 struct frame *f;
4070 Lisp_Object parms;
4071 int toolbar_p;
4072{
4073 register Lisp_Object tem0, tem1, tem2;
4074 long window_prompting = 0;
4075 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4076
4077 /* Default values if we fall through.
4078 Actually, if that happens we should get
4079 window manager prompting. */
5af5757b
KS
4080 SET_FRAME_COLS (f, DEFAULT_COLS);
4081 FRAME_LINES (f) = DEFAULT_ROWS;
972f4259
KS
4082 /* Window managers expect that if program-specified
4083 positions are not (0,0), they're intentional, not defaults. */
5af5757b
KS
4084 f->top_pos = 0;
4085 f->left_pos = 0;
972f4259 4086
5af5757b 4087 /* Ensure that old new_text_cols and new_text_lines will not override the
972f4259
KS
4088 values set here. */
4089 /* ++KFS: This was specific to W32, but seems ok for all platforms */
5af5757b 4090 f->new_text_cols = f->new_text_lines = 0;
972f4259
KS
4091
4092 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
4093 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
4094 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
4095 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
4096 {
4097 if (!EQ (tem0, Qunbound))
4098 {
4099 CHECK_NUMBER (tem0);
5af5757b 4100 FRAME_LINES (f) = XINT (tem0);
972f4259
KS
4101 }
4102 if (!EQ (tem1, Qunbound))
4103 {
4104 CHECK_NUMBER (tem1);
5af5757b 4105 SET_FRAME_COLS (f, XINT (tem1));
972f4259
KS
4106 }
4107 if (!NILP (tem2) && !EQ (tem2, Qunbound))
4108 window_prompting |= USSize;
4109 else
4110 window_prompting |= PSize;
4111 }
4112
5af5757b
KS
4113 f->scroll_bar_actual_width
4114 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
972f4259
KS
4115
4116 /* This used to be done _before_ calling x_figure_window_size, but
4117 since the height is reset here, this was really a no-op. I
4118 assume that moving it here does what Gerd intended (although he
4119 no longer can remember what that was... ++KFS, 2003-03-25. */
4120
4121 /* Add the tool-bar height to the initial frame height so that the
4122 user gets a text display area of the size he specified with -g or
4123 via .Xdefaults. Later changes of the tool-bar height don't
4124 change the frame size. This is done so that users can create
4125 tall Emacs frames without having to guess how tall the tool-bar
4126 will get. */
4127 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
4128 {
4129 int margin, relief, bar_height;
4130
4131 relief = (tool_bar_button_relief >= 0
4132 ? tool_bar_button_relief
4133 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4134
4135 if (INTEGERP (Vtool_bar_button_margin)
4136 && XINT (Vtool_bar_button_margin) > 0)
4137 margin = XFASTINT (Vtool_bar_button_margin);
4138 else if (CONSP (Vtool_bar_button_margin)
4139 && INTEGERP (XCDR (Vtool_bar_button_margin))
4140 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4141 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4142 else
4143 margin = 0;
4144
4145 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5af5757b 4146 FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
972f4259
KS
4147 }
4148
4149 compute_fringe_widths (f, 0);
4150
5af5757b
KS
4151 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, FRAME_COLS (f));
4152 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
972f4259
KS
4153
4154 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
4155 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
4156 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
4157 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
4158 {
4159 if (EQ (tem0, Qminus))
4160 {
5af5757b 4161 f->top_pos = 0;
972f4259
KS
4162 window_prompting |= YNegative;
4163 }
4164 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
4165 && CONSP (XCDR (tem0))
4166 && INTEGERP (XCAR (XCDR (tem0))))
4167 {
5af5757b 4168 f->top_pos = - XINT (XCAR (XCDR (tem0)));
972f4259
KS
4169 window_prompting |= YNegative;
4170 }
4171 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
4172 && CONSP (XCDR (tem0))
4173 && INTEGERP (XCAR (XCDR (tem0))))
4174 {
5af5757b 4175 f->top_pos = XINT (XCAR (XCDR (tem0)));
972f4259
KS
4176 }
4177 else if (EQ (tem0, Qunbound))
5af5757b 4178 f->top_pos = 0;
972f4259
KS
4179 else
4180 {
4181 CHECK_NUMBER (tem0);
5af5757b
KS
4182 f->top_pos = XINT (tem0);
4183 if (f->top_pos < 0)
972f4259
KS
4184 window_prompting |= YNegative;
4185 }
4186
4187 if (EQ (tem1, Qminus))
4188 {
5af5757b 4189 f->left_pos = 0;
972f4259
KS
4190 window_prompting |= XNegative;
4191 }
4192 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
4193 && CONSP (XCDR (tem1))
4194 && INTEGERP (XCAR (XCDR (tem1))))
4195 {
5af5757b 4196 f->left_pos = - XINT (XCAR (XCDR (tem1)));
972f4259
KS
4197 window_prompting |= XNegative;
4198 }
4199 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
4200 && CONSP (XCDR (tem1))
4201 && INTEGERP (XCAR (XCDR (tem1))))
4202 {
5af5757b 4203 f->left_pos = XINT (XCAR (XCDR (tem1)));
972f4259
KS
4204 }
4205 else if (EQ (tem1, Qunbound))
5af5757b 4206 f->left_pos = 0;
972f4259
KS
4207 else
4208 {
4209 CHECK_NUMBER (tem1);
5af5757b
KS
4210 f->left_pos = XINT (tem1);
4211 if (f->left_pos < 0)
972f4259
KS
4212 window_prompting |= XNegative;
4213 }
4214
4215 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
4216 window_prompting |= USPosition;
4217 else
4218 window_prompting |= PPosition;
4219 }
4220
5af5757b 4221 if (f->want_fullscreen != FULLSCREEN_NONE)
972f4259
KS
4222 {
4223 int left, top;
4224 int width, height;
4225
4226 /* It takes both for some WM:s to place it where we want */
4227 window_prompting = USPosition | PPosition;
4228 x_fullscreen_adjust (f, &width, &height, &top, &left);
5af5757b
KS
4229 FRAME_COLS (f) = width;
4230 FRAME_LINES (f) = height;
4231 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
4232 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
4233 f->left_pos = left;
4234 f->top_pos = top;
972f4259
KS
4235 }
4236
4237 if (window_prompting & XNegative)
4238 {
4239 if (window_prompting & YNegative)
5af5757b 4240 f->win_gravity = SouthEastGravity;
972f4259 4241 else
5af5757b 4242 f->win_gravity = NorthEastGravity;
972f4259
KS
4243 }
4244 else
4245 {
4246 if (window_prompting & YNegative)
5af5757b 4247 f->win_gravity = SouthWestGravity;
972f4259 4248 else
5af5757b 4249 f->win_gravity = NorthWestGravity;
972f4259
KS
4250 }
4251
5af5757b 4252 f->size_hint_flags = window_prompting;
972f4259
KS
4253
4254 return window_prompting;
4255}
4256
4257
4258
4259#endif /* HAVE_WINDOW_SYSTEM */
4260
4261
4262\f
4263/***********************************************************************
4264 Initialization
4265 ***********************************************************************/
4266
4267void
4268syms_of_frame ()
4269{
4270 Qframep = intern ("framep");
4271 staticpro (&Qframep);
4272 Qframe_live_p = intern ("frame-live-p");
4273 staticpro (&Qframe_live_p);
4274 Qheight = intern ("height");
4275 staticpro (&Qheight);
4276 Qicon = intern ("icon");
4277 staticpro (&Qicon);
4278 Qminibuffer = intern ("minibuffer");
4279 staticpro (&Qminibuffer);
4280 Qmodeline = intern ("modeline");
4281 staticpro (&Qmodeline);
4282 Qonly = intern ("only");
4283 staticpro (&Qonly);
4284 Qwidth = intern ("width");
4285 staticpro (&Qwidth);
4286 Qgeometry = intern ("geometry");
4287 staticpro (&Qgeometry);
4288 Qicon_left = intern ("icon-left");
4289 staticpro (&Qicon_left);
4290 Qicon_top = intern ("icon-top");
4291 staticpro (&Qicon_top);
4292 Qleft = intern ("left");
4293 staticpro (&Qleft);
4294 Qright = intern ("right");
4295 staticpro (&Qright);
4296 Quser_position = intern ("user-position");
4297 staticpro (&Quser_position);
4298 Quser_size = intern ("user-size");
4299 staticpro (&Quser_size);
4300 Qwindow_id = intern ("window-id");
4301 staticpro (&Qwindow_id);
4302#ifdef HAVE_X_WINDOWS
4303 Qouter_window_id = intern ("outer-window-id");
4304 staticpro (&Qouter_window_id);
4305#endif
4306 Qparent_id = intern ("parent-id");
4307 staticpro (&Qparent_id);
4308 Qx = intern ("x");
4309 staticpro (&Qx);
4310 Qw32 = intern ("w32");
4311 staticpro (&Qw32);
4312 Qpc = intern ("pc");
4313 staticpro (&Qpc);
4314 Qmac = intern ("mac");
4315 staticpro (&Qmac);
4316 Qvisible = intern ("visible");
4317 staticpro (&Qvisible);
4318 Qbuffer_predicate = intern ("buffer-predicate");
4319 staticpro (&Qbuffer_predicate);
4320 Qbuffer_list = intern ("buffer-list");
4321 staticpro (&Qbuffer_list);
a18b8cb5
KL
4322 Qburied_buffer_list = intern ("buried-buffer-list");
4323 staticpro (&Qburied_buffer_list);
972f4259
KS
4324 Qdisplay_type = intern ("display-type");
4325 staticpro (&Qdisplay_type);
4326 Qbackground_mode = intern ("background-mode");
4327 staticpro (&Qbackground_mode);
4328 Qtty_color_mode = intern ("tty-color-mode");
4329 staticpro (&Qtty_color_mode);
28d440ab
KL
4330 Qtty = intern ("tty");
4331 staticpro (&Qtty);
4332 Qtty_type = intern ("tty-type");
4333 staticpro (&Qtty_type);
7f19e125
KL
4334 Qwindow_system = intern ("window-system");
4335 staticpro (&Qwindow_system);
da8e8fc1
KL
4336 Qenvironment = intern ("environment");
4337 staticpro (&Qenvironment);
7f19e125 4338
972f4259
KS
4339 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
4340 staticpro (&Qface_set_after_frame_default);
4341
26c34ec2
CY
4342 Qinhibit_face_set_after_frame_default
4343 = intern ("inhibit-face-set-after-frame-default");
4344 staticpro (&Qinhibit_face_set_after_frame_default);
4345
972f4259
KS
4346 Qfullwidth = intern ("fullwidth");
4347 staticpro (&Qfullwidth);
4348 Qfullheight = intern ("fullheight");
4349 staticpro (&Qfullheight);
4350 Qfullboth = intern ("fullboth");
4351 staticpro (&Qfullboth);
4352 Qx_resource_name = intern ("x-resource-name");
4353 staticpro (&Qx_resource_name);
4354
4355 Qx_frame_parameter = intern ("x-frame-parameter");
4356 staticpro (&Qx_frame_parameter);
4357
6ed8eeff
KL
4358 Qterminal = intern ("terminal");
4359 staticpro (&Qterminal);
4360 Qterminal_live_p = intern ("terminal-live-p");
4361 staticpro (&Qterminal_live_p);
b6660415 4362
972f4259
KS
4363 {
4364 int i;
4365
4366 for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++)
4367 {
4368 Lisp_Object v = intern (frame_parms[i].name);
4369 if (frame_parms[i].variable)
4370 {
4371 *frame_parms[i].variable = v;
4372 staticpro (frame_parms[i].variable);
4373 }
4374 Fput (v, Qx_frame_parameter, make_number (i));
4375 }
4376 }
4377
2731a0ad 4378#ifdef HAVE_WINDOW_SYSTEM
972f4259
KS
4379 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
4380 doc: /* The name Emacs uses to look up X resources.
4381`x-get-resource' uses this as the first component of the instance name
4382when requesting resource values.
4383Emacs initially sets `x-resource-name' to the name under which Emacs
4384was invoked, or to the value specified with the `-name' or `-rn'
4385switches, if present.
4386
4387It may be useful to bind this variable locally around a call
4388to `x-get-resource'. See also the variable `x-resource-class'. */);
4389 Vx_resource_name = Qnil;
4390
4391 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
4392 doc: /* The class Emacs uses to look up X resources.
4393`x-get-resource' uses this as the first component of the instance class
4394when requesting resource values.
4395
4396Emacs initially sets `x-resource-class' to "Emacs".
4397
4398Setting this variable permanently is not a reasonable thing to do,
4399but binding this variable locally around a call to `x-get-resource'
4400is a reasonable practice. See also the variable `x-resource-name'. */);
4401 Vx_resource_class = build_string (EMACS_CLASS);
2731a0ad 4402#endif
972f4259
KS
4403
4404 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
4405 doc: /* Alist of default values for frame creation.
4406These may be set in your init file, like this:
5ff00c42 4407 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
972f4259
KS
4408These override values given in window system configuration data,
4409 including X Windows' defaults database.
4410For values specific to the first Emacs frame, see `initial-frame-alist'.
095fe281 4411For window-system specific values, see `window-system-default-frame-alist'.
972f4259
KS
4412For values specific to the separate minibuffer frame, see
4413 `minibuffer-frame-alist'.
4414The `menu-bar-lines' element of the list controls whether new frames
4415 have menu bars; `menu-bar-mode' works by altering this element.
4416Setting this variable does not affect existing frames, only new ones. */);
4417 Vdefault_frame_alist = Qnil;
4418
a6e20602
KS
4419 DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
4420 doc: /* Default position of scroll bars on this window-system. */);
4421#ifdef HAVE_WINDOW_SYSTEM
b15325b2 4422#if defined(HAVE_NTGUI) || defined(MAC_OS)
a6e20602
KS
4423 /* MS-Windows has scroll bars on the right by default. */
4424 Vdefault_frame_scroll_bars = Qright;
4425#else
4426 Vdefault_frame_scroll_bars = Qleft;
4427#endif
4428#else
4429 Vdefault_frame_scroll_bars = Qnil;
4430#endif
4431
daf01701
KL
4432 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
4433 doc: /* The initial frame-object, which represents Emacs's stdout. */);
4434
972f4259 4435 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
bd45aef7 4436 doc: /* Non-nil if all of Emacs is iconified and frame updates are not needed. */);
972f4259
KS
4437 Vemacs_iconified = Qnil;
4438
4439 DEFVAR_LISP ("mouse-position-function", &Vmouse_position_function,
4440 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4441`mouse-position' calls this function, passing its usual return value as
4442argument, and returns whatever this function returns.
4443This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4444which need to do mouse handling at the Lisp level. */);
4445 Vmouse_position_function = Qnil;
4446
4447 DEFVAR_LISP ("mouse-highlight", &Vmouse_highlight,
4448 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4449If the value is an integer, highlighting is only shown after moving the
4450mouse, while keyboard input turns off the highlight even when the mouse
4451is over the clickable text. However, the mouse shape still indicates
4452when the mouse is over clickable text. */);
4453 Vmouse_highlight = Qt;
4454
4455 DEFVAR_LISP ("delete-frame-functions", &Vdelete_frame_functions,
4456 doc: /* Functions to be run before deleting a frame.
4457The functions are run with one arg, the frame to be deleted.
e519a50b
KL
4458See `delete-frame'.
4459
4460Note that functions in this list may be called twice on the same
4461frame. In the second invocation, the frame is already deleted, and
4462the function should do nothing. (You can use `frame-live-p' to check
4463for this.) This wrinkle happens when an earlier function in
4464`delete-frame-functions' (indirectly) calls delete-frame
4465recursively. */);
972f4259
KS
4466 Vdelete_frame_functions = Qnil;
4467
4468 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
4469 doc: /* Minibufferless frames use this frame's minibuffer.
4470
4471Emacs cannot create minibufferless frames unless this is set to an
4472appropriate surrogate.
4473
4474Emacs consults this variable only when creating minibufferless
4475frames; once the frame is created, it sticks with its assigned
4476minibuffer, no matter what this variable is set to. This means that
4477this variable doesn't necessarily say anything meaningful about the
4478current set of frames, or where the minibuffer is currently being
4479displayed.
4480
4481This variable is local to the current terminal and cannot be buffer-local. */);
4482
4483 staticpro (&Vframe_list);
4484
4485 defsubr (&Sactive_minibuffer_window);
4486 defsubr (&Sframep);
4487 defsubr (&Sframe_live_p);
428a555e 4488 defsubr (&Swindow_system);
972f4259
KS
4489 defsubr (&Smake_terminal_frame);
4490 defsubr (&Shandle_switch_frame);
972f4259
KS
4491 defsubr (&Sselect_frame);
4492 defsubr (&Sselected_frame);
4493 defsubr (&Swindow_frame);
4494 defsubr (&Sframe_root_window);
4495 defsubr (&Sframe_first_window);
4496 defsubr (&Sframe_selected_window);
4497 defsubr (&Sset_frame_selected_window);
4498 defsubr (&Sframe_list);
4499 defsubr (&Snext_frame);
4500 defsubr (&Sprevious_frame);
4501 defsubr (&Sdelete_frame);
4502 defsubr (&Smouse_position);
4503 defsubr (&Smouse_pixel_position);
4504 defsubr (&Sset_mouse_position);
4505 defsubr (&Sset_mouse_pixel_position);
4506#if 0
4507 defsubr (&Sframe_configuration);
4508 defsubr (&Srestore_frame_configuration);
4509#endif
4510 defsubr (&Smake_frame_visible);
4511 defsubr (&Smake_frame_invisible);
4512 defsubr (&Siconify_frame);
4513 defsubr (&Sframe_visible_p);
4514 defsubr (&Svisible_frame_list);
4515 defsubr (&Sraise_frame);
4516 defsubr (&Slower_frame);
4517 defsubr (&Sredirect_frame_focus);
4518 defsubr (&Sframe_focus);
4519 defsubr (&Sframe_parameters);
4520 defsubr (&Sframe_parameter);
4521 defsubr (&Smodify_frame_parameters);
da8e8fc1 4522 defsubr (&Sframe_with_environment);
972f4259
KS
4523 defsubr (&Sframe_char_height);
4524 defsubr (&Sframe_char_width);
4525 defsubr (&Sframe_pixel_height);
4526 defsubr (&Sframe_pixel_width);
4527 defsubr (&Sset_frame_height);
4528 defsubr (&Sset_frame_width);
4529 defsubr (&Sset_frame_size);
4530 defsubr (&Sset_frame_position);
4531
4532#ifdef HAVE_WINDOW_SYSTEM
4533 defsubr (&Sx_get_resource);
4534 defsubr (&Sx_parse_geometry);
4535#endif
4536
dc6f92b8 4537}
ab5796a9
MB
4538
4539/* arch-tag: 7dbf2c69-9aad-45f8-8296-db893d6dd039
4540 (do not change this comment) */