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