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