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