* window.h (struct window): Replace hchild, vchild and buffer slots
[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;
5f24fa51
DA
158 w->top_line += n;
159 w->total_lines -= n;
177c0ea7 160
a249de79 161 /* Handle just the top child in a vertical split. */
e74aeda8
DA
162 if (WINDOW_VERTICAL_COMBINATION_P (w))
163 set_menu_bar_lines_1 (w->contents, n);
164 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
165 /* Adjust all children in a horizontal split. */
166 for (window = w->contents; !NILP (window); window = w->next)
167 {
168 w = XWINDOW (window);
169 set_menu_bar_lines_1 (window, n);
170 }
a249de79
RS
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
5f24fa51
DA
335 XWINDOW (root_window)->total_cols = 10;
336 XWINDOW (root_window)->total_lines = mini_p ? 9 : 10;
dc6f92b8
JB
337
338 if (mini_p)
339 {
5f24fa51
DA
340 XWINDOW (mini_window)->total_cols = 10;
341 XWINDOW (mini_window)->top_line = 9;
342 XWINDOW (mini_window)->total_lines = 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. */
e74aeda8 424 if (NILP (Fmemq (XWINDOW (mini_window)->contents, 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,
e74aeda8 1192 XWINDOW (minibuf_window)->contents, 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
e74aeda8 1596 for (; !NILP (window); window = w->next)
98ce1622
RS
1597 {
1598 w = XWINDOW (window);
e74aeda8
DA
1599 if (WINDOWP (w->contents))
1600 make_frame_visible_1 (w->contents);
1601 else
1602 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
98ce1622
RS
1603 }
1604}
1605
ff11dfa1 1606DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
808c0f20 1607 0, 2, "",
c38eb027 1608 doc: /* Make the frame FRAME invisible.
14ff1ee0 1609If omitted, FRAME defaults to the currently selected frame.
c38eb027
CY
1610On graphical displays, invisible frames are not updated and are
1611usually not displayed at all, even in a window system's \"taskbar\".
1612
14ff1ee0 1613Normally you may not make FRAME invisible if all other frames are invisible,
c38eb027
CY
1614but if the second optional argument FORCE is non-nil, you may do so.
1615
c6bf3022
CY
1616This function has no effect on text terminal frames. Such frames are
1617always considered visible, whether or not they are currently being
c38eb027 1618displayed in the terminal. */)
5842a27b 1619 (Lisp_Object frame, Lisp_Object force)
dc6f92b8 1620{
d9f07150 1621 struct frame *f = decode_live_frame (frame);
1aa66088 1622
d9f07150 1623 if (NILP (force) && !other_visible_frames (f))
808c0f20
RS
1624 error ("Attempt to make invisible the sole visible or iconified frame");
1625
9c394f17 1626 /* Don't allow minibuf_window to remain on a deleted frame. */
d9f07150 1627 if (EQ (f->minibuffer_window, minibuf_window))
9c394f17 1628 {
8d2666fe 1629 struct frame *sf = XFRAME (selected_frame);
08908aca
MR
1630 /* Use set_window_buffer instead of Fset_window_buffer (see
1631 discussion of bug#11984, bug#12025, bug#12026). */
1632 set_window_buffer (sf->minibuffer_window,
e74aeda8 1633 XWINDOW (minibuf_window)->contents, 0, 0);
e69b0960 1634 minibuf_window = sf->minibuffer_window;
9c394f17
RS
1635 }
1636
dbc4e1c1 1637 /* I think this should be done with a hook. */
032d78fe 1638#ifdef HAVE_WINDOW_SYSTEM
d9f07150
DA
1639 if (FRAME_WINDOW_P (f))
1640 x_make_frame_invisible (f);
fd0c2bd1 1641#endif
dc6f92b8 1642
d19be8a9 1643 /* Make menu bar update for the Buffers and Frames menus. */
565620a5
RS
1644 windows_or_buffers_changed++;
1645
dc6f92b8
JB
1646 return Qnil;
1647}
1648
a7ca3326 1649DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
1aa66088 1650 0, 1, "",
14ff1ee0
PJ
1651 doc: /* Make the frame FRAME into an icon.
1652If omitted, FRAME defaults to the currently selected frame. */)
5842a27b 1653 (Lisp_Object frame)
dc6f92b8 1654{
d9f07150 1655 struct frame *f = decode_live_frame (frame);
9c394f17 1656
08908aca 1657 /* Don't allow minibuf_window to remain on an iconified frame. */
d9f07150 1658 if (EQ (f->minibuffer_window, minibuf_window))
9c394f17 1659 {
8d2666fe 1660 struct frame *sf = XFRAME (selected_frame);
08908aca
MR
1661 /* Use set_window_buffer instead of Fset_window_buffer (see
1662 discussion of bug#11984, bug#12025, bug#12026). */
1663 set_window_buffer (sf->minibuffer_window,
e74aeda8 1664 XWINDOW (minibuf_window)->contents, 0, 0);
e69b0960 1665 minibuf_window = sf->minibuffer_window;
9c394f17
RS
1666 }
1667
dbc4e1c1 1668 /* I think this should be done with a hook. */
032d78fe 1669#ifdef HAVE_WINDOW_SYSTEM
d9f07150
DA
1670 if (FRAME_WINDOW_P (f))
1671 x_iconify_frame (f);
fd0c2bd1 1672#endif
dc6f92b8 1673
d19be8a9 1674 /* Make menu bar update for the Buffers and Frames menus. */
565620a5
RS
1675 windows_or_buffers_changed++;
1676
dc6f92b8
JB
1677 return Qnil;
1678}
1679
ff11dfa1 1680DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
dc6f92b8 1681 1, 1, 0,
c38eb027
CY
1682 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
1683Return the symbol `icon' if FRAME is iconified or \"minimized\".
1684Return nil if FRAME was made invisible, via `make-frame-invisible'.
1685On graphical displays, invisible frames are not updated and are
1686usually not displayed at all, even in a window system's \"taskbar\".
1687
c6bf3022 1688If FRAME is a text terminal frame, this always returns t.
c38eb027
CY
1689Such frames are always considered visible, whether or not they are
1690currently being displayed on the terminal. */)
5842a27b 1691 (Lisp_Object frame)
dc6f92b8 1692{
b7826503 1693 CHECK_LIVE_FRAME (frame);
dc6f92b8 1694
a42e9724 1695 if (FRAME_VISIBLE_P (XFRAME (frame)))
dc6f92b8 1696 return Qt;
a42e9724 1697 if (FRAME_ICONIFIED_P (XFRAME (frame)))
fd0c2bd1 1698 return Qicon;
dc6f92b8
JB
1699 return Qnil;
1700}
1701
ff11dfa1 1702DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
dc6f92b8 1703 0, 0, 0,
14ff1ee0 1704 doc: /* Return a list of all frames now \"visible\" (being updated). */)
5842a27b 1705 (void)
dc6f92b8 1706{
5b04e9f9
DA
1707 Lisp_Object tail, frame, value = Qnil;
1708
1709 FOR_EACH_FRAME (tail, frame)
1710 if (FRAME_VISIBLE_P (XFRAME (frame)))
1711 value = Fcons (frame, value);
dc6f92b8 1712
dc6f92b8
JB
1713 return value;
1714}
d5e7c279
JB
1715
1716
a7ca3326 1717DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
14ff1ee0 1718 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
e4ed805e 1719If FRAME is invisible or iconified, make it visible.
14ff1ee0
PJ
1720If you don't specify a frame, the selected frame is used.
1721If Emacs is displaying on an ordinary terminal or some other device which
1bf72735 1722doesn't support multiple overlapping frames, this function selects FRAME. */)
5842a27b 1723 (Lisp_Object frame)
dbc4e1c1 1724{
d9f07150 1725 struct frame *f = decode_live_frame (frame);
828ac693 1726
d9f07150 1727 XSETFRAME (frame, f);
a3547743 1728
1bf72735 1729 if (FRAME_TERMCAP_P (f))
c6bf3022 1730 /* On a text terminal select FRAME. */
216e6a14 1731 Fselect_frame (frame, Qnil);
1bf72735
MR
1732 else
1733 /* Do like the documentation says. */
1734 Fmake_frame_visible (frame);
8a981af5 1735
6ed8eeff
KL
1736 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
1737 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
dbc4e1c1
JB
1738
1739 return Qnil;
1740}
1741
b49f5578 1742/* Should we have a corresponding function called Flower_Power? */
e518d5e1 1743DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
14ff1ee0
PJ
1744 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
1745If you don't specify a frame, the selected frame is used.
1746If Emacs is displaying on an ordinary terminal or some other device which
1747doesn't support multiple overlapping frames, this function does nothing. */)
5842a27b 1748 (Lisp_Object frame)
dbc4e1c1 1749{
d9f07150 1750 struct frame *f = decode_live_frame (frame);
a3547743 1751
6ed8eeff
KL
1752 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
1753 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
dbc4e1c1
JB
1754
1755 return Qnil;
1756}
1757
d5e7c279 1758\f
a7ca3326 1759DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
d5e7c279 1760 1, 2, 0,
14ff1ee0
PJ
1761 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
1762In other words, switch-frame events caused by events in FRAME will
1763request a switch to FOCUS-FRAME, and `last-event-frame' will be
1764FOCUS-FRAME after reading an event typed at FRAME.
1765
8137e7b3
MR
1766If FOCUS-FRAME is nil, any existing redirection is canceled, and the
1767frame again receives its own keystrokes.
14ff1ee0
PJ
1768
1769Focus redirection is useful for temporarily redirecting keystrokes to
1770a surrogate minibuffer frame when a frame doesn't have its own
1771minibuffer window.
1772
66a9dbbe 1773A frame's focus redirection can be changed by `select-frame'. If frame
14ff1ee0
PJ
1774FOO is selected, and then a different frame BAR is selected, any
1775frames redirecting their focus to FOO are shifted to redirect their
1776focus to BAR. This allows focus redirection to work properly when the
1777user switches from one frame to another using `select-window'.
1778
1779This means that a frame whose focus is redirected to itself is treated
1780differently from a frame whose focus is redirected to nil; the former
66a9dbbe 1781is affected by `select-frame', while the latter is not.
14ff1ee0
PJ
1782
1783The redirection lasts until `redirect-frame-focus' is called to change it. */)
5842a27b 1784 (Lisp_Object frame, Lisp_Object focus_frame)
d5e7c279 1785{
13144095
JB
1786 /* Note that we don't check for a live frame here. It's reasonable
1787 to redirect the focus of a frame you're about to delete, if you
1788 know what other frame should receive those keystrokes. */
d9f07150 1789 struct frame *f = decode_any_frame (frame);
f9898cc6 1790
a42e9724 1791 if (! NILP (focus_frame))
b7826503 1792 CHECK_LIVE_FRAME (focus_frame);
d5e7c279 1793
f00af5b1 1794 fset_focus_frame (f, focus_frame);
d5e7c279 1795
6ed8eeff
KL
1796 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
1797 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
177c0ea7 1798
d5e7c279
JB
1799 return Qnil;
1800}
1801
1802
d9f07150 1803DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
14ff1ee0 1804 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
d9f07150
DA
1805If FRAME is omitted or nil, the selected frame is used.
1806Return nil if FRAME's focus is not redirected.
14ff1ee0 1807See `redirect-frame-focus'. */)
5842a27b 1808 (Lisp_Object frame)
d5e7c279 1809{
d9f07150 1810 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
d5e7c279
JB
1811}
1812
1813
dc6f92b8 1814\f
329ca574
RS
1815/* Return the value of frame parameter PROP in frame FRAME. */
1816
298819b9 1817#ifdef HAVE_WINDOW_SYSTEM
b5b7745f 1818#if !HAVE_NS && !defined(WINDOWSNT)
81626931
PE
1819static
1820#endif
dc6f92b8 1821Lisp_Object
971de7fb 1822get_frame_param (register struct frame *frame, Lisp_Object prop)
dc6f92b8
JB
1823{
1824 register Lisp_Object tem;
1825
e69b0960 1826 tem = Fassq (prop, frame->param_alist);
dc6f92b8
JB
1827 if (EQ (tem, Qnil))
1828 return tem;
1829 return Fcdr (tem);
1830}
298819b9 1831#endif
dc6f92b8 1832
a18b8cb5 1833/* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
fa54c6ae
RS
1834
1835void
971de7fb 1836frames_discard_buffer (Lisp_Object buffer)
fa54c6ae
RS
1837{
1838 Lisp_Object frame, tail;
1839
1840 FOR_EACH_FRAME (tail, frame)
1841 {
f00af5b1
PE
1842 fset_buffer_list
1843 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
1844 fset_buried_buffer_list
1845 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
fa54c6ae
RS
1846 }
1847}
1848
329ca574
RS
1849/* Modify the alist in *ALISTPTR to associate PROP with VAL.
1850 If the alist already has an element for PROP, we change it. */
1851
dc6f92b8 1852void
971de7fb 1853store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
dc6f92b8
JB
1854{
1855 register Lisp_Object tem;
dc6f92b8 1856
dc6f92b8
JB
1857 tem = Fassq (prop, *alistptr);
1858 if (EQ (tem, Qnil))
1859 *alistptr = Fcons (Fcons (prop, val), *alistptr);
1860 else
1861 Fsetcdr (tem, val);
1862}
1863
e5317d61 1864static int
d311d28c 1865frame_name_fnn_p (char *str, ptrdiff_t len)
e5317d61 1866{
5e073ec7 1867 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
e5317d61 1868 {
5e073ec7
PE
1869 char *p = str + 2;
1870 while ('0' <= *p && *p <= '9')
1871 p++;
1872 if (p == str + len)
e5317d61
EZ
1873 return 1;
1874 }
1875 return 0;
1876}
1877
1878/* Set the name of the terminal frame. Also used by MSDOS frames.
1879 Modeled after x_set_name which is used for WINDOW frames. */
1880
66a9dbbe 1881static void
971de7fb 1882set_term_frame_name (struct frame *f, Lisp_Object name)
e5317d61
EZ
1883{
1884 f->explicit_name = ! NILP (name);
1885
1886 /* If NAME is nil, set the name to F<num>. */
1887 if (NILP (name))
1888 {
8a401434 1889 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
e5317d61
EZ
1890
1891 /* Check for no change needed in this very common case
1892 before we do any consing. */
e69b0960 1893 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
e5317d61
EZ
1894 return;
1895
a8290ec3 1896 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
e5317d61
EZ
1897 }
1898 else
1899 {
b7826503 1900 CHECK_STRING (name);
e5317d61
EZ
1901
1902 /* Don't change the name if it's already NAME. */
e69b0960 1903 if (! NILP (Fstring_equal (name, f->name)))
e5317d61
EZ
1904 return;
1905
1906 /* Don't allow the user to set the frame name to F<num>, so it
1907 doesn't clash with the names we generate for terminal frames. */
42a5b22f 1908 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
e5317d61
EZ
1909 error ("Frame names of the form F<num> are usurped by Emacs");
1910 }
1911
f00af5b1 1912 fset_name (f, name);
e5317d61
EZ
1913 update_mode_lines = 1;
1914}
1915
dc6f92b8 1916void
971de7fb 1917store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
dc6f92b8 1918{
7eb63b72 1919 register Lisp_Object old_alist_elt;
dc6f92b8 1920
a18b8cb5 1921 /* The buffer-list parameters are stored in a special place and not
52eb77a6 1922 in the alist. All buffers must be live. */
fa54c6ae
RS
1923 if (EQ (prop, Qbuffer_list))
1924 {
52eb77a6
CY
1925 Lisp_Object list = Qnil;
1926 for (; CONSP (val); val = XCDR (val))
1927 if (!NILP (Fbuffer_live_p (XCAR (val))))
1928 list = Fcons (XCAR (val), list);
f00af5b1 1929 fset_buffer_list (f, Fnreverse (list));
fa54c6ae
RS
1930 return;
1931 }
a18b8cb5
KL
1932 if (EQ (prop, Qburied_buffer_list))
1933 {
52eb77a6
CY
1934 Lisp_Object list = Qnil;
1935 for (; CONSP (val); val = XCDR (val))
1936 if (!NILP (Fbuffer_live_p (XCAR (val))))
1937 list = Fcons (XCAR (val), list);
f00af5b1 1938 fset_buried_buffer_list (f, Fnreverse (list));
a18b8cb5
KL
1939 return;
1940 }
fa54c6ae 1941
7eb63b72
GM
1942 /* If PROP is a symbol which is supposed to have frame-local values,
1943 and it is set up based on this frame, switch to the global
1944 binding. That way, we can create or alter the frame-local binding
1945 without messing up the symbol's status. */
1946 if (SYMBOLP (prop))
1947 {
ce5b453a
SM
1948 struct Lisp_Symbol *sym = XSYMBOL (prop);
1949 start:
1950 switch (sym->redirect)
1951 {
1952 case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
1953 case SYMBOL_PLAINVAL: case SYMBOL_FORWARDED: break;
1954 case SYMBOL_LOCALIZED:
1955 { struct Lisp_Buffer_Local_Value *blv = sym->val.blv;
a04e2c62 1956 if (blv->frame_local && blv_found (blv) && XFRAME (blv->where) == f)
ce5b453a
SM
1957 swap_in_global_binding (sym);
1958 break;
1959 }
1088b922 1960 default: emacs_abort ();
ce5b453a 1961 }
7eb63b72
GM
1962 }
1963
9b2cd403
SM
1964 /* The tty color needed to be set before the frame's parameter
1965 alist was updated with the new value. This is not true any more,
1966 but we still do this test early on. */
1967 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
1968 && f == FRAME_TTY (f)->previous_frame)
1969 /* Force redisplay of this tty. */
1970 FRAME_TTY (f)->previous_frame = NULL;
94674d18 1971
7eb63b72 1972 /* Update the frame parameter alist. */
e69b0960 1973 old_alist_elt = Fassq (prop, f->param_alist);
7eb63b72 1974 if (EQ (old_alist_elt, Qnil))
f00af5b1 1975 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
dc6f92b8 1976 else
7eb63b72 1977 Fsetcdr (old_alist_elt, val);
bc93c097 1978
7eb63b72
GM
1979 /* Update some other special parameters in their special places
1980 in addition to the alist. */
177c0ea7 1981
329ca574 1982 if (EQ (prop, Qbuffer_predicate))
f00af5b1 1983 fset_buffer_predicate (f, val);
329ca574 1984
032d78fe 1985 if (! FRAME_WINDOW_P (f))
e5317d61
EZ
1986 {
1987 if (EQ (prop, Qmenu_bar_lines))
1988 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
1989 else if (EQ (prop, Qname))
1990 set_term_frame_name (f, val);
1991 }
a249de79 1992
e35d291d 1993 if (EQ (prop, Qminibuffer) && WINDOWP (val))
bc93c097
JB
1994 {
1995 if (! MINI_WINDOW_P (XWINDOW (val)))
6b61353c 1996 error ("Surrogate minibuffer windows must be minibuffer windows");
bc93c097 1997
213bac8a 1998 if ((FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
e69b0960 1999 && !EQ (val, f->minibuffer_window))
7af7ef38 2000 error ("Can't change the surrogate minibuffer of a frame with its own minibuffer");
bc93c097
JB
2001
2002 /* Install the chosen minibuffer window, with proper buffer. */
f00af5b1 2003 fset_minibuffer_window (f, val);
bc93c097 2004 }
dc6f92b8
JB
2005}
2006
ff11dfa1 2007DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
14ff1ee0
PJ
2008 doc: /* Return the parameters-alist of frame FRAME.
2009It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2010The meaningful PARMs depend on the kind of frame.
d9f07150 2011If FRAME is omitted or nil, return information on the currently selected frame. */)
5842a27b 2012 (Lisp_Object frame)
dc6f92b8
JB
2013{
2014 Lisp_Object alist;
d9f07150 2015 struct frame *f = decode_any_frame (frame);
dd10ec4f 2016 int height, width;
57629833 2017 struct gcpro gcpro1;
dc6f92b8 2018
f769f1b2 2019 if (!FRAME_LIVE_P (f))
dc6f92b8
JB
2020 return Qnil;
2021
e69b0960 2022 alist = Fcopy_alist (f->param_alist);
57629833 2023 GCPRO1 (alist);
177c0ea7 2024
2d764c78 2025 if (!FRAME_WINDOW_P (f))
bb221971 2026 {
4aec4b29
EZ
2027 int fg = FRAME_FOREGROUND_PIXEL (f);
2028 int bg = FRAME_BACKGROUND_PIXEL (f);
e1d0bbc9
EZ
2029 Lisp_Object elt;
2030
2031 /* If the frame's parameter alist says the colors are
2032 unspecified and reversed, take the frame's background pixel
2033 for foreground and vice versa. */
2034 elt = Fassq (Qforeground_color, alist);
19b5e79b 2035 if (CONSP (elt) && STRINGP (XCDR (elt)))
70de9f06 2036 {
42a5b22f 2037 if (strncmp (SSDATA (XCDR (elt)),
70de9f06 2038 unspecified_bg,
d5db4077 2039 SCHARS (XCDR (elt))) == 0)
70de9f06 2040 store_in_alist (&alist, Qforeground_color, tty_color_name (f, bg));
42a5b22f 2041 else if (strncmp (SSDATA (XCDR (elt)),
70de9f06 2042 unspecified_fg,
d5db4077 2043 SCHARS (XCDR (elt))) == 0)
70de9f06
EZ
2044 store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
2045 }
e1d0bbc9
EZ
2046 else
2047 store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
2048 elt = Fassq (Qbackground_color, alist);
19b5e79b 2049 if (CONSP (elt) && STRINGP (XCDR (elt)))
70de9f06 2050 {
42a5b22f 2051 if (strncmp (SSDATA (XCDR (elt)),
70de9f06 2052 unspecified_fg,
d5db4077 2053 SCHARS (XCDR (elt))) == 0)
70de9f06 2054 store_in_alist (&alist, Qbackground_color, tty_color_name (f, fg));
42a5b22f 2055 else if (strncmp (SSDATA (XCDR (elt)),
70de9f06 2056 unspecified_bg,
d5db4077 2057 SCHARS (XCDR (elt))) == 0)
70de9f06
EZ
2058 store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
2059 }
e1d0bbc9
EZ
2060 else
2061 store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
2d764c78
EZ
2062 store_in_alist (&alist, intern ("font"),
2063 build_string (FRAME_MSDOS_P (f)
2064 ? "ms-dos"
4ec0d3c1 2065 : FRAME_W32_P (f) ? "w32term"
4ec0d3c1 2066 :"tty"));
bb221971 2067 }
e69b0960 2068 store_in_alist (&alist, Qname, f->name);
5af5757b 2069 height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
dd10ec4f 2070 store_in_alist (&alist, Qheight, make_number (height));
5af5757b 2071 width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
dd10ec4f 2072 store_in_alist (&alist, Qwidth, make_number (width));
f769f1b2 2073 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
fd0c2bd1 2074 store_in_alist (&alist, Qminibuffer,
39acc701 2075 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
f769f1b2
KH
2076 : FRAME_MINIBUF_ONLY_P (f) ? Qonly
2077 : FRAME_MINIBUF_WINDOW (f)));
2078 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
d9f07150
DA
2079 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
2080 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
fd0c2bd1 2081
dbc4e1c1 2082 /* I think this should be done with a hook. */
032d78fe
GV
2083#ifdef HAVE_WINDOW_SYSTEM
2084 if (FRAME_WINDOW_P (f))
ff11dfa1 2085 x_report_frame_params (f, &alist);
b6dd20ed 2086 else
fd0c2bd1 2087#endif
16a3738c
KH
2088 {
2089 /* This ought to be correct in f->param_alist for an X frame. */
2090 Lisp_Object lines;
f4e93c40 2091 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
16a3738c
KH
2092 store_in_alist (&alist, Qmenu_bar_lines, lines);
2093 }
57629833
GM
2094
2095 UNGCPRO;
dc6f92b8
JB
2096 return alist;
2097}
2098
8b60f7bc 2099
a7ca3326 2100DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
14ff1ee0
PJ
2101 doc: /* Return FRAME's value for parameter PARAMETER.
2102If FRAME is nil, describe the currently selected frame. */)
5842a27b 2103 (Lisp_Object frame, Lisp_Object parameter)
8b60f7bc 2104{
d9f07150
DA
2105 struct frame *f = decode_any_frame (frame);
2106 Lisp_Object value = Qnil;
8b60f7bc 2107
b7826503 2108 CHECK_SYMBOL (parameter);
177c0ea7 2109
d9f07150 2110 XSETFRAME (frame, f);
177c0ea7 2111
8b60f7bc
GM
2112 if (FRAME_LIVE_P (f))
2113 {
5cd62b8c 2114 /* Avoid consing in frequent cases. */
67d853e6 2115 if (EQ (parameter, Qname))
e69b0960 2116 value = f->name;
6345f6aa
GM
2117#ifdef HAVE_X_WINDOWS
2118 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
2119 value = XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element);
2120#endif /* HAVE_X_WINDOWS */
75700ff2
GM
2121 else if (EQ (parameter, Qbackground_color)
2122 || EQ (parameter, Qforeground_color))
67d853e6 2123 {
e69b0960 2124 value = Fassq (parameter, f->param_alist);
67d853e6 2125 if (CONSP (value))
5f65b39d 2126 {
5f65b39d
EZ
2127 value = XCDR (value);
2128 /* Fframe_parameters puts the actual fg/bg color names,
2129 even if f->param_alist says otherwise. This is
2130 important when param_alist's notion of colors is
2131 "unspecified". We need to do the same here. */
2132 if (STRINGP (value) && !FRAME_WINDOW_P (f))
2133 {
c9b08ba8 2134 const char *color_name;
d311d28c 2135 ptrdiff_t csz;
e1d0bbc9
EZ
2136
2137 if (EQ (parameter, Qbackground_color))
2138 {
42a5b22f 2139 color_name = SSDATA (value);
d5db4077 2140 csz = SCHARS (value);
e1d0bbc9
EZ
2141 if (strncmp (color_name, unspecified_bg, csz) == 0)
2142 value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
2143 else if (strncmp (color_name, unspecified_fg, csz) == 0)
2144 value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
2145 }
2146 else if (EQ (parameter, Qforeground_color))
2147 {
42a5b22f 2148 color_name = SSDATA (value);
d5db4077 2149 csz = SCHARS (value);
e1d0bbc9
EZ
2150 if (strncmp (color_name, unspecified_fg, csz) == 0)
2151 value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
2152 else if (strncmp (color_name, unspecified_bg, csz) == 0)
2153 value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
2154 }
5f65b39d
EZ
2155 }
2156 }
b23236fb
EZ
2157 else
2158 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
67d853e6 2159 }
75700ff2
GM
2160 else if (EQ (parameter, Qdisplay_type)
2161 || EQ (parameter, Qbackground_mode))
e69b0960 2162 value = Fcdr (Fassq (parameter, f->param_alist));
75700ff2 2163 else
ce5b453a
SM
2164 /* FIXME: Avoid this code path at all (as well as code duplication)
2165 by sharing more code with Fframe_parameters. */
75700ff2 2166 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
8b60f7bc 2167 }
177c0ea7 2168
8b60f7bc
GM
2169 return value;
2170}
2171
2172
a7ca3326 2173DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
ff11dfa1 2174 Smodify_frame_parameters, 2, 2, 0,
14ff1ee0
PJ
2175 doc: /* Modify the parameters of frame FRAME according to ALIST.
2176If FRAME is nil, it defaults to the selected frame.
2177ALIST is an alist of parameters to change and their new values.
2178Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
2179The meaningful PARMs depend on the kind of frame.
2180Undefined PARMs are ignored, but stored in the frame's parameter list
2181so that `frame-parameters' will return them.
2182
2183The value of frame parameter FOO can also be accessed
2184as a frame-local binding for the variable FOO, if you have
cf36572d
GM
2185enabled such bindings for that variable with `make-variable-frame-local'.
2186Note that this functionality is obsolete as of Emacs 22.2, and its
2187use is not recommended. Explicitly check for a frame-parameter instead. */)
5842a27b 2188 (Lisp_Object frame, Lisp_Object alist)
dc6f92b8 2189{
d9f07150 2190 struct frame *f = decode_live_frame (frame);
213bac8a 2191 register Lisp_Object tail, prop, val;
dc6f92b8 2192
dbc4e1c1 2193 /* I think this should be done with a hook. */
032d78fe
GV
2194#ifdef HAVE_WINDOW_SYSTEM
2195 if (FRAME_WINDOW_P (f))
fd0c2bd1 2196 x_set_frame_parameters (f, alist);
329ca574 2197 else
bb221971
RS
2198#endif
2199#ifdef MSDOS
2200 if (FRAME_MSDOS_P (f))
2201 IT_set_frame_parameters (f, alist);
2202 else
329ca574 2203#endif
574a1a90 2204
41d44f1f 2205 {
d311d28c
PE
2206 EMACS_INT length = XFASTINT (Flength (alist));
2207 ptrdiff_t i;
2208 Lisp_Object *parms;
2209 Lisp_Object *values;
2210 USE_SAFE_ALLOCA;
2211 SAFE_ALLOCA_LISP (parms, 2 * length);
2212 values = parms + length;
41d44f1f
RS
2213
2214 /* Extract parm names and values into those vectors. */
2215
2216 i = 0;
d7b10f4c 2217 for (tail = alist; CONSP (tail); tail = XCDR (tail))
41d44f1f 2218 {
213bac8a 2219 Lisp_Object elt;
41d44f1f 2220
d7b10f4c 2221 elt = XCAR (tail);
41d44f1f
RS
2222 parms[i] = Fcar (elt);
2223 values[i] = Fcdr (elt);
2224 i++;
2225 }
2226
2227 /* Now process them in reverse of specified order. */
5ffe6683 2228 while (--i >= 0)
41d44f1f
RS
2229 {
2230 prop = parms[i];
2231 val = values[i];
2232 store_frame_param (f, prop, val);
33d537f0 2233
043604ee
CY
2234 if (EQ (prop, Qforeground_color)
2235 || EQ (prop, Qbackground_color))
2236 update_face_from_frame_parameter (f, prop, val);
41d44f1f 2237 }
d311d28c
PE
2238
2239 SAFE_FREE ();
41d44f1f 2240 }
3b58be21 2241 return Qnil;
dc6f92b8
JB
2242}
2243\f
a26a1f95 2244DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
14ff1ee0
PJ
2245 0, 1, 0,
2246 doc: /* Height in pixels of a line in the font in frame FRAME.
d9f07150 2247If FRAME is omitted or nil, the selected frame is used.
14ff1ee0 2248For a terminal frame, the value is always 1. */)
5842a27b 2249 (Lisp_Object frame)
dc6f92b8 2250{
032d78fe 2251#ifdef HAVE_WINDOW_SYSTEM
d9f07150
DA
2252 struct frame *f = decode_any_frame (frame);
2253
032d78fe 2254 if (FRAME_WINDOW_P (f))
1700db3c 2255 return make_number (FRAME_LINE_HEIGHT (f));
a26a1f95 2256 else
dc6d9681 2257#endif
a26a1f95
RS
2258 return make_number (1);
2259}
dc6d9681 2260
dc6f92b8 2261
a26a1f95 2262DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
14ff1ee0
PJ
2263 0, 1, 0,
2264 doc: /* Width in pixels of characters in the font in frame FRAME.
d9f07150 2265If FRAME is omitted or nil, the selected frame is used.
31b7cc74 2266On a graphical screen, the width is the standard width of the default font.
14ff1ee0 2267For a terminal screen, the value is always 1. */)
5842a27b 2268 (Lisp_Object frame)
dc6f92b8 2269{
032d78fe 2270#ifdef HAVE_WINDOW_SYSTEM
d9f07150
DA
2271 struct frame *f = decode_any_frame (frame);
2272
032d78fe 2273 if (FRAME_WINDOW_P (f))
1700db3c 2274 return make_number (FRAME_COLUMN_WIDTH (f));
a26a1f95
RS
2275 else
2276#endif
2277 return make_number (1);
dc6f92b8
JB
2278}
2279
177c0ea7 2280DEFUN ("frame-pixel-height", Fframe_pixel_height,
a26a1f95 2281 Sframe_pixel_height, 0, 1, 0,
14ff1ee0 2282 doc: /* Return a FRAME's height in pixels.
d9f07150 2283If FRAME is omitted or nil, the selected frame is used. The exact value
9ec6f100
GM
2284of the result depends on the window-system and toolkit in use:
2285
2286In the Gtk+ version of Emacs, it includes only any window (including
4c36be58 2287the minibuffer or echo area), mode line, and header line. It does not
9ec6f100
GM
2288include the tool bar or menu bar.
2289
02615da0
JD
2290With other graphical versions, it also includes the tool bar and the
2291menu bar.
9ec6f100 2292
c6bf3022 2293For a text terminal, it includes the menu bar. In this case, the
9ec6f100
GM
2294result is really in characters rather than pixels (i.e., is identical
2295to `frame-height'). */)
5842a27b 2296 (Lisp_Object frame)
dc6f92b8 2297{
d9f07150 2298 struct frame *f = decode_any_frame (frame);
a26a1f95 2299
032d78fe
GV
2300#ifdef HAVE_WINDOW_SYSTEM
2301 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2302 return make_number (x_pixel_height (f));
2303 else
dc6d9681 2304#endif
5af5757b 2305 return make_number (FRAME_LINES (f));
a26a1f95
RS
2306}
2307
177c0ea7 2308DEFUN ("frame-pixel-width", Fframe_pixel_width,
a26a1f95 2309 Sframe_pixel_width, 0, 1, 0,
14ff1ee0
PJ
2310 doc: /* Return FRAME's width in pixels.
2311For a terminal frame, the result really gives the width in characters.
d9f07150 2312If FRAME is omitted or nil, the selected frame is used. */)
5842a27b 2313 (Lisp_Object frame)
a26a1f95 2314{
d9f07150 2315 struct frame *f = decode_any_frame (frame);
dc6f92b8 2316
032d78fe
GV
2317#ifdef HAVE_WINDOW_SYSTEM
2318 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2319 return make_number (x_pixel_width (f));
2320 else
2321#endif
5af5757b 2322 return make_number (FRAME_COLS (f));
a26a1f95 2323}
fb0cf781
J
2324
2325DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
2326 Stool_bar_pixel_width, 0, 1, 0,
2327 doc: /* Return width in pixels of FRAME's tool bar.
2328The result is greater than zero only when the tool bar is on the left
d9f07150
DA
2329or right side of FRAME. If FRAME is omitted or nil, the selected frame
2330is used. */)
fb0cf781
J
2331 (Lisp_Object frame)
2332{
fb0cf781 2333#ifdef FRAME_TOOLBAR_WIDTH
d9f07150
DA
2334 struct frame *f = decode_any_frame (frame);
2335
2336 if (FRAME_WINDOW_P (f))
2337 return make_number (FRAME_TOOLBAR_WIDTH (f));
fb0cf781 2338#endif
4ddb20d6 2339 return make_number (0);
fb0cf781 2340}
a26a1f95 2341\f
ff11dfa1 2342DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
14ff1ee0
PJ
2343 doc: /* Specify that the frame FRAME has LINES lines.
2344Optional third arg non-nil means that redisplay should use LINES lines
2345but that the idea of the actual height of the frame should not be changed. */)
5842a27b 2346 (Lisp_Object frame, Lisp_Object lines, Lisp_Object pretend)
dc6f92b8 2347{
d9f07150 2348 register struct frame *f = decode_live_frame (frame);
dc6f92b8 2349
d311d28c 2350 CHECK_TYPE_RANGED_INTEGER (int, lines);
dc6f92b8 2351
dbc4e1c1 2352 /* I think this should be done with a hook. */
032d78fe
GV
2353#ifdef HAVE_WINDOW_SYSTEM
2354 if (FRAME_WINDOW_P (f))
dc6f92b8 2355 {
5af5757b
KS
2356 if (XINT (lines) != FRAME_LINES (f))
2357 x_set_window_size (f, 1, FRAME_COLS (f), XINT (lines));
32347cf4 2358 do_pending_window_change (0);
dc6f92b8
JB
2359 }
2360 else
fd0c2bd1 2361#endif
32347cf4 2362 change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0, 0);
dc6f92b8
JB
2363 return Qnil;
2364}
2365
ff11dfa1 2366DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
14ff1ee0
PJ
2367 doc: /* Specify that the frame FRAME has COLS columns.
2368Optional third arg non-nil means that redisplay should use COLS columns
2369but that the idea of the actual width of the frame should not be changed. */)
5842a27b 2370 (Lisp_Object frame, Lisp_Object cols, Lisp_Object pretend)
dc6f92b8 2371{
d9f07150
DA
2372 register struct frame *f = decode_live_frame (frame);
2373
d311d28c 2374 CHECK_TYPE_RANGED_INTEGER (int, cols);
dc6f92b8 2375
dbc4e1c1 2376 /* I think this should be done with a hook. */
032d78fe
GV
2377#ifdef HAVE_WINDOW_SYSTEM
2378 if (FRAME_WINDOW_P (f))
dc6f92b8 2379 {
5af5757b
KS
2380 if (XINT (cols) != FRAME_COLS (f))
2381 x_set_window_size (f, 1, XINT (cols), FRAME_LINES (f));
32347cf4 2382 do_pending_window_change (0);
dc6f92b8
JB
2383 }
2384 else
fd0c2bd1 2385#endif
32347cf4 2386 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0, 0);
dc6f92b8
JB
2387 return Qnil;
2388}
2389
ff11dfa1 2390DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
14ff1ee0 2391 doc: /* Sets size of FRAME to COLS by ROWS, measured in characters. */)
5842a27b 2392 (Lisp_Object frame, Lisp_Object cols, Lisp_Object rows)
dc6f92b8 2393{
ff11dfa1 2394 register struct frame *f;
dc6f92b8 2395
b7826503 2396 CHECK_LIVE_FRAME (frame);
d311d28c
PE
2397 CHECK_TYPE_RANGED_INTEGER (int, cols);
2398 CHECK_TYPE_RANGED_INTEGER (int, rows);
ff11dfa1 2399 f = XFRAME (frame);
dc6f92b8 2400
dbc4e1c1 2401 /* I think this should be done with a hook. */
032d78fe
GV
2402#ifdef HAVE_WINDOW_SYSTEM
2403 if (FRAME_WINDOW_P (f))
dc6f92b8 2404 {
5af5757b
KS
2405 if (XINT (rows) != FRAME_LINES (f)
2406 || XINT (cols) != FRAME_COLS (f)
2407 || f->new_text_lines || f->new_text_cols)
808c0f20 2408 x_set_window_size (f, 1, XINT (cols), XINT (rows));
32347cf4 2409 do_pending_window_change (0);
dc6f92b8
JB
2410 }
2411 else
fd0c2bd1 2412#endif
32347cf4 2413 change_frame_size (f, XINT (rows), XINT (cols), 0, 0, 0);
dc6f92b8
JB
2414
2415 return Qnil;
2416}
2417
177c0ea7 2418DEFUN ("set-frame-position", Fset_frame_position,
ff11dfa1 2419 Sset_frame_position, 3, 3, 0,
14ff1ee0
PJ
2420 doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
2421This is actually the position of the upper left corner of the frame.
2422Negative values for XOFFSET or YOFFSET are interpreted relative to
2423the rightmost or bottommost possible position (that stays within the screen). */)
5842a27b 2424 (Lisp_Object frame, Lisp_Object xoffset, Lisp_Object yoffset)
dc6f92b8 2425{
ff11dfa1 2426 register struct frame *f;
dc6f92b8 2427
b7826503 2428 CHECK_LIVE_FRAME (frame);
d311d28c
PE
2429 CHECK_TYPE_RANGED_INTEGER (int, xoffset);
2430 CHECK_TYPE_RANGED_INTEGER (int, yoffset);
ff11dfa1 2431 f = XFRAME (frame);
dc6f92b8 2432
dbc4e1c1 2433 /* I think this should be done with a hook. */
032d78fe
GV
2434#ifdef HAVE_WINDOW_SYSTEM
2435 if (FRAME_WINDOW_P (f))
c7c70761 2436 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
fd0c2bd1 2437#endif
dc6f92b8
JB
2438
2439 return Qt;
2440}
dc6d9681 2441
dc6f92b8 2442\f
972f4259
KS
2443/***********************************************************************
2444 Frame Parameters
2445 ***********************************************************************/
2446
2447/* Connect the frame-parameter names for X frames
2448 to the ways of passing the parameter values to the window system.
2449
2450 The name of a parameter, as a Lisp symbol,
2451 has an `x-frame-parameter' property which is an integer in Lisp
2452 that is an index in this table. */
2453
2454struct frame_parm_table {
675e2c69 2455 const char *name;
972f4259
KS
2456 Lisp_Object *variable;
2457};
2458
94eed851 2459static const struct frame_parm_table frame_parms[] =
972f4259
KS
2460{
2461 {"auto-raise", &Qauto_raise},
2462 {"auto-lower", &Qauto_lower},
2463 {"background-color", 0},
2464 {"border-color", &Qborder_color},
2465 {"border-width", &Qborder_width},
2466 {"cursor-color", &Qcursor_color},
2467 {"cursor-type", &Qcursor_type},
2468 {"font", 0},
2469 {"foreground-color", 0},
2470 {"icon-name", &Qicon_name},
2471 {"icon-type", &Qicon_type},
2472 {"internal-border-width", &Qinternal_border_width},
2473 {"menu-bar-lines", &Qmenu_bar_lines},
2474 {"mouse-color", &Qmouse_color},
2475 {"name", &Qname},
2476 {"scroll-bar-width", &Qscroll_bar_width},
2477 {"title", &Qtitle},
2478 {"unsplittable", &Qunsplittable},
2479 {"vertical-scroll-bars", &Qvertical_scroll_bars},
2480 {"visibility", &Qvisibility},
2481 {"tool-bar-lines", &Qtool_bar_lines},
2482 {"scroll-bar-foreground", &Qscroll_bar_foreground},
2483 {"scroll-bar-background", &Qscroll_bar_background},
2484 {"screen-gamma", &Qscreen_gamma},
2485 {"line-spacing", &Qline_spacing},
2486 {"left-fringe", &Qleft_fringe},
2487 {"right-fringe", &Qright_fringe},
2488 {"wait-for-wm", &Qwait_for_wm},
2489 {"fullscreen", &Qfullscreen},
0a708637 2490 {"font-backend", &Qfont_backend},
cad9ef74
JD
2491 {"alpha", &Qalpha},
2492 {"sticky", &Qsticky},
bfeabdc3 2493 {"tool-bar-position", &Qtool_bar_position},
972f4259
KS
2494};
2495
0fda9b75 2496#ifdef HAVE_NTGUI
972f4259 2497
972f4259 2498/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
bd45aef7 2499 wanted positions of the WM window (not Emacs window).
972f4259
KS
2500 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
2501 window (FRAME_X_WINDOW).
2502 */
2503
dfcf069d 2504void
971de7fb 2505x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos)
dc6f92b8 2506{
5af5757b
KS
2507 int newwidth = FRAME_COLS (f);
2508 int newheight = FRAME_LINES (f);
05eb7cdc 2509 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
dc6f92b8 2510
5af5757b
KS
2511 *top_pos = f->top_pos;
2512 *left_pos = f->left_pos;
3df1fda2 2513
5af5757b 2514 if (f->want_fullscreen & FULLSCREEN_HEIGHT)
972f4259
KS
2515 {
2516 int ph;
2517
a0fe6cca 2518 ph = x_display_pixel_height (dpyinfo);
5af5757b
KS
2519 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
2520 ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
2521 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
972f4259
KS
2522 *top_pos = 0;
2523 }
dc6f92b8 2524
5af5757b 2525 if (f->want_fullscreen & FULLSCREEN_WIDTH)
972f4259
KS
2526 {
2527 int pw;
2528
a0fe6cca 2529 pw = x_display_pixel_width (dpyinfo);
5af5757b
KS
2530 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
2531 pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
2532 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
972f4259
KS
2533 *left_pos = 0;
2534 }
dc6f92b8 2535
972f4259
KS
2536 *width = newwidth;
2537 *height = newheight;
2538}
dc6f92b8 2539
0fda9b75 2540#endif /* HAVE_NTGUI */
81626931
PE
2541
2542#ifdef HAVE_WINDOW_SYSTEM
beb0bc36 2543
972f4259
KS
2544/* Change the parameters of frame F as specified by ALIST.
2545 If a parameter is not specially recognized, do nothing special;
2546 otherwise call the `x_set_...' function for that parameter.
2547 Except for certain geometry properties, always call store_frame_param
2548 to store the new value in the parameter alist. */
14ff1ee0 2549
972f4259 2550void
971de7fb 2551x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
972f4259
KS
2552{
2553 Lisp_Object tail;
dc6f92b8 2554
972f4259
KS
2555 /* If both of these parameters are present, it's more efficient to
2556 set them both at once. So we wait until we've looked at the
2557 entire list before we set them. */
2558 int width, height;
3df1fda2 2559
972f4259
KS
2560 /* Same here. */
2561 Lisp_Object left, top;
2562
2563 /* Same with these. */
2564 Lisp_Object icon_left, icon_top;
2565
2566 /* Record in these vectors all the parms specified. */
2567 Lisp_Object *parms;
2568 Lisp_Object *values;
f66c7cf8 2569 ptrdiff_t i, p;
972f4259
KS
2570 int left_no_change = 0, top_no_change = 0;
2571 int icon_left_no_change = 0, icon_top_no_change = 0;
3f1c6666 2572 int size_changed = 0;
972f4259
KS
2573 struct gcpro gcpro1, gcpro2;
2574
2575 i = 0;
7d7bbefd 2576 for (tail = alist; CONSP (tail); tail = XCDR (tail))
972f4259
KS
2577 i++;
2578
38182d90
PE
2579 parms = alloca (i * sizeof *parms);
2580 values = alloca (i * sizeof *values);
972f4259
KS
2581
2582 /* Extract parm names and values into those vectors. */
2583
2584 i = 0;
d7b10f4c 2585 for (tail = alist; CONSP (tail); tail = XCDR (tail))
972f4259
KS
2586 {
2587 Lisp_Object elt;
2588
d7b10f4c 2589 elt = XCAR (tail);
972f4259
KS
2590 parms[i] = Fcar (elt);
2591 values[i] = Fcdr (elt);
2592 i++;
2593 }
2594 /* TAIL and ALIST are not used again below here. */
2595 alist = tail = Qnil;
2596
2597 GCPRO2 (*parms, *values);
2598 gcpro1.nvars = i;
2599 gcpro2.nvars = i;
2600
2601 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
2602 because their values appear in VALUES and strings are not valid. */
2603 top = left = Qunbound;
2604 icon_left = icon_top = Qunbound;
2605
2606 /* Provide default values for HEIGHT and WIDTH. */
5af5757b
KS
2607 width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
2608 height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
972f4259
KS
2609
2610 /* Process foreground_color and background_color before anything else.
2611 They are independent of other properties, but other properties (e.g.,
2612 cursor_color) are dependent upon them. */
2613 /* Process default font as well, since fringe widths depends on it. */
972f4259
KS
2614 for (p = 0; p < i; p++)
2615 {
2616 Lisp_Object prop, val;
2617
2618 prop = parms[p];
2619 val = values[p];
2620 if (EQ (prop, Qforeground_color)
2621 || EQ (prop, Qbackground_color)
3f1c6666 2622 || EQ (prop, Qfont))
972f4259
KS
2623 {
2624 register Lisp_Object param_index, old_value;
2625
2626 old_value = get_frame_param (f, prop);
972f4259
KS
2627 if (NILP (Fequal (val, old_value)))
2628 {
2629 store_frame_param (f, prop, val);
2630
2631 param_index = Fget (prop, Qx_frame_parameter);
2632 if (NATNUMP (param_index)
2633 && (XFASTINT (param_index)
2634 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
2635 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
2636 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
972f4259
KS
2637 }
2638 }
2639 }
2640
2641 /* Now process them in reverse of specified order. */
c5101a77 2642 while (i-- != 0)
972f4259
KS
2643 {
2644 Lisp_Object prop, val;
2645
2646 prop = parms[i];
2647 val = values[i];
2648
d311d28c 2649 if (EQ (prop, Qwidth) && RANGED_INTEGERP (0, val, INT_MAX))
3f1c6666
JD
2650 {
2651 size_changed = 1;
2652 width = XFASTINT (val);
2653 }
d311d28c 2654 else if (EQ (prop, Qheight) && RANGED_INTEGERP (0, val, INT_MAX))
3f1c6666
JD
2655 {
2656 size_changed = 1;
2657 height = XFASTINT (val);
2658 }
972f4259
KS
2659 else if (EQ (prop, Qtop))
2660 top = val;
2661 else if (EQ (prop, Qleft))
2662 left = val;
2663 else if (EQ (prop, Qicon_top))
2664 icon_top = val;
2665 else if (EQ (prop, Qicon_left))
2666 icon_left = val;
2667 else if (EQ (prop, Qforeground_color)
2668 || EQ (prop, Qbackground_color)
3f1c6666 2669 || EQ (prop, Qfont))
972f4259
KS
2670 /* Processed above. */
2671 continue;
2672 else
2673 {
2674 register Lisp_Object param_index, old_value;
2675
2676 old_value = get_frame_param (f, prop);
2677
2678 store_frame_param (f, prop, val);
2679
2680 param_index = Fget (prop, Qx_frame_parameter);
2681 if (NATNUMP (param_index)
2682 && (XFASTINT (param_index)
2683 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
2684 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
2685 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
972f4259
KS
2686 }
2687 }
2688
2689 /* Don't die if just one of these was set. */
5fbfb018 2690 if (EQ (left, Qunbound))
972f4259
KS
2691 {
2692 left_no_change = 1;
5af5757b
KS
2693 if (f->left_pos < 0)
2694 left = Fcons (Qplus, Fcons (make_number (f->left_pos), Qnil));
972f4259 2695 else
5af5757b 2696 XSETINT (left, f->left_pos);
972f4259 2697 }
5fbfb018 2698 if (EQ (top, Qunbound))
972f4259
KS
2699 {
2700 top_no_change = 1;
5af5757b
KS
2701 if (f->top_pos < 0)
2702 top = Fcons (Qplus, Fcons (make_number (f->top_pos), Qnil));
972f4259 2703 else
5af5757b 2704 XSETINT (top, f->top_pos);
972f4259
KS
2705 }
2706
2707 /* If one of the icon positions was not set, preserve or default it. */
d311d28c 2708 if (! TYPE_RANGED_INTEGERP (int, icon_left))
972f4259
KS
2709 {
2710 icon_left_no_change = 1;
e69b0960 2711 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
972f4259
KS
2712 if (NILP (icon_left))
2713 XSETINT (icon_left, 0);
2714 }
d311d28c 2715 if (! TYPE_RANGED_INTEGERP (int, icon_top))
972f4259
KS
2716 {
2717 icon_top_no_change = 1;
e69b0960 2718 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
972f4259
KS
2719 if (NILP (icon_top))
2720 XSETINT (icon_top, 0);
2721 }
2722
972f4259
KS
2723 /* Don't set these parameters unless they've been explicitly
2724 specified. The window might be mapped or resized while we're in
2725 this function, and we don't want to override that unless the lisp
2726 code has asked for it.
2727
2728 Don't set these parameters unless they actually differ from the
2729 window's current parameters; the window may not actually exist
2730 yet. */
2731 {
2732 Lisp_Object frame;
2733
2734 check_frame_size (f, &height, &width);
2735
2736 XSETFRAME (frame, f);
2737
3f1c6666
JD
2738 if (size_changed
2739 && (width != FRAME_COLS (f)
2740 || height != FRAME_LINES (f)
2741 || f->new_text_lines || f->new_text_cols))
2742 Fset_frame_size (frame, make_number (width), make_number (height));
972f4259
KS
2743
2744 if ((!NILP (left) || !NILP (top))
2745 && ! (left_no_change && top_no_change)
5af5757b
KS
2746 && ! (NUMBERP (left) && XINT (left) == f->left_pos
2747 && NUMBERP (top) && XINT (top) == f->top_pos))
972f4259
KS
2748 {
2749 int leftpos = 0;
2750 int toppos = 0;
2751
2752 /* Record the signs. */
5af5757b 2753 f->size_hint_flags &= ~ (XNegative | YNegative);
972f4259 2754 if (EQ (left, Qminus))
5af5757b 2755 f->size_hint_flags |= XNegative;
b8898fda 2756 else if (TYPE_RANGED_INTEGERP (int, left))
972f4259
KS
2757 {
2758 leftpos = XINT (left);
2759 if (leftpos < 0)
5af5757b 2760 f->size_hint_flags |= XNegative;
972f4259
KS
2761 }
2762 else if (CONSP (left) && EQ (XCAR (left), Qminus)
2763 && CONSP (XCDR (left))
b8898fda 2764 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
972f4259
KS
2765 {
2766 leftpos = - XINT (XCAR (XCDR (left)));
5af5757b 2767 f->size_hint_flags |= XNegative;
972f4259
KS
2768 }
2769 else if (CONSP (left) && EQ (XCAR (left), Qplus)
2770 && CONSP (XCDR (left))
b8898fda 2771 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
972f4259
KS
2772 {
2773 leftpos = XINT (XCAR (XCDR (left)));
2774 }
2775
2776 if (EQ (top, Qminus))
5af5757b 2777 f->size_hint_flags |= YNegative;
b8898fda 2778 else if (TYPE_RANGED_INTEGERP (int, top))
972f4259
KS
2779 {
2780 toppos = XINT (top);
2781 if (toppos < 0)
5af5757b 2782 f->size_hint_flags |= YNegative;
972f4259
KS
2783 }
2784 else if (CONSP (top) && EQ (XCAR (top), Qminus)
2785 && CONSP (XCDR (top))
b8898fda 2786 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
972f4259
KS
2787 {
2788 toppos = - XINT (XCAR (XCDR (top)));
5af5757b 2789 f->size_hint_flags |= YNegative;
972f4259
KS
2790 }
2791 else if (CONSP (top) && EQ (XCAR (top), Qplus)
2792 && CONSP (XCDR (top))
b8898fda 2793 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
972f4259
KS
2794 {
2795 toppos = XINT (XCAR (XCDR (top)));
2796 }
2797
2798
2799 /* Store the numeric value of the position. */
5af5757b
KS
2800 f->top_pos = toppos;
2801 f->left_pos = leftpos;
972f4259 2802
5af5757b 2803 f->win_gravity = NorthWestGravity;
972f4259
KS
2804
2805 /* Actually set that position, and convert to absolute. */
2806 x_set_offset (f, leftpos, toppos, -1);
2807 }
2808
2809 if ((!NILP (icon_left) || !NILP (icon_top))
2810 && ! (icon_left_no_change && icon_top_no_change))
2811 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
2812 }
2813
2814 UNGCPRO;
2815}
2816
2817
2818/* Insert a description of internally-recorded parameters of frame X
2819 into the parameter alist *ALISTPTR that is to be given to the user.
2820 Only parameters that are specific to the X window system
2821 and whose values are not correctly recorded in the frame's
2822 param_alist need to be considered here. */
2823
2824void
971de7fb 2825x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
972f4259 2826{
972f4259 2827 Lisp_Object tem;
82ef37c1
PE
2828 uprintmax_t w;
2829 char buf[INT_BUFSIZE_BOUND (w)];
972f4259
KS
2830
2831 /* Represent negative positions (off the top or left screen edge)
2832 in a way that Fmodify_frame_parameters will understand correctly. */
5af5757b
KS
2833 XSETINT (tem, f->left_pos);
2834 if (f->left_pos >= 0)
972f4259
KS
2835 store_in_alist (alistptr, Qleft, tem);
2836 else
2837 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
2838
5af5757b
KS
2839 XSETINT (tem, f->top_pos);
2840 if (f->top_pos >= 0)
972f4259
KS
2841 store_in_alist (alistptr, Qtop, tem);
2842 else
2843 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
2844
2845 store_in_alist (alistptr, Qborder_width,
5af5757b 2846 make_number (f->border_width));
972f4259 2847 store_in_alist (alistptr, Qinternal_border_width,
5af5757b 2848 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
972f4259 2849 store_in_alist (alistptr, Qleft_fringe,
5af5757b 2850 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
972f4259 2851 store_in_alist (alistptr, Qright_fringe,
5af5757b 2852 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
972f4259
KS
2853 store_in_alist (alistptr, Qscroll_bar_width,
2854 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2855 ? make_number (0)
5af5757b
KS
2856 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
2857 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
2858 /* nil means "use default width"
2859 for non-toolkit scroll bar.
2860 ruler-mode.el depends on this. */
2861 : Qnil));
208a048d
EZ
2862 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
2863 MS-Windows it returns a value whose type is HANDLE, which is
2864 actually a pointer. Explicit casting avoids compiler
2865 warnings. */
82ef37c1 2866 w = (uintptr_t) FRAME_X_WINDOW (f);
972f4259 2867 store_in_alist (alistptr, Qwindow_id,
62aba0d4 2868 make_formatted_string (buf, "%"pMu, w));
972f4259
KS
2869#ifdef HAVE_X_WINDOWS
2870#ifdef USE_X_TOOLKIT
2871 /* Tooltip frame may not have this widget. */
2872 if (FRAME_X_OUTPUT (f)->widget)
2873#endif
82ef37c1 2874 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
972f4259 2875 store_in_alist (alistptr, Qouter_window_id,
62aba0d4 2876 make_formatted_string (buf, "%"pMu, w));
972f4259 2877#endif
e69b0960 2878 store_in_alist (alistptr, Qicon_name, f->icon_name);
972f4259
KS
2879 store_in_alist (alistptr, Qvisibility,
2880 (FRAME_VISIBLE_P (f) ? Qt
2881 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
2882 store_in_alist (alistptr, Qdisplay,
2883 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
2884
2885 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
2886 tem = Qnil;
2887 else
2888 XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
5839d7e8 2889 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
972f4259 2890 store_in_alist (alistptr, Qparent_id, tem);
e69b0960 2891 store_in_alist (alistptr, Qtool_bar_position, f->tool_bar_position);
972f4259
KS
2892}
2893
2894
2895/* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
2896 the previous value of that parameter, NEW_VALUE is the new value. */
2897
2898void
971de7fb 2899x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
972f4259 2900{
972f4259 2901 if (NILP (new_value))
5af5757b 2902 f->want_fullscreen = FULLSCREEN_NONE;
3f1c6666 2903 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
5af5757b 2904 f->want_fullscreen = FULLSCREEN_BOTH;
972f4259 2905 else if (EQ (new_value, Qfullwidth))
5af5757b 2906 f->want_fullscreen = FULLSCREEN_WIDTH;
972f4259 2907 else if (EQ (new_value, Qfullheight))
5af5757b 2908 f->want_fullscreen = FULLSCREEN_HEIGHT;
3f1c6666
JD
2909 else if (EQ (new_value, Qmaximized))
2910 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
d761dd42 2911
a3547743 2912 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
974b73e8 2913 FRAME_TERMINAL (f)->fullscreen_hook (f);
972f4259
KS
2914}
2915
2916
2917/* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
2918 the previous value of that parameter, NEW_VALUE is the new value. */
2919
2920void
971de7fb 2921x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
972f4259
KS
2922{
2923 if (NILP (new_value))
2924 f->extra_line_spacing = 0;
d311d28c 2925 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
972f4259
KS
2926 f->extra_line_spacing = XFASTINT (new_value);
2927 else
9dc95187 2928 signal_error ("Invalid line-spacing", new_value);
972f4259
KS
2929 if (FRAME_VISIBLE_P (f))
2930 redraw_frame (f);
2931}
2932
2933
2934/* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
2935 the previous value of that parameter, NEW_VALUE is the new value. */
2936
2937void
971de7fb 2938x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
972f4259 2939{
05fc2ef7
CY
2940 Lisp_Object bgcolor;
2941
972f4259
KS
2942 if (NILP (new_value))
2943 f->gamma = 0;
2944 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
05fc2ef7
CY
2945 /* The value 0.4545 is the normal viewing gamma. */
2946 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
972f4259 2947 else
9dc95187 2948 signal_error ("Invalid screen-gamma", new_value);
972f4259 2949
05fc2ef7 2950 /* Apply the new gamma value to the frame background. */
e69b0960 2951 bgcolor = Fassq (Qbackground_color, f->param_alist);
05fc2ef7
CY
2952 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
2953 {
76c1cebc
PE
2954 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
2955 if (NATNUMP (parm_index)
2956 && (XFASTINT (parm_index)
05fc2ef7 2957 < sizeof (frame_parms)/sizeof (frame_parms[0]))
76c1cebc
PE
2958 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
2959 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
6baa22c1 2960 (f, bgcolor, Qnil);
05fc2ef7
CY
2961 }
2962
2963 Fclear_face_cache (Qnil);
972f4259
KS
2964}
2965
2966
2967void
971de7fb 2968x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259 2969{
6045c4fd 2970 Lisp_Object font_object;
e0c8ad78 2971 int fontset = -1;
6045c4fd
PE
2972#ifdef HAVE_X_WINDOWS
2973 Lisp_Object font_param = arg;
2974#endif
972f4259 2975
178377e1 2976 /* Set the frame parameter back to the old value because we may
e0c8ad78
KH
2977 fail to use ARG as the new parameter value. */
2978 store_frame_param (f, Qfont, oldval);
0169d360 2979
d507f8d7
KH
2980 /* ARG is a fontset name, a font name, a cons of fontset name and a
2981 font object, or a font object. In the last case, this function
2982 never fail. */
e0c8ad78
KH
2983 if (STRINGP (arg))
2984 {
2985 fontset = fs_query_fontset (arg, 0);
2986 if (fontset < 0)
0169d360 2987 {
d7ea76b4 2988 font_object = font_open_by_name (f, arg);
e0c8ad78 2989 if (NILP (font_object))
42a5b22f 2990 error ("Font `%s' is not defined", SSDATA (arg));
e0c8ad78 2991 arg = AREF (font_object, FONT_NAME_INDEX);
0169d360 2992 }
e0c8ad78
KH
2993 else if (fontset > 0)
2994 {
d7ea76b4 2995 font_object = font_open_by_name (f, fontset_ascii (fontset));
e0c8ad78
KH
2996 if (NILP (font_object))
2997 error ("Font `%s' is not defined", SDATA (arg));
97d42150 2998 arg = AREF (font_object, FONT_NAME_INDEX);
e0c8ad78 2999 }
0169d360 3000 else
e0c8ad78 3001 error ("The default fontset can't be used for a frame font");
0169d360 3002 }
d507f8d7
KH
3003 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
3004 {
3005 /* This is the case that the ASCII font of F's fontset XCAR
3006 (arg) is changed to the font XCDR (arg) by
3007 `set-fontset-font'. */
3008 fontset = fs_query_fontset (XCAR (arg), 0);
3009 if (fontset < 0)
3010 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
3011 font_object = XCDR (arg);
3012 arg = AREF (font_object, FONT_NAME_INDEX);
6045c4fd 3013#ifdef HAVE_X_WINDOWS
581e51e8 3014 font_param = Ffont_get (font_object, QCname);
6045c4fd 3015#endif
d507f8d7 3016 }
e0c8ad78 3017 else if (FONT_OBJECT_P (arg))
698ca23e 3018 {
e0c8ad78 3019 font_object = arg;
6045c4fd 3020#ifdef HAVE_X_WINDOWS
581e51e8 3021 font_param = Ffont_get (font_object, QCname);
6045c4fd 3022#endif
b17ae93a 3023 /* This is to store the XLFD font name in the frame parameter for
057bce6f 3024 backward compatibility. We should store the font-object
e0c8ad78
KH
3025 itself in the future. */
3026 arg = AREF (font_object, FONT_NAME_INDEX);
b17ae93a 3027 fontset = FRAME_FONTSET (f);
518c4881
KH
3028 /* Check if we can use the current fontset. If not, set FONTSET
3029 to -1 to generate a new fontset from FONT-OBJECT. */
3030 if (fontset >= 0)
3031 {
3032 Lisp_Object ascii_font = fontset_ascii (fontset);
3033 Lisp_Object spec = font_spec_from_name (ascii_font);
3034
e483264c
SM
3035 if (NILP (spec))
3036 signal_error ("Invalid font name", ascii_font);
3037
518c4881
KH
3038 if (! font_match_p (spec, font_object))
3039 fontset = -1;
3040 }
698ca23e 3041 }
e0c8ad78
KH
3042 else
3043 signal_error ("Invalid font", arg);
972f4259 3044
e0c8ad78
KH
3045 if (! NILP (Fequal (font_object, oldval)))
3046 return;
5a9aae2e 3047
e0c8ad78
KH
3048 x_new_font (f, font_object, fontset);
3049 store_frame_param (f, Qfont, arg);
581e51e8
JD
3050#ifdef HAVE_X_WINDOWS
3051 store_frame_param (f, Qfont_param, font_param);
3052#endif
e0c8ad78
KH
3053 /* Recalculate toolbar height. */
3054 f->n_tool_bar_rows = 0;
3055 /* Ensure we redraw it. */
3056 clear_current_matrices (f);
ca03f883 3057
e0c8ad78 3058 recompute_basic_faces (f);
972f4259
KS
3059
3060 do_pending_window_change (0);
3061
a6f75881
CY
3062 /* We used to call face-set-after-frame-default here, but it leads to
3063 recursive calls (since that function can set the `default' face's
3064 font which in turns changes the frame's `font' parameter).
3065 Also I don't know what this call is meant to do, but it seems the
3066 wrong way to do it anyway (it does a lot more work than what seems
3067 reasonable in response to a change to `font'). */
972f4259
KS
3068}
3069
3070
1a356571 3071void
971de7fb 3072x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1a356571 3073{
1a356571
KH
3074 if (! NILP (new_value)
3075 && !CONSP (new_value))
3076 {
3077 char *p0, *p1;
1bf72735 3078
1a356571 3079 CHECK_STRING (new_value);
42a5b22f 3080 p0 = p1 = SSDATA (new_value);
1a356571
KH
3081 new_value = Qnil;
3082 while (*p0)
3083 {
620f13b0 3084 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
1a356571
KH
3085 if (p0 < p1)
3086 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
3087 new_value);
3088 if (*p1)
22e64f7c
KH
3089 {
3090 int c;
3091
620f13b0 3092 while ((c = *++p1) && c_isspace (c));
22e64f7c 3093 }
1a356571
KH
3094 p0 = p1;
3095 }
8fb9e675
KH
3096 new_value = Fnreverse (new_value);
3097 }
3098
3099 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
3100 return;
3101
e0c8ad78 3102 if (FRAME_FONT (f))
dfdf55c0 3103 free_all_realized_faces (Qnil);
1a356571 3104
dfdf55c0 3105 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
8fb9e675 3106 if (NILP (new_value))
dfdf55c0
KH
3107 {
3108 if (NILP (old_value))
3109 error ("No font backend available");
3110 font_update_drivers (f, old_value);
3111 error ("None of specified font backends are available");
3112 }
8fb9e675
KH
3113 store_frame_param (f, Qfont_backend, new_value);
3114
e0c8ad78 3115 if (FRAME_FONT (f))
8fb9e675
KH
3116 {
3117 Lisp_Object frame;
3118
3119 XSETFRAME (frame, f);
3120 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
3121 ++face_change_count;
3122 ++windows_or_buffers_changed;
3123 }
1a356571 3124}
1a356571
KH
3125
3126
972f4259 3127void
971de7fb 3128x_set_fringe_width (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
972f4259
KS
3129{
3130 compute_fringe_widths (f, 1);
bfeabdc3
JD
3131#ifdef HAVE_X_WINDOWS
3132 /* Must adjust this so window managers report correct number of columns. */
3133 if (FRAME_X_WINDOW (f) != 0)
3134 x_wm_set_size_hint (f, 0, 0);
3135#endif
972f4259
KS
3136}
3137
3138void
971de7fb 3139x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259 3140{
d311d28c 3141 CHECK_TYPE_RANGED_INTEGER (int, arg);
972f4259 3142
5af5757b 3143 if (XINT (arg) == f->border_width)
972f4259
KS
3144 return;
3145
972f4259 3146 if (FRAME_X_WINDOW (f) != 0)
dac85f4b 3147 error ("Cannot change the border width of a frame");
972f4259 3148
5af5757b 3149 f->border_width = XINT (arg);
972f4259
KS
3150}
3151
3152void
971de7fb 3153x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259 3154{
5af5757b 3155 int old = FRAME_INTERNAL_BORDER_WIDTH (f);
972f4259 3156
d311d28c 3157 CHECK_TYPE_RANGED_INTEGER (int, arg);
5af5757b
KS
3158 FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
3159 if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
3160 FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
972f4259
KS
3161
3162#ifdef USE_X_TOOLKIT
3163 if (FRAME_X_OUTPUT (f)->edit_widget)
3164 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
3165#endif
3166
5af5757b 3167 if (FRAME_INTERNAL_BORDER_WIDTH (f) == old)
972f4259
KS
3168 return;
3169
3170 if (FRAME_X_WINDOW (f) != 0)
3171 {
5af5757b 3172 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3173 SET_FRAME_GARBAGED (f);
3174 do_pending_window_change (0);
3175 }
3176 else
3177 SET_FRAME_GARBAGED (f);
3178}
3179
3180void
971de7fb 3181x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
972f4259
KS
3182{
3183 Lisp_Object frame;
3184 XSETFRAME (frame, f);
3185
3186 if (NILP (value))
3187 Fmake_frame_invisible (frame, Qt);
3188 else if (EQ (value, Qicon))
3189 Ficonify_frame (frame);
3190 else
3191 Fmake_frame_visible (frame);
3192}
3193
3194void
971de7fb 3195x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259
KS
3196{
3197 f->auto_raise = !EQ (Qnil, arg);
3198}
3199
3200void
971de7fb 3201x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259
KS
3202{
3203 f->auto_lower = !EQ (Qnil, arg);
3204}
3205
3206void
971de7fb 3207x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259
KS
3208{
3209 f->no_split = !NILP (arg);
3210}
3211
3212void
971de7fb 3213x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259
KS
3214{
3215 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3216 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
3217 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3218 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
3219 {
3220 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
3221 = (NILP (arg)
3222 ? vertical_scroll_bar_none
3223 : EQ (Qleft, arg)
3224 ? vertical_scroll_bar_left
3225 : EQ (Qright, arg)
3226 ? vertical_scroll_bar_right
6b61353c
KH
3227 : EQ (Qleft, Vdefault_frame_scroll_bars)
3228 ? vertical_scroll_bar_left
3229 : EQ (Qright, Vdefault_frame_scroll_bars)
3230 ? vertical_scroll_bar_right
3231 : vertical_scroll_bar_none);
972f4259
KS
3232
3233 /* We set this parameter before creating the X window for the
3234 frame, so we can get the geometry right from the start.
3235 However, if the window hasn't been created yet, we shouldn't
3236 call x_set_window_size. */
3237 if (FRAME_X_WINDOW (f))
5af5757b 3238 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3239 do_pending_window_change (0);
3240 }
3241}
3242
3243void
971de7fb 3244x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259 3245{
5af5757b 3246 int wid = FRAME_COLUMN_WIDTH (f);
972f4259
KS
3247
3248 if (NILP (arg))
3249 {
3250 x_set_scroll_bar_default_width (f);
3251
3252 if (FRAME_X_WINDOW (f))
5af5757b 3253 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3254 do_pending_window_change (0);
3255 }
b8898fda 3256 else if (RANGED_INTEGERP (1, arg, INT_MAX)
5af5757b 3257 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3258 {
3259 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
3260 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
3261
5af5757b
KS
3262 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
3263 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
972f4259 3264 if (FRAME_X_WINDOW (f))
5af5757b 3265 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3266 do_pending_window_change (0);
3267 }
3268
5af5757b 3269 change_frame_size (f, 0, FRAME_COLS (f), 0, 0, 0);
972f4259
KS
3270 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3271 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3272}
3273
3274
3275
3276/* Return non-nil if frame F wants a bitmap icon. */
3277
3278Lisp_Object
971de7fb 3279x_icon_type (FRAME_PTR f)
972f4259
KS
3280{
3281 Lisp_Object tem;
3282
e69b0960 3283 tem = assq_no_quit (Qicon_type, f->param_alist);
972f4259
KS
3284 if (CONSP (tem))
3285 return XCDR (tem);
3286 else
3287 return Qnil;
3288}
3289
0a708637 3290void
971de7fb 3291x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
0a708637
GM
3292{
3293 double alpha = 1.0;
3294 double newval[2];
b8898fda 3295 int i;
0a708637
GM
3296 Lisp_Object item;
3297
3298 for (i = 0; i < 2; i++)
3299 {
3300 newval[i] = 1.0;
3301 if (CONSP (arg))
3302 {
3303 item = CAR (arg);
3304 arg = CDR (arg);
3305 }
3306 else
1fd877d6 3307 item = arg;
0a708637 3308
62e62ea8
CY
3309 if (NILP (item))
3310 alpha = - 1.0;
3311 else if (FLOATP (item))
3312 {
3313 alpha = XFLOAT_DATA (item);
908589fd 3314 if (alpha < 0.0 || alpha > 1.0)
62e62ea8
CY
3315 args_out_of_range (make_float (0.0), make_float (1.0));
3316 }
3317 else if (INTEGERP (item))
3318 {
b8898fda 3319 EMACS_INT ialpha = XINT (item);
908589fd 3320 if (ialpha < 0 || ialpha > 100)
62e62ea8
CY
3321 args_out_of_range (make_number (0), make_number (100));
3322 else
3323 alpha = ialpha / 100.0;
3324 }
3325 else
3326 wrong_type_argument (Qnumberp, item);
0a708637
GM
3327 newval[i] = alpha;
3328 }
3329
3330 for (i = 0; i < 2; i++)
3331 f->alpha[i] = newval[i];
3332
59bc82c0 3333#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
4d7e6e51 3334 block_input ();
0a708637 3335 x_set_frame_alpha (f);
4d7e6e51 3336 unblock_input ();
0a708637
GM
3337#endif
3338
3339 return;
3340}
3341
972f4259
KS
3342\f
3343/* Subroutines of creating an X frame. */
3344
3345/* Make sure that Vx_resource_name is set to a reasonable value.
3346 Fix it up, or set it to `emacs' if it is too hopeless. */
3347
3348void
971de7fb 3349validate_x_resource_name (void)
972f4259 3350{
8a401434 3351 ptrdiff_t len = 0;
972f4259 3352 /* Number of valid characters in the resource name. */
8a401434 3353 ptrdiff_t good_count = 0;
972f4259 3354 /* Number of invalid characters in the resource name. */
8a401434 3355 ptrdiff_t bad_count = 0;
972f4259 3356 Lisp_Object new;
8a401434 3357 ptrdiff_t i;
972f4259
KS
3358
3359 if (!STRINGP (Vx_resource_class))
3360 Vx_resource_class = build_string (EMACS_CLASS);
3361
3362 if (STRINGP (Vx_resource_name))
3363 {
3364 unsigned char *p = SDATA (Vx_resource_name);
972f4259
KS
3365
3366 len = SBYTES (Vx_resource_name);
3367
3368 /* Only letters, digits, - and _ are valid in resource names.
3369 Count the valid characters and count the invalid ones. */
3370 for (i = 0; i < len; i++)
3371 {
3372 int c = p[i];
3373 if (! ((c >= 'a' && c <= 'z')
3374 || (c >= 'A' && c <= 'Z')
3375 || (c >= '0' && c <= '9')
3376 || c == '-' || c == '_'))
3377 bad_count++;
3378 else
3379 good_count++;
3380 }
3381 }
3382 else
3383 /* Not a string => completely invalid. */
3384 bad_count = 5, good_count = 0;
3385
3386 /* If name is valid already, return. */
3387 if (bad_count == 0)
3388 return;
3389
8a401434
PE
3390 /* If name is entirely invalid, or nearly so, or is so implausibly
3391 large that alloca might not work, use `emacs'. */
3392 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
972f4259
KS
3393 {
3394 Vx_resource_name = build_string ("emacs");
3395 return;
3396 }
3397
3398 /* Name is partly valid. Copy it and replace the invalid characters
3399 with underscores. */
3400
3401 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3402
3403 for (i = 0; i < len; i++)
3404 {
3405 int c = SREF (new, i);
3406 if (! ((c >= 'a' && c <= 'z')
3407 || (c >= 'A' && c <= 'Z')
3408 || (c >= '0' && c <= '9')
3409 || c == '-' || c == '_'))
3410 SSET (new, i, '_');
3411 }
3412}
3413
3414
eec47d6b 3415extern char *x_get_string_resource (XrmDatabase, const char *, const char *);
f57e2426 3416extern Display_Info *check_x_display_info (Lisp_Object);
972f4259
KS
3417
3418
b5251fe7 3419/* Get specified attribute from resource database RDB.
972f4259
KS
3420 See Fx_get_resource below for other parameters. */
3421
3422static Lisp_Object
971de7fb 3423xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
972f4259
KS
3424{
3425 register char *value;
3426 char *name_key;
3427 char *class_key;
3428
3429 CHECK_STRING (attribute);
3430 CHECK_STRING (class);
3431
3432 if (!NILP (component))
3433 CHECK_STRING (component);
3434 if (!NILP (subclass))
3435 CHECK_STRING (subclass);
3436 if (NILP (component) != NILP (subclass))
3437 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3438
3439 validate_x_resource_name ();
3440
3441 /* Allocate space for the components, the dots which separate them,
3442 and the final '\0'. Make them big enough for the worst case. */
38182d90
PE
3443 name_key = alloca (SBYTES (Vx_resource_name)
3444 + (STRINGP (component)
3445 ? SBYTES (component) : 0)
3446 + SBYTES (attribute)
3447 + 3);
3448
3449 class_key = alloca (SBYTES (Vx_resource_class)
3450 + SBYTES (class)
3451 + (STRINGP (subclass)
3452 ? SBYTES (subclass) : 0)
3453 + 3);
972f4259
KS
3454
3455 /* Start with emacs.FRAMENAME for the name (the specific one)
3456 and with `Emacs' for the class key (the general one). */
42a5b22f
PE
3457 strcpy (name_key, SSDATA (Vx_resource_name));
3458 strcpy (class_key, SSDATA (Vx_resource_class));
972f4259
KS
3459
3460 strcat (class_key, ".");
42a5b22f 3461 strcat (class_key, SSDATA (class));
972f4259
KS
3462
3463 if (!NILP (component))
3464 {
3465 strcat (class_key, ".");
42a5b22f 3466 strcat (class_key, SSDATA (subclass));
972f4259
KS
3467
3468 strcat (name_key, ".");
42a5b22f 3469 strcat (name_key, SSDATA (component));
972f4259
KS
3470 }
3471
3472 strcat (name_key, ".");
42a5b22f 3473 strcat (name_key, SSDATA (attribute));
972f4259
KS
3474
3475 value = x_get_string_resource (rdb, name_key, class_key);
3476
feabfb6c 3477 if (value != (char *) 0 && *value)
972f4259
KS
3478 return build_string (value);
3479 else
3480 return Qnil;
3481}
3482
3483
3484DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
3485 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
3486This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
3487class, where INSTANCE is the name under which Emacs was invoked, or
3488the name specified by the `-name' or `-rn' command-line arguments.
3489
3490The optional arguments COMPONENT and SUBCLASS add to the key and the
3491class, respectively. You must specify both of them or neither.
3492If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
3493and the class is `Emacs.CLASS.SUBCLASS'. */)
2bf7d27a
DA
3494 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
3495 Lisp_Object subclass)
972f4259
KS
3496{
3497#ifdef HAVE_X_WINDOWS
3498 check_x ();
3499#endif
3500
3501 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
3502 attribute, class, component, subclass);
3503}
3504
3505/* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
3506
3507Lisp_Object
2bf7d27a
DA
3508display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
3509 Lisp_Object class, Lisp_Object component,
3510 Lisp_Object subclass)
972f4259
KS
3511{
3512 return xrdb_get_resource (dpyinfo->xrdb,
3513 attribute, class, component, subclass);
3514}
3515
018c5e19
PE
3516#if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT
3517/* Used when C code wants a resource value. */
3518/* Called from oldXMenu/Create.c. */
3519char *
3520x_get_resource_string (const char *attribute, const char *class)
3521{
8a401434 3522 char *result;
018c5e19 3523 struct frame *sf = SELECTED_FRAME ();
8a401434
PE
3524 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
3525 USE_SAFE_ALLOCA;
018c5e19
PE
3526
3527 /* Allocate space for the components, the dots which separate them,
3528 and the final '\0'. */
98c6f1e3
PE
3529 char *name_key = SAFE_ALLOCA (invocation_namelen + strlen (attribute) + 2);
3530 char *class_key = alloca ((sizeof (EMACS_CLASS) - 1) + strlen (class) + 2);
018c5e19 3531
8a401434 3532 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
018c5e19
PE
3533 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3534
8a401434
PE
3535 result = x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
3536 name_key, class_key);
3537 SAFE_FREE ();
3538 return result;
018c5e19
PE
3539}
3540#endif
3541
972f4259
KS
3542/* Return the value of parameter PARAM.
3543
3544 First search ALIST, then Vdefault_frame_alist, then the X defaults
3545 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3546
3547 Convert the resource to the type specified by desired_type.
3548
3549 If no default is specified, return Qunbound. If you call
3550 x_get_arg, make sure you deal with Qunbound in a reasonable way,
3551 and don't let it get stored in any Lisp-visible variables! */
3552
3553Lisp_Object
eec47d6b
DN
3554x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
3555 const char *attribute, const char *class, enum resource_types type)
972f4259
KS
3556{
3557 register Lisp_Object tem;
3558
3559 tem = Fassq (param, alist);
d00368cf
RS
3560
3561 if (!NILP (tem))
3562 {
3563 /* If we find this parm in ALIST, clear it out
3564 so that it won't be "left over" at the end. */
5f694926 3565 Lisp_Object tail;
d00368cf 3566 XSETCAR (tem, Qnil);
5f694926
RS
3567 /* In case the parameter appears more than once in the alist,
3568 clear it out. */
3569 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3570 if (CONSP (XCAR (tail))
3571 && EQ (XCAR (XCAR (tail)), param))
3572 XSETCAR (XCAR (tail), Qnil);
d00368cf
RS
3573 }
3574 else
972f4259 3575 tem = Fassq (param, Vdefault_frame_alist);
d00368cf
RS
3576
3577 /* If it wasn't specified in ALIST or the Lisp-level defaults,
3578 look in the X resources. */
972f4259
KS
3579 if (EQ (tem, Qnil))
3580 {
4e23bedb 3581 if (attribute && dpyinfo)
972f4259
KS
3582 {
3583 tem = display_x_get_resource (dpyinfo,
3584 build_string (attribute),
3585 build_string (class),
3586 Qnil, Qnil);
3587
3588 if (NILP (tem))
3589 return Qunbound;
3590
3591 switch (type)
3592 {
3593 case RES_TYPE_NUMBER:
42a5b22f 3594 return make_number (atoi (SSDATA (tem)));
972f4259 3595
93318cbd 3596 case RES_TYPE_BOOLEAN_NUMBER:
42a5b22f
PE
3597 if (!strcmp (SSDATA (tem), "on")
3598 || !strcmp (SSDATA (tem), "true"))
93318cbd 3599 return make_number (1);
42a5b22f 3600 return make_number (atoi (SSDATA (tem)));
93318cbd
JD
3601 break;
3602
972f4259 3603 case RES_TYPE_FLOAT:
42a5b22f 3604 return make_float (atof (SSDATA (tem)));
972f4259
KS
3605
3606 case RES_TYPE_BOOLEAN:
3607 tem = Fdowncase (tem);
42a5b22f 3608 if (!strcmp (SSDATA (tem), "on")
edfda783 3609#ifdef HAVE_NS
42a5b22f 3610 || !strcmp (SSDATA (tem), "yes")
edfda783 3611#endif
42a5b22f 3612 || !strcmp (SSDATA (tem), "true"))
972f4259
KS
3613 return Qt;
3614 else
3615 return Qnil;
3616
3617 case RES_TYPE_STRING:
3618 return tem;
3619
3620 case RES_TYPE_SYMBOL:
3621 /* As a special case, we map the values `true' and `on'
3622 to Qt, and `false' and `off' to Qnil. */
3623 {
3624 Lisp_Object lower;
3625 lower = Fdowncase (tem);
42a5b22f 3626 if (!strcmp (SSDATA (lower), "on")
edfda783 3627#ifdef HAVE_NS
42a5b22f 3628 || !strcmp (SSDATA (lower), "yes")
edfda783 3629#endif
42a5b22f 3630 || !strcmp (SSDATA (lower), "true"))
972f4259 3631 return Qt;
42a5b22f 3632 else if (!strcmp (SSDATA (lower), "off")
edfda783 3633#ifdef HAVE_NS
42a5b22f 3634 || !strcmp (SSDATA (lower), "no")
edfda783 3635#endif
42a5b22f 3636 || !strcmp (SSDATA (lower), "false"))
972f4259
KS
3637 return Qnil;
3638 else
3639 return Fintern (tem, Qnil);
3640 }
3641
3642 default:
1088b922 3643 emacs_abort ();
972f4259
KS
3644 }
3645 }
3646 else
3647 return Qunbound;
3648 }
3649 return Fcdr (tem);
3650}
3651
2f7c71a1 3652static Lisp_Object
eec47d6b
DN
3653x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
3654 const char *attribute, const char *class,
3655 enum resource_types type)
972f4259
KS
3656{
3657 return x_get_arg (FRAME_X_DISPLAY_INFO (f),
3658 alist, param, attribute, class, type);
3659}
3660
3661/* Like x_frame_get_arg, but also record the value in f->param_alist. */
3662
3663Lisp_Object
eec47d6b
DN
3664x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
3665 Lisp_Object param,
3666 const char *attribute, const char *class,
3667 enum resource_types type)
972f4259
KS
3668{
3669 Lisp_Object value;
3670
3671 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
3672 attribute, class, type);
edd1c685 3673 if (! NILP (value) && ! EQ (value, Qunbound))
972f4259
KS
3674 store_frame_param (f, param, value);
3675
3676 return value;
3677}
3678
3679
3680/* Record in frame F the specified or default value according to ALIST
3681 of the parameter named PROP (a Lisp symbol).
3682 If no value is specified for PROP, look for an X default for XPROP
3683 on the frame named NAME.
3684 If that is not found either, use the value DEFLT. */
3685
3686Lisp_Object
eec47d6b
DN
3687x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
3688 Lisp_Object deflt, const char *xprop, const char *xclass,
3689 enum resource_types type)
972f4259
KS
3690{
3691 Lisp_Object tem;
3692
3693 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
3694 if (EQ (tem, Qunbound))
3695 tem = deflt;
3696 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3697 return tem;
3698}
3699
3700
e543ae91
JD
3701#if !defined (HAVE_X_WINDOWS) && defined (NoValue)
3702
3703/*
3704 * XParseGeometry parses strings of the form
3705 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
3706 * width, height, xoffset, and yoffset are unsigned integers.
3707 * Example: "=80x24+300-49"
3708 * The equal sign is optional.
3709 * It returns a bitmask that indicates which of the four values
3710 * were actually found in the string. For each value found,
3711 * the corresponding argument is updated; for each value
3712 * not found, the corresponding argument is left unchanged.
3713 */
3714
3715static int
e543ae91
JD
3716XParseGeometry (char *string,
3717 int *x, int *y,
3718 unsigned int *width, unsigned int *height)
3719{
3720 int mask = NoValue;
05642592
PE
3721 char *strind;
3722 unsigned long int tempWidth, tempHeight;
3723 long int tempX, tempY;
e543ae91
JD
3724 char *nextCharacter;
3725
05642592
PE
3726 if (string == NULL || *string == '\0')
3727 return mask;
e543ae91
JD
3728 if (*string == '=')
3729 string++; /* ignore possible '=' at beg of geometry spec */
3730
05642592 3731 strind = string;
e543ae91
JD
3732 if (*strind != '+' && *strind != '-' && *strind != 'x')
3733 {
05642592 3734 tempWidth = strtoul (strind, &nextCharacter, 10);
e543ae91 3735 if (strind == nextCharacter)
05642592 3736 return 0;
e543ae91
JD
3737 strind = nextCharacter;
3738 mask |= WidthValue;
3739 }
3740
3741 if (*strind == 'x' || *strind == 'X')
3742 {
3743 strind++;
05642592 3744 tempHeight = strtoul (strind, &nextCharacter, 10);
e543ae91 3745 if (strind == nextCharacter)
05642592 3746 return 0;
e543ae91
JD
3747 strind = nextCharacter;
3748 mask |= HeightValue;
3749 }
3750
05642592 3751 if (*strind == '+' || *strind == '-')
e543ae91
JD
3752 {
3753 if (*strind == '-')
05642592
PE
3754 mask |= XNegative;
3755 tempX = strtol (strind, &nextCharacter, 10);
3756 if (strind == nextCharacter)
3757 return 0;
3758 strind = nextCharacter;
e543ae91 3759 mask |= XValue;
05642592 3760 if (*strind == '+' || *strind == '-')
e543ae91
JD
3761 {
3762 if (*strind == '-')
05642592
PE
3763 mask |= YNegative;
3764 tempY = strtol (strind, &nextCharacter, 10);
3765 if (strind == nextCharacter)
3766 return 0;
3767 strind = nextCharacter;
e543ae91
JD
3768 mask |= YValue;
3769 }
3770 }
3771
3772 /* If strind isn't at the end of the string then it's an invalid
3773 geometry specification. */
3774
05642592
PE
3775 if (*strind != '\0')
3776 return 0;
e543ae91
JD
3777
3778 if (mask & XValue)
05642592 3779 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
e543ae91 3780 if (mask & YValue)
05642592 3781 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
e543ae91 3782 if (mask & WidthValue)
05642592 3783 *width = min (tempWidth, UINT_MAX);
e543ae91 3784 if (mask & HeightValue)
05642592
PE
3785 *height = min (tempHeight, UINT_MAX);
3786 return mask;
e543ae91
JD
3787}
3788
3789#endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
972f4259
KS
3790
3791\f
7ab5d780
GM
3792/* NS used to define x-parse-geometry in ns-win.el, but that confused
3793 make-docfile: the documentation string in ns-win.el was used for
3794 x-parse-geometry even in non-NS builds.
3795
3796 With two definitions of x-parse-geometry in this file, various
3797 things still get confused (eg M-x apropos documentation), so that
3798 it is best if the two definitions just share the same doc-string.
3799*/
972f4259 3800DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
7ab5d780 3801 doc: /* Parse a display geometry string STRING.
972f4259
KS
3802Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3803The properties returned may include `top', `left', `height', and `width'.
7ab5d780 3804For X, the value of `left' or `top' may be an integer,
972f4259 3805or a list (+ N) meaning N pixels relative to top/left corner,
7ab5d780
GM
3806or a list (- N) meaning -N pixels relative to bottom/right corner.
3807On Nextstep, this just calls `ns-parse-geometry'. */)
5842a27b 3808 (Lisp_Object string)
972f4259
KS
3809{
3810 int geometry, x, y;
3811 unsigned int width, height;
3812 Lisp_Object result;
3813
3814 CHECK_STRING (string);
3815
e543ae91
JD
3816#ifdef HAVE_NS
3817 if (strchr (SSDATA (string), ' ') != NULL)
3818 return call1 (Qns_parse_geometry, string);
3819#endif
51b59d79 3820 geometry = XParseGeometry (SSDATA (string),
972f4259 3821 &x, &y, &width, &height);
972f4259
KS
3822 result = Qnil;
3823 if (geometry & XValue)
3824 {
3825 Lisp_Object element;
3826
3827 if (x >= 0 && (geometry & XNegative))
3828 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3829 else if (x < 0 && ! (geometry & XNegative))
3830 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3831 else
3832 element = Fcons (Qleft, make_number (x));
3833 result = Fcons (element, result);
3834 }
3835
3836 if (geometry & YValue)
3837 {
3838 Lisp_Object element;
3839
3840 if (y >= 0 && (geometry & YNegative))
3841 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3842 else if (y < 0 && ! (geometry & YNegative))
3843 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3844 else
3845 element = Fcons (Qtop, make_number (y));
3846 result = Fcons (element, result);
3847 }
3848
3849 if (geometry & WidthValue)
3850 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3851 if (geometry & HeightValue)
3852 result = Fcons (Fcons (Qheight, make_number (height)), result);
3853
3854 return result;
7ab5d780 3855}
dc4db71c 3856
972f4259
KS
3857
3858/* Calculate the desired size and position of frame F.
3859 Return the flags saying which aspects were specified.
3860
3861 Also set the win_gravity and size_hint_flags of F.
3862
3863 Adjust height for toolbar if TOOLBAR_P is 1.
3864
3865 This function does not make the coordinates positive. */
3866
c024ac08 3867#define DEFAULT_ROWS 35
972f4259
KS
3868#define DEFAULT_COLS 80
3869
3870int
971de7fb 3871x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p)
972f4259
KS
3872{
3873 register Lisp_Object tem0, tem1, tem2;
3874 long window_prompting = 0;
3875 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3876
3877 /* Default values if we fall through.
3878 Actually, if that happens we should get
3879 window manager prompting. */
5af5757b
KS
3880 SET_FRAME_COLS (f, DEFAULT_COLS);
3881 FRAME_LINES (f) = DEFAULT_ROWS;
972f4259
KS
3882 /* Window managers expect that if program-specified
3883 positions are not (0,0), they're intentional, not defaults. */
5af5757b
KS
3884 f->top_pos = 0;
3885 f->left_pos = 0;
972f4259 3886
5af5757b 3887 /* Ensure that old new_text_cols and new_text_lines will not override the
972f4259
KS
3888 values set here. */
3889 /* ++KFS: This was specific to W32, but seems ok for all platforms */
5af5757b 3890 f->new_text_cols = f->new_text_lines = 0;
972f4259
KS
3891
3892 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3893 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3894 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3895 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3896 {
3897 if (!EQ (tem0, Qunbound))
3898 {
3899 CHECK_NUMBER (tem0);
b8898fda
PE
3900 if (! (0 <= XINT (tem0) && XINT (tem0) <= INT_MAX))
3901 xsignal1 (Qargs_out_of_range, tem0);
5af5757b 3902 FRAME_LINES (f) = XINT (tem0);
972f4259
KS
3903 }
3904 if (!EQ (tem1, Qunbound))
3905 {
3906 CHECK_NUMBER (tem1);
b8898fda
PE
3907 if (! (0 <= XINT (tem1) && XINT (tem1) <= INT_MAX))
3908 xsignal1 (Qargs_out_of_range, tem1);
5af5757b 3909 SET_FRAME_COLS (f, XINT (tem1));
972f4259
KS
3910 }
3911 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3912 window_prompting |= USSize;
3913 else
3914 window_prompting |= PSize;
3915 }
3916
5af5757b
KS
3917 f->scroll_bar_actual_width
3918 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
972f4259
KS
3919
3920 /* This used to be done _before_ calling x_figure_window_size, but
3921 since the height is reset here, this was really a no-op. I
3922 assume that moving it here does what Gerd intended (although he
3923 no longer can remember what that was... ++KFS, 2003-03-25. */
3924
3925 /* Add the tool-bar height to the initial frame height so that the
3926 user gets a text display area of the size he specified with -g or
3927 via .Xdefaults. Later changes of the tool-bar height don't
3928 change the frame size. This is done so that users can create
3929 tall Emacs frames without having to guess how tall the tool-bar
3930 will get. */
3931 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
3932 {
3933 int margin, relief, bar_height;
3934
3935 relief = (tool_bar_button_relief >= 0
3936 ? tool_bar_button_relief
3937 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
3938
b8898fda 3939 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
972f4259
KS
3940 margin = XFASTINT (Vtool_bar_button_margin);
3941 else if (CONSP (Vtool_bar_button_margin)
b8898fda 3942 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
972f4259
KS
3943 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
3944 else
3945 margin = 0;
3946
3947 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5af5757b 3948 FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
972f4259
KS
3949 }
3950
3951 compute_fringe_widths (f, 0);
3952
5af5757b
KS
3953 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, FRAME_COLS (f));
3954 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
972f4259
KS
3955
3956 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3957 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3958 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3959 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3960 {
3961 if (EQ (tem0, Qminus))
3962 {
5af5757b 3963 f->top_pos = 0;
972f4259
KS
3964 window_prompting |= YNegative;
3965 }
3966 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3967 && CONSP (XCDR (tem0))
b8898fda 3968 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem0)), INT_MAX))
972f4259 3969 {
5af5757b 3970 f->top_pos = - XINT (XCAR (XCDR (tem0)));
972f4259
KS
3971 window_prompting |= YNegative;
3972 }
3973 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3974 && CONSP (XCDR (tem0))
b8898fda 3975 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem0))))
972f4259 3976 {
5af5757b 3977 f->top_pos = XINT (XCAR (XCDR (tem0)));
972f4259
KS
3978 }
3979 else if (EQ (tem0, Qunbound))
5af5757b 3980 f->top_pos = 0;
972f4259
KS
3981 else
3982 {
d311d28c 3983 CHECK_TYPE_RANGED_INTEGER (int, tem0);
5af5757b
KS
3984 f->top_pos = XINT (tem0);
3985 if (f->top_pos < 0)
972f4259
KS
3986 window_prompting |= YNegative;
3987 }
3988
3989 if (EQ (tem1, Qminus))
3990 {
5af5757b 3991 f->left_pos = 0;
972f4259
KS
3992 window_prompting |= XNegative;
3993 }
3994 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3995 && CONSP (XCDR (tem1))
b8898fda 3996 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem1)), INT_MAX))
972f4259 3997 {
5af5757b 3998 f->left_pos = - XINT (XCAR (XCDR (tem1)));
972f4259
KS
3999 window_prompting |= XNegative;
4000 }
4001 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
4002 && CONSP (XCDR (tem1))
b8898fda 4003 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem1))))
972f4259 4004 {
5af5757b 4005 f->left_pos = XINT (XCAR (XCDR (tem1)));
972f4259
KS
4006 }
4007 else if (EQ (tem1, Qunbound))
5af5757b 4008 f->left_pos = 0;
972f4259
KS
4009 else
4010 {
d311d28c 4011 CHECK_TYPE_RANGED_INTEGER (int, tem1);
5af5757b
KS
4012 f->left_pos = XINT (tem1);
4013 if (f->left_pos < 0)
972f4259
KS
4014 window_prompting |= XNegative;
4015 }
4016
4017 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
4018 window_prompting |= USPosition;
4019 else
4020 window_prompting |= PPosition;
4021 }
4022
972f4259
KS
4023 if (window_prompting & XNegative)
4024 {
4025 if (window_prompting & YNegative)
5af5757b 4026 f->win_gravity = SouthEastGravity;
972f4259 4027 else
5af5757b 4028 f->win_gravity = NorthEastGravity;
972f4259
KS
4029 }
4030 else
4031 {
4032 if (window_prompting & YNegative)
5af5757b 4033 f->win_gravity = SouthWestGravity;
972f4259 4034 else
5af5757b 4035 f->win_gravity = NorthWestGravity;
972f4259
KS
4036 }
4037
5af5757b 4038 f->size_hint_flags = window_prompting;
972f4259
KS
4039
4040 return window_prompting;
4041}
4042
4043
4044
4045#endif /* HAVE_WINDOW_SYSTEM */
4046
e044e4fc 4047void
971de7fb 4048frame_make_pointer_invisible (void)
e044e4fc
JD
4049{
4050 if (! NILP (Vmake_pointer_invisible))
4051 {
abeafb2a 4052 struct frame *f;
ece2d4ed
JD
4053 if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
4054 return;
4055
abeafb2a 4056 f = SELECTED_FRAME ();
e044e4fc
JD
4057 if (f && !f->pointer_invisible
4058 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4059 {
4060 f->mouse_moved = 0;
4061 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
4062 f->pointer_invisible = 1;
4063 }
4064 }
4065}
4066
4067void
971de7fb 4068frame_make_pointer_visible (void)
e044e4fc
JD
4069{
4070 /* We don't check Vmake_pointer_invisible here in case the
4071 pointer was invisible when Vmake_pointer_invisible was set to nil. */
abeafb2a 4072 struct frame *f;
e044e4fc 4073
ece2d4ed
JD
4074 if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
4075 return;
4076
abeafb2a 4077 f = SELECTED_FRAME ();
e044e4fc
JD
4078 if (f && f->pointer_invisible && f->mouse_moved
4079 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4080 {
4081 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
4082 f->pointer_invisible = 0;
4083 }
4084}
4085
c978536f
JD
4086DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
4087 Sframe_pointer_visible_p, 0, 1, 0,
4088 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
4089Otherwise it returns nil. FRAME omitted or nil means the
4090selected frame. This is useful when `make-pointer-invisible' is set. */)
4091 (Lisp_Object frame)
4092{
d9f07150 4093 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
c978536f 4094}
972f4259
KS
4095
4096\f
4097/***********************************************************************
4098 Initialization
4099 ***********************************************************************/
4100
4101void
971de7fb 4102syms_of_frame (void)
972f4259 4103{
cd3520a4
JB
4104 DEFSYM (Qframep, "framep");
4105 DEFSYM (Qframe_live_p, "frame-live-p");
4106 DEFSYM (Qexplicit_name, "explicit-name");
4107 DEFSYM (Qheight, "height");
4108 DEFSYM (Qicon, "icon");
4109 DEFSYM (Qminibuffer, "minibuffer");
4110 DEFSYM (Qmodeline, "modeline");
4111 DEFSYM (Qonly, "only");
9fb0c957 4112 DEFSYM (Qnone, "none");
cd3520a4
JB
4113 DEFSYM (Qwidth, "width");
4114 DEFSYM (Qgeometry, "geometry");
4115 DEFSYM (Qicon_left, "icon-left");
4116 DEFSYM (Qicon_top, "icon-top");
4117 DEFSYM (Qtooltip, "tooltip");
4118 DEFSYM (Qleft, "left");
4119 DEFSYM (Qright, "right");
4120 DEFSYM (Quser_position, "user-position");
4121 DEFSYM (Quser_size, "user-size");
4122 DEFSYM (Qwindow_id, "window-id");
972f4259 4123#ifdef HAVE_X_WINDOWS
cd3520a4 4124 DEFSYM (Qouter_window_id, "outer-window-id");
972f4259 4125#endif
cd3520a4
JB
4126 DEFSYM (Qparent_id, "parent-id");
4127 DEFSYM (Qx, "x");
4128 DEFSYM (Qw32, "w32");
4129 DEFSYM (Qpc, "pc");
cd3520a4
JB
4130 DEFSYM (Qns, "ns");
4131 DEFSYM (Qvisible, "visible");
4132 DEFSYM (Qbuffer_predicate, "buffer-predicate");
4133 DEFSYM (Qbuffer_list, "buffer-list");
4134 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
4135 DEFSYM (Qdisplay_type, "display-type");
4136 DEFSYM (Qbackground_mode, "background-mode");
4137 DEFSYM (Qnoelisp, "noelisp");
4138 DEFSYM (Qtty_color_mode, "tty-color-mode");
4139 DEFSYM (Qtty, "tty");
4140 DEFSYM (Qtty_type, "tty-type");
4141
4142 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
4143
4144 DEFSYM (Qfullwidth, "fullwidth");
4145 DEFSYM (Qfullheight, "fullheight");
4146 DEFSYM (Qfullboth, "fullboth");
4147 DEFSYM (Qmaximized, "maximized");
4148 DEFSYM (Qx_resource_name, "x-resource-name");
4149 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
4150
4151 DEFSYM (Qterminal, "terminal");
4152 DEFSYM (Qterminal_live_p, "terminal-live-p");
a3547743 4153
dc4db71c 4154#ifdef HAVE_NS
cd3520a4 4155 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
dc4db71c
CY
4156#endif
4157
972f4259
KS
4158 {
4159 int i;
4160
4161 for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++)
4162 {
d67b4f80 4163 Lisp_Object v = intern_c_string (frame_parms[i].name);
972f4259
KS
4164 if (frame_parms[i].variable)
4165 {
4166 *frame_parms[i].variable = v;
4167 staticpro (frame_parms[i].variable);
4168 }
4169 Fput (v, Qx_frame_parameter, make_number (i));
4170 }
4171 }
4172
2731a0ad 4173#ifdef HAVE_WINDOW_SYSTEM
29208e82 4174 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
972f4259
KS
4175 doc: /* The name Emacs uses to look up X resources.
4176`x-get-resource' uses this as the first component of the instance name
4177when requesting resource values.
4178Emacs initially sets `x-resource-name' to the name under which Emacs
4179was invoked, or to the value specified with the `-name' or `-rn'
4180switches, if present.
4181
4182It may be useful to bind this variable locally around a call
4183to `x-get-resource'. See also the variable `x-resource-class'. */);
4184 Vx_resource_name = Qnil;
4185
29208e82 4186 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
972f4259
KS
4187 doc: /* The class Emacs uses to look up X resources.
4188`x-get-resource' uses this as the first component of the instance class
4189when requesting resource values.
4190
4191Emacs initially sets `x-resource-class' to "Emacs".
4192
4193Setting this variable permanently is not a reasonable thing to do,
4194but binding this variable locally around a call to `x-get-resource'
4195is a reasonable practice. See also the variable `x-resource-name'. */);
4196 Vx_resource_class = build_string (EMACS_CLASS);
0a708637 4197
29208e82 4198 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
0a708637
GM
4199 doc: /* The lower limit of the frame opacity (alpha transparency).
4200The value should range from 0 (invisible) to 100 (completely opaque).
4201You can also use a floating number between 0.0 and 1.0.
4202The default is 20. */);
4203 Vframe_alpha_lower_limit = make_number (20);
2731a0ad 4204#endif
972f4259 4205
29208e82 4206 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
972f4259
KS
4207 doc: /* Alist of default values for frame creation.
4208These may be set in your init file, like this:
5ff00c42 4209 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
972f4259
KS
4210These override values given in window system configuration data,
4211 including X Windows' defaults database.
4212For values specific to the first Emacs frame, see `initial-frame-alist'.
095fe281 4213For window-system specific values, see `window-system-default-frame-alist'.
972f4259
KS
4214For values specific to the separate minibuffer frame, see
4215 `minibuffer-frame-alist'.
4216The `menu-bar-lines' element of the list controls whether new frames
4217 have menu bars; `menu-bar-mode' works by altering this element.
4218Setting this variable does not affect existing frames, only new ones. */);
fac580eb 4219 Vdefault_frame_alist = Qnil;
972f4259 4220
29208e82 4221 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
6b61353c
KH
4222 doc: /* Default position of scroll bars on this window-system. */);
4223#ifdef HAVE_WINDOW_SYSTEM
5e617bc2 4224#if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
303500aa
CY
4225 /* MS-Windows, Mac OS X, and GTK have scroll bars on the right by
4226 default. */
6b61353c 4227 Vdefault_frame_scroll_bars = Qright;
303500aa
CY
4228#else
4229 Vdefault_frame_scroll_bars = Qleft;
4230#endif
6b61353c
KH
4231#else
4232 Vdefault_frame_scroll_bars = Qnil;
4233#endif
4234
fd9547e8
JD
4235 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
4236 scroll_bar_adjust_thumb_portion_p,
4237 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
4238Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
4239even if the end of the buffer is shown (i.e. overscrolling).
4240Set to nil if you want the thumb to be at the bottom when the end of the buffer
4241is shown. Also, the thumb fills the whole scroll bar when the entire buffer
4242is visible. In this case you can not overscroll. */);
4243 scroll_bar_adjust_thumb_portion_p = 1;
4244
29208e82 4245 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
daf01701 4246 doc: /* The initial frame-object, which represents Emacs's stdout. */);
972f4259 4247
29208e82 4248 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
972f4259
KS
4249 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4250`mouse-position' calls this function, passing its usual return value as
4251argument, and returns whatever this function returns.
4252This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4253which need to do mouse handling at the Lisp level. */);
4254 Vmouse_position_function = Qnil;
4255
29208e82 4256 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
972f4259
KS
4257 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4258If the value is an integer, highlighting is only shown after moving the
4259mouse, while keyboard input turns off the highlight even when the mouse
4260is over the clickable text. However, the mouse shape still indicates
4261when the mouse is over clickable text. */);
4262 Vmouse_highlight = Qt;
4263
29208e82 4264 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
e044e4fc
JD
4265 doc: /* If non-nil, make pointer invisible while typing.
4266The pointer becomes visible again when the mouse is moved. */);
4267 Vmake_pointer_invisible = Qt;
4268
29208e82 4269 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
e5d9c0d1 4270 doc: /* Functions run before deleting a frame.
972f4259 4271The functions are run with one arg, the frame to be deleted.
e519a50b
KL
4272See `delete-frame'.
4273
58555d81
SM
4274Note that functions in this list may be called just before the frame is
4275actually deleted, or some time later (or even both when an earlier function
4276in `delete-frame-functions' (indirectly) calls `delete-frame'
4277recursively). */);
972f4259 4278 Vdelete_frame_functions = Qnil;
cd3520a4 4279 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
972f4259 4280
29208e82 4281 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
e1fd756b
GM
4282 doc: /* Non-nil if Menu-Bar mode is enabled.
4283See the command `menu-bar-mode' for a description of this minor mode.
4284Setting this variable directly does not take effect;
4285either customize it (see the info node `Easy Customization')
4286or call the function `menu-bar-mode'. */);
6431f2e6
CY
4287 Vmenu_bar_mode = Qt;
4288
29208e82 4289 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
9d794026
GM
4290 doc: /* Non-nil if Tool-Bar mode is enabled.
4291See the command `tool-bar-mode' for a description of this minor mode.
4292Setting this variable directly does not take effect;
4293either customize it (see the info node `Easy Customization')
4294or call the function `tool-bar-mode'. */);
c8c59954 4295#ifdef HAVE_WINDOW_SYSTEM
6431f2e6 4296 Vtool_bar_mode = Qt;
c8c59954
GM
4297#else
4298 Vtool_bar_mode = Qnil;
4299#endif
6431f2e6 4300
972f4259
KS
4301 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
4302 doc: /* Minibufferless frames use this frame's minibuffer.
4303
4304Emacs cannot create minibufferless frames unless this is set to an
4305appropriate surrogate.
4306
4307Emacs consults this variable only when creating minibufferless
4308frames; once the frame is created, it sticks with its assigned
4309minibuffer, no matter what this variable is set to. This means that
4310this variable doesn't necessarily say anything meaningful about the
4311current set of frames, or where the minibuffer is currently being
4312displayed.
4313
4314This variable is local to the current terminal and cannot be buffer-local. */);
4315
29208e82 4316 DEFVAR_BOOL ("focus-follows-mouse", focus_follows_mouse,
da1da002
MR
4317 doc: /* Non-nil if window system changes focus when you move the mouse.
4318You should set this variable to tell Emacs how your window manager
4319handles focus, since there is no way in general for Emacs to find out
86677b58 4320automatically. See also `mouse-autoselect-window'. */);
da1da002 4321 focus_follows_mouse = 0;
a3547743 4322
972f4259
KS
4323 staticpro (&Vframe_list);
4324
972f4259
KS
4325 defsubr (&Sframep);
4326 defsubr (&Sframe_live_p);
428a555e 4327 defsubr (&Swindow_system);
972f4259
KS
4328 defsubr (&Smake_terminal_frame);
4329 defsubr (&Shandle_switch_frame);
972f4259
KS
4330 defsubr (&Sselect_frame);
4331 defsubr (&Sselected_frame);
972f4259
KS
4332 defsubr (&Sframe_list);
4333 defsubr (&Snext_frame);
4334 defsubr (&Sprevious_frame);
4335 defsubr (&Sdelete_frame);
4336 defsubr (&Smouse_position);
4337 defsubr (&Smouse_pixel_position);
4338 defsubr (&Sset_mouse_position);
4339 defsubr (&Sset_mouse_pixel_position);
4340#if 0
4341 defsubr (&Sframe_configuration);
4342 defsubr (&Srestore_frame_configuration);
4343#endif
4344 defsubr (&Smake_frame_visible);
4345 defsubr (&Smake_frame_invisible);
4346 defsubr (&Siconify_frame);
4347 defsubr (&Sframe_visible_p);
4348 defsubr (&Svisible_frame_list);
4349 defsubr (&Sraise_frame);
4350 defsubr (&Slower_frame);
4351 defsubr (&Sredirect_frame_focus);
4352 defsubr (&Sframe_focus);
4353 defsubr (&Sframe_parameters);
4354 defsubr (&Sframe_parameter);
4355 defsubr (&Smodify_frame_parameters);
4356 defsubr (&Sframe_char_height);
4357 defsubr (&Sframe_char_width);
4358 defsubr (&Sframe_pixel_height);
4359 defsubr (&Sframe_pixel_width);
fb0cf781 4360 defsubr (&Stool_bar_pixel_width);
972f4259
KS
4361 defsubr (&Sset_frame_height);
4362 defsubr (&Sset_frame_width);
4363 defsubr (&Sset_frame_size);
4364 defsubr (&Sset_frame_position);
c978536f 4365 defsubr (&Sframe_pointer_visible_p);
972f4259
KS
4366
4367#ifdef HAVE_WINDOW_SYSTEM
4368 defsubr (&Sx_get_resource);
4369 defsubr (&Sx_parse_geometry);
4370#endif
4371
dc6f92b8 4372}