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