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