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