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