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