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