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