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