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