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