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