* buffer.h (BSET): Remove.
[bpt/emacs.git] / src / frame.c
CommitLineData
ff11dfa1 1/* Generic frame functions.
e9bffc61 2
acaf905b 3Copyright (C) 1993-1995, 1997, 1999-2012 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>
d7306fe6 27#include <setjmp.h>
620f13b0
PE
28
29#include <c-ctype.h>
30
cc38027b 31#include "lisp.h"
83be827a 32#include "character.h"
6d55d620 33#ifdef HAVE_X_WINDOWS
dfcf069d 34#include "xterm.h"
71025e5e 35#endif
8f23f280
AI
36#ifdef WINDOWSNT
37#include "w32term.h"
38#endif
edfda783
AR
39#ifdef HAVE_NS
40#include "nsterm.h"
41#endif
2538fae4
AI
42#include "buffer.h"
43/* These help us bind and responding to switch-frame events. */
44#include "commands.h"
45#include "keyboard.h"
cc38027b 46#include "frame.h"
972f4259 47#include "blockinput.h"
28d440ab 48#include "termchar.h"
bc1ed486 49#include "termhooks.h"
dfcf069d 50#include "dispextern.h"
f769f1b2 51#include "window.h"
e0c8ad78 52#include "font.h"
2cc7b62f 53#ifdef HAVE_WINDOW_SYSTEM
e0c8ad78
KH
54#include "fontset.h"
55#endif
87485d6f
MW
56#ifdef MSDOS
57#include "msdos.h"
4aec4b29 58#include "dosfns.h"
87485d6f 59#endif
e5d77022 60
972f4259 61
2731a0ad
KS
62#ifdef HAVE_WINDOW_SYSTEM
63
2731a0ad 64#endif
972f4259 65
dc4db71c
CY
66#ifdef HAVE_NS
67Lisp_Object Qns_parse_geometry;
68#endif
69
972f4259
KS
70Lisp_Object Qframep, Qframe_live_p;
71Lisp_Object Qicon, Qmodeline;
9fb0c957 72Lisp_Object Qonly, Qnone;
edfda783 73Lisp_Object Qx, Qw32, Qmac, Qpc, Qns;
f7af3f7b 74Lisp_Object Qvisible;
8b60f7bc 75Lisp_Object Qdisplay_type;
955cbe7b 76static Lisp_Object Qbackground_mode;
c53956fe 77Lisp_Object Qnoelisp;
972f4259 78
955cbe7b 79static Lisp_Object Qx_frame_parameter;
972f4259 80Lisp_Object Qx_resource_name;
6ed8eeff
KL
81Lisp_Object Qterminal;
82Lisp_Object Qterminal_live_p;
972f4259
KS
83
84/* Frame parameters (set or reported). */
85
86Lisp_Object Qauto_raise, Qauto_lower;
87Lisp_Object Qborder_color, Qborder_width;
88Lisp_Object Qcursor_color, Qcursor_type;
955cbe7b 89static Lisp_Object Qgeometry; /* Not used */
972f4259
KS
90Lisp_Object Qheight, Qwidth;
91Lisp_Object Qleft, Qright;
92Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
54ee7410 93Lisp_Object Qtooltip;
972f4259
KS
94Lisp_Object Qinternal_border_width;
95Lisp_Object Qmouse_color;
96Lisp_Object Qminibuffer;
97Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
98Lisp_Object Qvisibility;
99Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
100Lisp_Object Qscreen_gamma;
101Lisp_Object Qline_spacing;
955cbe7b 102static Lisp_Object Quser_position, Quser_size;
972f4259 103Lisp_Object Qwait_for_wm;
955cbe7b 104static Lisp_Object Qwindow_id;
972f4259 105#ifdef HAVE_X_WINDOWS
955cbe7b 106static Lisp_Object Qouter_window_id;
972f4259
KS
107#endif
108Lisp_Object Qparent_id;
109Lisp_Object Qtitle, Qname;
955cbe7b 110static Lisp_Object Qexplicit_name;
972f4259 111Lisp_Object Qunsplittable;
bfeabdc3 112Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position;
972f4259 113Lisp_Object Qleft_fringe, Qright_fringe;
955cbe7b
PE
114Lisp_Object Qbuffer_predicate;
115static Lisp_Object Qbuffer_list, Qburied_buffer_list;
94674d18 116Lisp_Object Qtty_color_mode;
28d440ab 117Lisp_Object Qtty, Qtty_type;
dc6f92b8 118
3f1c6666 119Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth, Qmaximized;
cad9ef74 120Lisp_Object Qsticky;
1a356571 121Lisp_Object Qfont_backend;
0a708637 122Lisp_Object Qalpha;
972f4259
KS
123
124Lisp_Object Qface_set_after_frame_default;
125
29208e82 126static Lisp_Object Qdelete_frame_functions;
da1da002 127
81626931
PE
128#ifdef HAVE_WINDOW_SYSTEM
129static void x_report_frame_params (struct frame *, Lisp_Object *);
130#endif
131
f00af5b1
PE
132/* These setters are used only in this file, so they can be private. */
133static inline void
134fset_buffer_predicate (struct frame *f, Lisp_Object val)
135{
136 f->buffer_predicate = val;
137}
138static inline void
139fset_minibuffer_window (struct frame *f, Lisp_Object val)
140{
141 f->minibuffer_window = val;
142}
143
a249de79
RS
144\f
145static void
971de7fb 146set_menu_bar_lines_1 (Lisp_Object window, int n)
a249de79
RS
147{
148 struct window *w = XWINDOW (window);
149
80b00b08 150 w->last_modified = 0;
e8c17b81
PE
151 wset_top_line (w, make_number (XFASTINT (w->top_line) + n));
152 wset_total_lines (w, make_number (XFASTINT (w->total_lines) - n));
177c0ea7 153
a249de79 154 /* Handle just the top child in a vertical split. */
d3d50620
DA
155 if (!NILP (w->vchild))
156 set_menu_bar_lines_1 (w->vchild, n);
a249de79
RS
157
158 /* Adjust all children in a horizontal split. */
d3d50620 159 for (window = w->hchild; !NILP (window); window = w->next)
a249de79
RS
160 {
161 w = XWINDOW (window);
162 set_menu_bar_lines_1 (window, n);
163 }
164}
165
e48f782c 166void
971de7fb 167set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
a249de79
RS
168{
169 int nlines;
170 int olines = FRAME_MENU_BAR_LINES (f);
171
172 /* Right now, menu bars don't work properly in minibuf-only frames;
173 most of the commands try to apply themselves to the minibuffer
e3678b64 174 frame itself, and get an error because you can't switch buffers
a249de79
RS
175 in or split the minibuffer window. */
176 if (FRAME_MINIBUF_ONLY_P (f))
177 return;
178
b8898fda 179 if (TYPE_RANGED_INTEGERP (int, value))
a249de79
RS
180 nlines = XINT (value);
181 else
182 nlines = 0;
183
57aeea1e
RS
184 if (nlines != olines)
185 {
186 windows_or_buffers_changed++;
187 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
188 FRAME_MENU_BAR_LINES (f) = nlines;
e69b0960 189 set_menu_bar_lines_1 (f->root_window, nlines - olines);
18082e2d 190 adjust_glyphs (f);
57aeea1e 191 }
a249de79
RS
192}
193\f
a249de79 194Lisp_Object Vframe_list;
a249de79 195
dc6f92b8 196\f
ff11dfa1 197DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
14ff1ee0 198 doc: /* Return non-nil if OBJECT is a frame.
89baa1df
EZ
199Value is:
200 t for a termcap frame (a character-only terminal),
201 'x' for an Emacs frame that is really an X window,
202 'w32' for an Emacs frame that is a window on MS-Windows display,
203 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
204 'pc' for a direct-write MS-DOS frame.
14ff1ee0 205See also `frame-live-p'. */)
5842a27b 206 (Lisp_Object object)
dc6f92b8 207{
e35d291d 208 if (!FRAMEP (object))
dc6f92b8 209 return Qnil;
ff11dfa1 210 switch (XFRAME (object)->output_method)
dc6f92b8 211 {
3224dac1 212 case output_initial: /* The initial frame is like a termcap frame. */
dc6f92b8
JB
213 case output_termcap:
214 return Qt;
215 case output_x_window:
fd0c2bd1 216 return Qx;
fbd6baed
GV
217 case output_w32:
218 return Qw32;
bb221971
RS
219 case output_msdos_raw:
220 return Qpc;
574a1a90
RS
221 case output_mac:
222 return Qmac;
edfda783
AR
223 case output_ns:
224 return Qns;
dc6f92b8
JB
225 default:
226 abort ();
227 }
228}
229
dbc4e1c1 230DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
14ff1ee0
PJ
231 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
232Value is nil if OBJECT is not a live frame. If object is a live
6ed8eeff 233frame, the return value indicates what sort of terminal device it is
f6fa0866 234displayed on. See the documentation of `framep' for possible
4e10df59 235return values. */)
5842a27b 236 (Lisp_Object object)
f9898cc6 237{
ff11dfa1
JB
238 return ((FRAMEP (object)
239 && FRAME_LIVE_P (XFRAME (object)))
240 ? Fframep (object)
f9898cc6
JB
241 : Qnil);
242}
243
a7ca3326 244DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
428a555e 245 doc: /* The name of the window system that FRAME is displaying through.
89baa1df
EZ
246The value is a symbol:
247 nil for a termcap frame (a character-only terminal),
248 'x' for an Emacs frame that is really an X window,
249 'w32' for an Emacs frame that is a window on MS-Windows display,
250 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
251 'pc' for a direct-write MS-DOS frame.
252
253FRAME defaults to the currently selected frame.
254
255Use of this function as a predicate is deprecated. Instead,
256use `display-graphic-p' or any of the other `display-*-p'
257predicates which report frame's specific UI-related capabilities. */)
5842a27b 258 (Lisp_Object frame)
428a555e
KL
259{
260 Lisp_Object type;
261 if (NILP (frame))
262 frame = selected_frame;
263
264 type = Fframep (frame);
265
266 if (NILP (type))
267 wrong_type_argument (Qframep, frame);
268
269 if (EQ (type, Qt))
270 return Qnil;
271 else
272 return type;
a3547743 273}
428a555e 274
ff11dfa1 275struct frame *
971de7fb 276make_frame (int mini_p)
dc6f92b8 277{
ff11dfa1
JB
278 Lisp_Object frame;
279 register struct frame *f;
dc6f92b8
JB
280 register Lisp_Object root_window;
281 register Lisp_Object mini_window;
e9c96c62
GM
282
283 f = allocate_frame ();
36af7d69 284 XSETFRAME (frame, f);
ff11dfa1 285
62efea5e
DA
286 /* Initialize Lisp data. Note that allocate_frame initializes all
287 Lisp data to nil, so do it only for slots which should not be nil. */
f00af5b1 288 fset_tool_bar_position (f, Qtop);
62efea5e
DA
289
290 /* Initialize non-Lisp data. Note that allocate_frame zeroes out all
291 non-Lisp data, so do it only for slots which should not be zero.
292 To avoid subtle bugs and for the sake of readability, it's better to
293 initialize enum members explicitly even if their values are zero. */
ff11dfa1 294 f->wants_modeline = 1;
10689a01 295 f->garbaged = 1;
ff11dfa1 296 f->has_minibuffer = mini_p;
3a43d2dd 297 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
5af5757b
KS
298 f->column_width = 1; /* !FRAME_WINDOW_P value */
299 f->line_height = 1; /* !FRAME_WINDOW_P value */
93421a1f 300#ifdef HAVE_WINDOW_SYSTEM
5af5757b 301 f->want_fullscreen = FULLSCREEN_NONE;
93421a1f 302#endif
dc6f92b8 303
cc38027b 304 root_window = make_window ();
dc6f92b8
JB
305 if (mini_p)
306 {
cc38027b 307 mini_window = make_window ();
e8c17b81
PE
308 wset_next (XWINDOW (root_window), mini_window);
309 wset_prev (XWINDOW (mini_window), root_window);
c98ff5dd 310 XWINDOW (mini_window)->mini = 1;
e8c17b81 311 wset_frame (XWINDOW (mini_window), frame);
f00af5b1 312 fset_minibuffer_window (f, mini_window);
dc6f92b8
JB
313 }
314 else
315 {
316 mini_window = Qnil;
e8c17b81 317 wset_next (XWINDOW (root_window), Qnil);
f00af5b1 318 fset_minibuffer_window (f, Qnil);
dc6f92b8
JB
319 }
320
e8c17b81 321 wset_frame (XWINDOW (root_window), frame);
dc6f92b8
JB
322
323 /* 10 is arbitrary,
324 just so that there is "something there."
ff11dfa1 325 Correct size will be set up later with change_frame_size. */
dc6f92b8 326
5af5757b
KS
327 SET_FRAME_COLS (f, 10);
328 FRAME_LINES (f) = 10;
dc6f92b8 329
e8c17b81
PE
330 wset_total_cols (XWINDOW (root_window), make_number (10));
331 wset_total_lines (XWINDOW (root_window), make_number (mini_p ? 9 : 10));
dc6f92b8
JB
332
333 if (mini_p)
334 {
e8c17b81
PE
335 wset_total_cols (XWINDOW (mini_window), make_number (10));
336 wset_top_line (XWINDOW (mini_window), make_number (9));
337 wset_total_lines (XWINDOW (mini_window), make_number (1));
dc6f92b8
JB
338 }
339
ff11dfa1 340 /* Choose a buffer for the frame's root window. */
5bce042c
JB
341 {
342 Lisp_Object buf;
343
e8c17b81 344 wset_buffer (XWINDOW (root_window), Qt);
5bce042c
JB
345 buf = Fcurrent_buffer ();
346 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
347 a space), try to find another one. */
d5db4077 348 if (SREF (Fbuffer_name (buf), 0) == ' ')
e10ac9f1 349 buf = other_buffer_safely (buf);
fa54c6ae 350
18082e2d
GM
351 /* Use set_window_buffer, not Fset_window_buffer, and don't let
352 hooks be run by it. The reason is that the whole frame/window
cd1181db 353 arrangement is not yet fully initialized at this point. Windows
18082e2d
GM
354 don't have the right size, glyph matrices aren't initialized
355 etc. Running Lisp functions at this point surely ends in a
356 SEGV. */
5af5757b 357 set_window_buffer (root_window, buf, 0, 0);
f00af5b1 358 fset_buffer_list (f, Fcons (buf, Qnil));
5bce042c
JB
359 }
360
dc6f92b8
JB
361 if (mini_p)
362 {
e8c17b81 363 wset_buffer (XWINDOW (mini_window), Qt);
18082e2d
GM
364 set_window_buffer (mini_window,
365 (NILP (Vminibuffer_list)
366 ? get_minibuffer (0)
367 : Fcar (Vminibuffer_list)),
5af5757b 368 0, 0);
dc6f92b8
JB
369 }
370
f00af5b1
PE
371 fset_root_window (f, root_window);
372 fset_selected_window (f, root_window);
d5e7c279
JB
373 /* Make sure this window seems more recently used than
374 a newly-created, never-selected window. */
e69b0960 375 XWINDOW (f->selected_window)->use_time = ++window_select_count;
dc6f92b8 376
ff11dfa1 377 return f;
dc6f92b8
JB
378}
379\f
bba88bb1 380#ifdef HAVE_WINDOW_SYSTEM
ff11dfa1 381/* Make a frame using a separate minibuffer window on another frame.
dc6f92b8
JB
382 MINI_WINDOW is the minibuffer window to use. nil means use the
383 default (the global minibuffer). */
384
ff11dfa1 385struct frame *
971de7fb 386make_frame_without_minibuffer (register Lisp_Object mini_window, KBOARD *kb, Lisp_Object display)
dc6f92b8 387{
ff11dfa1 388 register struct frame *f;
363b873b 389 struct gcpro gcpro1;
dc6f92b8 390
b0660239 391 if (!NILP (mini_window))
b7826503 392 CHECK_LIVE_WINDOW (mini_window);
dc6f92b8 393
b0660239 394 if (!NILP (mini_window)
d3d50620 395 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
6ed8eeff 396 error ("Frame and minibuffer must be on the same terminal");
662ac59a 397
ff11dfa1
JB
398 /* Make a frame containing just a root window. */
399 f = make_frame (0);
dc6f92b8 400
b0660239
KH
401 if (NILP (mini_window))
402 {
403 /* Use default-minibuffer-frame if possible. */
1344aad4
TT
404 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
405 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
b0660239 406 {
363b873b
RS
407 Lisp_Object frame_dummy;
408
409 XSETFRAME (frame_dummy, f);
410 GCPRO1 (frame_dummy);
b0660239 411 /* If there's no minibuffer frame to use, create one. */
15dbb4d6
PE
412 kset_default_minibuffer_frame
413 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
363b873b 414 UNGCPRO;
b0660239 415 }
177c0ea7 416
e69b0960
DA
417 mini_window
418 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
b0660239 419 }
a2812a26 420
f00af5b1 421 fset_minibuffer_window (f, mini_window);
a2812a26
RS
422
423 /* Make the chosen minibuffer window display the proper minibuffer,
424 unless it is already showing a minibuffer. */
d3d50620 425 if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
08908aca
MR
426 /* Use set_window_buffer instead of Fset_window_buffer (see
427 discussion of bug#11984, bug#12025, bug#12026). */
428 set_window_buffer (mini_window,
429 (NILP (Vminibuffer_list)
430 ? get_minibuffer (0)
431 : Fcar (Vminibuffer_list)), 0, 0);
ff11dfa1 432 return f;
dc6f92b8
JB
433}
434
ff11dfa1 435/* Make a frame containing only a minibuffer window. */
dc6f92b8 436
ff11dfa1 437struct frame *
971de7fb 438make_minibuffer_frame (void)
dc6f92b8 439{
ff11dfa1 440 /* First make a frame containing just a root window, no minibuffer. */
dc6f92b8 441
ff11dfa1 442 register struct frame *f = make_frame (0);
dc6f92b8 443 register Lisp_Object mini_window;
ff11dfa1 444 register Lisp_Object frame;
dc6f92b8 445
2d80a27a 446 XSETFRAME (frame, f);
dc6f92b8 447
804518aa 448 f->auto_raise = 0;
ff11dfa1
JB
449 f->auto_lower = 0;
450 f->no_split = 1;
451 f->wants_modeline = 0;
452 f->has_minibuffer = 1;
dc6f92b8
JB
453
454 /* Now label the root window as also being the minibuffer.
455 Avoid infinite looping on the window chain by marking next pointer
456 as nil. */
457
f00af5b1
PE
458 mini_window = f->root_window;
459 fset_minibuffer_window (f, mini_window);
c98ff5dd 460 XWINDOW (mini_window)->mini = 1;
e8c17b81
PE
461 wset_next (XWINDOW (mini_window), Qnil);
462 wset_prev (XWINDOW (mini_window), Qnil);
463 wset_frame (XWINDOW (mini_window), frame);
dc6f92b8
JB
464
465 /* Put the proper buffer in that window. */
466
08908aca
MR
467 /* Use set_window_buffer instead of Fset_window_buffer (see
468 discussion of bug#11984, bug#12025, bug#12026). */
469 set_window_buffer (mini_window,
470 (NILP (Vminibuffer_list)
471 ? get_minibuffer (0)
472 : Fcar (Vminibuffer_list)), 0, 0);
ff11dfa1 473 return f;
dc6f92b8 474}
bba88bb1 475#endif /* HAVE_WINDOW_SYSTEM */
dc6f92b8 476\f
28d440ab 477/* Construct a frame that refers to a terminal. */
dc6f92b8 478
8a401434 479static printmax_t tty_frame_count;
bb1513c9 480
ff11dfa1 481struct frame *
3224dac1 482make_initial_frame (void)
dc6f92b8 483{
3224dac1 484 struct frame *f;
6ed8eeff 485 struct terminal *terminal;
d063751a 486 Lisp_Object frame;
bb1513c9 487
1bc973c2 488 eassert (initial_kboard);
b4f0ee5d 489
bb1513c9
RS
490 /* The first call must initialize Vframe_list. */
491 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
492 Vframe_list = Qnil;
ff11dfa1 493
6ed8eeff 494 terminal = init_initial_terminal ();
3224dac1
KL
495
496 f = make_frame (1);
497 XSETFRAME (frame, f);
498
499 Vframe_list = Fcons (frame, Vframe_list);
500
6ed8eeff 501 tty_frame_count = 1;
f00af5b1 502 fset_name (f, build_pure_c_string ("F1"));
3224dac1
KL
503
504 f->visible = 1;
505 f->async_visible = 1;
506
6ed8eeff
KL
507 f->output_method = terminal->type;
508 f->terminal = terminal;
509 f->terminal->reference_count++;
3224dac1 510 f->output_data.nothing = 0;
a3547743 511
3224dac1
KL
512 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
513 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
a3547743 514
3224dac1
KL
515 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
516 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3b8eff32
CY
517
518 /* The default value of menu-bar-mode is t. */
519 set_menu_bar_lines (f, make_number (1), Qnil);
3224dac1 520
edfda783
AR
521 if (!noninteractive)
522 init_frame_faces (f);
edfda783 523
3224dac1
KL
524 return f;
525}
526
527
81626931 528static struct frame *
6ed8eeff 529make_terminal_frame (struct terminal *terminal)
3224dac1
KL
530{
531 register struct frame *f;
3224dac1 532 Lisp_Object frame;
8a401434 533 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
ab797f65 534
4e213843
SM
535 if (!terminal->name)
536 error ("Terminal is not live, can't create new frames on it");
ab797f65 537
ff11dfa1 538 f = make_frame (1);
d063751a 539
2d80a27a 540 XSETFRAME (frame, f);
d063751a
RS
541 Vframe_list = Fcons (frame, Vframe_list);
542
f00af5b1 543 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
bb1513c9 544
bb1513c9
RS
545 f->visible = 1; /* FRAME_SET_VISIBLE wd set frame_garbaged. */
546 f->async_visible = 1; /* Don't let visible be cleared later. */
1266f9ef
EZ
547 f->terminal = terminal;
548 f->terminal->reference_count++;
bb221971 549#ifdef MSDOS
99dda2cd 550 f->output_data.tty->display_info = &the_only_display_info;
2d764c78
EZ
551 if (!inhibit_window_system
552 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
553 || XFRAME (selected_frame)->output_method == output_msdos_raw))
02ab7130 554 f->output_method = output_msdos_raw;
2d764c78
EZ
555 else
556 f->output_method = output_termcap;
5bbdf7aa
DN
557#else /* not MSDOS */
558 f->output_method = output_termcap;
559 create_tty_output (f);
560 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
561 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
562#endif /* not MSDOS */
574a1a90 563
1266f9ef
EZ
564 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
565 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
48104462 566 FRAME_MENU_BAR_LINES(f) = NILP (Vmenu_bar_mode) ? 0 : 1;
1266f9ef
EZ
567
568 /* Set the top frame to the newly created frame. */
569 if (FRAMEP (FRAME_TTY (f)->top_frame)
570 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
571 XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
572
573 FRAME_TTY (f)->top_frame = frame;
574
1a6d3623
EZ
575 if (!noninteractive)
576 init_frame_faces (f);
1a578e9b 577
ff11dfa1 578 return f;
dc6f92b8 579}
bb1513c9 580
ed8dad6b
KL
581/* Get a suitable value for frame parameter PARAMETER for a newly
582 created frame, based on (1) the user-supplied frame parameter
c1ef4455 583 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
ed8dad6b
KL
584
585static Lisp_Object
586get_future_frame_param (Lisp_Object parameter,
587 Lisp_Object supplied_parms,
588 char *current_value)
589{
590 Lisp_Object result;
591
592 result = Fassq (parameter, supplied_parms);
593 if (NILP (result))
e69b0960 594 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
ed8dad6b
KL
595 if (NILP (result) && current_value != NULL)
596 result = build_string (current_value);
ed8dad6b
KL
597 if (!NILP (result) && !STRINGP (result))
598 result = XCDR (result);
599 if (NILP (result) || !STRINGP (result))
600 result = Qnil;
601
602 return result;
603}
604
bb1513c9 605DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
14ff1ee0 606 1, 1, 0,
28d440ab 607 doc: /* Create an additional terminal frame, possibly on another terminal.
14ff1ee0 608This function takes one argument, an alist specifying frame parameters.
28d440ab 609
c6bf3022
CY
610You can create multiple frames on a single text terminal, but only one
611of them (the selected terminal frame) is actually displayed.
28d440ab
KL
612
613In practice, generally you don't need to specify any parameters,
614except when you want to create a new frame on another terminal.
615In that case, the `tty' parameter specifies the device file to open,
616and the `tty-type' parameter specifies the terminal type. Example:
617
618 (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
619
0b0d3e0b
KL
620Note that changing the size of one terminal frame automatically
621affects all frames on the same terminal device. */)
5842a27b 622 (Lisp_Object parms)
bb1513c9
RS
623{
624 struct frame *f;
6ed8eeff 625 struct terminal *t = NULL;
574a1a90 626 Lisp_Object frame, tem;
8d2666fe 627 struct frame *sf = SELECTED_FRAME ();
bb1513c9 628
541580aa 629#ifdef MSDOS
2d764c78
EZ
630 if (sf->output_method != output_msdos_raw
631 && sf->output_method != output_termcap)
bb221971 632 abort ();
574a1a90
RS
633#else /* not MSDOS */
634
99b72cc4 635#ifdef WINDOWSNT /* This should work now! */
8d2666fe 636 if (sf->output_method != output_termcap)
bb1513c9 637 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
bb221971 638#endif
574a1a90 639#endif /* not MSDOS */
a3547743 640
b6660415 641 {
6ed8eeff 642 Lisp_Object terminal;
bb1513c9 643
6ed8eeff
KL
644 terminal = Fassq (Qterminal, parms);
645 if (!NILP (terminal))
28d440ab 646 {
6ed8eeff
KL
647 terminal = XCDR (terminal);
648 t = get_terminal (terminal, 1);
28d440ab 649 }
1266f9ef
EZ
650#ifdef MSDOS
651 if (t && t != the_only_display_info.terminal)
652 /* msdos.c assumes a single tty_display_info object. */
653 error ("Multiple terminals are not supported on this platform");
654 if (!t)
655 t = the_only_display_info.terminal;
656#endif
28d440ab 657 }
a3547743 658
6ed8eeff 659 if (!t)
a3547743 660 {
b6660415 661 char *name = 0, *type = 0;
ed8dad6b 662 Lisp_Object tty, tty_type;
b6660415 663
ed8dad6b
KL
664 tty = get_future_frame_param
665 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
666 ? FRAME_TTY (XFRAME (selected_frame))->name
667 : NULL));
668 if (!NILP (tty))
b6660415 669 {
38182d90 670 name = alloca (SBYTES (tty) + 1);
e99a530f 671 memcpy (name, SSDATA (tty), SBYTES (tty));
b6660415
KL
672 name[SBYTES (tty)] = 0;
673 }
a3547743 674
ed8dad6b
KL
675 tty_type = get_future_frame_param
676 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
677 ? FRAME_TTY (XFRAME (selected_frame))->type
678 : NULL));
679 if (!NILP (tty_type))
b6660415 680 {
38182d90 681 type = alloca (SBYTES (tty_type) + 1);
e99a530f 682 memcpy (type, SSDATA (tty_type), SBYTES (tty_type));
b6660415
KL
683 type[SBYTES (tty_type)] = 0;
684 }
685
6ed8eeff 686 t = init_tty (name, type, 0); /* Errors are not fatal. */
b6660415 687 }
bb1513c9 688
6ed8eeff 689 f = make_terminal_frame (t);
574a1a90 690
9628b887
KL
691 {
692 int width, height;
0b0d3e0b 693 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
9628b887
KL
694 change_frame_size (f, height, width, 0, 0, 0);
695 }
a3547743 696
18082e2d 697 adjust_glyphs (f);
bb1513c9
RS
698 calculate_costs (f);
699 XSETFRAME (frame, f);
700 Fmodify_frame_parameters (frame, parms);
ed8dad6b 701 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtty_type,
6ed8eeff 702 build_string (t->display_info.tty->type)),
ed8dad6b 703 Qnil));
db9d7d9a
KL
704 if (t->display_info.tty->name != NULL)
705 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtty,
706 build_string (t->display_info.tty->name)),
707 Qnil));
708 else
709 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtty, Qnil), Qnil));
a3547743 710
87f1940e
EZ
711 /* Make the frame face alist be frame-specific, so that each
712 frame could change its face definitions independently. */
f00af5b1 713 fset_face_alist (f, Fcopy_alist (sf->face_alist));
87f1940e
EZ
714 /* Simple Fcopy_alist isn't enough, because we need the contents of
715 the vectors which are the CDRs of associations in face_alist to
716 be copied as well. */
e69b0960 717 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
f3fbd155 718 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
bb1513c9
RS
719 return frame;
720}
1e8324d9 721
dc6f92b8 722\f
1e8324d9
GM
723/* Perform the switch to frame FRAME.
724
725 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
726 FRAME1 as frame.
727
728 If TRACK is non-zero and the frame that currently has the focus
729 redirects its focus to the selected frame, redirect that focused
730 frame's focus to FRAME instead.
731
732 FOR_DELETION non-zero means that the selected frame is being
6ed8eeff 733 deleted, which includes the possibility that the frame's terminal
216e6a14
MR
734 is dead.
735
736 The value of NORECORD is passed as argument to Fselect_window. */
1e8324d9 737
61f94483 738Lisp_Object
971de7fb 739do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
dc6f92b8 740{
8d2666fe 741 struct frame *sf = SELECTED_FRAME ();
177c0ea7 742
2f0b07e0
JB
743 /* If FRAME is a switch-frame event, extract the frame we should
744 switch to. */
745 if (CONSP (frame)
7539e11f
KR
746 && EQ (XCAR (frame), Qswitch_frame)
747 && CONSP (XCDR (frame)))
748 frame = XCAR (XCDR (frame));
2f0b07e0 749
09907c3a
KH
750 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
751 a switch-frame event to arrive after a frame is no longer live,
752 especially when deleting the initial frame during startup. */
b7826503 753 CHECK_FRAME (frame);
09907c3a
KH
754 if (! FRAME_LIVE_P (XFRAME (frame)))
755 return Qnil;
dc6f92b8 756
8d2666fe 757 if (sf == XFRAME (frame))
ff11dfa1 758 return frame;
dc6f92b8 759
0aed85f4
KH
760 /* This is too greedy; it causes inappropriate focus redirection
761 that's hard to get rid of. */
762#if 0
a42e9724
JB
763 /* If a frame's focus has been redirected toward the currently
764 selected frame, we should change the redirection to point to the
765 newly selected frame. This means that if the focus is redirected
766 from a minibufferless frame to a surrogate minibuffer frame, we
767 can use `other-window' to switch between all the frames using
768 that minibuffer frame, and the focus redirection will follow us
769 around. */
0aed85f4
KH
770 if (track)
771 {
772 Lisp_Object tail;
a42e9724 773
7539e11f 774 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
0aed85f4
KH
775 {
776 Lisp_Object focus;
a42e9724 777
7539e11f 778 if (!FRAMEP (XCAR (tail)))
0aed85f4 779 abort ();
a42e9724 780
7539e11f 781 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
a42e9724 782
8d2666fe 783 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
7539e11f 784 Fredirect_frame_focus (XCAR (tail), frame);
0aed85f4
KH
785 }
786 }
787#else /* ! 0 */
788 /* Instead, apply it only to the frame we're pointing to. */
032d78fe 789#ifdef HAVE_WINDOW_SYSTEM
1e8324d9 790 if (track && FRAME_WINDOW_P (XFRAME (frame)))
0aed85f4
KH
791 {
792 Lisp_Object focus, xfocus;
793
d7266360 794 xfocus = x_get_focus_frame (XFRAME (frame));
0aed85f4
KH
795 if (FRAMEP (xfocus))
796 {
797 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
8d2666fe 798 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
0aed85f4
KH
799 Fredirect_frame_focus (xfocus, frame);
800 }
801 }
802#endif /* HAVE_X_WINDOWS */
803#endif /* ! 0 */
a42e9724 804
1e8324d9 805 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
550f0e6a
GM
806 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
807
a4e628d4 808 if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame)))
9628b887 809 {
9b2cd403
SM
810 if (FRAMEP (FRAME_TTY (XFRAME (frame))->top_frame))
811 /* Mark previously displayed frame as now obscured. */
812 XFRAME (FRAME_TTY (XFRAME (frame))->top_frame)->async_visible = 2;
9628b887
KL
813 XFRAME (frame)->async_visible = 1;
814 FRAME_TTY (XFRAME (frame))->top_frame = frame;
815 }
816
8d2666fe
GM
817 selected_frame = frame;
818 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
819 last_nonminibuf_frame = XFRAME (selected_frame);
d5e7c279 820
e69b0960 821 Fselect_window (XFRAME (frame)->selected_window, norecord);
dc6f92b8 822
074577b8 823 /* We want to make sure that the next event generates a frame-switch
eb8c3be9 824 event to the appropriate frame. This seems kludgy to me, but
074577b8
JB
825 before you take it out, make sure that evaluating something like
826 (select-window (frame-root-window (new-frame))) doesn't end up
827 with your typing being interpreted in the new frame instead of
828 the one you're actually typing in. */
ef352596 829 internal_last_event_frame = Qnil;
074577b8 830
ff11dfa1 831 return frame;
dc6f92b8
JB
832}
833
a7ca3326 834DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
216e6a14 835 doc: /* Select FRAME.
14ff1ee0 836Subsequent editing commands apply to its selected window.
216e6a14
MR
837Optional argument NORECORD means to neither change the order of
838recently selected windows nor the buffer list.
839
14ff1ee0 840The selection of FRAME lasts until the next time the user does
216e6a14
MR
841something to select a different frame, or until the next time
842this function is called. If you are using a window system, the
843previously selected frame may be restored as the selected frame
057bce6f 844when returning to the command loop, because it still may have
c6bf3022
CY
845the window system's input focus. On a text terminal, the next
846redisplay will display FRAME.
e4ed805e
LT
847
848This function returns FRAME, or nil if FRAME has been deleted. */)
5842a27b 849 (Lisp_Object frame, Lisp_Object norecord)
0aed85f4 850{
216e6a14 851 return do_switch_frame (frame, 1, 0, norecord);
0aed85f4
KH
852}
853
854
20dc6fbb 855DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "e",
14ff1ee0
PJ
856 doc: /* Handle a switch-frame event EVENT.
857Switch-frame events are usually bound to this function.
858A switch-frame event tells Emacs that the window manager has requested
859that the user's events be directed to the frame mentioned in the event.
860This function selects the selected window of the frame of EVENT.
861
862If EVENT is frame object, handle it as if it were a switch-frame event
863to that frame. */)
5842a27b 864 (Lisp_Object event)
0aed85f4 865{
6951cd71 866 /* Preserve prefix arg that the command loop just cleared. */
15dbb4d6 867 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
dee091a3 868 Frun_hooks (1, &Qmouse_leave_buffer_hook);
216e6a14 869 return do_switch_frame (event, 0, 0, Qnil);
0aed85f4
KH
870}
871
a7ca3326 872DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
14ff1ee0 873 doc: /* Return the frame that is now selected. */)
5842a27b 874 (void)
dc6f92b8 875{
8d2666fe 876 return selected_frame;
dc6f92b8 877}
4a7cfafc 878\f
ff11dfa1 879DEFUN ("frame-list", Fframe_list, Sframe_list,
dc6f92b8 880 0, 0, 0,
c15dfb29 881 doc: /* Return a list of all live frames. */)
5842a27b 882 (void)
dc6f92b8 883{
d74c1900
GM
884 Lisp_Object frames;
885 frames = Fcopy_sequence (Vframe_list);
6a65b1b5 886#ifdef HAVE_WINDOW_SYSTEM
d74c1900
GM
887 if (FRAMEP (tip_frame))
888 frames = Fdelq (tip_frame, frames);
6a65b1b5 889#endif
d74c1900 890 return frames;
dc6f92b8
JB
891}
892
ff11dfa1 893/* Return the next frame in the frame list after FRAME.
ff11dfa1 894 If MINIBUF is nil, exclude minibuffer-only frames.
a9986780
RS
895 If MINIBUF is a window, include only its own frame
896 and any frame now using that window as the minibuffer.
f7af3f7b 897 If MINIBUF is `visible', include all visible frames.
a9986780 898 If MINIBUF is 0, include all visible and iconified frames.
f7af3f7b
RS
899 Otherwise, include all frames. */
900
66a9dbbe 901static Lisp_Object
971de7fb 902next_frame (Lisp_Object frame, Lisp_Object minibuf)
dc6f92b8
JB
903{
904 Lisp_Object tail;
905 int passed = 0;
906
ff11dfa1
JB
907 /* There must always be at least one frame in Vframe_list. */
908 if (! CONSP (Vframe_list))
f9898cc6
JB
909 abort ();
910
dbc4e1c1
JB
911 /* If this frame is dead, it won't be in Vframe_list, and we'll loop
912 forever. Forestall that. */
b7826503 913 CHECK_LIVE_FRAME (frame);
dbc4e1c1 914
dc6f92b8 915 while (1)
7539e11f 916 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
dc6f92b8 917 {
ab9f008d 918 Lisp_Object f;
d06a8a56 919
7539e11f 920 f = XCAR (tail);
06537cc8
RS
921
922 if (passed
9628b887
KL
923 && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
924 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
925 || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
926 && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))))
d5e7c279 927 {
d06a8a56
JB
928 /* Decide whether this frame is eligible to be returned. */
929
930 /* If we've looped all the way around without finding any
931 eligible frames, return the original frame. */
932 if (EQ (f, frame))
933 return f;
934
935 /* Let minibuf decide if this frame is acceptable. */
936 if (NILP (minibuf))
937 {
938 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
939 return f;
940 }
f7af3f7b
RS
941 else if (EQ (minibuf, Qvisible))
942 {
943 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
944 if (FRAME_VISIBLE_P (XFRAME (f)))
945 return f;
946 }
3780bc22 947 else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
a9986780
RS
948 {
949 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
950 if (FRAME_VISIBLE_P (XFRAME (f))
951 || FRAME_ICONIFIED_P (XFRAME (f)))
952 return f;
953 }
f7af3f7b 954 else if (WINDOWP (minibuf))
d06a8a56 955 {
a9986780 956 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
551645f8
GM
957 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
958 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
959 FRAME_FOCUS_FRAME (XFRAME (f))))
d06a8a56
JB
960 return f;
961 }
962 else
ff11dfa1 963 return f;
d5e7c279 964 }
dc6f92b8 965
d06a8a56 966 if (EQ (frame, f))
dc6f92b8
JB
967 passed++;
968 }
969}
970
ff11dfa1 971/* Return the previous frame in the frame list before FRAME.
ff11dfa1 972 If MINIBUF is nil, exclude minibuffer-only frames.
a9986780
RS
973 If MINIBUF is a window, include only its own frame
974 and any frame now using that window as the minibuffer.
f7af3f7b 975 If MINIBUF is `visible', include all visible frames.
a9986780 976 If MINIBUF is 0, include all visible and iconified frames.
f7af3f7b
RS
977 Otherwise, include all frames. */
978
66a9dbbe 979static Lisp_Object
971de7fb 980prev_frame (Lisp_Object frame, Lisp_Object minibuf)
dc6f92b8
JB
981{
982 Lisp_Object tail;
983 Lisp_Object prev;
984
ff11dfa1
JB
985 /* There must always be at least one frame in Vframe_list. */
986 if (! CONSP (Vframe_list))
f9898cc6
JB
987 abort ();
988
dc6f92b8 989 prev = Qnil;
7539e11f 990 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
f9898cc6 991 {
ab9f008d 992 Lisp_Object f;
f9898cc6 993
7539e11f 994 f = XCAR (tail);
e35d291d 995 if (!FRAMEP (f))
d06a8a56 996 abort ();
f9898cc6 997
d06a8a56
JB
998 if (EQ (frame, f) && !NILP (prev))
999 return prev;
f9898cc6 1000
9628b887
KL
1001 if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
1002 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
1003 || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
1004 && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))
f7af3f7b 1005 {
06537cc8
RS
1006 /* Decide whether this frame is eligible to be returned,
1007 according to minibuf. */
1008 if (NILP (minibuf))
1009 {
1010 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
1011 prev = f;
1012 }
1013 else if (WINDOWP (minibuf))
1014 {
1015 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
551645f8
GM
1016 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
1017 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1018 FRAME_FOCUS_FRAME (XFRAME (f))))
06537cc8
RS
1019 prev = f;
1020 }
1021 else if (EQ (minibuf, Qvisible))
1022 {
1023 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
1024 if (FRAME_VISIBLE_P (XFRAME (f)))
1025 prev = f;
1026 }
1027 else if (XFASTINT (minibuf) == 0)
1028 {
1029 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
1030 if (FRAME_VISIBLE_P (XFRAME (f))
1031 || FRAME_ICONIFIED_P (XFRAME (f)))
1032 prev = f;
1033 }
1034 else
a9986780
RS
1035 prev = f;
1036 }
f9898cc6 1037 }
d06a8a56
JB
1038
1039 /* We've scanned the entire list. */
1040 if (NILP (prev))
1041 /* We went through the whole frame list without finding a single
1042 acceptable frame. Return the original frame. */
1043 return frame;
1044 else
1045 /* There were no acceptable frames in the list before FRAME; otherwise,
1046 we would have returned directly from the loop. Since PREV is the last
1047 acceptable frame in the list, return it. */
1048 return prev;
dc6f92b8
JB
1049}
1050
ef2c57ac 1051
ff11dfa1 1052DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
14ff1ee0
PJ
1053 doc: /* Return the next frame in the frame list after FRAME.
1054It considers only frames on the same terminal as FRAME.
1055By default, skip minibuffer-only frames.
1056If omitted, FRAME defaults to the selected frame.
1057If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1058If MINIFRAME is a window, include only its own frame
1059and any frame now using that window as the minibuffer.
1060If MINIFRAME is `visible', include all visible frames.
1061If MINIFRAME is 0, include all visible and iconified frames.
1062Otherwise, include all frames. */)
5842a27b 1063 (Lisp_Object frame, Lisp_Object miniframe)
dc6f92b8 1064{
ff11dfa1 1065 if (NILP (frame))
8d2666fe 1066 frame = selected_frame;
177c0ea7 1067
b7826503 1068 CHECK_LIVE_FRAME (frame);
ff11dfa1 1069 return next_frame (frame, miniframe);
dc6f92b8 1070}
dbc4e1c1 1071
ef2c57ac 1072DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
14ff1ee0
PJ
1073 doc: /* Return the previous frame in the frame list before FRAME.
1074It considers only frames on the same terminal as FRAME.
1075By default, skip minibuffer-only frames.
1076If omitted, FRAME defaults to the selected frame.
1077If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1078If MINIFRAME is a window, include only its own frame
1079and any frame now using that window as the minibuffer.
1080If MINIFRAME is `visible', include all visible frames.
1081If MINIFRAME is 0, include all visible and iconified frames.
1082Otherwise, include all frames. */)
5842a27b 1083 (Lisp_Object frame, Lisp_Object miniframe)
ef2c57ac 1084{
ef2c57ac 1085 if (NILP (frame))
8d2666fe 1086 frame = selected_frame;
b7826503 1087 CHECK_LIVE_FRAME (frame);
ef2c57ac
RM
1088 return prev_frame (frame, miniframe);
1089}
dc6f92b8 1090\f
808c0f20
RS
1091/* Return 1 if it is ok to delete frame F;
1092 0 if all frames aside from F are invisible.
1093 (Exception: if F is the terminal frame, and we are using X, return 1.) */
dc6f92b8 1094
4475bec4 1095static int
971de7fb 1096other_visible_frames (FRAME_PTR f)
808c0f20 1097{
1de11f56 1098 Lisp_Object frames;
c08c95c7 1099
1de11f56
CY
1100 for (frames = Vframe_list; CONSP (frames); frames = XCDR (frames))
1101 {
1102 Lisp_Object this = XCAR (frames);
1103 if (f == XFRAME (this))
1104 continue;
c08c95c7 1105
1de11f56
CY
1106 /* Verify that we can still talk to the frame's X window,
1107 and note any recent change in visibility. */
032d78fe 1108#ifdef HAVE_WINDOW_SYSTEM
1de11f56
CY
1109 if (FRAME_WINDOW_P (XFRAME (this)))
1110 {
1111 x_sync (XFRAME (this));
1112 FRAME_SAMPLE_VISIBILITY (XFRAME (this));
1113 }
5e7b7c5b
RS
1114#endif
1115
1de11f56
CY
1116 if (FRAME_VISIBLE_P (XFRAME (this))
1117 || FRAME_ICONIFIED_P (XFRAME (this))
1118 /* Allow deleting the terminal frame when at least one X
1119 frame exists. */
1120 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
1121 return 1;
c08c95c7 1122 }
1de11f56 1123 return 0;
808c0f20
RS
1124}
1125
56f2de10
MR
1126/* Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1127 unconditionally. x_connection_closed and delete_terminal use
1128 this. Any other value of FORCE implements the semantics
1129 described for Fdelete_frame. */
1130Lisp_Object
971de7fb 1131delete_frame (Lisp_Object frame, Lisp_Object force)
808c0f20
RS
1132{
1133 struct frame *f;
8d2666fe 1134 struct frame *sf = SELECTED_FRAME ();
bedb9c0e
KL
1135 struct kboard *kb;
1136
54ee7410 1137 int minibuffer_selected, tooltip_frame;
808c0f20
RS
1138
1139 if (EQ (frame, Qnil))
1140 {
8d2666fe 1141 f = sf;
2d80a27a 1142 XSETFRAME (frame, f);
808c0f20
RS
1143 }
1144 else
1145 {
b7826503 1146 CHECK_FRAME (frame);
808c0f20
RS
1147 f = XFRAME (frame);
1148 }
1149
1150 if (! FRAME_LIVE_P (f))
1151 return Qnil;
1152
e39a993c 1153 if (NILP (force) && !other_visible_frames (f))
808c0f20 1154 error ("Attempt to delete the sole visible or iconified frame");
d5e7c279 1155
56f2de10 1156 /* x_connection_closed must have set FORCE to `noelisp' in order
00c5fd51 1157 to delete the last frame, if it is gone. */
56f2de10 1158 if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp))
e9687ee8
RS
1159 error ("Attempt to delete the only frame");
1160
ff11dfa1
JB
1161 /* Does this frame have a minibuffer, and is it the surrogate
1162 minibuffer for any other frame? */
fd0c2bd1 1163 if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
dc6f92b8 1164 {
ff11dfa1 1165 Lisp_Object frames;
1113d9db 1166
ff11dfa1
JB
1167 for (frames = Vframe_list;
1168 CONSP (frames);
7539e11f 1169 frames = XCDR (frames))
1113d9db 1170 {
7a8cc307 1171 Lisp_Object this;
7539e11f 1172 this = XCAR (frames);
1113d9db 1173
ff11dfa1
JB
1174 if (! EQ (this, frame)
1175 && EQ (frame,
7a8cc307
RS
1176 WINDOW_FRAME (XWINDOW
1177 (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
a31787b1 1178 {
56f2de10
MR
1179 /* If we MUST delete this frame, delete the other first.
1180 But do this only if FORCE equals `noelisp'. */
1181 if (EQ (force, Qnoelisp))
1182 delete_frame (this, Qnoelisp);
a31787b1
RS
1183 else
1184 error ("Attempt to delete a surrogate minibuffer frame");
1185 }
1113d9db 1186 }
dc6f92b8
JB
1187 }
1188
54ee7410
CY
1189 tooltip_frame = !NILP (Fframe_parameter (frame, intern ("tooltip")));
1190
56f2de10
MR
1191 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1192 frame is a tooltip. FORCE is set to `noelisp' when handling
1193 a disconnect from the terminal, so we don't dare call Lisp
1194 code. */
54ee7410 1195 if (NILP (Vrun_hooks) || tooltip_frame)
58555d81 1196 ;
54ee7410 1197 else if (EQ (force, Qnoelisp))
58555d81
SM
1198 pending_funcalls
1199 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1200 pending_funcalls);
1201 else
1dd3c2d9
CY
1202 {
1203#ifdef HAVE_X_WINDOWS
58179cce 1204 /* Also, save clipboard to the clipboard manager. */
1dd3c2d9
CY
1205 x_clipboard_manager_save_frame (frame);
1206#endif
1207
1208 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1209 }
0e662342 1210
b6660415
KL
1211 /* The hook may sometimes (indirectly) cause the frame to be deleted. */
1212 if (! FRAME_LIVE_P (f))
1213 return Qnil;
1214
a31787b1
RS
1215 /* At this point, we are committed to deleting the frame.
1216 There is no more chance for errors to prevent it. */
1217
99b92e64
RS
1218 minibuffer_selected = EQ (minibuf_window, selected_window);
1219
ff11dfa1 1220 /* Don't let the frame remain selected. */
8d2666fe 1221 if (f == sf)
06537cc8
RS
1222 {
1223 Lisp_Object tail, frame1;
1224
1225 /* Look for another visible frame on the same terminal. */
1226 frame1 = next_frame (frame, Qvisible);
1227
1228 /* If there is none, find *some* other frame. */
1229 if (NILP (frame1) || EQ (frame1, frame))
1230 {
1231 FOR_EACH_FRAME (tail, frame1)
1232 {
fca177d4 1233 if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
c6bf3022
CY
1234 {
1235 /* Do not change a text terminal's top-frame. */
1236 struct frame *f1 = XFRAME (frame1);
1237 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1238 {
1239 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1240 if (!EQ (top_frame, frame))
1241 frame1 = top_frame;
1242 }
1243 break;
1244 }
06537cc8
RS
1245 }
1246 }
ac71ced7
SM
1247#ifdef NS_IMPL_COCOA
1248 else
1249 /* Under NS, there is no system mechanism for choosing a new
1250 window to get focus -- it is left to application code.
1251 So the portion of THIS application interfacing with NS
1252 needs to know about it. We call Fraise_frame, but the
1253 purpose is really to transfer focus. */
1254 Fraise_frame (frame1);
1255#endif
06537cc8 1256
216e6a14 1257 do_switch_frame (frame1, 0, 1, Qnil);
79a65b7f 1258 sf = SELECTED_FRAME ();
06537cc8 1259 }
dc6f92b8 1260
ff11dfa1 1261 /* Don't allow minibuf_window to remain on a deleted frame. */
e69b0960 1262 if (EQ (f->minibuffer_window, minibuf_window))
dc6f92b8 1263 {
08908aca
MR
1264 /* Use set_window_buffer instead of Fset_window_buffer (see
1265 discussion of bug#11984, bug#12025, bug#12026). */
1266 set_window_buffer (sf->minibuffer_window,
1267 XWINDOW (minibuf_window)->buffer, 0, 0);
e69b0960 1268 minibuf_window = sf->minibuffer_window;
99b92e64
RS
1269
1270 /* If the dying minibuffer window was selected,
1271 select the new one. */
1272 if (minibuffer_selected)
f1321dc3 1273 Fselect_window (minibuf_window, Qnil);
dc6f92b8
JB
1274 }
1275
130adcb7 1276 /* Don't let echo_area_window to remain on a deleted frame. */
e69b0960
DA
1277 if (EQ (f->minibuffer_window, echo_area_window))
1278 echo_area_window = sf->minibuffer_window;
130adcb7 1279
bb2a0a65
RS
1280 /* Clear any X selections for this frame. */
1281#ifdef HAVE_X_WINDOWS
1282 if (FRAME_X_P (f))
1283 x_clear_frame_selections (f);
1284#endif
1285
177c0ea7
JB
1286 /* Free glyphs.
1287 This function must be called before the window tree of the
18082e2d
GM
1288 frame is deleted because windows contain dynamically allocated
1289 memory. */
1290 free_glyphs (f);
1291
1ccdfd33 1292#ifdef HAVE_WINDOW_SYSTEM
50e3873c
KH
1293 /* Give chance to each font driver to free a frame specific data. */
1294 font_update_drivers (f, Qnil);
1ccdfd33 1295#endif
50e3873c 1296
4a88b3b0
JB
1297 /* Mark all the windows that used to be on FRAME as deleted, and then
1298 remove the reference to them. */
e69b0960 1299 delete_all_child_windows (f->root_window);
f00af5b1 1300 fset_root_window (f, Qnil);
4a88b3b0 1301
ff11dfa1 1302 Vframe_list = Fdelq (frame, Vframe_list);
a42e9724 1303 FRAME_SET_VISIBLE (f, 0);
dc6f92b8 1304
a90af46f
CY
1305 /* Allow the vector of menu bar contents to be freed in the next
1306 garbage collection. The frame object itself may not be garbage
1307 collected until much later, because recent_keys and other data
1308 structures can still refer to it. */
f00af5b1 1309 fset_menu_bar_vector (f, Qnil);
acc49a52 1310
ebbbc028 1311 free_font_driver_list (f);
70fdbb46
JM
1312 xfree (f->namebuf);
1313 xfree (f->decode_mode_spec_buffer);
1314 xfree (FRAME_INSERT_COST (f));
1315 xfree (FRAME_DELETEN_COST (f));
1316 xfree (FRAME_INSERTN_COST (f));
1317 xfree (FRAME_DELETE_COST (f));
1318 xfree (FRAME_MESSAGE_BUF (f));
d2bee99e 1319
8678b9cc 1320 /* Since some events are handled at the interrupt level, we may get
6ed8eeff 1321 an event for f at any time; if we zero out the frame's terminal
8678b9cc 1322 now, then we may trip up the event-handling code. Instead, we'll
6ed8eeff
KL
1323 promise that the terminal of the frame must be valid until we
1324 have called the window-system-dependent frame destruction
1325 routine. */
dbc4e1c1 1326
6ed8eeff
KL
1327 if (FRAME_TERMINAL (f)->delete_frame_hook)
1328 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
d5e7c279 1329
428a555e 1330 {
6ed8eeff 1331 struct terminal *terminal = FRAME_TERMINAL (f);
a3547743 1332 f->output_data.nothing = 0;
6ed8eeff 1333 f->terminal = 0; /* Now the frame is dead. */
428a555e 1334
6ed8eeff 1335 /* If needed, delete the terminal that this frame was on.
bedb9c0e 1336 (This must be done after the frame is killed.) */
6ed8eeff 1337 terminal->reference_count--;
a2addb04
TH
1338#ifdef USE_GTK
1339 /* FIXME: Deleting the terminal crashes emacs because of a GTK
1340 bug.
1341 http://lists.gnu.org/archive/html/emacs-devel/2011-10/msg00363.html */
1342 if (terminal->reference_count == 0 && terminal->type == output_x_window)
1343 terminal->reference_count = 1;
1344#endif /* USE_GTK */
6ed8eeff 1345 if (terminal->reference_count == 0)
bedb9c0e 1346 {
174105f7
SM
1347 Lisp_Object tmp;
1348 XSETTERMINAL (tmp, terminal);
1349
bedb9c0e 1350 kb = NULL;
174105f7 1351 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
bedb9c0e
KL
1352 }
1353 else
6ed8eeff 1354 kb = terminal->kboard;
428a555e 1355 }
8678b9cc 1356
ff11dfa1 1357 /* If we've deleted the last_nonminibuf_frame, then try to find
d5e7c279 1358 another one. */
ff11dfa1 1359 if (f == last_nonminibuf_frame)
d5e7c279 1360 {
ff11dfa1 1361 Lisp_Object frames;
1113d9db 1362
ff11dfa1 1363 last_nonminibuf_frame = 0;
d5e7c279 1364
ff11dfa1
JB
1365 for (frames = Vframe_list;
1366 CONSP (frames);
7539e11f 1367 frames = XCDR (frames))
d5e7c279 1368 {
7539e11f 1369 f = XFRAME (XCAR (frames));
ff11dfa1 1370 if (!FRAME_MINIBUF_ONLY_P (f))
d5e7c279 1371 {
ff11dfa1 1372 last_nonminibuf_frame = f;
d5e7c279
JB
1373 break;
1374 }
1375 }
1376 }
dc6f92b8 1377
8ceb7434
RS
1378 /* If there's no other frame on the same kboard, get out of
1379 single-kboard state if we're in it for this kboard. */
bedb9c0e
KL
1380 if (kb != NULL)
1381 {
1382 Lisp_Object frames;
1383 /* Some frame we found on the same kboard, or nil if there are none. */
1384 Lisp_Object frame_on_same_kboard;
8ceb7434 1385
bedb9c0e 1386 frame_on_same_kboard = Qnil;
8ceb7434 1387
bedb9c0e
KL
1388 for (frames = Vframe_list;
1389 CONSP (frames);
1390 frames = XCDR (frames))
1391 {
1392 Lisp_Object this;
1393 struct frame *f1;
8ceb7434 1394
bedb9c0e
KL
1395 this = XCAR (frames);
1396 if (!FRAMEP (this))
1397 abort ();
1398 f1 = XFRAME (this);
8ceb7434 1399
bedb9c0e
KL
1400 if (kb == FRAME_KBOARD (f1))
1401 frame_on_same_kboard = this;
1402 }
8ceb7434 1403
bedb9c0e
KL
1404 if (NILP (frame_on_same_kboard))
1405 not_single_kboard_state (kb);
1406 }
8ceb7434
RS
1407
1408
c4c6d073
KH
1409 /* If we've deleted this keyboard's default_minibuffer_frame, try to
1410 find another one. Prefer minibuffer-only frames, but also notice
1411 frames with other windows. */
1344aad4 1412 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
1113d9db 1413 {
ff11dfa1 1414 Lisp_Object frames;
1113d9db 1415
ff11dfa1 1416 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
ab9f008d 1417 Lisp_Object frame_with_minibuf;
32fda9ba
RS
1418 /* Some frame we found on the same kboard, or nil if there are none. */
1419 Lisp_Object frame_on_same_kboard;
1113d9db 1420
32fda9ba 1421 frame_on_same_kboard = Qnil;
ab9f008d 1422 frame_with_minibuf = Qnil;
32fda9ba 1423
ff11dfa1
JB
1424 for (frames = Vframe_list;
1425 CONSP (frames);
7539e11f 1426 frames = XCDR (frames))
1113d9db 1427 {
ab9f008d 1428 Lisp_Object this;
c4c6d073 1429 struct frame *f1;
1113d9db 1430
7539e11f 1431 this = XCAR (frames);
e35d291d 1432 if (!FRAMEP (this))
1113d9db 1433 abort ();
c4c6d073 1434 f1 = XFRAME (this);
1113d9db 1435
c4c6d073
KH
1436 /* Consider only frames on the same kboard
1437 and only those with minibuffers. */
bedb9c0e 1438 if (kb == FRAME_KBOARD (f1)
c4c6d073 1439 && FRAME_HAS_MINIBUF_P (f1))
1113d9db 1440 {
ff11dfa1 1441 frame_with_minibuf = this;
c4c6d073 1442 if (FRAME_MINIBUF_ONLY_P (f1))
1113d9db
JB
1443 break;
1444 }
32fda9ba 1445
bedb9c0e 1446 if (kb == FRAME_KBOARD (f1))
32fda9ba 1447 frame_on_same_kboard = this;
1113d9db
JB
1448 }
1449
32fda9ba
RS
1450 if (!NILP (frame_on_same_kboard))
1451 {
1452 /* We know that there must be some frame with a minibuffer out
1453 there. If this were not true, all of the frames present
1454 would have to be minibufferless, which implies that at some
1455 point their minibuffer frames must have been deleted, but
1456 that is prohibited at the top; you can't delete surrogate
1457 minibuffer frames. */
1458 if (NILP (frame_with_minibuf))
1459 abort ();
1113d9db 1460
15dbb4d6 1461 kset_default_minibuffer_frame (kb, frame_with_minibuf);
32fda9ba
RS
1462 }
1463 else
1464 /* No frames left on this kboard--say no minibuffer either. */
15dbb4d6 1465 kset_default_minibuffer_frame (kb, Qnil);
1113d9db
JB
1466 }
1467
e681c92a 1468 /* Cause frame titles to update--necessary if we now have just one frame. */
54ee7410
CY
1469 if (!tooltip_frame)
1470 update_mode_lines = 1;
e681c92a 1471
dc6f92b8
JB
1472 return Qnil;
1473}
56f2de10
MR
1474
1475DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
1476 doc: /* Delete FRAME, permanently eliminating it from use.
1477FRAME defaults to the selected frame.
1478
1479A frame may not be deleted if its minibuffer is used by other frames.
1480Normally, you may not delete a frame if all other frames are invisible,
1481but if the second optional argument FORCE is non-nil, you may do so.
1482
1483This function runs `delete-frame-functions' before actually
1484deleting the frame, unless the frame is a tooltip.
1485The functions are run with one argument, the frame to be deleted. */)
5842a27b 1486 (Lisp_Object frame, Lisp_Object force)
56f2de10
MR
1487{
1488 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
1489}
1490
dc6f92b8
JB
1491\f
1492/* Return mouse position in character cell units. */
1493
f9898cc6 1494DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
14ff1ee0
PJ
1495 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1496The position is given in character cells, where (0, 0) is the
d0cd961e
EZ
1497upper-left corner of the frame, X is the horizontal offset, and Y is
1498the vertical offset.
14ff1ee0
PJ
1499If Emacs is running on a mouseless terminal or hasn't been programmed
1500to read the mouse position, it returns the selected frame for FRAME
1501and nil for X and Y.
1502If `mouse-position-function' is non-nil, `mouse-position' calls it,
1503passing the normal return value to that function as an argument,
1504and returns whatever that function returns. */)
5842a27b 1505 (void)
dc6f92b8 1506{
ff11dfa1 1507 FRAME_PTR f;
dbc4e1c1 1508 Lisp_Object lispy_dummy;
fd2777e0 1509 enum scroll_bar_part party_dummy;
beb0bc36 1510 Lisp_Object x, y, retval;
5384466a 1511 int col, row;
08dc5ae6 1512 Time long_dummy;
cb2255b3 1513 struct gcpro gcpro1;
dc6f92b8 1514
8d2666fe 1515 f = SELECTED_FRAME ();
c5074d8c
RS
1516 x = y = Qnil;
1517
67f6e31c 1518#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
c5074d8c 1519 /* It's okay for the hook to refrain from storing anything. */
6ed8eeff
KL
1520 if (FRAME_TERMINAL (f)->mouse_position_hook)
1521 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1522 &lispy_dummy, &party_dummy,
1523 &x, &y,
1524 &long_dummy);
76db7eb4
KH
1525 if (! NILP (x))
1526 {
1527 col = XINT (x);
1528 row = XINT (y);
8126c3b4 1529 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
76db7eb4
KH
1530 XSETINT (x, col);
1531 XSETINT (y, row);
1532 }
f443c170 1533#endif
2d80a27a 1534 XSETFRAME (lispy_dummy, f);
beb0bc36 1535 retval = Fcons (lispy_dummy, Fcons (x, y));
cb2255b3 1536 GCPRO1 (retval);
beb0bc36 1537 if (!NILP (Vmouse_position_function))
cb2255b3
GM
1538 retval = call1 (Vmouse_position_function, retval);
1539 RETURN_UNGCPRO (retval);
dc6f92b8
JB
1540}
1541
152e6c70
RS
1542DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
1543 Smouse_pixel_position, 0, 0, 0,
14ff1ee0
PJ
1544 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1545The position is given in pixel units, where (0, 0) is the
d0cd961e
EZ
1546upper-left corner of the frame, X is the horizontal offset, and Y is
1547the vertical offset.
14ff1ee0
PJ
1548If Emacs is running on a mouseless terminal or hasn't been programmed
1549to read the mouse position, it returns the selected frame for FRAME
1550and nil for X and Y. */)
5842a27b 1551 (void)
152e6c70
RS
1552{
1553 FRAME_PTR f;
1554 Lisp_Object lispy_dummy;
1555 enum scroll_bar_part party_dummy;
1556 Lisp_Object x, y;
08dc5ae6 1557 Time long_dummy;
152e6c70 1558
8d2666fe 1559 f = SELECTED_FRAME ();
152e6c70
RS
1560 x = y = Qnil;
1561
67f6e31c 1562#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
152e6c70 1563 /* It's okay for the hook to refrain from storing anything. */
6ed8eeff
KL
1564 if (FRAME_TERMINAL (f)->mouse_position_hook)
1565 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1566 &lispy_dummy, &party_dummy,
1567 &x, &y,
1568 &long_dummy);
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 }
2120 default: abort ();
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
2477With the Motif or Lucid toolkits, it also includes the tool bar (but
2478not the menu bar).
2479
2480In a graphical version with no toolkit, it includes both the tool bar
2481and menu bar.
2482
c6bf3022 2483For a text terminal, it includes the menu bar. In this case, the
9ec6f100
GM
2484result is really in characters rather than pixels (i.e., is identical
2485to `frame-height'). */)
5842a27b 2486 (Lisp_Object frame)
dc6f92b8 2487{
a26a1f95
RS
2488 struct frame *f;
2489
2490 if (NILP (frame))
8d2666fe 2491 frame = selected_frame;
b7826503 2492 CHECK_FRAME (frame);
8d2666fe 2493 f = XFRAME (frame);
a26a1f95 2494
032d78fe
GV
2495#ifdef HAVE_WINDOW_SYSTEM
2496 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2497 return make_number (x_pixel_height (f));
2498 else
dc6d9681 2499#endif
5af5757b 2500 return make_number (FRAME_LINES (f));
a26a1f95
RS
2501}
2502
177c0ea7 2503DEFUN ("frame-pixel-width", Fframe_pixel_width,
a26a1f95 2504 Sframe_pixel_width, 0, 1, 0,
14ff1ee0
PJ
2505 doc: /* Return FRAME's width in pixels.
2506For a terminal frame, the result really gives the width in characters.
2507If FRAME is omitted, the selected frame is used. */)
5842a27b 2508 (Lisp_Object frame)
a26a1f95
RS
2509{
2510 struct frame *f;
2511
2512 if (NILP (frame))
8d2666fe 2513 frame = selected_frame;
b7826503 2514 CHECK_FRAME (frame);
8d2666fe 2515 f = XFRAME (frame);
dc6f92b8 2516
032d78fe
GV
2517#ifdef HAVE_WINDOW_SYSTEM
2518 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2519 return make_number (x_pixel_width (f));
2520 else
2521#endif
5af5757b 2522 return make_number (FRAME_COLS (f));
a26a1f95 2523}
fb0cf781
J
2524
2525DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
2526 Stool_bar_pixel_width, 0, 1, 0,
2527 doc: /* Return width in pixels of FRAME's tool bar.
2528The result is greater than zero only when the tool bar is on the left
2529or right side of FRAME. If FRAME is omitted, the selected frame is
2530used. */)
2531 (Lisp_Object frame)
2532{
fb0cf781
J
2533 if (NILP (frame))
2534 frame = selected_frame;
2535 CHECK_FRAME (frame);
fb0cf781
J
2536
2537#ifdef FRAME_TOOLBAR_WIDTH
6045c4fd
PE
2538 if (FRAME_WINDOW_P (XFRAME (frame)))
2539 return make_number (FRAME_TOOLBAR_WIDTH (XFRAME (frame)));
fb0cf781 2540#endif
4ddb20d6 2541 return make_number (0);
fb0cf781 2542}
a26a1f95 2543\f
ff11dfa1 2544DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
14ff1ee0
PJ
2545 doc: /* Specify that the frame FRAME has LINES lines.
2546Optional third arg non-nil means that redisplay should use LINES lines
2547but that the idea of the actual height of the frame should not be changed. */)
5842a27b 2548 (Lisp_Object frame, Lisp_Object lines, Lisp_Object pretend)
dc6f92b8 2549{
ff11dfa1 2550 register struct frame *f;
dc6f92b8 2551
d311d28c 2552 CHECK_TYPE_RANGED_INTEGER (int, lines);
ff11dfa1 2553 if (NILP (frame))
8d2666fe 2554 frame = selected_frame;
b7826503 2555 CHECK_LIVE_FRAME (frame);
8d2666fe 2556 f = XFRAME (frame);
dc6f92b8 2557
dbc4e1c1 2558 /* I think this should be done with a hook. */
032d78fe
GV
2559#ifdef HAVE_WINDOW_SYSTEM
2560 if (FRAME_WINDOW_P (f))
dc6f92b8 2561 {
5af5757b
KS
2562 if (XINT (lines) != FRAME_LINES (f))
2563 x_set_window_size (f, 1, FRAME_COLS (f), XINT (lines));
32347cf4 2564 do_pending_window_change (0);
dc6f92b8
JB
2565 }
2566 else
fd0c2bd1 2567#endif
32347cf4 2568 change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0, 0);
dc6f92b8
JB
2569 return Qnil;
2570}
2571
ff11dfa1 2572DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
14ff1ee0
PJ
2573 doc: /* Specify that the frame FRAME has COLS columns.
2574Optional third arg non-nil means that redisplay should use COLS columns
2575but that the idea of the actual width of the frame should not be changed. */)
5842a27b 2576 (Lisp_Object frame, Lisp_Object cols, Lisp_Object pretend)
dc6f92b8 2577{
ff11dfa1 2578 register struct frame *f;
d311d28c 2579 CHECK_TYPE_RANGED_INTEGER (int, cols);
ff11dfa1 2580 if (NILP (frame))
8d2666fe 2581 frame = selected_frame;
b7826503 2582 CHECK_LIVE_FRAME (frame);
8d2666fe 2583 f = XFRAME (frame);
dc6f92b8 2584
dbc4e1c1 2585 /* I think this should be done with a hook. */
032d78fe
GV
2586#ifdef HAVE_WINDOW_SYSTEM
2587 if (FRAME_WINDOW_P (f))
dc6f92b8 2588 {
5af5757b
KS
2589 if (XINT (cols) != FRAME_COLS (f))
2590 x_set_window_size (f, 1, XINT (cols), FRAME_LINES (f));
32347cf4 2591 do_pending_window_change (0);
dc6f92b8
JB
2592 }
2593 else
fd0c2bd1 2594#endif
32347cf4 2595 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0, 0);
dc6f92b8
JB
2596 return Qnil;
2597}
2598
ff11dfa1 2599DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
14ff1ee0 2600 doc: /* Sets size of FRAME to COLS by ROWS, measured in characters. */)
5842a27b 2601 (Lisp_Object frame, Lisp_Object cols, Lisp_Object rows)
dc6f92b8 2602{
ff11dfa1 2603 register struct frame *f;
dc6f92b8 2604
b7826503 2605 CHECK_LIVE_FRAME (frame);
d311d28c
PE
2606 CHECK_TYPE_RANGED_INTEGER (int, cols);
2607 CHECK_TYPE_RANGED_INTEGER (int, rows);
ff11dfa1 2608 f = XFRAME (frame);
dc6f92b8 2609
dbc4e1c1 2610 /* I think this should be done with a hook. */
032d78fe
GV
2611#ifdef HAVE_WINDOW_SYSTEM
2612 if (FRAME_WINDOW_P (f))
dc6f92b8 2613 {
5af5757b
KS
2614 if (XINT (rows) != FRAME_LINES (f)
2615 || XINT (cols) != FRAME_COLS (f)
2616 || f->new_text_lines || f->new_text_cols)
808c0f20 2617 x_set_window_size (f, 1, XINT (cols), XINT (rows));
32347cf4 2618 do_pending_window_change (0);
dc6f92b8
JB
2619 }
2620 else
fd0c2bd1 2621#endif
32347cf4 2622 change_frame_size (f, XINT (rows), XINT (cols), 0, 0, 0);
dc6f92b8
JB
2623
2624 return Qnil;
2625}
2626
177c0ea7 2627DEFUN ("set-frame-position", Fset_frame_position,
ff11dfa1 2628 Sset_frame_position, 3, 3, 0,
14ff1ee0
PJ
2629 doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
2630This is actually the position of the upper left corner of the frame.
2631Negative values for XOFFSET or YOFFSET are interpreted relative to
2632the rightmost or bottommost possible position (that stays within the screen). */)
5842a27b 2633 (Lisp_Object frame, Lisp_Object xoffset, Lisp_Object yoffset)
dc6f92b8 2634{
ff11dfa1 2635 register struct frame *f;
dc6f92b8 2636
b7826503 2637 CHECK_LIVE_FRAME (frame);
d311d28c
PE
2638 CHECK_TYPE_RANGED_INTEGER (int, xoffset);
2639 CHECK_TYPE_RANGED_INTEGER (int, yoffset);
ff11dfa1 2640 f = XFRAME (frame);
dc6f92b8 2641
dbc4e1c1 2642 /* I think this should be done with a hook. */
032d78fe
GV
2643#ifdef HAVE_WINDOW_SYSTEM
2644 if (FRAME_WINDOW_P (f))
c7c70761 2645 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
fd0c2bd1 2646#endif
dc6f92b8
JB
2647
2648 return Qt;
2649}
dc6d9681 2650
dc6f92b8 2651\f
972f4259
KS
2652/***********************************************************************
2653 Frame Parameters
2654 ***********************************************************************/
2655
2656/* Connect the frame-parameter names for X frames
2657 to the ways of passing the parameter values to the window system.
2658
2659 The name of a parameter, as a Lisp symbol,
2660 has an `x-frame-parameter' property which is an integer in Lisp
2661 that is an index in this table. */
2662
2663struct frame_parm_table {
675e2c69 2664 const char *name;
972f4259
KS
2665 Lisp_Object *variable;
2666};
2667
94eed851 2668static const struct frame_parm_table frame_parms[] =
972f4259
KS
2669{
2670 {"auto-raise", &Qauto_raise},
2671 {"auto-lower", &Qauto_lower},
2672 {"background-color", 0},
2673 {"border-color", &Qborder_color},
2674 {"border-width", &Qborder_width},
2675 {"cursor-color", &Qcursor_color},
2676 {"cursor-type", &Qcursor_type},
2677 {"font", 0},
2678 {"foreground-color", 0},
2679 {"icon-name", &Qicon_name},
2680 {"icon-type", &Qicon_type},
2681 {"internal-border-width", &Qinternal_border_width},
2682 {"menu-bar-lines", &Qmenu_bar_lines},
2683 {"mouse-color", &Qmouse_color},
2684 {"name", &Qname},
2685 {"scroll-bar-width", &Qscroll_bar_width},
2686 {"title", &Qtitle},
2687 {"unsplittable", &Qunsplittable},
2688 {"vertical-scroll-bars", &Qvertical_scroll_bars},
2689 {"visibility", &Qvisibility},
2690 {"tool-bar-lines", &Qtool_bar_lines},
2691 {"scroll-bar-foreground", &Qscroll_bar_foreground},
2692 {"scroll-bar-background", &Qscroll_bar_background},
2693 {"screen-gamma", &Qscreen_gamma},
2694 {"line-spacing", &Qline_spacing},
2695 {"left-fringe", &Qleft_fringe},
2696 {"right-fringe", &Qright_fringe},
2697 {"wait-for-wm", &Qwait_for_wm},
2698 {"fullscreen", &Qfullscreen},
0a708637 2699 {"font-backend", &Qfont_backend},
cad9ef74
JD
2700 {"alpha", &Qalpha},
2701 {"sticky", &Qsticky},
bfeabdc3 2702 {"tool-bar-position", &Qtool_bar_position},
972f4259
KS
2703};
2704
81626931 2705#ifdef WINDOWSNT
972f4259 2706
972f4259 2707/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
bd45aef7 2708 wanted positions of the WM window (not Emacs window).
972f4259
KS
2709 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
2710 window (FRAME_X_WINDOW).
2711 */
2712
dfcf069d 2713void
971de7fb 2714x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos)
dc6f92b8 2715{
5af5757b
KS
2716 int newwidth = FRAME_COLS (f);
2717 int newheight = FRAME_LINES (f);
05eb7cdc 2718 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
dc6f92b8 2719
5af5757b
KS
2720 *top_pos = f->top_pos;
2721 *left_pos = f->left_pos;
3df1fda2 2722
5af5757b 2723 if (f->want_fullscreen & FULLSCREEN_HEIGHT)
972f4259
KS
2724 {
2725 int ph;
2726
a0fe6cca 2727 ph = x_display_pixel_height (dpyinfo);
5af5757b
KS
2728 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
2729 ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
2730 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
972f4259
KS
2731 *top_pos = 0;
2732 }
dc6f92b8 2733
5af5757b 2734 if (f->want_fullscreen & FULLSCREEN_WIDTH)
972f4259
KS
2735 {
2736 int pw;
2737
a0fe6cca 2738 pw = x_display_pixel_width (dpyinfo);
5af5757b
KS
2739 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
2740 pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
2741 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
972f4259
KS
2742 *left_pos = 0;
2743 }
dc6f92b8 2744
972f4259
KS
2745 *width = newwidth;
2746 *height = newheight;
2747}
dc6f92b8 2748
81626931
PE
2749#endif /* WINDOWSNT */
2750
2751#ifdef HAVE_WINDOW_SYSTEM
beb0bc36 2752
972f4259
KS
2753/* Change the parameters of frame F as specified by ALIST.
2754 If a parameter is not specially recognized, do nothing special;
2755 otherwise call the `x_set_...' function for that parameter.
2756 Except for certain geometry properties, always call store_frame_param
2757 to store the new value in the parameter alist. */
14ff1ee0 2758
972f4259 2759void
971de7fb 2760x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
972f4259
KS
2761{
2762 Lisp_Object tail;
dc6f92b8 2763
972f4259
KS
2764 /* If both of these parameters are present, it's more efficient to
2765 set them both at once. So we wait until we've looked at the
2766 entire list before we set them. */
2767 int width, height;
3df1fda2 2768
972f4259
KS
2769 /* Same here. */
2770 Lisp_Object left, top;
2771
2772 /* Same with these. */
2773 Lisp_Object icon_left, icon_top;
2774
2775 /* Record in these vectors all the parms specified. */
2776 Lisp_Object *parms;
2777 Lisp_Object *values;
f66c7cf8 2778 ptrdiff_t i, p;
972f4259
KS
2779 int left_no_change = 0, top_no_change = 0;
2780 int icon_left_no_change = 0, icon_top_no_change = 0;
3f1c6666 2781 int size_changed = 0;
972f4259
KS
2782 struct gcpro gcpro1, gcpro2;
2783
2784 i = 0;
7d7bbefd 2785 for (tail = alist; CONSP (tail); tail = XCDR (tail))
972f4259
KS
2786 i++;
2787
38182d90
PE
2788 parms = alloca (i * sizeof *parms);
2789 values = alloca (i * sizeof *values);
972f4259
KS
2790
2791 /* Extract parm names and values into those vectors. */
2792
2793 i = 0;
d7b10f4c 2794 for (tail = alist; CONSP (tail); tail = XCDR (tail))
972f4259
KS
2795 {
2796 Lisp_Object elt;
2797
d7b10f4c 2798 elt = XCAR (tail);
972f4259
KS
2799 parms[i] = Fcar (elt);
2800 values[i] = Fcdr (elt);
2801 i++;
2802 }
2803 /* TAIL and ALIST are not used again below here. */
2804 alist = tail = Qnil;
2805
2806 GCPRO2 (*parms, *values);
2807 gcpro1.nvars = i;
2808 gcpro2.nvars = i;
2809
2810 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
2811 because their values appear in VALUES and strings are not valid. */
2812 top = left = Qunbound;
2813 icon_left = icon_top = Qunbound;
2814
2815 /* Provide default values for HEIGHT and WIDTH. */
5af5757b
KS
2816 width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
2817 height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
972f4259
KS
2818
2819 /* Process foreground_color and background_color before anything else.
2820 They are independent of other properties, but other properties (e.g.,
2821 cursor_color) are dependent upon them. */
2822 /* Process default font as well, since fringe widths depends on it. */
972f4259
KS
2823 for (p = 0; p < i; p++)
2824 {
2825 Lisp_Object prop, val;
2826
2827 prop = parms[p];
2828 val = values[p];
2829 if (EQ (prop, Qforeground_color)
2830 || EQ (prop, Qbackground_color)
3f1c6666 2831 || EQ (prop, Qfont))
972f4259
KS
2832 {
2833 register Lisp_Object param_index, old_value;
2834
2835 old_value = get_frame_param (f, prop);
972f4259
KS
2836 if (NILP (Fequal (val, old_value)))
2837 {
2838 store_frame_param (f, prop, val);
2839
2840 param_index = Fget (prop, Qx_frame_parameter);
2841 if (NATNUMP (param_index)
2842 && (XFASTINT (param_index)
2843 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
2844 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
2845 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
972f4259
KS
2846 }
2847 }
2848 }
2849
2850 /* Now process them in reverse of specified order. */
c5101a77 2851 while (i-- != 0)
972f4259
KS
2852 {
2853 Lisp_Object prop, val;
2854
2855 prop = parms[i];
2856 val = values[i];
2857
d311d28c 2858 if (EQ (prop, Qwidth) && RANGED_INTEGERP (0, val, INT_MAX))
3f1c6666
JD
2859 {
2860 size_changed = 1;
2861 width = XFASTINT (val);
2862 }
d311d28c 2863 else if (EQ (prop, Qheight) && RANGED_INTEGERP (0, val, INT_MAX))
3f1c6666
JD
2864 {
2865 size_changed = 1;
2866 height = XFASTINT (val);
2867 }
972f4259
KS
2868 else if (EQ (prop, Qtop))
2869 top = val;
2870 else if (EQ (prop, Qleft))
2871 left = val;
2872 else if (EQ (prop, Qicon_top))
2873 icon_top = val;
2874 else if (EQ (prop, Qicon_left))
2875 icon_left = val;
2876 else if (EQ (prop, Qforeground_color)
2877 || EQ (prop, Qbackground_color)
3f1c6666 2878 || EQ (prop, Qfont))
972f4259
KS
2879 /* Processed above. */
2880 continue;
2881 else
2882 {
2883 register Lisp_Object param_index, old_value;
2884
2885 old_value = get_frame_param (f, prop);
2886
2887 store_frame_param (f, prop, val);
2888
2889 param_index = Fget (prop, Qx_frame_parameter);
2890 if (NATNUMP (param_index)
2891 && (XFASTINT (param_index)
2892 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
2893 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
2894 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
972f4259
KS
2895 }
2896 }
2897
2898 /* Don't die if just one of these was set. */
5fbfb018 2899 if (EQ (left, Qunbound))
972f4259
KS
2900 {
2901 left_no_change = 1;
5af5757b
KS
2902 if (f->left_pos < 0)
2903 left = Fcons (Qplus, Fcons (make_number (f->left_pos), Qnil));
972f4259 2904 else
5af5757b 2905 XSETINT (left, f->left_pos);
972f4259 2906 }
5fbfb018 2907 if (EQ (top, Qunbound))
972f4259
KS
2908 {
2909 top_no_change = 1;
5af5757b
KS
2910 if (f->top_pos < 0)
2911 top = Fcons (Qplus, Fcons (make_number (f->top_pos), Qnil));
972f4259 2912 else
5af5757b 2913 XSETINT (top, f->top_pos);
972f4259
KS
2914 }
2915
2916 /* If one of the icon positions was not set, preserve or default it. */
d311d28c 2917 if (! TYPE_RANGED_INTEGERP (int, icon_left))
972f4259
KS
2918 {
2919 icon_left_no_change = 1;
e69b0960 2920 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
972f4259
KS
2921 if (NILP (icon_left))
2922 XSETINT (icon_left, 0);
2923 }
d311d28c 2924 if (! TYPE_RANGED_INTEGERP (int, icon_top))
972f4259
KS
2925 {
2926 icon_top_no_change = 1;
e69b0960 2927 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
972f4259
KS
2928 if (NILP (icon_top))
2929 XSETINT (icon_top, 0);
2930 }
2931
972f4259
KS
2932 /* Don't set these parameters unless they've been explicitly
2933 specified. The window might be mapped or resized while we're in
2934 this function, and we don't want to override that unless the lisp
2935 code has asked for it.
2936
2937 Don't set these parameters unless they actually differ from the
2938 window's current parameters; the window may not actually exist
2939 yet. */
2940 {
2941 Lisp_Object frame;
2942
2943 check_frame_size (f, &height, &width);
2944
2945 XSETFRAME (frame, f);
2946
3f1c6666
JD
2947 if (size_changed
2948 && (width != FRAME_COLS (f)
2949 || height != FRAME_LINES (f)
2950 || f->new_text_lines || f->new_text_cols))
2951 Fset_frame_size (frame, make_number (width), make_number (height));
972f4259
KS
2952
2953 if ((!NILP (left) || !NILP (top))
2954 && ! (left_no_change && top_no_change)
5af5757b
KS
2955 && ! (NUMBERP (left) && XINT (left) == f->left_pos
2956 && NUMBERP (top) && XINT (top) == f->top_pos))
972f4259
KS
2957 {
2958 int leftpos = 0;
2959 int toppos = 0;
2960
2961 /* Record the signs. */
5af5757b 2962 f->size_hint_flags &= ~ (XNegative | YNegative);
972f4259 2963 if (EQ (left, Qminus))
5af5757b 2964 f->size_hint_flags |= XNegative;
b8898fda 2965 else if (TYPE_RANGED_INTEGERP (int, left))
972f4259
KS
2966 {
2967 leftpos = XINT (left);
2968 if (leftpos < 0)
5af5757b 2969 f->size_hint_flags |= XNegative;
972f4259
KS
2970 }
2971 else if (CONSP (left) && EQ (XCAR (left), Qminus)
2972 && CONSP (XCDR (left))
b8898fda 2973 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
972f4259
KS
2974 {
2975 leftpos = - XINT (XCAR (XCDR (left)));
5af5757b 2976 f->size_hint_flags |= XNegative;
972f4259
KS
2977 }
2978 else if (CONSP (left) && EQ (XCAR (left), Qplus)
2979 && CONSP (XCDR (left))
b8898fda 2980 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
972f4259
KS
2981 {
2982 leftpos = XINT (XCAR (XCDR (left)));
2983 }
2984
2985 if (EQ (top, Qminus))
5af5757b 2986 f->size_hint_flags |= YNegative;
b8898fda 2987 else if (TYPE_RANGED_INTEGERP (int, top))
972f4259
KS
2988 {
2989 toppos = XINT (top);
2990 if (toppos < 0)
5af5757b 2991 f->size_hint_flags |= YNegative;
972f4259
KS
2992 }
2993 else if (CONSP (top) && EQ (XCAR (top), Qminus)
2994 && CONSP (XCDR (top))
b8898fda 2995 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
972f4259
KS
2996 {
2997 toppos = - XINT (XCAR (XCDR (top)));
5af5757b 2998 f->size_hint_flags |= YNegative;
972f4259
KS
2999 }
3000 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3001 && CONSP (XCDR (top))
b8898fda 3002 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
972f4259
KS
3003 {
3004 toppos = XINT (XCAR (XCDR (top)));
3005 }
3006
3007
3008 /* Store the numeric value of the position. */
5af5757b
KS
3009 f->top_pos = toppos;
3010 f->left_pos = leftpos;
972f4259 3011
5af5757b 3012 f->win_gravity = NorthWestGravity;
972f4259
KS
3013
3014 /* Actually set that position, and convert to absolute. */
3015 x_set_offset (f, leftpos, toppos, -1);
3016 }
3017
3018 if ((!NILP (icon_left) || !NILP (icon_top))
3019 && ! (icon_left_no_change && icon_top_no_change))
3020 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3021 }
3022
3023 UNGCPRO;
3024}
3025
3026
3027/* Insert a description of internally-recorded parameters of frame X
3028 into the parameter alist *ALISTPTR that is to be given to the user.
3029 Only parameters that are specific to the X window system
3030 and whose values are not correctly recorded in the frame's
3031 param_alist need to be considered here. */
3032
3033void
971de7fb 3034x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
972f4259
KS
3035{
3036 char buf[16];
3037 Lisp_Object tem;
8a401434 3038 unsigned long w;
972f4259
KS
3039
3040 /* Represent negative positions (off the top or left screen edge)
3041 in a way that Fmodify_frame_parameters will understand correctly. */
5af5757b
KS
3042 XSETINT (tem, f->left_pos);
3043 if (f->left_pos >= 0)
972f4259
KS
3044 store_in_alist (alistptr, Qleft, tem);
3045 else
3046 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
3047
5af5757b
KS
3048 XSETINT (tem, f->top_pos);
3049 if (f->top_pos >= 0)
972f4259
KS
3050 store_in_alist (alistptr, Qtop, tem);
3051 else
3052 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
3053
3054 store_in_alist (alistptr, Qborder_width,
5af5757b 3055 make_number (f->border_width));
972f4259 3056 store_in_alist (alistptr, Qinternal_border_width,
5af5757b 3057 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
972f4259 3058 store_in_alist (alistptr, Qleft_fringe,
5af5757b 3059 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
972f4259 3060 store_in_alist (alistptr, Qright_fringe,
5af5757b 3061 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
972f4259
KS
3062 store_in_alist (alistptr, Qscroll_bar_width,
3063 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3064 ? make_number (0)
5af5757b
KS
3065 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
3066 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3067 /* nil means "use default width"
3068 for non-toolkit scroll bar.
3069 ruler-mode.el depends on this. */
3070 : Qnil));
208a048d
EZ
3071 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
3072 MS-Windows it returns a value whose type is HANDLE, which is
3073 actually a pointer. Explicit casting avoids compiler
3074 warnings. */
3075 w = (unsigned long) FRAME_X_WINDOW (f);
972f4259 3076 store_in_alist (alistptr, Qwindow_id,
a8290ec3 3077 make_formatted_string (buf, "%lu", w));
972f4259
KS
3078#ifdef HAVE_X_WINDOWS
3079#ifdef USE_X_TOOLKIT
3080 /* Tooltip frame may not have this widget. */
3081 if (FRAME_X_OUTPUT (f)->widget)
3082#endif
a8290ec3 3083 w = (unsigned long) FRAME_OUTER_WINDOW (f);
972f4259 3084 store_in_alist (alistptr, Qouter_window_id,
a8290ec3 3085 make_formatted_string (buf, "%lu", w));
972f4259 3086#endif
e69b0960 3087 store_in_alist (alistptr, Qicon_name, f->icon_name);
972f4259
KS
3088 FRAME_SAMPLE_VISIBILITY (f);
3089 store_in_alist (alistptr, Qvisibility,
3090 (FRAME_VISIBLE_P (f) ? Qt
3091 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
3092 store_in_alist (alistptr, Qdisplay,
3093 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
3094
3095 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
3096 tem = Qnil;
3097 else
3098 XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
5839d7e8 3099 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
972f4259 3100 store_in_alist (alistptr, Qparent_id, tem);
e69b0960 3101 store_in_alist (alistptr, Qtool_bar_position, f->tool_bar_position);
972f4259
KS
3102}
3103
3104
3105/* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
3106 the previous value of that parameter, NEW_VALUE is the new value. */
3107
3108void
971de7fb 3109x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
972f4259 3110{
972f4259 3111 if (NILP (new_value))
5af5757b 3112 f->want_fullscreen = FULLSCREEN_NONE;
3f1c6666 3113 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
5af5757b 3114 f->want_fullscreen = FULLSCREEN_BOTH;
972f4259 3115 else if (EQ (new_value, Qfullwidth))
5af5757b 3116 f->want_fullscreen = FULLSCREEN_WIDTH;
972f4259 3117 else if (EQ (new_value, Qfullheight))
5af5757b 3118 f->want_fullscreen = FULLSCREEN_HEIGHT;
3f1c6666
JD
3119 else if (EQ (new_value, Qmaximized))
3120 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
d761dd42 3121
a3547743 3122 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
974b73e8 3123 FRAME_TERMINAL (f)->fullscreen_hook (f);
972f4259
KS
3124}
3125
3126
3127/* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
3128 the previous value of that parameter, NEW_VALUE is the new value. */
3129
3130void
971de7fb 3131x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
972f4259
KS
3132{
3133 if (NILP (new_value))
3134 f->extra_line_spacing = 0;
d311d28c 3135 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
972f4259
KS
3136 f->extra_line_spacing = XFASTINT (new_value);
3137 else
9dc95187 3138 signal_error ("Invalid line-spacing", new_value);
972f4259
KS
3139 if (FRAME_VISIBLE_P (f))
3140 redraw_frame (f);
3141}
3142
3143
3144/* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
3145 the previous value of that parameter, NEW_VALUE is the new value. */
3146
3147void
971de7fb 3148x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
972f4259 3149{
05fc2ef7
CY
3150 Lisp_Object bgcolor;
3151
972f4259
KS
3152 if (NILP (new_value))
3153 f->gamma = 0;
3154 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
05fc2ef7
CY
3155 /* The value 0.4545 is the normal viewing gamma. */
3156 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
972f4259 3157 else
9dc95187 3158 signal_error ("Invalid screen-gamma", new_value);
972f4259 3159
05fc2ef7 3160 /* Apply the new gamma value to the frame background. */
e69b0960 3161 bgcolor = Fassq (Qbackground_color, f->param_alist);
05fc2ef7
CY
3162 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
3163 {
76c1cebc
PE
3164 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
3165 if (NATNUMP (parm_index)
3166 && (XFASTINT (parm_index)
05fc2ef7 3167 < sizeof (frame_parms)/sizeof (frame_parms[0]))
76c1cebc
PE
3168 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3169 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
6baa22c1 3170 (f, bgcolor, Qnil);
05fc2ef7
CY
3171 }
3172
3173 Fclear_face_cache (Qnil);
972f4259
KS
3174}
3175
3176
3177void
971de7fb 3178x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
972f4259 3179{
6045c4fd 3180 Lisp_Object font_object;
e0c8ad78 3181 int fontset = -1;
6045c4fd
PE
3182#ifdef HAVE_X_WINDOWS
3183 Lisp_Object font_param = arg;
3184#endif
972f4259 3185
178377e1 3186 /* Set the frame parameter back to the old value because we may
e0c8ad78
KH
3187 fail to use ARG as the new parameter value. */
3188 store_frame_param (f, Qfont, oldval);
0169d360 3189
d507f8d7
KH
3190 /* ARG is a fontset name, a font name, a cons of fontset name and a
3191 font object, or a font object. In the last case, this function
3192 never fail. */
e0c8ad78
KH
3193 if (STRINGP (arg))
3194 {
3195 fontset = fs_query_fontset (arg, 0);
3196 if (fontset < 0)
0169d360 3197 {
d7ea76b4 3198 font_object = font_open_by_name (f, arg);
e0c8ad78 3199 if (NILP (font_object))
42a5b22f 3200 error ("Font `%s' is not defined", SSDATA (arg));
e0c8ad78 3201 arg = AREF (font_object, FONT_NAME_INDEX);
0169d360 3202 }
e0c8ad78
KH
3203 else if (fontset > 0)
3204 {
d7ea76b4 3205 font_object = font_open_by_name (f, fontset_ascii (fontset));
e0c8ad78
KH
3206 if (NILP (font_object))
3207 error ("Font `%s' is not defined", SDATA (arg));
97d42150 3208 arg = AREF (font_object, FONT_NAME_INDEX);
e0c8ad78 3209 }
0169d360 3210 else
e0c8ad78 3211 error ("The default fontset can't be used for a frame font");
0169d360 3212 }
d507f8d7
KH
3213 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
3214 {
3215 /* This is the case that the ASCII font of F's fontset XCAR
3216 (arg) is changed to the font XCDR (arg) by
3217 `set-fontset-font'. */
3218 fontset = fs_query_fontset (XCAR (arg), 0);
3219 if (fontset < 0)
3220 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
3221 font_object = XCDR (arg);
3222 arg = AREF (font_object, FONT_NAME_INDEX);
6045c4fd 3223#ifdef HAVE_X_WINDOWS
581e51e8 3224 font_param = Ffont_get (font_object, QCname);
6045c4fd 3225#endif
d507f8d7 3226 }
e0c8ad78 3227 else if (FONT_OBJECT_P (arg))
698ca23e 3228 {
e0c8ad78 3229 font_object = arg;
6045c4fd 3230#ifdef HAVE_X_WINDOWS
581e51e8 3231 font_param = Ffont_get (font_object, QCname);
6045c4fd 3232#endif
b17ae93a 3233 /* This is to store the XLFD font name in the frame parameter for
057bce6f 3234 backward compatibility. We should store the font-object
e0c8ad78
KH
3235 itself in the future. */
3236 arg = AREF (font_object, FONT_NAME_INDEX);
b17ae93a 3237 fontset = FRAME_FONTSET (f);
518c4881
KH
3238 /* Check if we can use the current fontset. If not, set FONTSET
3239 to -1 to generate a new fontset from FONT-OBJECT. */
3240 if (fontset >= 0)
3241 {
3242 Lisp_Object ascii_font = fontset_ascii (fontset);
3243 Lisp_Object spec = font_spec_from_name (ascii_font);
3244
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)
0a708637
GM
3541 BLOCK_INPUT;
3542 x_set_frame_alpha (f);
3543 UNBLOCK_INPUT;
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:
3847 abort ();
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
3905
3906\f
7ab5d780
GM
3907/* NS used to define x-parse-geometry in ns-win.el, but that confused
3908 make-docfile: the documentation string in ns-win.el was used for
3909 x-parse-geometry even in non-NS builds.
3910
3911 With two definitions of x-parse-geometry in this file, various
3912 things still get confused (eg M-x apropos documentation), so that
3913 it is best if the two definitions just share the same doc-string.
3914*/
972f4259 3915DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
7ab5d780 3916 doc: /* Parse a display geometry string STRING.
972f4259
KS
3917Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3918The properties returned may include `top', `left', `height', and `width'.
7ab5d780 3919For X, the value of `left' or `top' may be an integer,
972f4259 3920or a list (+ N) meaning N pixels relative to top/left corner,
7ab5d780
GM
3921or a list (- N) meaning -N pixels relative to bottom/right corner.
3922On Nextstep, this just calls `ns-parse-geometry'. */)
5842a27b 3923 (Lisp_Object string)
972f4259 3924{
7ab5d780 3925#ifdef HAVE_NS
6045c4fd 3926 return call1 (Qns_parse_geometry, string);
7ab5d780 3927#else
972f4259
KS
3928 int geometry, x, y;
3929 unsigned int width, height;
3930 Lisp_Object result;
3931
3932 CHECK_STRING (string);
3933
51b59d79 3934 geometry = XParseGeometry (SSDATA (string),
972f4259 3935 &x, &y, &width, &height);
972f4259
KS
3936 result = Qnil;
3937 if (geometry & XValue)
3938 {
3939 Lisp_Object element;
3940
3941 if (x >= 0 && (geometry & XNegative))
3942 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3943 else if (x < 0 && ! (geometry & XNegative))
3944 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3945 else
3946 element = Fcons (Qleft, make_number (x));
3947 result = Fcons (element, result);
3948 }
3949
3950 if (geometry & YValue)
3951 {
3952 Lisp_Object element;
3953
3954 if (y >= 0 && (geometry & YNegative))
3955 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3956 else if (y < 0 && ! (geometry & YNegative))
3957 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3958 else
3959 element = Fcons (Qtop, make_number (y));
3960 result = Fcons (element, result);
3961 }
3962
3963 if (geometry & WidthValue)
3964 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3965 if (geometry & HeightValue)
3966 result = Fcons (Fcons (Qheight, make_number (height)), result);
3967
3968 return result;
dc4db71c 3969#endif /* HAVE_NS */
7ab5d780 3970}
dc4db71c 3971
972f4259
KS
3972
3973/* Calculate the desired size and position of frame F.
3974 Return the flags saying which aspects were specified.
3975
3976 Also set the win_gravity and size_hint_flags of F.
3977
3978 Adjust height for toolbar if TOOLBAR_P is 1.
3979
3980 This function does not make the coordinates positive. */
3981
c024ac08 3982#define DEFAULT_ROWS 35
972f4259
KS
3983#define DEFAULT_COLS 80
3984
3985int
971de7fb 3986x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p)
972f4259
KS
3987{
3988 register Lisp_Object tem0, tem1, tem2;
3989 long window_prompting = 0;
3990 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3991
3992 /* Default values if we fall through.
3993 Actually, if that happens we should get
3994 window manager prompting. */
5af5757b
KS
3995 SET_FRAME_COLS (f, DEFAULT_COLS);
3996 FRAME_LINES (f) = DEFAULT_ROWS;
972f4259
KS
3997 /* Window managers expect that if program-specified
3998 positions are not (0,0), they're intentional, not defaults. */
5af5757b
KS
3999 f->top_pos = 0;
4000 f->left_pos = 0;
972f4259 4001
5af5757b 4002 /* Ensure that old new_text_cols and new_text_lines will not override the
972f4259
KS
4003 values set here. */
4004 /* ++KFS: This was specific to W32, but seems ok for all platforms */
5af5757b 4005 f->new_text_cols = f->new_text_lines = 0;
972f4259
KS
4006
4007 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
4008 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
4009 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
4010 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
4011 {
4012 if (!EQ (tem0, Qunbound))
4013 {
4014 CHECK_NUMBER (tem0);
b8898fda
PE
4015 if (! (0 <= XINT (tem0) && XINT (tem0) <= INT_MAX))
4016 xsignal1 (Qargs_out_of_range, tem0);
5af5757b 4017 FRAME_LINES (f) = XINT (tem0);
972f4259
KS
4018 }
4019 if (!EQ (tem1, Qunbound))
4020 {
4021 CHECK_NUMBER (tem1);
b8898fda
PE
4022 if (! (0 <= XINT (tem1) && XINT (tem1) <= INT_MAX))
4023 xsignal1 (Qargs_out_of_range, tem1);
5af5757b 4024 SET_FRAME_COLS (f, XINT (tem1));
972f4259
KS
4025 }
4026 if (!NILP (tem2) && !EQ (tem2, Qunbound))
4027 window_prompting |= USSize;
4028 else
4029 window_prompting |= PSize;
4030 }
4031
5af5757b
KS
4032 f->scroll_bar_actual_width
4033 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
972f4259
KS
4034
4035 /* This used to be done _before_ calling x_figure_window_size, but
4036 since the height is reset here, this was really a no-op. I
4037 assume that moving it here does what Gerd intended (although he
4038 no longer can remember what that was... ++KFS, 2003-03-25. */
4039
4040 /* Add the tool-bar height to the initial frame height so that the
4041 user gets a text display area of the size he specified with -g or
4042 via .Xdefaults. Later changes of the tool-bar height don't
4043 change the frame size. This is done so that users can create
4044 tall Emacs frames without having to guess how tall the tool-bar
4045 will get. */
4046 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
4047 {
4048 int margin, relief, bar_height;
4049
4050 relief = (tool_bar_button_relief >= 0
4051 ? tool_bar_button_relief
4052 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4053
b8898fda 4054 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
972f4259
KS
4055 margin = XFASTINT (Vtool_bar_button_margin);
4056 else if (CONSP (Vtool_bar_button_margin)
b8898fda 4057 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
972f4259
KS
4058 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4059 else
4060 margin = 0;
4061
4062 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5af5757b 4063 FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
972f4259
KS
4064 }
4065
4066 compute_fringe_widths (f, 0);
4067
5af5757b
KS
4068 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, FRAME_COLS (f));
4069 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
972f4259
KS
4070
4071 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
4072 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
4073 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
4074 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
4075 {
4076 if (EQ (tem0, Qminus))
4077 {
5af5757b 4078 f->top_pos = 0;
972f4259
KS
4079 window_prompting |= YNegative;
4080 }
4081 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
4082 && CONSP (XCDR (tem0))
b8898fda 4083 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem0)), INT_MAX))
972f4259 4084 {
5af5757b 4085 f->top_pos = - XINT (XCAR (XCDR (tem0)));
972f4259
KS
4086 window_prompting |= YNegative;
4087 }
4088 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
4089 && CONSP (XCDR (tem0))
b8898fda 4090 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem0))))
972f4259 4091 {
5af5757b 4092 f->top_pos = XINT (XCAR (XCDR (tem0)));
972f4259
KS
4093 }
4094 else if (EQ (tem0, Qunbound))
5af5757b 4095 f->top_pos = 0;
972f4259
KS
4096 else
4097 {
d311d28c 4098 CHECK_TYPE_RANGED_INTEGER (int, tem0);
5af5757b
KS
4099 f->top_pos = XINT (tem0);
4100 if (f->top_pos < 0)
972f4259
KS
4101 window_prompting |= YNegative;
4102 }
4103
4104 if (EQ (tem1, Qminus))
4105 {
5af5757b 4106 f->left_pos = 0;
972f4259
KS
4107 window_prompting |= XNegative;
4108 }
4109 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
4110 && CONSP (XCDR (tem1))
b8898fda 4111 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem1)), INT_MAX))
972f4259 4112 {
5af5757b 4113 f->left_pos = - XINT (XCAR (XCDR (tem1)));
972f4259
KS
4114 window_prompting |= XNegative;
4115 }
4116 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
4117 && CONSP (XCDR (tem1))
b8898fda 4118 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem1))))
972f4259 4119 {
5af5757b 4120 f->left_pos = XINT (XCAR (XCDR (tem1)));
972f4259
KS
4121 }
4122 else if (EQ (tem1, Qunbound))
5af5757b 4123 f->left_pos = 0;
972f4259
KS
4124 else
4125 {
d311d28c 4126 CHECK_TYPE_RANGED_INTEGER (int, tem1);
5af5757b
KS
4127 f->left_pos = XINT (tem1);
4128 if (f->left_pos < 0)
972f4259
KS
4129 window_prompting |= XNegative;
4130 }
4131
4132 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
4133 window_prompting |= USPosition;
4134 else
4135 window_prompting |= PPosition;
4136 }
4137
972f4259
KS
4138 if (window_prompting & XNegative)
4139 {
4140 if (window_prompting & YNegative)
5af5757b 4141 f->win_gravity = SouthEastGravity;
972f4259 4142 else
5af5757b 4143 f->win_gravity = NorthEastGravity;
972f4259
KS
4144 }
4145 else
4146 {
4147 if (window_prompting & YNegative)
5af5757b 4148 f->win_gravity = SouthWestGravity;
972f4259 4149 else
5af5757b 4150 f->win_gravity = NorthWestGravity;
972f4259
KS
4151 }
4152
5af5757b 4153 f->size_hint_flags = window_prompting;
972f4259
KS
4154
4155 return window_prompting;
4156}
4157
4158
4159
4160#endif /* HAVE_WINDOW_SYSTEM */
4161
e044e4fc 4162void
971de7fb 4163frame_make_pointer_invisible (void)
e044e4fc
JD
4164{
4165 if (! NILP (Vmake_pointer_invisible))
4166 {
abeafb2a 4167 struct frame *f;
ece2d4ed
JD
4168 if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
4169 return;
4170
abeafb2a 4171 f = SELECTED_FRAME ();
e044e4fc
JD
4172 if (f && !f->pointer_invisible
4173 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4174 {
4175 f->mouse_moved = 0;
4176 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
4177 f->pointer_invisible = 1;
4178 }
4179 }
4180}
4181
4182void
971de7fb 4183frame_make_pointer_visible (void)
e044e4fc
JD
4184{
4185 /* We don't check Vmake_pointer_invisible here in case the
4186 pointer was invisible when Vmake_pointer_invisible was set to nil. */
abeafb2a 4187 struct frame *f;
e044e4fc 4188
ece2d4ed
JD
4189 if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
4190 return;
4191
abeafb2a 4192 f = SELECTED_FRAME ();
e044e4fc
JD
4193 if (f && f->pointer_invisible && f->mouse_moved
4194 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4195 {
4196 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
4197 f->pointer_invisible = 0;
4198 }
4199}
4200
c978536f
JD
4201DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
4202 Sframe_pointer_visible_p, 0, 1, 0,
4203 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
4204Otherwise it returns nil. FRAME omitted or nil means the
4205selected frame. This is useful when `make-pointer-invisible' is set. */)
4206 (Lisp_Object frame)
4207{
4208 if (NILP (frame))
4209 frame = selected_frame;
4210
4211 CHECK_FRAME (frame);
4212
4213 return (XFRAME (frame)->pointer_invisible ? Qnil : Qt);
4214}
972f4259
KS
4215
4216\f
4217/***********************************************************************
4218 Initialization
4219 ***********************************************************************/
4220
4221void
971de7fb 4222syms_of_frame (void)
972f4259 4223{
cd3520a4
JB
4224 DEFSYM (Qframep, "framep");
4225 DEFSYM (Qframe_live_p, "frame-live-p");
4226 DEFSYM (Qexplicit_name, "explicit-name");
4227 DEFSYM (Qheight, "height");
4228 DEFSYM (Qicon, "icon");
4229 DEFSYM (Qminibuffer, "minibuffer");
4230 DEFSYM (Qmodeline, "modeline");
4231 DEFSYM (Qonly, "only");
9fb0c957 4232 DEFSYM (Qnone, "none");
cd3520a4
JB
4233 DEFSYM (Qwidth, "width");
4234 DEFSYM (Qgeometry, "geometry");
4235 DEFSYM (Qicon_left, "icon-left");
4236 DEFSYM (Qicon_top, "icon-top");
4237 DEFSYM (Qtooltip, "tooltip");
4238 DEFSYM (Qleft, "left");
4239 DEFSYM (Qright, "right");
4240 DEFSYM (Quser_position, "user-position");
4241 DEFSYM (Quser_size, "user-size");
4242 DEFSYM (Qwindow_id, "window-id");
972f4259 4243#ifdef HAVE_X_WINDOWS
cd3520a4 4244 DEFSYM (Qouter_window_id, "outer-window-id");
972f4259 4245#endif
cd3520a4
JB
4246 DEFSYM (Qparent_id, "parent-id");
4247 DEFSYM (Qx, "x");
4248 DEFSYM (Qw32, "w32");
4249 DEFSYM (Qpc, "pc");
4250 DEFSYM (Qmac, "mac");
4251 DEFSYM (Qns, "ns");
4252 DEFSYM (Qvisible, "visible");
4253 DEFSYM (Qbuffer_predicate, "buffer-predicate");
4254 DEFSYM (Qbuffer_list, "buffer-list");
4255 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
4256 DEFSYM (Qdisplay_type, "display-type");
4257 DEFSYM (Qbackground_mode, "background-mode");
4258 DEFSYM (Qnoelisp, "noelisp");
4259 DEFSYM (Qtty_color_mode, "tty-color-mode");
4260 DEFSYM (Qtty, "tty");
4261 DEFSYM (Qtty_type, "tty-type");
4262
4263 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
4264
4265 DEFSYM (Qfullwidth, "fullwidth");
4266 DEFSYM (Qfullheight, "fullheight");
4267 DEFSYM (Qfullboth, "fullboth");
4268 DEFSYM (Qmaximized, "maximized");
4269 DEFSYM (Qx_resource_name, "x-resource-name");
4270 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
4271
4272 DEFSYM (Qterminal, "terminal");
4273 DEFSYM (Qterminal_live_p, "terminal-live-p");
a3547743 4274
dc4db71c 4275#ifdef HAVE_NS
cd3520a4 4276 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
dc4db71c
CY
4277#endif
4278
972f4259
KS
4279 {
4280 int i;
4281
4282 for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++)
4283 {
d67b4f80 4284 Lisp_Object v = intern_c_string (frame_parms[i].name);
972f4259
KS
4285 if (frame_parms[i].variable)
4286 {
4287 *frame_parms[i].variable = v;
4288 staticpro (frame_parms[i].variable);
4289 }
4290 Fput (v, Qx_frame_parameter, make_number (i));
4291 }
4292 }
4293
2731a0ad 4294#ifdef HAVE_WINDOW_SYSTEM
29208e82 4295 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
972f4259
KS
4296 doc: /* The name Emacs uses to look up X resources.
4297`x-get-resource' uses this as the first component of the instance name
4298when requesting resource values.
4299Emacs initially sets `x-resource-name' to the name under which Emacs
4300was invoked, or to the value specified with the `-name' or `-rn'
4301switches, if present.
4302
4303It may be useful to bind this variable locally around a call
4304to `x-get-resource'. See also the variable `x-resource-class'. */);
4305 Vx_resource_name = Qnil;
4306
29208e82 4307 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
972f4259
KS
4308 doc: /* The class Emacs uses to look up X resources.
4309`x-get-resource' uses this as the first component of the instance class
4310when requesting resource values.
4311
4312Emacs initially sets `x-resource-class' to "Emacs".
4313
4314Setting this variable permanently is not a reasonable thing to do,
4315but binding this variable locally around a call to `x-get-resource'
4316is a reasonable practice. See also the variable `x-resource-name'. */);
4317 Vx_resource_class = build_string (EMACS_CLASS);
0a708637 4318
29208e82 4319 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
0a708637
GM
4320 doc: /* The lower limit of the frame opacity (alpha transparency).
4321The value should range from 0 (invisible) to 100 (completely opaque).
4322You can also use a floating number between 0.0 and 1.0.
4323The default is 20. */);
4324 Vframe_alpha_lower_limit = make_number (20);
2731a0ad 4325#endif
972f4259 4326
29208e82 4327 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
972f4259
KS
4328 doc: /* Alist of default values for frame creation.
4329These may be set in your init file, like this:
5ff00c42 4330 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
972f4259
KS
4331These override values given in window system configuration data,
4332 including X Windows' defaults database.
4333For values specific to the first Emacs frame, see `initial-frame-alist'.
095fe281 4334For window-system specific values, see `window-system-default-frame-alist'.
972f4259
KS
4335For values specific to the separate minibuffer frame, see
4336 `minibuffer-frame-alist'.
4337The `menu-bar-lines' element of the list controls whether new frames
4338 have menu bars; `menu-bar-mode' works by altering this element.
4339Setting this variable does not affect existing frames, only new ones. */);
fac580eb 4340 Vdefault_frame_alist = Qnil;
972f4259 4341
29208e82 4342 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
6b61353c
KH
4343 doc: /* Default position of scroll bars on this window-system. */);
4344#ifdef HAVE_WINDOW_SYSTEM
5e617bc2 4345#if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
303500aa
CY
4346 /* MS-Windows, Mac OS X, and GTK have scroll bars on the right by
4347 default. */
6b61353c 4348 Vdefault_frame_scroll_bars = Qright;
303500aa
CY
4349#else
4350 Vdefault_frame_scroll_bars = Qleft;
4351#endif
6b61353c
KH
4352#else
4353 Vdefault_frame_scroll_bars = Qnil;
4354#endif
4355
29208e82 4356 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
daf01701 4357 doc: /* The initial frame-object, which represents Emacs's stdout. */);
972f4259 4358
29208e82 4359 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
972f4259
KS
4360 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4361`mouse-position' calls this function, passing its usual return value as
4362argument, and returns whatever this function returns.
4363This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4364which need to do mouse handling at the Lisp level. */);
4365 Vmouse_position_function = Qnil;
4366
29208e82 4367 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
972f4259
KS
4368 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4369If the value is an integer, highlighting is only shown after moving the
4370mouse, while keyboard input turns off the highlight even when the mouse
4371is over the clickable text. However, the mouse shape still indicates
4372when the mouse is over clickable text. */);
4373 Vmouse_highlight = Qt;
4374
29208e82 4375 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
e044e4fc
JD
4376 doc: /* If non-nil, make pointer invisible while typing.
4377The pointer becomes visible again when the mouse is moved. */);
4378 Vmake_pointer_invisible = Qt;
4379
29208e82 4380 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
e5d9c0d1 4381 doc: /* Functions run before deleting a frame.
972f4259 4382The functions are run with one arg, the frame to be deleted.
e519a50b
KL
4383See `delete-frame'.
4384
58555d81
SM
4385Note that functions in this list may be called just before the frame is
4386actually deleted, or some time later (or even both when an earlier function
4387in `delete-frame-functions' (indirectly) calls `delete-frame'
4388recursively). */);
972f4259 4389 Vdelete_frame_functions = Qnil;
cd3520a4 4390 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
972f4259 4391
29208e82 4392 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
e1fd756b
GM
4393 doc: /* Non-nil if Menu-Bar mode is enabled.
4394See the command `menu-bar-mode' for a description of this minor mode.
4395Setting this variable directly does not take effect;
4396either customize it (see the info node `Easy Customization')
4397or call the function `menu-bar-mode'. */);
6431f2e6
CY
4398 Vmenu_bar_mode = Qt;
4399
29208e82 4400 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
9d794026
GM
4401 doc: /* Non-nil if Tool-Bar mode is enabled.
4402See the command `tool-bar-mode' for a description of this minor mode.
4403Setting this variable directly does not take effect;
4404either customize it (see the info node `Easy Customization')
4405or call the function `tool-bar-mode'. */);
c8c59954 4406#ifdef HAVE_WINDOW_SYSTEM
6431f2e6 4407 Vtool_bar_mode = Qt;
c8c59954
GM
4408#else
4409 Vtool_bar_mode = Qnil;
4410#endif
6431f2e6 4411
972f4259
KS
4412 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
4413 doc: /* Minibufferless frames use this frame's minibuffer.
4414
4415Emacs cannot create minibufferless frames unless this is set to an
4416appropriate surrogate.
4417
4418Emacs consults this variable only when creating minibufferless
4419frames; once the frame is created, it sticks with its assigned
4420minibuffer, no matter what this variable is set to. This means that
4421this variable doesn't necessarily say anything meaningful about the
4422current set of frames, or where the minibuffer is currently being
4423displayed.
4424
4425This variable is local to the current terminal and cannot be buffer-local. */);
4426
29208e82 4427 DEFVAR_BOOL ("focus-follows-mouse", focus_follows_mouse,
da1da002
MR
4428 doc: /* Non-nil if window system changes focus when you move the mouse.
4429You should set this variable to tell Emacs how your window manager
4430handles focus, since there is no way in general for Emacs to find out
86677b58 4431automatically. See also `mouse-autoselect-window'. */);
da1da002 4432 focus_follows_mouse = 0;
a3547743 4433
972f4259
KS
4434 staticpro (&Vframe_list);
4435
972f4259
KS
4436 defsubr (&Sframep);
4437 defsubr (&Sframe_live_p);
428a555e 4438 defsubr (&Swindow_system);
972f4259
KS
4439 defsubr (&Smake_terminal_frame);
4440 defsubr (&Shandle_switch_frame);
972f4259
KS
4441 defsubr (&Sselect_frame);
4442 defsubr (&Sselected_frame);
972f4259
KS
4443 defsubr (&Sframe_list);
4444 defsubr (&Snext_frame);
4445 defsubr (&Sprevious_frame);
4446 defsubr (&Sdelete_frame);
4447 defsubr (&Smouse_position);
4448 defsubr (&Smouse_pixel_position);
4449 defsubr (&Sset_mouse_position);
4450 defsubr (&Sset_mouse_pixel_position);
4451#if 0
4452 defsubr (&Sframe_configuration);
4453 defsubr (&Srestore_frame_configuration);
4454#endif
4455 defsubr (&Smake_frame_visible);
4456 defsubr (&Smake_frame_invisible);
4457 defsubr (&Siconify_frame);
4458 defsubr (&Sframe_visible_p);
4459 defsubr (&Svisible_frame_list);
4460 defsubr (&Sraise_frame);
4461 defsubr (&Slower_frame);
4462 defsubr (&Sredirect_frame_focus);
4463 defsubr (&Sframe_focus);
4464 defsubr (&Sframe_parameters);
4465 defsubr (&Sframe_parameter);
4466 defsubr (&Smodify_frame_parameters);
4467 defsubr (&Sframe_char_height);
4468 defsubr (&Sframe_char_width);
4469 defsubr (&Sframe_pixel_height);
4470 defsubr (&Sframe_pixel_width);
fb0cf781 4471 defsubr (&Stool_bar_pixel_width);
972f4259
KS
4472 defsubr (&Sset_frame_height);
4473 defsubr (&Sset_frame_width);
4474 defsubr (&Sset_frame_size);
4475 defsubr (&Sset_frame_position);
c978536f 4476 defsubr (&Sframe_pointer_visible_p);
972f4259
KS
4477
4478#ifdef HAVE_WINDOW_SYSTEM
4479 defsubr (&Sx_get_resource);
4480 defsubr (&Sx_parse_geometry);
4481#endif
4482
dc6f92b8 4483}