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