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