(delphi-tab): Indent region when Transient Mark mode is enabled 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
PJ
2645 doc: /* Return a FRAME's height in pixels.
2646This counts only the height available for text lines,
2647not menu bars on window-system Emacs frames.
2648For a terminal frame, the result really gives the height in characters.
2649If FRAME is omitted, the selected frame is used. */)
2650 (frame)
a26a1f95 2651 Lisp_Object frame;
dc6f92b8 2652{
a26a1f95
RS
2653 struct frame *f;
2654
2655 if (NILP (frame))
8d2666fe 2656 frame = selected_frame;
b7826503 2657 CHECK_FRAME (frame);
8d2666fe 2658 f = XFRAME (frame);
a26a1f95 2659
032d78fe
GV
2660#ifdef HAVE_WINDOW_SYSTEM
2661 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2662 return make_number (x_pixel_height (f));
2663 else
dc6d9681 2664#endif
5af5757b 2665 return make_number (FRAME_LINES (f));
a26a1f95
RS
2666}
2667
177c0ea7 2668DEFUN ("frame-pixel-width", Fframe_pixel_width,
a26a1f95 2669 Sframe_pixel_width, 0, 1, 0,
14ff1ee0
PJ
2670 doc: /* Return FRAME's width in pixels.
2671For a terminal frame, the result really gives the width in characters.
2672If FRAME is omitted, the selected frame is used. */)
2673 (frame)
a26a1f95
RS
2674 Lisp_Object frame;
2675{
2676 struct frame *f;
2677
2678 if (NILP (frame))
8d2666fe 2679 frame = selected_frame;
b7826503 2680 CHECK_FRAME (frame);
8d2666fe 2681 f = XFRAME (frame);
dc6f92b8 2682
032d78fe
GV
2683#ifdef HAVE_WINDOW_SYSTEM
2684 if (FRAME_WINDOW_P (f))
a26a1f95
RS
2685 return make_number (x_pixel_width (f));
2686 else
2687#endif
5af5757b 2688 return make_number (FRAME_COLS (f));
a26a1f95
RS
2689}
2690\f
ff11dfa1 2691DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
14ff1ee0
PJ
2692 doc: /* Specify that the frame FRAME has LINES lines.
2693Optional third arg non-nil means that redisplay should use LINES lines
2694but that the idea of the actual height of the frame should not be changed. */)
2695 (frame, lines, pretend)
735eeca3 2696 Lisp_Object frame, lines, pretend;
dc6f92b8 2697{
ff11dfa1 2698 register struct frame *f;
dc6f92b8 2699
b7826503 2700 CHECK_NUMBER (lines);
ff11dfa1 2701 if (NILP (frame))
8d2666fe 2702 frame = selected_frame;
b7826503 2703 CHECK_LIVE_FRAME (frame);
8d2666fe 2704 f = XFRAME (frame);
dc6f92b8 2705
dbc4e1c1 2706 /* I think this should be done with a hook. */
032d78fe
GV
2707#ifdef HAVE_WINDOW_SYSTEM
2708 if (FRAME_WINDOW_P (f))
dc6f92b8 2709 {
5af5757b
KS
2710 if (XINT (lines) != FRAME_LINES (f))
2711 x_set_window_size (f, 1, FRAME_COLS (f), XINT (lines));
32347cf4 2712 do_pending_window_change (0);
dc6f92b8
JB
2713 }
2714 else
fd0c2bd1 2715#endif
32347cf4 2716 change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0, 0);
dc6f92b8
JB
2717 return Qnil;
2718}
2719
ff11dfa1 2720DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
14ff1ee0
PJ
2721 doc: /* Specify that the frame FRAME has COLS columns.
2722Optional third arg non-nil means that redisplay should use COLS columns
2723but that the idea of the actual width of the frame should not be changed. */)
2724 (frame, cols, pretend)
fd0c2bd1 2725 Lisp_Object frame, cols, pretend;
dc6f92b8 2726{
ff11dfa1 2727 register struct frame *f;
b7826503 2728 CHECK_NUMBER (cols);
ff11dfa1 2729 if (NILP (frame))
8d2666fe 2730 frame = selected_frame;
b7826503 2731 CHECK_LIVE_FRAME (frame);
8d2666fe 2732 f = XFRAME (frame);
dc6f92b8 2733
dbc4e1c1 2734 /* I think this should be done with a hook. */
032d78fe
GV
2735#ifdef HAVE_WINDOW_SYSTEM
2736 if (FRAME_WINDOW_P (f))
dc6f92b8 2737 {
5af5757b
KS
2738 if (XINT (cols) != FRAME_COLS (f))
2739 x_set_window_size (f, 1, XINT (cols), FRAME_LINES (f));
32347cf4 2740 do_pending_window_change (0);
dc6f92b8
JB
2741 }
2742 else
fd0c2bd1 2743#endif
32347cf4 2744 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0, 0);
dc6f92b8
JB
2745 return Qnil;
2746}
2747
ff11dfa1 2748DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
14ff1ee0
PJ
2749 doc: /* Sets size of FRAME to COLS by ROWS, measured in characters. */)
2750 (frame, cols, rows)
ff11dfa1 2751 Lisp_Object frame, cols, rows;
dc6f92b8 2752{
ff11dfa1 2753 register struct frame *f;
dc6f92b8 2754
b7826503
PJ
2755 CHECK_LIVE_FRAME (frame);
2756 CHECK_NUMBER (cols);
2757 CHECK_NUMBER (rows);
ff11dfa1 2758 f = XFRAME (frame);
dc6f92b8 2759
dbc4e1c1 2760 /* I think this should be done with a hook. */
032d78fe
GV
2761#ifdef HAVE_WINDOW_SYSTEM
2762 if (FRAME_WINDOW_P (f))
dc6f92b8 2763 {
5af5757b
KS
2764 if (XINT (rows) != FRAME_LINES (f)
2765 || XINT (cols) != FRAME_COLS (f)
2766 || f->new_text_lines || f->new_text_cols)
808c0f20 2767 x_set_window_size (f, 1, XINT (cols), XINT (rows));
32347cf4 2768 do_pending_window_change (0);
dc6f92b8
JB
2769 }
2770 else
fd0c2bd1 2771#endif
32347cf4 2772 change_frame_size (f, XINT (rows), XINT (cols), 0, 0, 0);
dc6f92b8
JB
2773
2774 return Qnil;
2775}
2776
177c0ea7 2777DEFUN ("set-frame-position", Fset_frame_position,
ff11dfa1 2778 Sset_frame_position, 3, 3, 0,
14ff1ee0
PJ
2779 doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
2780This is actually the position of the upper left corner of the frame.
2781Negative values for XOFFSET or YOFFSET are interpreted relative to
2782the rightmost or bottommost possible position (that stays within the screen). */)
2783 (frame, xoffset, yoffset)
ff11dfa1 2784 Lisp_Object frame, xoffset, yoffset;
dc6f92b8 2785{
ff11dfa1 2786 register struct frame *f;
dc6f92b8 2787
b7826503
PJ
2788 CHECK_LIVE_FRAME (frame);
2789 CHECK_NUMBER (xoffset);
2790 CHECK_NUMBER (yoffset);
ff11dfa1 2791 f = XFRAME (frame);
dc6f92b8 2792
dbc4e1c1 2793 /* I think this should be done with a hook. */
032d78fe
GV
2794#ifdef HAVE_WINDOW_SYSTEM
2795 if (FRAME_WINDOW_P (f))
c7c70761 2796 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
fd0c2bd1 2797#endif
dc6f92b8
JB
2798
2799 return Qt;
2800}
dc6d9681 2801
dc6f92b8 2802\f
972f4259
KS
2803/***********************************************************************
2804 Frame Parameters
2805 ***********************************************************************/
2806
2807/* Connect the frame-parameter names for X frames
2808 to the ways of passing the parameter values to the window system.
2809
2810 The name of a parameter, as a Lisp symbol,
2811 has an `x-frame-parameter' property which is an integer in Lisp
2812 that is an index in this table. */
2813
2814struct frame_parm_table {
2815 char *name;
2816 Lisp_Object *variable;
2817};
2818
2819static struct frame_parm_table frame_parms[] =
2820{
2821 {"auto-raise", &Qauto_raise},
2822 {"auto-lower", &Qauto_lower},
2823 {"background-color", 0},
2824 {"border-color", &Qborder_color},
2825 {"border-width", &Qborder_width},
2826 {"cursor-color", &Qcursor_color},
2827 {"cursor-type", &Qcursor_type},
2828 {"font", 0},
2829 {"foreground-color", 0},
2830 {"icon-name", &Qicon_name},
2831 {"icon-type", &Qicon_type},
2832 {"internal-border-width", &Qinternal_border_width},
2833 {"menu-bar-lines", &Qmenu_bar_lines},
2834 {"mouse-color", &Qmouse_color},
2835 {"name", &Qname},
2836 {"scroll-bar-width", &Qscroll_bar_width},
2837 {"title", &Qtitle},
2838 {"unsplittable", &Qunsplittable},
2839 {"vertical-scroll-bars", &Qvertical_scroll_bars},
2840 {"visibility", &Qvisibility},
2841 {"tool-bar-lines", &Qtool_bar_lines},
2842 {"scroll-bar-foreground", &Qscroll_bar_foreground},
2843 {"scroll-bar-background", &Qscroll_bar_background},
2844 {"screen-gamma", &Qscreen_gamma},
2845 {"line-spacing", &Qline_spacing},
2846 {"left-fringe", &Qleft_fringe},
2847 {"right-fringe", &Qright_fringe},
2848 {"wait-for-wm", &Qwait_for_wm},
2849 {"fullscreen", &Qfullscreen},
0a708637 2850 {"font-backend", &Qfont_backend},
cad9ef74
JD
2851 {"alpha", &Qalpha},
2852 {"sticky", &Qsticky},
972f4259
KS
2853};
2854
2855#ifdef HAVE_WINDOW_SYSTEM
2856
2857extern Lisp_Object Qbox;
2858extern Lisp_Object Qtop;
2859
2860/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
bd45aef7 2861 wanted positions of the WM window (not Emacs window).
972f4259
KS
2862 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
2863 window (FRAME_X_WINDOW).
2864 */
2865
dfcf069d 2866void
972f4259
KS
2867x_fullscreen_adjust (f, width, height, top_pos, left_pos)
2868 struct frame *f;
2869 int *width;
2870 int *height;
2871 int *top_pos;
2872 int *left_pos;
dc6f92b8 2873{
5af5757b
KS
2874 int newwidth = FRAME_COLS (f);
2875 int newheight = FRAME_LINES (f);
05eb7cdc 2876 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
dc6f92b8 2877
5af5757b
KS
2878 *top_pos = f->top_pos;
2879 *left_pos = f->left_pos;
3df1fda2 2880
5af5757b 2881 if (f->want_fullscreen & FULLSCREEN_HEIGHT)
972f4259
KS
2882 {
2883 int ph;
2884
a0fe6cca 2885 ph = x_display_pixel_height (dpyinfo);
5af5757b
KS
2886 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
2887 ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
2888 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
972f4259
KS
2889 *top_pos = 0;
2890 }
dc6f92b8 2891
5af5757b 2892 if (f->want_fullscreen & FULLSCREEN_WIDTH)
972f4259
KS
2893 {
2894 int pw;
2895
a0fe6cca 2896 pw = x_display_pixel_width (dpyinfo);
5af5757b
KS
2897 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
2898 pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
2899 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
972f4259
KS
2900 *left_pos = 0;
2901 }
dc6f92b8 2902
972f4259
KS
2903 *width = newwidth;
2904 *height = newheight;
2905}
dc6f92b8 2906
beb0bc36 2907
972f4259
KS
2908/* Change the parameters of frame F as specified by ALIST.
2909 If a parameter is not specially recognized, do nothing special;
2910 otherwise call the `x_set_...' function for that parameter.
2911 Except for certain geometry properties, always call store_frame_param
2912 to store the new value in the parameter alist. */
14ff1ee0 2913
972f4259
KS
2914void
2915x_set_frame_parameters (f, alist)
2916 FRAME_PTR f;
2917 Lisp_Object alist;
2918{
2919 Lisp_Object tail;
dc6f92b8 2920
972f4259
KS
2921 /* If both of these parameters are present, it's more efficient to
2922 set them both at once. So we wait until we've looked at the
2923 entire list before we set them. */
2924 int width, height;
3df1fda2 2925
972f4259
KS
2926 /* Same here. */
2927 Lisp_Object left, top;
2928
2929 /* Same with these. */
2930 Lisp_Object icon_left, icon_top;
2931
2932 /* Record in these vectors all the parms specified. */
2933 Lisp_Object *parms;
2934 Lisp_Object *values;
2935 int i, p;
2936 int left_no_change = 0, top_no_change = 0;
2937 int icon_left_no_change = 0, icon_top_no_change = 0;
3f1c6666 2938 int size_changed = 0;
972f4259
KS
2939 struct gcpro gcpro1, gcpro2;
2940
2941 i = 0;
2942 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2943 i++;
2944
2945 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
2946 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
2947
2948 /* Extract parm names and values into those vectors. */
2949
2950 i = 0;
d7b10f4c 2951 for (tail = alist; CONSP (tail); tail = XCDR (tail))
972f4259
KS
2952 {
2953 Lisp_Object elt;
2954
d7b10f4c 2955 elt = XCAR (tail);
972f4259
KS
2956 parms[i] = Fcar (elt);
2957 values[i] = Fcdr (elt);
2958 i++;
2959 }
2960 /* TAIL and ALIST are not used again below here. */
2961 alist = tail = Qnil;
2962
2963 GCPRO2 (*parms, *values);
2964 gcpro1.nvars = i;
2965 gcpro2.nvars = i;
2966
2967 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
2968 because their values appear in VALUES and strings are not valid. */
2969 top = left = Qunbound;
2970 icon_left = icon_top = Qunbound;
2971
2972 /* Provide default values for HEIGHT and WIDTH. */
5af5757b
KS
2973 width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
2974 height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
972f4259
KS
2975
2976 /* Process foreground_color and background_color before anything else.
2977 They are independent of other properties, but other properties (e.g.,
2978 cursor_color) are dependent upon them. */
2979 /* Process default font as well, since fringe widths depends on it. */
972f4259
KS
2980 for (p = 0; p < i; p++)
2981 {
2982 Lisp_Object prop, val;
2983
2984 prop = parms[p];
2985 val = values[p];
2986 if (EQ (prop, Qforeground_color)
2987 || EQ (prop, Qbackground_color)
3f1c6666 2988 || EQ (prop, Qfont))
972f4259
KS
2989 {
2990 register Lisp_Object param_index, old_value;
2991
2992 old_value = get_frame_param (f, prop);
972f4259
KS
2993 if (NILP (Fequal (val, old_value)))
2994 {
2995 store_frame_param (f, prop, val);
2996
2997 param_index = Fget (prop, Qx_frame_parameter);
2998 if (NATNUMP (param_index)
2999 && (XFASTINT (param_index)
3000 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
3001 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3002 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
972f4259
KS
3003 }
3004 }
3005 }
3006
3007 /* Now process them in reverse of specified order. */
3008 for (i--; i >= 0; i--)
3009 {
3010 Lisp_Object prop, val;
3011
3012 prop = parms[i];
3013 val = values[i];
3014
629c715d 3015 if (EQ (prop, Qwidth) && NATNUMP (val))
3f1c6666
JD
3016 {
3017 size_changed = 1;
3018 width = XFASTINT (val);
3019 }
629c715d 3020 else if (EQ (prop, Qheight) && NATNUMP (val))
3f1c6666
JD
3021 {
3022 size_changed = 1;
3023 height = XFASTINT (val);
3024 }
972f4259
KS
3025 else if (EQ (prop, Qtop))
3026 top = val;
3027 else if (EQ (prop, Qleft))
3028 left = val;
3029 else if (EQ (prop, Qicon_top))
3030 icon_top = val;
3031 else if (EQ (prop, Qicon_left))
3032 icon_left = val;
3033 else if (EQ (prop, Qforeground_color)
3034 || EQ (prop, Qbackground_color)
3f1c6666 3035 || EQ (prop, Qfont))
972f4259
KS
3036 /* Processed above. */
3037 continue;
3038 else
3039 {
3040 register Lisp_Object param_index, old_value;
3041
3042 old_value = get_frame_param (f, prop);
3043
3044 store_frame_param (f, prop, val);
3045
3046 param_index = Fget (prop, Qx_frame_parameter);
3047 if (NATNUMP (param_index)
3048 && (XFASTINT (param_index)
3049 < sizeof (frame_parms)/sizeof (frame_parms[0]))
fa971ac3
KL
3050 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3051 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
972f4259
KS
3052 }
3053 }
3054
3055 /* Don't die if just one of these was set. */
3056 if (EQ (left, Qunbound))
3057 {
3058 left_no_change = 1;
5af5757b
KS
3059 if (f->left_pos < 0)
3060 left = Fcons (Qplus, Fcons (make_number (f->left_pos), Qnil));
972f4259 3061 else
5af5757b 3062 XSETINT (left, f->left_pos);
972f4259
KS
3063 }
3064 if (EQ (top, Qunbound))
3065 {
3066 top_no_change = 1;
5af5757b
KS
3067 if (f->top_pos < 0)
3068 top = Fcons (Qplus, Fcons (make_number (f->top_pos), Qnil));
972f4259 3069 else
5af5757b 3070 XSETINT (top, f->top_pos);
972f4259
KS
3071 }
3072
3073 /* If one of the icon positions was not set, preserve or default it. */
3074 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
3075 {
3076 icon_left_no_change = 1;
3077 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3078 if (NILP (icon_left))
3079 XSETINT (icon_left, 0);
3080 }
3081 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
3082 {
3083 icon_top_no_change = 1;
3084 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3085 if (NILP (icon_top))
3086 XSETINT (icon_top, 0);
3087 }
3088
972f4259
KS
3089 /* Don't set these parameters unless they've been explicitly
3090 specified. The window might be mapped or resized while we're in
3091 this function, and we don't want to override that unless the lisp
3092 code has asked for it.
3093
3094 Don't set these parameters unless they actually differ from the
3095 window's current parameters; the window may not actually exist
3096 yet. */
3097 {
3098 Lisp_Object frame;
3099
3100 check_frame_size (f, &height, &width);
3101
3102 XSETFRAME (frame, f);
3103
3f1c6666
JD
3104 if (size_changed
3105 && (width != FRAME_COLS (f)
3106 || height != FRAME_LINES (f)
3107 || f->new_text_lines || f->new_text_cols))
3108 Fset_frame_size (frame, make_number (width), make_number (height));
972f4259
KS
3109
3110 if ((!NILP (left) || !NILP (top))
3111 && ! (left_no_change && top_no_change)
5af5757b
KS
3112 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3113 && NUMBERP (top) && XINT (top) == f->top_pos))
972f4259
KS
3114 {
3115 int leftpos = 0;
3116 int toppos = 0;
3117
3118 /* Record the signs. */
5af5757b 3119 f->size_hint_flags &= ~ (XNegative | YNegative);
972f4259 3120 if (EQ (left, Qminus))
5af5757b 3121 f->size_hint_flags |= XNegative;
972f4259
KS
3122 else if (INTEGERP (left))
3123 {
3124 leftpos = XINT (left);
3125 if (leftpos < 0)
5af5757b 3126 f->size_hint_flags |= XNegative;
972f4259
KS
3127 }
3128 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3129 && CONSP (XCDR (left))
3130 && INTEGERP (XCAR (XCDR (left))))
3131 {
3132 leftpos = - XINT (XCAR (XCDR (left)));
5af5757b 3133 f->size_hint_flags |= XNegative;
972f4259
KS
3134 }
3135 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3136 && CONSP (XCDR (left))
3137 && INTEGERP (XCAR (XCDR (left))))
3138 {
3139 leftpos = XINT (XCAR (XCDR (left)));
3140 }
3141
3142 if (EQ (top, Qminus))
5af5757b 3143 f->size_hint_flags |= YNegative;
972f4259
KS
3144 else if (INTEGERP (top))
3145 {
3146 toppos = XINT (top);
3147 if (toppos < 0)
5af5757b 3148 f->size_hint_flags |= YNegative;
972f4259
KS
3149 }
3150 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3151 && CONSP (XCDR (top))
3152 && INTEGERP (XCAR (XCDR (top))))
3153 {
3154 toppos = - XINT (XCAR (XCDR (top)));
5af5757b 3155 f->size_hint_flags |= YNegative;
972f4259
KS
3156 }
3157 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3158 && CONSP (XCDR (top))
3159 && INTEGERP (XCAR (XCDR (top))))
3160 {
3161 toppos = XINT (XCAR (XCDR (top)));
3162 }
3163
3164
3165 /* Store the numeric value of the position. */
5af5757b
KS
3166 f->top_pos = toppos;
3167 f->left_pos = leftpos;
972f4259 3168
5af5757b 3169 f->win_gravity = NorthWestGravity;
972f4259
KS
3170
3171 /* Actually set that position, and convert to absolute. */
3172 x_set_offset (f, leftpos, toppos, -1);
3173 }
3174
3175 if ((!NILP (icon_left) || !NILP (icon_top))
3176 && ! (icon_left_no_change && icon_top_no_change))
3177 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3178 }
3179
3180 UNGCPRO;
3181}
3182
3183
3184/* Insert a description of internally-recorded parameters of frame X
3185 into the parameter alist *ALISTPTR that is to be given to the user.
3186 Only parameters that are specific to the X window system
3187 and whose values are not correctly recorded in the frame's
3188 param_alist need to be considered here. */
3189
3190void
3191x_report_frame_params (f, alistptr)
3192 struct frame *f;
3193 Lisp_Object *alistptr;
3194{
3195 char buf[16];
3196 Lisp_Object tem;
3197
3198 /* Represent negative positions (off the top or left screen edge)
3199 in a way that Fmodify_frame_parameters will understand correctly. */
5af5757b
KS
3200 XSETINT (tem, f->left_pos);
3201 if (f->left_pos >= 0)
972f4259
KS
3202 store_in_alist (alistptr, Qleft, tem);
3203 else
3204 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
3205
5af5757b
KS
3206 XSETINT (tem, f->top_pos);
3207 if (f->top_pos >= 0)
972f4259
KS
3208 store_in_alist (alistptr, Qtop, tem);
3209 else
3210 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
3211
3212 store_in_alist (alistptr, Qborder_width,
5af5757b 3213 make_number (f->border_width));
972f4259 3214 store_in_alist (alistptr, Qinternal_border_width,
5af5757b 3215 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
972f4259 3216 store_in_alist (alistptr, Qleft_fringe,
5af5757b 3217 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
972f4259 3218 store_in_alist (alistptr, Qright_fringe,
5af5757b 3219 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
972f4259
KS
3220 store_in_alist (alistptr, Qscroll_bar_width,
3221 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3222 ? make_number (0)
5af5757b
KS
3223 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
3224 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3225 /* nil means "use default width"
3226 for non-toolkit scroll bar.
3227 ruler-mode.el depends on this. */
3228 : Qnil));
3229 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
3230 store_in_alist (alistptr, Qwindow_id,
3231 build_string (buf));
3232#ifdef HAVE_X_WINDOWS
3233#ifdef USE_X_TOOLKIT
3234 /* Tooltip frame may not have this widget. */
3235 if (FRAME_X_OUTPUT (f)->widget)
3236#endif
3237 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
3238 store_in_alist (alistptr, Qouter_window_id,
3239 build_string (buf));
3240#endif
3241 store_in_alist (alistptr, Qicon_name, f->icon_name);
3242 FRAME_SAMPLE_VISIBILITY (f);
3243 store_in_alist (alistptr, Qvisibility,
3244 (FRAME_VISIBLE_P (f) ? Qt
3245 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
3246 store_in_alist (alistptr, Qdisplay,
3247 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
3248
3249 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
3250 tem = Qnil;
3251 else
3252 XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
5839d7e8 3253 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
972f4259
KS
3254 store_in_alist (alistptr, Qparent_id, tem);
3255}
3256
3257
3258/* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
3259 the previous value of that parameter, NEW_VALUE is the new value. */
3260
3261void
3262x_set_fullscreen (f, new_value, old_value)
3263 struct frame *f;
3264 Lisp_Object new_value, old_value;
3265{
972f4259 3266 if (NILP (new_value))
5af5757b 3267 f->want_fullscreen = FULLSCREEN_NONE;
3f1c6666 3268 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
5af5757b 3269 f->want_fullscreen = FULLSCREEN_BOTH;
972f4259 3270 else if (EQ (new_value, Qfullwidth))
5af5757b 3271 f->want_fullscreen = FULLSCREEN_WIDTH;
972f4259 3272 else if (EQ (new_value, Qfullheight))
5af5757b 3273 f->want_fullscreen = FULLSCREEN_HEIGHT;
3f1c6666
JD
3274 else if (EQ (new_value, Qmaximized))
3275 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
d761dd42 3276
a3547743 3277 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
974b73e8 3278 FRAME_TERMINAL (f)->fullscreen_hook (f);
972f4259
KS
3279}
3280
3281
3282/* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
3283 the previous value of that parameter, NEW_VALUE is the new value. */
3284
3285void
3286x_set_line_spacing (f, new_value, old_value)
3287 struct frame *f;
3288 Lisp_Object new_value, old_value;
3289{
3290 if (NILP (new_value))
3291 f->extra_line_spacing = 0;
3292 else if (NATNUMP (new_value))
3293 f->extra_line_spacing = XFASTINT (new_value);
3294 else
9dc95187 3295 signal_error ("Invalid line-spacing", new_value);
972f4259
KS
3296 if (FRAME_VISIBLE_P (f))
3297 redraw_frame (f);
3298}
3299
3300
3301/* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
3302 the previous value of that parameter, NEW_VALUE is the new value. */
3303
3304void
3305x_set_screen_gamma (f, new_value, old_value)
3306 struct frame *f;
3307 Lisp_Object new_value, old_value;
3308{
05fc2ef7
CY
3309 Lisp_Object bgcolor;
3310
972f4259
KS
3311 if (NILP (new_value))
3312 f->gamma = 0;
3313 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
05fc2ef7
CY
3314 /* The value 0.4545 is the normal viewing gamma. */
3315 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
972f4259 3316 else
9dc95187 3317 signal_error ("Invalid screen-gamma", new_value);
972f4259 3318
05fc2ef7
CY
3319 /* Apply the new gamma value to the frame background. */
3320 bgcolor = Fassq (Qbackground_color, f->param_alist);
3321 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
3322 {
3323 Lisp_Object index = Fget (Qbackground_color, Qx_frame_parameter);
3324 if (NATNUMP (index)
3325 && (XFASTINT (index)
3326 < sizeof (frame_parms)/sizeof (frame_parms[0]))
6baa22c1
KL
3327 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (index)])
3328 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (index)])
3329 (f, bgcolor, Qnil);
05fc2ef7
CY
3330 }
3331
3332 Fclear_face_cache (Qnil);
972f4259
KS
3333}
3334
3335
3336void
3337x_set_font (f, arg, oldval)
3338 struct frame *f;
3339 Lisp_Object arg, oldval;
3340{
472c3609 3341 Lisp_Object frame, font_object, lval;
e0c8ad78 3342 int fontset = -1;
972f4259 3343
178377e1 3344 /* Set the frame parameter back to the old value because we may
e0c8ad78
KH
3345 fail to use ARG as the new parameter value. */
3346 store_frame_param (f, Qfont, oldval);
0169d360 3347
d507f8d7
KH
3348 /* ARG is a fontset name, a font name, a cons of fontset name and a
3349 font object, or a font object. In the last case, this function
3350 never fail. */
e0c8ad78
KH
3351 if (STRINGP (arg))
3352 {
3353 fontset = fs_query_fontset (arg, 0);
3354 if (fontset < 0)
0169d360 3355 {
e0c8ad78
KH
3356 font_object = font_open_by_name (f, SDATA (arg));
3357 if (NILP (font_object))
3358 error ("Font `%s' is not defined", SDATA (arg));
3359 arg = AREF (font_object, FONT_NAME_INDEX);
0169d360 3360 }
e0c8ad78
KH
3361 else if (fontset > 0)
3362 {
3363 Lisp_Object ascii_font = fontset_ascii (fontset);
0169d360 3364
e0c8ad78
KH
3365 font_object = font_open_by_name (f, SDATA (ascii_font));
3366 if (NILP (font_object))
3367 error ("Font `%s' is not defined", SDATA (arg));
97d42150 3368 arg = AREF (font_object, FONT_NAME_INDEX);
e0c8ad78 3369 }
0169d360 3370 else
e0c8ad78 3371 error ("The default fontset can't be used for a frame font");
0169d360 3372 }
d507f8d7
KH
3373 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
3374 {
3375 /* This is the case that the ASCII font of F's fontset XCAR
3376 (arg) is changed to the font XCDR (arg) by
3377 `set-fontset-font'. */
3378 fontset = fs_query_fontset (XCAR (arg), 0);
3379 if (fontset < 0)
3380 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
3381 font_object = XCDR (arg);
3382 arg = AREF (font_object, FONT_NAME_INDEX);
3383 }
e0c8ad78 3384 else if (FONT_OBJECT_P (arg))
698ca23e 3385 {
e0c8ad78 3386 font_object = arg;
b17ae93a 3387 /* This is to store the XLFD font name in the frame parameter for
e0c8ad78
KH
3388 backward compatiblity. We should store the font-object
3389 itself in the future. */
3390 arg = AREF (font_object, FONT_NAME_INDEX);
b17ae93a 3391 fontset = FRAME_FONTSET (f);
518c4881
KH
3392 /* Check if we can use the current fontset. If not, set FONTSET
3393 to -1 to generate a new fontset from FONT-OBJECT. */
3394 if (fontset >= 0)
3395 {
3396 Lisp_Object ascii_font = fontset_ascii (fontset);
3397 Lisp_Object spec = font_spec_from_name (ascii_font);
3398
3399 if (! font_match_p (spec, font_object))
3400 fontset = -1;
3401 }
698ca23e 3402 }
e0c8ad78
KH
3403 else
3404 signal_error ("Invalid font", arg);
972f4259 3405
e0c8ad78
KH
3406 if (! NILP (Fequal (font_object, oldval)))
3407 return;
5a9aae2e
JD
3408
3409
472c3609 3410 lval = Fassq (Qfullscreen, f->param_alist);
5a9aae2e
JD
3411 if (CONSP (lval)) lval = CDR (lval);
3412
e0c8ad78
KH
3413 x_new_font (f, font_object, fontset);
3414 store_frame_param (f, Qfont, arg);
3415 /* Recalculate toolbar height. */
3416 f->n_tool_bar_rows = 0;
3417 /* Ensure we redraw it. */
3418 clear_current_matrices (f);
ca03f883 3419
e0c8ad78 3420 recompute_basic_faces (f);
972f4259
KS
3421
3422 do_pending_window_change (0);
3423
a6f75881
CY
3424 /* We used to call face-set-after-frame-default here, but it leads to
3425 recursive calls (since that function can set the `default' face's
3426 font which in turns changes the frame's `font' parameter).
3427 Also I don't know what this call is meant to do, but it seems the
3428 wrong way to do it anyway (it does a lot more work than what seems
3429 reasonable in response to a change to `font'). */
972f4259
KS
3430}
3431
3432
1a356571
KH
3433void
3434x_set_font_backend (f, new_value, old_value)
3435 struct frame *f;
3436 Lisp_Object new_value, old_value;
3437{
1a356571
KH
3438 if (! NILP (new_value)
3439 && !CONSP (new_value))
3440 {
3441 char *p0, *p1;
1bf72735 3442
1a356571
KH
3443 CHECK_STRING (new_value);
3444 p0 = p1 = SDATA (new_value);
3445 new_value = Qnil;
3446 while (*p0)
3447 {
22e64f7c 3448 while (*p1 && ! isspace (*p1) && *p1 != ',') p1++;
1a356571
KH
3449 if (p0 < p1)
3450 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
3451 new_value);
3452 if (*p1)
22e64f7c
KH
3453 {
3454 int c;
3455
3456 while ((c = *++p1) && isspace (c));
3457 }
1a356571
KH
3458 p0 = p1;
3459 }
8fb9e675
KH
3460 new_value = Fnreverse (new_value);
3461 }
3462
3463 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
3464 return;
3465
e0c8ad78 3466 if (FRAME_FONT (f))
dfdf55c0 3467 free_all_realized_faces (Qnil);
1a356571 3468
dfdf55c0 3469 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
8fb9e675 3470 if (NILP (new_value))
dfdf55c0
KH
3471 {
3472 if (NILP (old_value))
3473 error ("No font backend available");
3474 font_update_drivers (f, old_value);
3475 error ("None of specified font backends are available");
3476 }
8fb9e675
KH
3477 store_frame_param (f, Qfont_backend, new_value);
3478
e0c8ad78 3479 if (FRAME_FONT (f))
8fb9e675
KH
3480 {
3481 Lisp_Object frame;
3482
3483 XSETFRAME (frame, f);
3484 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
3485 ++face_change_count;
3486 ++windows_or_buffers_changed;
3487 }
1a356571 3488}
1a356571
KH
3489
3490
972f4259
KS
3491void
3492x_set_fringe_width (f, new_value, old_value)
3493 struct frame *f;
3494 Lisp_Object new_value, old_value;
3495{
3496 compute_fringe_widths (f, 1);
3497}
3498
3499void
3500x_set_border_width (f, arg, oldval)
3501 struct frame *f;
3502 Lisp_Object arg, oldval;
3503{
3504 CHECK_NUMBER (arg);
3505
5af5757b 3506 if (XINT (arg) == f->border_width)
972f4259
KS
3507 return;
3508
972f4259 3509 if (FRAME_X_WINDOW (f) != 0)
dac85f4b 3510 error ("Cannot change the border width of a frame");
972f4259 3511
5af5757b 3512 f->border_width = XINT (arg);
972f4259
KS
3513}
3514
3515void
3516x_set_internal_border_width (f, arg, oldval)
3517 struct frame *f;
3518 Lisp_Object arg, oldval;
3519{
5af5757b 3520 int old = FRAME_INTERNAL_BORDER_WIDTH (f);
972f4259
KS
3521
3522 CHECK_NUMBER (arg);
5af5757b
KS
3523 FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
3524 if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
3525 FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
972f4259
KS
3526
3527#ifdef USE_X_TOOLKIT
3528 if (FRAME_X_OUTPUT (f)->edit_widget)
3529 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
3530#endif
3531
5af5757b 3532 if (FRAME_INTERNAL_BORDER_WIDTH (f) == old)
972f4259
KS
3533 return;
3534
3535 if (FRAME_X_WINDOW (f) != 0)
3536 {
5af5757b 3537 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3538 SET_FRAME_GARBAGED (f);
3539 do_pending_window_change (0);
3540 }
3541 else
3542 SET_FRAME_GARBAGED (f);
3543}
3544
3545void
3546x_set_visibility (f, value, oldval)
3547 struct frame *f;
3548 Lisp_Object value, oldval;
3549{
3550 Lisp_Object frame;
3551 XSETFRAME (frame, f);
3552
3553 if (NILP (value))
3554 Fmake_frame_invisible (frame, Qt);
3555 else if (EQ (value, Qicon))
3556 Ficonify_frame (frame);
3557 else
3558 Fmake_frame_visible (frame);
3559}
3560
3561void
3562x_set_autoraise (f, arg, oldval)
3563 struct frame *f;
3564 Lisp_Object arg, oldval;
3565{
3566 f->auto_raise = !EQ (Qnil, arg);
3567}
3568
3569void
3570x_set_autolower (f, arg, oldval)
3571 struct frame *f;
3572 Lisp_Object arg, oldval;
3573{
3574 f->auto_lower = !EQ (Qnil, arg);
3575}
3576
3577void
3578x_set_unsplittable (f, arg, oldval)
3579 struct frame *f;
3580 Lisp_Object arg, oldval;
3581{
3582 f->no_split = !NILP (arg);
3583}
3584
3585void
3586x_set_vertical_scroll_bars (f, arg, oldval)
3587 struct frame *f;
3588 Lisp_Object arg, oldval;
3589{
3590 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3591 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
3592 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3593 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
3594 {
3595 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
3596 = (NILP (arg)
3597 ? vertical_scroll_bar_none
3598 : EQ (Qleft, arg)
3599 ? vertical_scroll_bar_left
3600 : EQ (Qright, arg)
3601 ? vertical_scroll_bar_right
6b61353c
KH
3602 : EQ (Qleft, Vdefault_frame_scroll_bars)
3603 ? vertical_scroll_bar_left
3604 : EQ (Qright, Vdefault_frame_scroll_bars)
3605 ? vertical_scroll_bar_right
3606 : vertical_scroll_bar_none);
972f4259
KS
3607
3608 /* We set this parameter before creating the X window for the
3609 frame, so we can get the geometry right from the start.
3610 However, if the window hasn't been created yet, we shouldn't
3611 call x_set_window_size. */
3612 if (FRAME_X_WINDOW (f))
5af5757b 3613 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3614 do_pending_window_change (0);
3615 }
3616}
3617
3618void
3619x_set_scroll_bar_width (f, arg, oldval)
3620 struct frame *f;
3621 Lisp_Object arg, oldval;
3622{
5af5757b 3623 int wid = FRAME_COLUMN_WIDTH (f);
972f4259
KS
3624
3625 if (NILP (arg))
3626 {
3627 x_set_scroll_bar_default_width (f);
3628
3629 if (FRAME_X_WINDOW (f))
5af5757b 3630 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3631 do_pending_window_change (0);
3632 }
3633 else if (INTEGERP (arg) && XINT (arg) > 0
5af5757b 3634 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3635 {
3636 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
3637 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
3638
5af5757b
KS
3639 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
3640 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
972f4259 3641 if (FRAME_X_WINDOW (f))
5af5757b 3642 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3643 do_pending_window_change (0);
3644 }
3645
5af5757b 3646 change_frame_size (f, 0, FRAME_COLS (f), 0, 0, 0);
972f4259
KS
3647 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3648 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3649}
3650
3651
3652
3653/* Return non-nil if frame F wants a bitmap icon. */
3654
3655Lisp_Object
3656x_icon_type (f)
3657 FRAME_PTR f;
3658{
3659 Lisp_Object tem;
3660
3661 tem = assq_no_quit (Qicon_type, f->param_alist);
3662 if (CONSP (tem))
3663 return XCDR (tem);
3664 else
3665 return Qnil;
3666}
3667
0a708637
GM
3668void
3669x_set_alpha (f, arg, oldval)
3670 struct frame *f;
3671 Lisp_Object arg, oldval;
3672{
3673 double alpha = 1.0;
3674 double newval[2];
3675 int i, ialpha;
3676 Lisp_Object item;
3677
3678 for (i = 0; i < 2; i++)
3679 {
3680 newval[i] = 1.0;
3681 if (CONSP (arg))
3682 {
3683 item = CAR (arg);
3684 arg = CDR (arg);
3685 }
3686 else
1fd877d6 3687 item = arg;
0a708637 3688
62e62ea8
CY
3689 if (NILP (item))
3690 alpha = - 1.0;
3691 else if (FLOATP (item))
3692 {
3693 alpha = XFLOAT_DATA (item);
3694 if (alpha < 0.0 || 1.0 < alpha)
3695 args_out_of_range (make_float (0.0), make_float (1.0));
3696 }
3697 else if (INTEGERP (item))
3698 {
3699 ialpha = XINT (item);
3700 if (ialpha < 0 || 100 < ialpha)
3701 args_out_of_range (make_number (0), make_number (100));
3702 else
3703 alpha = ialpha / 100.0;
3704 }
3705 else
3706 wrong_type_argument (Qnumberp, item);
0a708637
GM
3707 newval[i] = alpha;
3708 }
3709
3710 for (i = 0; i < 2; i++)
3711 f->alpha[i] = newval[i];
3712
59bc82c0 3713#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
0a708637
GM
3714 BLOCK_INPUT;
3715 x_set_frame_alpha (f);
3716 UNBLOCK_INPUT;
3717#endif
3718
3719 return;
3720}
3721
972f4259
KS
3722\f
3723/* Subroutines of creating an X frame. */
3724
3725/* Make sure that Vx_resource_name is set to a reasonable value.
3726 Fix it up, or set it to `emacs' if it is too hopeless. */
3727
3728void
3729validate_x_resource_name ()
3730{
3731 int len = 0;
3732 /* Number of valid characters in the resource name. */
3733 int good_count = 0;
3734 /* Number of invalid characters in the resource name. */
3735 int bad_count = 0;
3736 Lisp_Object new;
3737 int i;
3738
3739 if (!STRINGP (Vx_resource_class))
3740 Vx_resource_class = build_string (EMACS_CLASS);
3741
3742 if (STRINGP (Vx_resource_name))
3743 {
3744 unsigned char *p = SDATA (Vx_resource_name);
3745 int i;
3746
3747 len = SBYTES (Vx_resource_name);
3748
3749 /* Only letters, digits, - and _ are valid in resource names.
3750 Count the valid characters and count the invalid ones. */
3751 for (i = 0; i < len; i++)
3752 {
3753 int c = p[i];
3754 if (! ((c >= 'a' && c <= 'z')
3755 || (c >= 'A' && c <= 'Z')
3756 || (c >= '0' && c <= '9')
3757 || c == '-' || c == '_'))
3758 bad_count++;
3759 else
3760 good_count++;
3761 }
3762 }
3763 else
3764 /* Not a string => completely invalid. */
3765 bad_count = 5, good_count = 0;
3766
3767 /* If name is valid already, return. */
3768 if (bad_count == 0)
3769 return;
3770
3771 /* If name is entirely invalid, or nearly so, use `emacs'. */
3772 if (good_count == 0
3773 || (good_count == 1 && bad_count > 0))
3774 {
3775 Vx_resource_name = build_string ("emacs");
3776 return;
3777 }
3778
3779 /* Name is partly valid. Copy it and replace the invalid characters
3780 with underscores. */
3781
3782 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3783
3784 for (i = 0; i < len; i++)
3785 {
3786 int c = SREF (new, i);
3787 if (! ((c >= 'a' && c <= 'z')
3788 || (c >= 'A' && c <= 'Z')
3789 || (c >= '0' && c <= '9')
3790 || c == '-' || c == '_'))
3791 SSET (new, i, '_');
3792 }
3793}
3794
3795
3796extern char *x_get_string_resource P_ ((XrmDatabase, char *, char *));
3797extern Display_Info *check_x_display_info P_ ((Lisp_Object));
3798
3799
b5251fe7 3800/* Get specified attribute from resource database RDB.
972f4259
KS
3801 See Fx_get_resource below for other parameters. */
3802
3803static Lisp_Object
3804xrdb_get_resource (rdb, attribute, class, component, subclass)
3805 XrmDatabase rdb;
3806 Lisp_Object attribute, class, component, subclass;
3807{
3808 register char *value;
3809 char *name_key;
3810 char *class_key;
3811
3812 CHECK_STRING (attribute);
3813 CHECK_STRING (class);
3814
3815 if (!NILP (component))
3816 CHECK_STRING (component);
3817 if (!NILP (subclass))
3818 CHECK_STRING (subclass);
3819 if (NILP (component) != NILP (subclass))
3820 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3821
3822 validate_x_resource_name ();
3823
3824 /* Allocate space for the components, the dots which separate them,
3825 and the final '\0'. Make them big enough for the worst case. */
3826 name_key = (char *) alloca (SBYTES (Vx_resource_name)
3827 + (STRINGP (component)
3828 ? SBYTES (component) : 0)
3829 + SBYTES (attribute)
3830 + 3);
3831
3832 class_key = (char *) alloca (SBYTES (Vx_resource_class)
3833 + SBYTES (class)
3834 + (STRINGP (subclass)
3835 ? SBYTES (subclass) : 0)
3836 + 3);
3837
3838 /* Start with emacs.FRAMENAME for the name (the specific one)
3839 and with `Emacs' for the class key (the general one). */
3840 strcpy (name_key, SDATA (Vx_resource_name));
3841 strcpy (class_key, SDATA (Vx_resource_class));
3842
3843 strcat (class_key, ".");
3844 strcat (class_key, SDATA (class));
3845
3846 if (!NILP (component))
3847 {
3848 strcat (class_key, ".");
3849 strcat (class_key, SDATA (subclass));
3850
3851 strcat (name_key, ".");
3852 strcat (name_key, SDATA (component));
3853 }
3854
3855 strcat (name_key, ".");
3856 strcat (name_key, SDATA (attribute));
3857
3858 value = x_get_string_resource (rdb, name_key, class_key);
3859
3860 if (value != (char *) 0)
3861 return build_string (value);
3862 else
3863 return Qnil;
3864}
3865
3866
3867DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
3868 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
3869This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
3870class, where INSTANCE is the name under which Emacs was invoked, or
3871the name specified by the `-name' or `-rn' command-line arguments.
3872
3873The optional arguments COMPONENT and SUBCLASS add to the key and the
3874class, respectively. You must specify both of them or neither.
3875If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
3876and the class is `Emacs.CLASS.SUBCLASS'. */)
3877 (attribute, class, component, subclass)
3878 Lisp_Object attribute, class, component, subclass;
3879{
3880#ifdef HAVE_X_WINDOWS
3881 check_x ();
3882#endif
3883
3884 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
3885 attribute, class, component, subclass);
3886}
3887
3888/* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
3889
3890Lisp_Object
3891display_x_get_resource (dpyinfo, attribute, class, component, subclass)
a1702920 3892 Display_Info *dpyinfo;
972f4259
KS
3893 Lisp_Object attribute, class, component, subclass;
3894{
3895 return xrdb_get_resource (dpyinfo->xrdb,
3896 attribute, class, component, subclass);
3897}
3898
3899/* Used when C code wants a resource value. */
3900
3901char *
3902x_get_resource_string (attribute, class)
3903 char *attribute, *class;
3904{
3905 char *name_key;
3906 char *class_key;
3907 struct frame *sf = SELECTED_FRAME ();
3908
3909 /* Allocate space for the components, the dots which separate them,
3910 and the final '\0'. */
3911 name_key = (char *) alloca (SBYTES (Vinvocation_name)
3912 + strlen (attribute) + 2);
3913 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3914 + strlen (class) + 2);
3915
3916 sprintf (name_key, "%s.%s", SDATA (Vinvocation_name), attribute);
3917 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3918
3919 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
3920 name_key, class_key);
3921}
3922
3923
3924/* Return the value of parameter PARAM.
3925
3926 First search ALIST, then Vdefault_frame_alist, then the X defaults
3927 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3928
3929 Convert the resource to the type specified by desired_type.
3930
3931 If no default is specified, return Qunbound. If you call
3932 x_get_arg, make sure you deal with Qunbound in a reasonable way,
3933 and don't let it get stored in any Lisp-visible variables! */
3934
3935Lisp_Object
3936x_get_arg (dpyinfo, alist, param, attribute, class, type)
b5251fe7 3937 Display_Info *dpyinfo;
972f4259
KS
3938 Lisp_Object alist, param;
3939 char *attribute;
3940 char *class;
3941 enum resource_types type;
3942{
3943 register Lisp_Object tem;
3944
3945 tem = Fassq (param, alist);
d00368cf
RS
3946
3947 if (!NILP (tem))
3948 {
3949 /* If we find this parm in ALIST, clear it out
3950 so that it won't be "left over" at the end. */
5f694926 3951 Lisp_Object tail;
d00368cf 3952 XSETCAR (tem, Qnil);
5f694926
RS
3953 /* In case the parameter appears more than once in the alist,
3954 clear it out. */
3955 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3956 if (CONSP (XCAR (tail))
3957 && EQ (XCAR (XCAR (tail)), param))
3958 XSETCAR (XCAR (tail), Qnil);
d00368cf
RS
3959 }
3960 else
972f4259 3961 tem = Fassq (param, Vdefault_frame_alist);
d00368cf
RS
3962
3963 /* If it wasn't specified in ALIST or the Lisp-level defaults,
3964 look in the X resources. */
972f4259
KS
3965 if (EQ (tem, Qnil))
3966 {
4e23bedb 3967 if (attribute && dpyinfo)
972f4259
KS
3968 {
3969 tem = display_x_get_resource (dpyinfo,
3970 build_string (attribute),
3971 build_string (class),
3972 Qnil, Qnil);
3973
3974 if (NILP (tem))
3975 return Qunbound;
3976
3977 switch (type)
3978 {
3979 case RES_TYPE_NUMBER:
3980 return make_number (atoi (SDATA (tem)));
3981
3982 case RES_TYPE_FLOAT:
3983 return make_float (atof (SDATA (tem)));
3984
3985 case RES_TYPE_BOOLEAN:
3986 tem = Fdowncase (tem);
3987 if (!strcmp (SDATA (tem), "on")
edfda783
AR
3988#ifdef HAVE_NS
3989 || !strcmp(SDATA(tem), "yes")
3990#endif
972f4259
KS
3991 || !strcmp (SDATA (tem), "true"))
3992 return Qt;
3993 else
3994 return Qnil;
3995
3996 case RES_TYPE_STRING:
3997 return tem;
3998
3999 case RES_TYPE_SYMBOL:
4000 /* As a special case, we map the values `true' and `on'
4001 to Qt, and `false' and `off' to Qnil. */
4002 {
4003 Lisp_Object lower;
4004 lower = Fdowncase (tem);
4005 if (!strcmp (SDATA (lower), "on")
edfda783
AR
4006#ifdef HAVE_NS
4007 || !strcmp(SDATA(lower), "yes")
4008#endif
972f4259
KS
4009 || !strcmp (SDATA (lower), "true"))
4010 return Qt;
4011 else if (!strcmp (SDATA (lower), "off")
edfda783
AR
4012#ifdef HAVE_NS
4013 || !strcmp(SDATA(lower), "no")
4014#endif
972f4259
KS
4015 || !strcmp (SDATA (lower), "false"))
4016 return Qnil;
4017 else
4018 return Fintern (tem, Qnil);
4019 }
4020
4021 default:
4022 abort ();
4023 }
4024 }
4025 else
4026 return Qunbound;
4027 }
4028 return Fcdr (tem);
4029}
4030
4031Lisp_Object
4032x_frame_get_arg (f, alist, param, attribute, class, type)
4033 struct frame *f;
4034 Lisp_Object alist, param;
4035 char *attribute;
4036 char *class;
4037 enum resource_types type;
4038{
4039 return x_get_arg (FRAME_X_DISPLAY_INFO (f),
4040 alist, param, attribute, class, type);
4041}
4042
4043/* Like x_frame_get_arg, but also record the value in f->param_alist. */
4044
4045Lisp_Object
4046x_frame_get_and_record_arg (f, alist, param, attribute, class, type)
4047 struct frame *f;
4048 Lisp_Object alist, param;
4049 char *attribute;
4050 char *class;
4051 enum resource_types type;
4052{
4053 Lisp_Object value;
4054
4055 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
4056 attribute, class, type);
edd1c685 4057 if (! NILP (value) && ! EQ (value, Qunbound))
972f4259
KS
4058 store_frame_param (f, param, value);
4059
4060 return value;
4061}
4062
4063
4064/* Record in frame F the specified or default value according to ALIST
4065 of the parameter named PROP (a Lisp symbol).
4066 If no value is specified for PROP, look for an X default for XPROP
4067 on the frame named NAME.
4068 If that is not found either, use the value DEFLT. */
4069
4070Lisp_Object
4071x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
4072 struct frame *f;
4073 Lisp_Object alist;
4074 Lisp_Object prop;
4075 Lisp_Object deflt;
4076 char *xprop;
4077 char *xclass;
4078 enum resource_types type;
4079{
4080 Lisp_Object tem;
4081
4082 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
4083 if (EQ (tem, Qunbound))
4084 tem = deflt;
4085 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
4086 return tem;
4087}
4088
4089
4090
4091\f
dc4db71c
CY
4092#ifdef HAVE_NS
4093
4094/* We used to define x-parse-geometry directly in ns-win.el, but that
4095 confused make-docfile: the documentation string in ns-win.el was
4096 used for x-parse-geometry even in non-NS builds.. */
4097
4098DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
4099 doc: /* Parse a Nextstep-style geometry string STRING.
4100Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
4101The properties returned may include `top', `left', `height', and `width'.
4102This works by calling `ns-parse-geometry'. */)
4103 (string)
4104 Lisp_Object string;
4105{
4106 call1 (Qns_parse_geometry, string);
4107}
4108
4109#else /* !HAVE_NS */
4110
972f4259
KS
4111DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
4112 doc: /* Parse an X-style geometry string STRING.
4113Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
4114The properties returned may include `top', `left', `height', and `width'.
4115The value of `left' or `top' may be an integer,
4116or a list (+ N) meaning N pixels relative to top/left corner,
4117or a list (- N) meaning -N pixels relative to bottom/right corner. */)
4118 (string)
4119 Lisp_Object string;
4120{
4121 int geometry, x, y;
4122 unsigned int width, height;
4123 Lisp_Object result;
4124
4125 CHECK_STRING (string);
4126
4127 geometry = XParseGeometry ((char *) SDATA (string),
4128 &x, &y, &width, &height);
972f4259
KS
4129 result = Qnil;
4130 if (geometry & XValue)
4131 {
4132 Lisp_Object element;
4133
4134 if (x >= 0 && (geometry & XNegative))
4135 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
4136 else if (x < 0 && ! (geometry & XNegative))
4137 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
4138 else
4139 element = Fcons (Qleft, make_number (x));
4140 result = Fcons (element, result);
4141 }
4142
4143 if (geometry & YValue)
4144 {
4145 Lisp_Object element;
4146
4147 if (y >= 0 && (geometry & YNegative))
4148 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
4149 else if (y < 0 && ! (geometry & YNegative))
4150 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
4151 else
4152 element = Fcons (Qtop, make_number (y));
4153 result = Fcons (element, result);
4154 }
4155
4156 if (geometry & WidthValue)
4157 result = Fcons (Fcons (Qwidth, make_number (width)), result);
4158 if (geometry & HeightValue)
4159 result = Fcons (Fcons (Qheight, make_number (height)), result);
4160
4161 return result;
4162}
dc4db71c
CY
4163#endif /* HAVE_NS */
4164
972f4259
KS
4165
4166/* Calculate the desired size and position of frame F.
4167 Return the flags saying which aspects were specified.
4168
4169 Also set the win_gravity and size_hint_flags of F.
4170
4171 Adjust height for toolbar if TOOLBAR_P is 1.
4172
4173 This function does not make the coordinates positive. */
4174
4175#define DEFAULT_ROWS 40
4176#define DEFAULT_COLS 80
4177
4178int
4179x_figure_window_size (f, parms, toolbar_p)
4180 struct frame *f;
4181 Lisp_Object parms;
4182 int toolbar_p;
4183{
4184 register Lisp_Object tem0, tem1, tem2;
4185 long window_prompting = 0;
4186 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4187
4188 /* Default values if we fall through.
4189 Actually, if that happens we should get
4190 window manager prompting. */
5af5757b
KS
4191 SET_FRAME_COLS (f, DEFAULT_COLS);
4192 FRAME_LINES (f) = DEFAULT_ROWS;
972f4259
KS
4193 /* Window managers expect that if program-specified
4194 positions are not (0,0), they're intentional, not defaults. */
5af5757b
KS
4195 f->top_pos = 0;
4196 f->left_pos = 0;
972f4259 4197
5af5757b 4198 /* Ensure that old new_text_cols and new_text_lines will not override the
972f4259
KS
4199 values set here. */
4200 /* ++KFS: This was specific to W32, but seems ok for all platforms */
5af5757b 4201 f->new_text_cols = f->new_text_lines = 0;
972f4259
KS
4202
4203 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
4204 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
4205 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
4206 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
4207 {
4208 if (!EQ (tem0, Qunbound))
4209 {
4210 CHECK_NUMBER (tem0);
5af5757b 4211 FRAME_LINES (f) = XINT (tem0);
972f4259
KS
4212 }
4213 if (!EQ (tem1, Qunbound))
4214 {
4215 CHECK_NUMBER (tem1);
5af5757b 4216 SET_FRAME_COLS (f, XINT (tem1));
972f4259
KS
4217 }
4218 if (!NILP (tem2) && !EQ (tem2, Qunbound))
4219 window_prompting |= USSize;
4220 else
4221 window_prompting |= PSize;
4222 }
4223
5af5757b
KS
4224 f->scroll_bar_actual_width
4225 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
972f4259
KS
4226
4227 /* This used to be done _before_ calling x_figure_window_size, but
4228 since the height is reset here, this was really a no-op. I
4229 assume that moving it here does what Gerd intended (although he
4230 no longer can remember what that was... ++KFS, 2003-03-25. */
4231
4232 /* Add the tool-bar height to the initial frame height so that the
4233 user gets a text display area of the size he specified with -g or
4234 via .Xdefaults. Later changes of the tool-bar height don't
4235 change the frame size. This is done so that users can create
4236 tall Emacs frames without having to guess how tall the tool-bar
4237 will get. */
4238 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
4239 {
4240 int margin, relief, bar_height;
4241
4242 relief = (tool_bar_button_relief >= 0
4243 ? tool_bar_button_relief
4244 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4245
4246 if (INTEGERP (Vtool_bar_button_margin)
4247 && XINT (Vtool_bar_button_margin) > 0)
4248 margin = XFASTINT (Vtool_bar_button_margin);
4249 else if (CONSP (Vtool_bar_button_margin)
4250 && INTEGERP (XCDR (Vtool_bar_button_margin))
4251 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4252 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4253 else
4254 margin = 0;
4255
4256 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5af5757b 4257 FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
972f4259
KS
4258 }
4259
4260 compute_fringe_widths (f, 0);
4261
5af5757b
KS
4262 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, FRAME_COLS (f));
4263 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
972f4259
KS
4264
4265 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
4266 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
4267 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
4268 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
4269 {
4270 if (EQ (tem0, Qminus))
4271 {
5af5757b 4272 f->top_pos = 0;
972f4259
KS
4273 window_prompting |= YNegative;
4274 }
4275 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
4276 && CONSP (XCDR (tem0))
4277 && INTEGERP (XCAR (XCDR (tem0))))
4278 {
5af5757b 4279 f->top_pos = - XINT (XCAR (XCDR (tem0)));
972f4259
KS
4280 window_prompting |= YNegative;
4281 }
4282 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
4283 && CONSP (XCDR (tem0))
4284 && INTEGERP (XCAR (XCDR (tem0))))
4285 {
5af5757b 4286 f->top_pos = XINT (XCAR (XCDR (tem0)));
972f4259
KS
4287 }
4288 else if (EQ (tem0, Qunbound))
5af5757b 4289 f->top_pos = 0;
972f4259
KS
4290 else
4291 {
4292 CHECK_NUMBER (tem0);
5af5757b
KS
4293 f->top_pos = XINT (tem0);
4294 if (f->top_pos < 0)
972f4259
KS
4295 window_prompting |= YNegative;
4296 }
4297
4298 if (EQ (tem1, Qminus))
4299 {
5af5757b 4300 f->left_pos = 0;
972f4259
KS
4301 window_prompting |= XNegative;
4302 }
4303 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
4304 && CONSP (XCDR (tem1))
4305 && INTEGERP (XCAR (XCDR (tem1))))
4306 {
5af5757b 4307 f->left_pos = - XINT (XCAR (XCDR (tem1)));
972f4259
KS
4308 window_prompting |= XNegative;
4309 }
4310 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
4311 && CONSP (XCDR (tem1))
4312 && INTEGERP (XCAR (XCDR (tem1))))
4313 {
5af5757b 4314 f->left_pos = XINT (XCAR (XCDR (tem1)));
972f4259
KS
4315 }
4316 else if (EQ (tem1, Qunbound))
5af5757b 4317 f->left_pos = 0;
972f4259
KS
4318 else
4319 {
4320 CHECK_NUMBER (tem1);
5af5757b
KS
4321 f->left_pos = XINT (tem1);
4322 if (f->left_pos < 0)
972f4259
KS
4323 window_prompting |= XNegative;
4324 }
4325
4326 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
4327 window_prompting |= USPosition;
4328 else
4329 window_prompting |= PPosition;
4330 }
4331
972f4259
KS
4332 if (window_prompting & XNegative)
4333 {
4334 if (window_prompting & YNegative)
5af5757b 4335 f->win_gravity = SouthEastGravity;
972f4259 4336 else
5af5757b 4337 f->win_gravity = NorthEastGravity;
972f4259
KS
4338 }
4339 else
4340 {
4341 if (window_prompting & YNegative)
5af5757b 4342 f->win_gravity = SouthWestGravity;
972f4259 4343 else
5af5757b 4344 f->win_gravity = NorthWestGravity;
972f4259
KS
4345 }
4346
5af5757b 4347 f->size_hint_flags = window_prompting;
972f4259
KS
4348
4349 return window_prompting;
4350}
4351
4352
4353
4354#endif /* HAVE_WINDOW_SYSTEM */
4355
e044e4fc
JD
4356void
4357frame_make_pointer_invisible ()
4358{
4359 if (! NILP (Vmake_pointer_invisible))
4360 {
4361 struct frame *f = SELECTED_FRAME ();
4362 if (f && !f->pointer_invisible
4363 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4364 {
4365 f->mouse_moved = 0;
4366 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
4367 f->pointer_invisible = 1;
4368 }
4369 }
4370}
4371
4372void
4373frame_make_pointer_visible ()
4374{
4375 /* We don't check Vmake_pointer_invisible here in case the
4376 pointer was invisible when Vmake_pointer_invisible was set to nil. */
4377
4378 struct frame *f = SELECTED_FRAME ();
4379 if (f && f->pointer_invisible && f->mouse_moved
4380 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4381 {
4382 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
4383 f->pointer_invisible = 0;
4384 }
4385}
4386
972f4259
KS
4387
4388\f
4389/***********************************************************************
4390 Initialization
4391 ***********************************************************************/
4392
4393void
4394syms_of_frame ()
4395{
4396 Qframep = intern ("framep");
4397 staticpro (&Qframep);
4398 Qframe_live_p = intern ("frame-live-p");
4399 staticpro (&Qframe_live_p);
5839d7e8
MR
4400 Qexplicit_name = intern ("explicit-name");
4401 staticpro (&Qexplicit_name);
972f4259
KS
4402 Qheight = intern ("height");
4403 staticpro (&Qheight);
4404 Qicon = intern ("icon");
4405 staticpro (&Qicon);
4406 Qminibuffer = intern ("minibuffer");
4407 staticpro (&Qminibuffer);
4408 Qmodeline = intern ("modeline");
4409 staticpro (&Qmodeline);
4410 Qonly = intern ("only");
4411 staticpro (&Qonly);
4412 Qwidth = intern ("width");
4413 staticpro (&Qwidth);
4414 Qgeometry = intern ("geometry");
4415 staticpro (&Qgeometry);
4416 Qicon_left = intern ("icon-left");
4417 staticpro (&Qicon_left);
4418 Qicon_top = intern ("icon-top");
4419 staticpro (&Qicon_top);
4420 Qleft = intern ("left");
4421 staticpro (&Qleft);
4422 Qright = intern ("right");
4423 staticpro (&Qright);
4424 Quser_position = intern ("user-position");
4425 staticpro (&Quser_position);
4426 Quser_size = intern ("user-size");
4427 staticpro (&Quser_size);
4428 Qwindow_id = intern ("window-id");
4429 staticpro (&Qwindow_id);
4430#ifdef HAVE_X_WINDOWS
4431 Qouter_window_id = intern ("outer-window-id");
4432 staticpro (&Qouter_window_id);
4433#endif
4434 Qparent_id = intern ("parent-id");
4435 staticpro (&Qparent_id);
4436 Qx = intern ("x");
4437 staticpro (&Qx);
4438 Qw32 = intern ("w32");
4439 staticpro (&Qw32);
4440 Qpc = intern ("pc");
4441 staticpro (&Qpc);
4442 Qmac = intern ("mac");
4443 staticpro (&Qmac);
edfda783
AR
4444 Qns = intern ("ns");
4445 staticpro (&Qns);
972f4259
KS
4446 Qvisible = intern ("visible");
4447 staticpro (&Qvisible);
4448 Qbuffer_predicate = intern ("buffer-predicate");
4449 staticpro (&Qbuffer_predicate);
4450 Qbuffer_list = intern ("buffer-list");
4451 staticpro (&Qbuffer_list);
a18b8cb5
KL
4452 Qburied_buffer_list = intern ("buried-buffer-list");
4453 staticpro (&Qburied_buffer_list);
972f4259
KS
4454 Qdisplay_type = intern ("display-type");
4455 staticpro (&Qdisplay_type);
4456 Qbackground_mode = intern ("background-mode");
4457 staticpro (&Qbackground_mode);
c53956fe
SM
4458 Qnoelisp = intern ("noelisp");
4459 staticpro (&Qnoelisp);
972f4259
KS
4460 Qtty_color_mode = intern ("tty-color-mode");
4461 staticpro (&Qtty_color_mode);
28d440ab
KL
4462 Qtty = intern ("tty");
4463 staticpro (&Qtty);
4464 Qtty_type = intern ("tty-type");
4465 staticpro (&Qtty_type);
972f4259
KS
4466
4467 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
4468 staticpro (&Qface_set_after_frame_default);
4469
4470 Qfullwidth = intern ("fullwidth");
4471 staticpro (&Qfullwidth);
4472 Qfullheight = intern ("fullheight");
4473 staticpro (&Qfullheight);
4474 Qfullboth = intern ("fullboth");
4475 staticpro (&Qfullboth);
3f1c6666
JD
4476 Qmaximized = intern ("maximized");
4477 staticpro (&Qmaximized);
972f4259
KS
4478 Qx_resource_name = intern ("x-resource-name");
4479 staticpro (&Qx_resource_name);
4480
4481 Qx_frame_parameter = intern ("x-frame-parameter");
4482 staticpro (&Qx_frame_parameter);
4483
6ed8eeff
KL
4484 Qterminal = intern ("terminal");
4485 staticpro (&Qterminal);
4486 Qterminal_live_p = intern ("terminal-live-p");
4487 staticpro (&Qterminal_live_p);
a3547743 4488
dc4db71c
CY
4489#ifdef HAVE_NS
4490 Qns_parse_geometry = intern ("ns-parse-geometry");
4491 staticpro (&Qns_parse_geometry);
4492#endif
4493
972f4259
KS
4494 {
4495 int i;
4496
4497 for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++)
4498 {
4499 Lisp_Object v = intern (frame_parms[i].name);
4500 if (frame_parms[i].variable)
4501 {
4502 *frame_parms[i].variable = v;
4503 staticpro (frame_parms[i].variable);
4504 }
4505 Fput (v, Qx_frame_parameter, make_number (i));
4506 }
4507 }
4508
2731a0ad 4509#ifdef HAVE_WINDOW_SYSTEM
972f4259
KS
4510 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
4511 doc: /* The name Emacs uses to look up X resources.
4512`x-get-resource' uses this as the first component of the instance name
4513when requesting resource values.
4514Emacs initially sets `x-resource-name' to the name under which Emacs
4515was invoked, or to the value specified with the `-name' or `-rn'
4516switches, if present.
4517
4518It may be useful to bind this variable locally around a call
4519to `x-get-resource'. See also the variable `x-resource-class'. */);
4520 Vx_resource_name = Qnil;
4521
4522 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
4523 doc: /* The class Emacs uses to look up X resources.
4524`x-get-resource' uses this as the first component of the instance class
4525when requesting resource values.
4526
4527Emacs initially sets `x-resource-class' to "Emacs".
4528
4529Setting this variable permanently is not a reasonable thing to do,
4530but binding this variable locally around a call to `x-get-resource'
4531is a reasonable practice. See also the variable `x-resource-name'. */);
4532 Vx_resource_class = build_string (EMACS_CLASS);
0a708637
GM
4533
4534 DEFVAR_LISP ("frame-alpha-lower-limit", &Vframe_alpha_lower_limit,
4535 doc: /* The lower limit of the frame opacity (alpha transparency).
4536The value should range from 0 (invisible) to 100 (completely opaque).
4537You can also use a floating number between 0.0 and 1.0.
4538The default is 20. */);
4539 Vframe_alpha_lower_limit = make_number (20);
2731a0ad 4540#endif
972f4259
KS
4541
4542 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
4543 doc: /* Alist of default values for frame creation.
4544These may be set in your init file, like this:
5ff00c42 4545 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
972f4259
KS
4546These override values given in window system configuration data,
4547 including X Windows' defaults database.
4548For values specific to the first Emacs frame, see `initial-frame-alist'.
095fe281 4549For window-system specific values, see `window-system-default-frame-alist'.
972f4259
KS
4550For values specific to the separate minibuffer frame, see
4551 `minibuffer-frame-alist'.
4552The `menu-bar-lines' element of the list controls whether new frames
4553 have menu bars; `menu-bar-mode' works by altering this element.
4554Setting this variable does not affect existing frames, only new ones. */);
4555 Vdefault_frame_alist = Qnil;
4556
6b61353c
KH
4557 DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
4558 doc: /* Default position of scroll bars on this window-system. */);
4559#ifdef HAVE_WINDOW_SYSTEM
9e2a2647 4560#if defined(HAVE_NTGUI) || defined(NS_IMPL_COCOA)
edfda783 4561 /* MS-Windows and Mac OS X have scroll bars on the right by default. */
6b61353c
KH
4562 Vdefault_frame_scroll_bars = Qright;
4563#else
4564 Vdefault_frame_scroll_bars = Qleft;
4565#endif
4566#else
4567 Vdefault_frame_scroll_bars = Qnil;
4568#endif
4569
972f4259 4570 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
daf01701 4571 doc: /* The initial frame-object, which represents Emacs's stdout. */);
972f4259 4572
972f4259
KS
4573 DEFVAR_LISP ("mouse-position-function", &Vmouse_position_function,
4574 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4575`mouse-position' calls this function, passing its usual return value as
4576argument, and returns whatever this function returns.
4577This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4578which need to do mouse handling at the Lisp level. */);
4579 Vmouse_position_function = Qnil;
4580
4581 DEFVAR_LISP ("mouse-highlight", &Vmouse_highlight,
4582 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4583If the value is an integer, highlighting is only shown after moving the
4584mouse, while keyboard input turns off the highlight even when the mouse
4585is over the clickable text. However, the mouse shape still indicates
4586when the mouse is over clickable text. */);
4587 Vmouse_highlight = Qt;
4588
e044e4fc
JD
4589 DEFVAR_LISP ("make-pointer-invisible", &Vmake_pointer_invisible,
4590 doc: /* If non-nil, make pointer invisible while typing.
4591The pointer becomes visible again when the mouse is moved. */);
4592 Vmake_pointer_invisible = Qt;
4593
972f4259
KS
4594 DEFVAR_LISP ("delete-frame-functions", &Vdelete_frame_functions,
4595 doc: /* Functions to be run before deleting a frame.
4596The functions are run with one arg, the frame to be deleted.
e519a50b
KL
4597See `delete-frame'.
4598
58555d81
SM
4599Note that functions in this list may be called just before the frame is
4600actually deleted, or some time later (or even both when an earlier function
4601in `delete-frame-functions' (indirectly) calls `delete-frame'
4602recursively). */);
972f4259 4603 Vdelete_frame_functions = Qnil;
58555d81
SM
4604 Qdelete_frame_functions = intern ("delete-frame-functions");
4605 staticpro (&Qdelete_frame_functions);
972f4259
KS
4606
4607 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
4608 doc: /* Minibufferless frames use this frame's minibuffer.
4609
4610Emacs cannot create minibufferless frames unless this is set to an
4611appropriate surrogate.
4612
4613Emacs consults this variable only when creating minibufferless
4614frames; once the frame is created, it sticks with its assigned
4615minibuffer, no matter what this variable is set to. This means that
4616this variable doesn't necessarily say anything meaningful about the
4617current set of frames, or where the minibuffer is currently being
4618displayed.
4619
4620This variable is local to the current terminal and cannot be buffer-local. */);
4621
da1da002
MR
4622 DEFVAR_BOOL ("focus-follows-mouse", &focus_follows_mouse,
4623 doc: /* Non-nil if window system changes focus when you move the mouse.
4624You should set this variable to tell Emacs how your window manager
4625handles focus, since there is no way in general for Emacs to find out
4626automatically. */);
4627#ifdef HAVE_WINDOW_SYSTEM
9e2a2647 4628#if defined(HAVE_NTGUI) || defined(HAVE_NS)
da1da002
MR
4629 focus_follows_mouse = 0;
4630#else
4631 focus_follows_mouse = 1;
4632#endif
4633#else
4634 focus_follows_mouse = 0;
4635#endif
a3547743 4636
972f4259
KS
4637 staticpro (&Vframe_list);
4638
4639 defsubr (&Sactive_minibuffer_window);
4640 defsubr (&Sframep);
4641 defsubr (&Sframe_live_p);
428a555e 4642 defsubr (&Swindow_system);
972f4259
KS
4643 defsubr (&Smake_terminal_frame);
4644 defsubr (&Shandle_switch_frame);
972f4259
KS
4645 defsubr (&Sselect_frame);
4646 defsubr (&Sselected_frame);
4647 defsubr (&Swindow_frame);
4648 defsubr (&Sframe_root_window);
4649 defsubr (&Sframe_first_window);
4650 defsubr (&Sframe_selected_window);
4651 defsubr (&Sset_frame_selected_window);
4652 defsubr (&Sframe_list);
4653 defsubr (&Snext_frame);
4654 defsubr (&Sprevious_frame);
4655 defsubr (&Sdelete_frame);
4656 defsubr (&Smouse_position);
4657 defsubr (&Smouse_pixel_position);
4658 defsubr (&Sset_mouse_position);
4659 defsubr (&Sset_mouse_pixel_position);
4660#if 0
4661 defsubr (&Sframe_configuration);
4662 defsubr (&Srestore_frame_configuration);
4663#endif
4664 defsubr (&Smake_frame_visible);
4665 defsubr (&Smake_frame_invisible);
4666 defsubr (&Siconify_frame);
4667 defsubr (&Sframe_visible_p);
4668 defsubr (&Svisible_frame_list);
4669 defsubr (&Sraise_frame);
4670 defsubr (&Slower_frame);
4671 defsubr (&Sredirect_frame_focus);
4672 defsubr (&Sframe_focus);
4673 defsubr (&Sframe_parameters);
4674 defsubr (&Sframe_parameter);
4675 defsubr (&Smodify_frame_parameters);
4676 defsubr (&Sframe_char_height);
4677 defsubr (&Sframe_char_width);
4678 defsubr (&Sframe_pixel_height);
4679 defsubr (&Sframe_pixel_width);
4680 defsubr (&Sset_frame_height);
4681 defsubr (&Sset_frame_width);
4682 defsubr (&Sset_frame_size);
4683 defsubr (&Sset_frame_position);
4684
4685#ifdef HAVE_WINDOW_SYSTEM
4686 defsubr (&Sx_get_resource);
4687 defsubr (&Sx_parse_geometry);
4688#endif
4689
dc6f92b8 4690}
6b61353c
KH
4691
4692/* arch-tag: 7dbf2c69-9aad-45f8-8296-db893d6dd039
4693 (do not change this comment) */