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