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