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