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