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