(Qmonospace, Qsans_serif, Qserif, Qmono, Qsans)
[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
972f4259 3159 if (FRAME_X_WINDOW (f) != 0)
dac85f4b 3160 error ("Cannot change the border width of a frame");
972f4259 3161
5af5757b 3162 f->border_width = XINT (arg);
972f4259
KS
3163}
3164
3165void
3166x_set_internal_border_width (f, arg, oldval)
3167 struct frame *f;
3168 Lisp_Object arg, oldval;
3169{
5af5757b 3170 int old = FRAME_INTERNAL_BORDER_WIDTH (f);
972f4259
KS
3171
3172 CHECK_NUMBER (arg);
5af5757b
KS
3173 FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
3174 if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
3175 FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
972f4259
KS
3176
3177#ifdef USE_X_TOOLKIT
3178 if (FRAME_X_OUTPUT (f)->edit_widget)
3179 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
3180#endif
3181
5af5757b 3182 if (FRAME_INTERNAL_BORDER_WIDTH (f) == old)
972f4259
KS
3183 return;
3184
3185 if (FRAME_X_WINDOW (f) != 0)
3186 {
5af5757b 3187 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3188 SET_FRAME_GARBAGED (f);
3189 do_pending_window_change (0);
3190 }
3191 else
3192 SET_FRAME_GARBAGED (f);
3193}
3194
3195void
3196x_set_visibility (f, value, oldval)
3197 struct frame *f;
3198 Lisp_Object value, oldval;
3199{
3200 Lisp_Object frame;
3201 XSETFRAME (frame, f);
3202
3203 if (NILP (value))
3204 Fmake_frame_invisible (frame, Qt);
3205 else if (EQ (value, Qicon))
3206 Ficonify_frame (frame);
3207 else
3208 Fmake_frame_visible (frame);
3209}
3210
3211void
3212x_set_autoraise (f, arg, oldval)
3213 struct frame *f;
3214 Lisp_Object arg, oldval;
3215{
3216 f->auto_raise = !EQ (Qnil, arg);
3217}
3218
3219void
3220x_set_autolower (f, arg, oldval)
3221 struct frame *f;
3222 Lisp_Object arg, oldval;
3223{
3224 f->auto_lower = !EQ (Qnil, arg);
3225}
3226
3227void
3228x_set_unsplittable (f, arg, oldval)
3229 struct frame *f;
3230 Lisp_Object arg, oldval;
3231{
3232 f->no_split = !NILP (arg);
3233}
3234
3235void
3236x_set_vertical_scroll_bars (f, arg, oldval)
3237 struct frame *f;
3238 Lisp_Object arg, oldval;
3239{
3240 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3241 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
3242 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3243 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
3244 {
3245 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
3246 = (NILP (arg)
3247 ? vertical_scroll_bar_none
3248 : EQ (Qleft, arg)
3249 ? vertical_scroll_bar_left
3250 : EQ (Qright, arg)
3251 ? vertical_scroll_bar_right
6b61353c
KH
3252 : EQ (Qleft, Vdefault_frame_scroll_bars)
3253 ? vertical_scroll_bar_left
3254 : EQ (Qright, Vdefault_frame_scroll_bars)
3255 ? vertical_scroll_bar_right
3256 : vertical_scroll_bar_none);
972f4259
KS
3257
3258 /* We set this parameter before creating the X window for the
3259 frame, so we can get the geometry right from the start.
3260 However, if the window hasn't been created yet, we shouldn't
3261 call x_set_window_size. */
3262 if (FRAME_X_WINDOW (f))
5af5757b 3263 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3264 do_pending_window_change (0);
3265 }
3266}
3267
3268void
3269x_set_scroll_bar_width (f, arg, oldval)
3270 struct frame *f;
3271 Lisp_Object arg, oldval;
3272{
5af5757b 3273 int wid = FRAME_COLUMN_WIDTH (f);
972f4259
KS
3274
3275 if (NILP (arg))
3276 {
3277 x_set_scroll_bar_default_width (f);
3278
3279 if (FRAME_X_WINDOW (f))
5af5757b 3280 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3281 do_pending_window_change (0);
3282 }
3283 else if (INTEGERP (arg) && XINT (arg) > 0
5af5757b 3284 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
972f4259
KS
3285 {
3286 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
3287 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
3288
5af5757b
KS
3289 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
3290 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
972f4259 3291 if (FRAME_X_WINDOW (f))
5af5757b 3292 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
972f4259
KS
3293 do_pending_window_change (0);
3294 }
3295
5af5757b 3296 change_frame_size (f, 0, FRAME_COLS (f), 0, 0, 0);
972f4259
KS
3297 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3298 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3299}
3300
3301
3302
3303/* Return non-nil if frame F wants a bitmap icon. */
3304
3305Lisp_Object
3306x_icon_type (f)
3307 FRAME_PTR f;
3308{
3309 Lisp_Object tem;
3310
3311 tem = assq_no_quit (Qicon_type, f->param_alist);
3312 if (CONSP (tem))
3313 return XCDR (tem);
3314 else
3315 return Qnil;
3316}
3317
3318\f
3319/* Subroutines of creating an X frame. */
3320
3321/* Make sure that Vx_resource_name is set to a reasonable value.
3322 Fix it up, or set it to `emacs' if it is too hopeless. */
3323
3324void
3325validate_x_resource_name ()
3326{
3327 int len = 0;
3328 /* Number of valid characters in the resource name. */
3329 int good_count = 0;
3330 /* Number of invalid characters in the resource name. */
3331 int bad_count = 0;
3332 Lisp_Object new;
3333 int i;
3334
3335 if (!STRINGP (Vx_resource_class))
3336 Vx_resource_class = build_string (EMACS_CLASS);
3337
3338 if (STRINGP (Vx_resource_name))
3339 {
3340 unsigned char *p = SDATA (Vx_resource_name);
3341 int i;
3342
3343 len = SBYTES (Vx_resource_name);
3344
3345 /* Only letters, digits, - and _ are valid in resource names.
3346 Count the valid characters and count the invalid ones. */
3347 for (i = 0; i < len; i++)
3348 {
3349 int c = p[i];
3350 if (! ((c >= 'a' && c <= 'z')
3351 || (c >= 'A' && c <= 'Z')
3352 || (c >= '0' && c <= '9')
3353 || c == '-' || c == '_'))
3354 bad_count++;
3355 else
3356 good_count++;
3357 }
3358 }
3359 else
3360 /* Not a string => completely invalid. */
3361 bad_count = 5, good_count = 0;
3362
3363 /* If name is valid already, return. */
3364 if (bad_count == 0)
3365 return;
3366
3367 /* If name is entirely invalid, or nearly so, use `emacs'. */
3368 if (good_count == 0
3369 || (good_count == 1 && bad_count > 0))
3370 {
3371 Vx_resource_name = build_string ("emacs");
3372 return;
3373 }
3374
3375 /* Name is partly valid. Copy it and replace the invalid characters
3376 with underscores. */
3377
3378 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3379
3380 for (i = 0; i < len; i++)
3381 {
3382 int c = SREF (new, i);
3383 if (! ((c >= 'a' && c <= 'z')
3384 || (c >= 'A' && c <= 'Z')
3385 || (c >= '0' && c <= '9')
3386 || c == '-' || c == '_'))
3387 SSET (new, i, '_');
3388 }
3389}
3390
3391
3392extern char *x_get_string_resource P_ ((XrmDatabase, char *, char *));
3393extern Display_Info *check_x_display_info P_ ((Lisp_Object));
3394
3395
b5251fe7 3396/* Get specified attribute from resource database RDB.
972f4259
KS
3397 See Fx_get_resource below for other parameters. */
3398
3399static Lisp_Object
3400xrdb_get_resource (rdb, attribute, class, component, subclass)
3401 XrmDatabase rdb;
3402 Lisp_Object attribute, class, component, subclass;
3403{
3404 register char *value;
3405 char *name_key;
3406 char *class_key;
3407
3408 CHECK_STRING (attribute);
3409 CHECK_STRING (class);
3410
3411 if (!NILP (component))
3412 CHECK_STRING (component);
3413 if (!NILP (subclass))
3414 CHECK_STRING (subclass);
3415 if (NILP (component) != NILP (subclass))
3416 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3417
3418 validate_x_resource_name ();
3419
3420 /* Allocate space for the components, the dots which separate them,
3421 and the final '\0'. Make them big enough for the worst case. */
3422 name_key = (char *) alloca (SBYTES (Vx_resource_name)
3423 + (STRINGP (component)
3424 ? SBYTES (component) : 0)
3425 + SBYTES (attribute)
3426 + 3);
3427
3428 class_key = (char *) alloca (SBYTES (Vx_resource_class)
3429 + SBYTES (class)
3430 + (STRINGP (subclass)
3431 ? SBYTES (subclass) : 0)
3432 + 3);
3433
3434 /* Start with emacs.FRAMENAME for the name (the specific one)
3435 and with `Emacs' for the class key (the general one). */
3436 strcpy (name_key, SDATA (Vx_resource_name));
3437 strcpy (class_key, SDATA (Vx_resource_class));
3438
3439 strcat (class_key, ".");
3440 strcat (class_key, SDATA (class));
3441
3442 if (!NILP (component))
3443 {
3444 strcat (class_key, ".");
3445 strcat (class_key, SDATA (subclass));
3446
3447 strcat (name_key, ".");
3448 strcat (name_key, SDATA (component));
3449 }
3450
3451 strcat (name_key, ".");
3452 strcat (name_key, SDATA (attribute));
3453
3454 value = x_get_string_resource (rdb, name_key, class_key);
3455
3456 if (value != (char *) 0)
3457 return build_string (value);
3458 else
3459 return Qnil;
3460}
3461
3462
3463DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
3464 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
3465This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
3466class, where INSTANCE is the name under which Emacs was invoked, or
3467the name specified by the `-name' or `-rn' command-line arguments.
3468
3469The optional arguments COMPONENT and SUBCLASS add to the key and the
3470class, respectively. You must specify both of them or neither.
3471If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
3472and the class is `Emacs.CLASS.SUBCLASS'. */)
3473 (attribute, class, component, subclass)
3474 Lisp_Object attribute, class, component, subclass;
3475{
3476#ifdef HAVE_X_WINDOWS
3477 check_x ();
3478#endif
3479
3480 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
3481 attribute, class, component, subclass);
3482}
3483
3484/* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
3485
3486Lisp_Object
3487display_x_get_resource (dpyinfo, attribute, class, component, subclass)
a1702920 3488 Display_Info *dpyinfo;
972f4259
KS
3489 Lisp_Object attribute, class, component, subclass;
3490{
3491 return xrdb_get_resource (dpyinfo->xrdb,
3492 attribute, class, component, subclass);
3493}
3494
3495/* Used when C code wants a resource value. */
3496
3497char *
3498x_get_resource_string (attribute, class)
3499 char *attribute, *class;
3500{
3501 char *name_key;
3502 char *class_key;
3503 struct frame *sf = SELECTED_FRAME ();
3504
3505 /* Allocate space for the components, the dots which separate them,
3506 and the final '\0'. */
3507 name_key = (char *) alloca (SBYTES (Vinvocation_name)
3508 + strlen (attribute) + 2);
3509 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3510 + strlen (class) + 2);
3511
3512 sprintf (name_key, "%s.%s", SDATA (Vinvocation_name), attribute);
3513 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3514
3515 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
3516 name_key, class_key);
3517}
3518
3519
3520/* Return the value of parameter PARAM.
3521
3522 First search ALIST, then Vdefault_frame_alist, then the X defaults
3523 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3524
3525 Convert the resource to the type specified by desired_type.
3526
3527 If no default is specified, return Qunbound. If you call
3528 x_get_arg, make sure you deal with Qunbound in a reasonable way,
3529 and don't let it get stored in any Lisp-visible variables! */
3530
3531Lisp_Object
3532x_get_arg (dpyinfo, alist, param, attribute, class, type)
b5251fe7 3533 Display_Info *dpyinfo;
972f4259
KS
3534 Lisp_Object alist, param;
3535 char *attribute;
3536 char *class;
3537 enum resource_types type;
3538{
3539 register Lisp_Object tem;
3540
3541 tem = Fassq (param, alist);
d00368cf
RS
3542
3543 if (!NILP (tem))
3544 {
3545 /* If we find this parm in ALIST, clear it out
3546 so that it won't be "left over" at the end. */
58ec2913 3547#ifndef WINDOWSNT /* w32fns.c has not yet been changed to cope with this. */
5f694926 3548 Lisp_Object tail;
d00368cf 3549 XSETCAR (tem, Qnil);
5f694926
RS
3550 /* In case the parameter appears more than once in the alist,
3551 clear it out. */
3552 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3553 if (CONSP (XCAR (tail))
3554 && EQ (XCAR (XCAR (tail)), param))
3555 XSETCAR (XCAR (tail), Qnil);
d00368cf
RS
3556#endif
3557 }
3558 else
972f4259 3559 tem = Fassq (param, Vdefault_frame_alist);
d00368cf
RS
3560
3561 /* If it wasn't specified in ALIST or the Lisp-level defaults,
3562 look in the X resources. */
972f4259
KS
3563 if (EQ (tem, Qnil))
3564 {
3565 if (attribute)
3566 {
3567 tem = display_x_get_resource (dpyinfo,
3568 build_string (attribute),
3569 build_string (class),
3570 Qnil, Qnil);
3571
3572 if (NILP (tem))
3573 return Qunbound;
3574
3575 switch (type)
3576 {
3577 case RES_TYPE_NUMBER:
3578 return make_number (atoi (SDATA (tem)));
3579
3580 case RES_TYPE_FLOAT:
3581 return make_float (atof (SDATA (tem)));
3582
3583 case RES_TYPE_BOOLEAN:
3584 tem = Fdowncase (tem);
3585 if (!strcmp (SDATA (tem), "on")
3586 || !strcmp (SDATA (tem), "true"))
3587 return Qt;
3588 else
3589 return Qnil;
3590
3591 case RES_TYPE_STRING:
3592 return tem;
3593
3594 case RES_TYPE_SYMBOL:
3595 /* As a special case, we map the values `true' and `on'
3596 to Qt, and `false' and `off' to Qnil. */
3597 {
3598 Lisp_Object lower;
3599 lower = Fdowncase (tem);
3600 if (!strcmp (SDATA (lower), "on")
3601 || !strcmp (SDATA (lower), "true"))
3602 return Qt;
3603 else if (!strcmp (SDATA (lower), "off")
3604 || !strcmp (SDATA (lower), "false"))
3605 return Qnil;
3606 else
3607 return Fintern (tem, Qnil);
3608 }
3609
3610 default:
3611 abort ();
3612 }
3613 }
3614 else
3615 return Qunbound;
3616 }
3617 return Fcdr (tem);
3618}
3619
3620Lisp_Object
3621x_frame_get_arg (f, alist, param, attribute, class, type)
3622 struct frame *f;
3623 Lisp_Object alist, param;
3624 char *attribute;
3625 char *class;
3626 enum resource_types type;
3627{
3628 return x_get_arg (FRAME_X_DISPLAY_INFO (f),
3629 alist, param, attribute, class, type);
3630}
3631
3632/* Like x_frame_get_arg, but also record the value in f->param_alist. */
3633
3634Lisp_Object
3635x_frame_get_and_record_arg (f, alist, param, attribute, class, type)
3636 struct frame *f;
3637 Lisp_Object alist, param;
3638 char *attribute;
3639 char *class;
3640 enum resource_types type;
3641{
3642 Lisp_Object value;
3643
3644 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
3645 attribute, class, type);
edd1c685 3646 if (! NILP (value) && ! EQ (value, Qunbound))
972f4259
KS
3647 store_frame_param (f, param, value);
3648
3649 return value;
3650}
3651
3652
3653/* Record in frame F the specified or default value according to ALIST
3654 of the parameter named PROP (a Lisp symbol).
3655 If no value is specified for PROP, look for an X default for XPROP
3656 on the frame named NAME.
3657 If that is not found either, use the value DEFLT. */
3658
3659Lisp_Object
3660x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3661 struct frame *f;
3662 Lisp_Object alist;
3663 Lisp_Object prop;
3664 Lisp_Object deflt;
3665 char *xprop;
3666 char *xclass;
3667 enum resource_types type;
3668{
3669 Lisp_Object tem;
3670
3671 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
3672 if (EQ (tem, Qunbound))
3673 tem = deflt;
3674 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3675 return tem;
3676}
3677
3678
3679
3680\f
3681DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3682 doc: /* Parse an X-style geometry string STRING.
3683Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3684The properties returned may include `top', `left', `height', and `width'.
3685The value of `left' or `top' may be an integer,
3686or a list (+ N) meaning N pixels relative to top/left corner,
3687or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3688 (string)
3689 Lisp_Object string;
3690{
3691 int geometry, x, y;
3692 unsigned int width, height;
3693 Lisp_Object result;
3694
3695 CHECK_STRING (string);
3696
3697 geometry = XParseGeometry ((char *) SDATA (string),
3698 &x, &y, &width, &height);
3699
3700#if 0
3701 if (!!(geometry & XValue) != !!(geometry & YValue))
3702 error ("Must specify both x and y position, or neither");
3703#endif
3704
3705 result = Qnil;
3706 if (geometry & XValue)
3707 {
3708 Lisp_Object element;
3709
3710 if (x >= 0 && (geometry & XNegative))
3711 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3712 else if (x < 0 && ! (geometry & XNegative))
3713 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3714 else
3715 element = Fcons (Qleft, make_number (x));
3716 result = Fcons (element, result);
3717 }
3718
3719 if (geometry & YValue)
3720 {
3721 Lisp_Object element;
3722
3723 if (y >= 0 && (geometry & YNegative))
3724 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3725 else if (y < 0 && ! (geometry & YNegative))
3726 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3727 else
3728 element = Fcons (Qtop, make_number (y));
3729 result = Fcons (element, result);
3730 }
3731
3732 if (geometry & WidthValue)
3733 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3734 if (geometry & HeightValue)
3735 result = Fcons (Fcons (Qheight, make_number (height)), result);
3736
3737 return result;
3738}
3739
3740/* Calculate the desired size and position of frame F.
3741 Return the flags saying which aspects were specified.
3742
3743 Also set the win_gravity and size_hint_flags of F.
3744
3745 Adjust height for toolbar if TOOLBAR_P is 1.
3746
3747 This function does not make the coordinates positive. */
3748
3749#define DEFAULT_ROWS 40
3750#define DEFAULT_COLS 80
3751
3752int
3753x_figure_window_size (f, parms, toolbar_p)
3754 struct frame *f;
3755 Lisp_Object parms;
3756 int toolbar_p;
3757{
3758 register Lisp_Object tem0, tem1, tem2;
3759 long window_prompting = 0;
3760 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3761
3762 /* Default values if we fall through.
3763 Actually, if that happens we should get
3764 window manager prompting. */
5af5757b
KS
3765 SET_FRAME_COLS (f, DEFAULT_COLS);
3766 FRAME_LINES (f) = DEFAULT_ROWS;
972f4259
KS
3767 /* Window managers expect that if program-specified
3768 positions are not (0,0), they're intentional, not defaults. */
5af5757b
KS
3769 f->top_pos = 0;
3770 f->left_pos = 0;
972f4259 3771
5af5757b 3772 /* Ensure that old new_text_cols and new_text_lines will not override the
972f4259
KS
3773 values set here. */
3774 /* ++KFS: This was specific to W32, but seems ok for all platforms */
5af5757b 3775 f->new_text_cols = f->new_text_lines = 0;
972f4259
KS
3776
3777 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3778 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3779 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3780 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3781 {
3782 if (!EQ (tem0, Qunbound))
3783 {
3784 CHECK_NUMBER (tem0);
5af5757b 3785 FRAME_LINES (f) = XINT (tem0);
972f4259
KS
3786 }
3787 if (!EQ (tem1, Qunbound))
3788 {
3789 CHECK_NUMBER (tem1);
5af5757b 3790 SET_FRAME_COLS (f, XINT (tem1));
972f4259
KS
3791 }
3792 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3793 window_prompting |= USSize;
3794 else
3795 window_prompting |= PSize;
3796 }
3797
5af5757b
KS
3798 f->scroll_bar_actual_width
3799 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
972f4259
KS
3800
3801 /* This used to be done _before_ calling x_figure_window_size, but
3802 since the height is reset here, this was really a no-op. I
3803 assume that moving it here does what Gerd intended (although he
3804 no longer can remember what that was... ++KFS, 2003-03-25. */
3805
3806 /* Add the tool-bar height to the initial frame height so that the
3807 user gets a text display area of the size he specified with -g or
3808 via .Xdefaults. Later changes of the tool-bar height don't
3809 change the frame size. This is done so that users can create
3810 tall Emacs frames without having to guess how tall the tool-bar
3811 will get. */
3812 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
3813 {
3814 int margin, relief, bar_height;
3815
3816 relief = (tool_bar_button_relief >= 0
3817 ? tool_bar_button_relief
3818 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
3819
3820 if (INTEGERP (Vtool_bar_button_margin)
3821 && XINT (Vtool_bar_button_margin) > 0)
3822 margin = XFASTINT (Vtool_bar_button_margin);
3823 else if (CONSP (Vtool_bar_button_margin)
3824 && INTEGERP (XCDR (Vtool_bar_button_margin))
3825 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
3826 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
3827 else
3828 margin = 0;
3829
3830 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5af5757b 3831 FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
972f4259
KS
3832 }
3833
3834 compute_fringe_widths (f, 0);
3835
5af5757b
KS
3836 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, FRAME_COLS (f));
3837 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
972f4259
KS
3838
3839 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3840 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3841 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3842 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3843 {
3844 if (EQ (tem0, Qminus))
3845 {
5af5757b 3846 f->top_pos = 0;
972f4259
KS
3847 window_prompting |= YNegative;
3848 }
3849 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3850 && CONSP (XCDR (tem0))
3851 && INTEGERP (XCAR (XCDR (tem0))))
3852 {
5af5757b 3853 f->top_pos = - XINT (XCAR (XCDR (tem0)));
972f4259
KS
3854 window_prompting |= YNegative;
3855 }
3856 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3857 && CONSP (XCDR (tem0))
3858 && INTEGERP (XCAR (XCDR (tem0))))
3859 {
5af5757b 3860 f->top_pos = XINT (XCAR (XCDR (tem0)));
972f4259
KS
3861 }
3862 else if (EQ (tem0, Qunbound))
5af5757b 3863 f->top_pos = 0;
972f4259
KS
3864 else
3865 {
3866 CHECK_NUMBER (tem0);
5af5757b
KS
3867 f->top_pos = XINT (tem0);
3868 if (f->top_pos < 0)
972f4259
KS
3869 window_prompting |= YNegative;
3870 }
3871
3872 if (EQ (tem1, Qminus))
3873 {
5af5757b 3874 f->left_pos = 0;
972f4259
KS
3875 window_prompting |= XNegative;
3876 }
3877 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3878 && CONSP (XCDR (tem1))
3879 && INTEGERP (XCAR (XCDR (tem1))))
3880 {
5af5757b 3881 f->left_pos = - XINT (XCAR (XCDR (tem1)));
972f4259
KS
3882 window_prompting |= XNegative;
3883 }
3884 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3885 && CONSP (XCDR (tem1))
3886 && INTEGERP (XCAR (XCDR (tem1))))
3887 {
5af5757b 3888 f->left_pos = XINT (XCAR (XCDR (tem1)));
972f4259
KS
3889 }
3890 else if (EQ (tem1, Qunbound))
5af5757b 3891 f->left_pos = 0;
972f4259
KS
3892 else
3893 {
3894 CHECK_NUMBER (tem1);
5af5757b
KS
3895 f->left_pos = XINT (tem1);
3896 if (f->left_pos < 0)
972f4259
KS
3897 window_prompting |= XNegative;
3898 }
3899
3900 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3901 window_prompting |= USPosition;
3902 else
3903 window_prompting |= PPosition;
3904 }
3905
5af5757b 3906 if (f->want_fullscreen != FULLSCREEN_NONE)
972f4259
KS
3907 {
3908 int left, top;
3909 int width, height;
3910
3911 /* It takes both for some WM:s to place it where we want */
3912 window_prompting = USPosition | PPosition;
3913 x_fullscreen_adjust (f, &width, &height, &top, &left);
5af5757b
KS
3914 FRAME_COLS (f) = width;
3915 FRAME_LINES (f) = height;
3916 FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
3917 FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
3918 f->left_pos = left;
3919 f->top_pos = top;
972f4259
KS
3920 }
3921
3922 if (window_prompting & XNegative)
3923 {
3924 if (window_prompting & YNegative)
5af5757b 3925 f->win_gravity = SouthEastGravity;
972f4259 3926 else
5af5757b 3927 f->win_gravity = NorthEastGravity;
972f4259
KS
3928 }
3929 else
3930 {
3931 if (window_prompting & YNegative)
5af5757b 3932 f->win_gravity = SouthWestGravity;
972f4259 3933 else
5af5757b 3934 f->win_gravity = NorthWestGravity;
972f4259
KS
3935 }
3936
5af5757b 3937 f->size_hint_flags = window_prompting;
972f4259
KS
3938
3939 return window_prompting;
3940}
3941
3942
3943
3944#endif /* HAVE_WINDOW_SYSTEM */
3945
3946
3947\f
3948/***********************************************************************
3949 Initialization
3950 ***********************************************************************/
3951
3952void
3953syms_of_frame ()
3954{
3955 Qframep = intern ("framep");
3956 staticpro (&Qframep);
3957 Qframe_live_p = intern ("frame-live-p");
3958 staticpro (&Qframe_live_p);
3959 Qheight = intern ("height");
3960 staticpro (&Qheight);
3961 Qicon = intern ("icon");
3962 staticpro (&Qicon);
3963 Qminibuffer = intern ("minibuffer");
3964 staticpro (&Qminibuffer);
3965 Qmodeline = intern ("modeline");
3966 staticpro (&Qmodeline);
3967 Qonly = intern ("only");
3968 staticpro (&Qonly);
3969 Qwidth = intern ("width");
3970 staticpro (&Qwidth);
3971 Qgeometry = intern ("geometry");
3972 staticpro (&Qgeometry);
3973 Qicon_left = intern ("icon-left");
3974 staticpro (&Qicon_left);
3975 Qicon_top = intern ("icon-top");
3976 staticpro (&Qicon_top);
3977 Qleft = intern ("left");
3978 staticpro (&Qleft);
3979 Qright = intern ("right");
3980 staticpro (&Qright);
3981 Quser_position = intern ("user-position");
3982 staticpro (&Quser_position);
3983 Quser_size = intern ("user-size");
3984 staticpro (&Quser_size);
3985 Qwindow_id = intern ("window-id");
3986 staticpro (&Qwindow_id);
3987#ifdef HAVE_X_WINDOWS
3988 Qouter_window_id = intern ("outer-window-id");
3989 staticpro (&Qouter_window_id);
3990#endif
3991 Qparent_id = intern ("parent-id");
3992 staticpro (&Qparent_id);
3993 Qx = intern ("x");
3994 staticpro (&Qx);
3995 Qw32 = intern ("w32");
3996 staticpro (&Qw32);
3997 Qpc = intern ("pc");
3998 staticpro (&Qpc);
3999 Qmac = intern ("mac");
4000 staticpro (&Qmac);
4001 Qvisible = intern ("visible");
4002 staticpro (&Qvisible);
4003 Qbuffer_predicate = intern ("buffer-predicate");
4004 staticpro (&Qbuffer_predicate);
4005 Qbuffer_list = intern ("buffer-list");
4006 staticpro (&Qbuffer_list);
4007 Qdisplay_type = intern ("display-type");
4008 staticpro (&Qdisplay_type);
4009 Qbackground_mode = intern ("background-mode");
4010 staticpro (&Qbackground_mode);
4011 Qtty_color_mode = intern ("tty-color-mode");
4012 staticpro (&Qtty_color_mode);
4013
4014 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
4015 staticpro (&Qface_set_after_frame_default);
4016
4017 Qfullwidth = intern ("fullwidth");
4018 staticpro (&Qfullwidth);
4019 Qfullheight = intern ("fullheight");
4020 staticpro (&Qfullheight);
4021 Qfullboth = intern ("fullboth");
4022 staticpro (&Qfullboth);
4023 Qx_resource_name = intern ("x-resource-name");
4024 staticpro (&Qx_resource_name);
4025
4026 Qx_frame_parameter = intern ("x-frame-parameter");
4027 staticpro (&Qx_frame_parameter);
4028
4029 {
4030 int i;
4031
4032 for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++)
4033 {
4034 Lisp_Object v = intern (frame_parms[i].name);
4035 if (frame_parms[i].variable)
4036 {
4037 *frame_parms[i].variable = v;
4038 staticpro (frame_parms[i].variable);
4039 }
4040 Fput (v, Qx_frame_parameter, make_number (i));
4041 }
4042 }
4043
2731a0ad 4044#ifdef HAVE_WINDOW_SYSTEM
972f4259
KS
4045 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
4046 doc: /* The name Emacs uses to look up X resources.
4047`x-get-resource' uses this as the first component of the instance name
4048when requesting resource values.
4049Emacs initially sets `x-resource-name' to the name under which Emacs
4050was invoked, or to the value specified with the `-name' or `-rn'
4051switches, if present.
4052
4053It may be useful to bind this variable locally around a call
4054to `x-get-resource'. See also the variable `x-resource-class'. */);
4055 Vx_resource_name = Qnil;
4056
4057 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
4058 doc: /* The class Emacs uses to look up X resources.
4059`x-get-resource' uses this as the first component of the instance class
4060when requesting resource values.
4061
4062Emacs initially sets `x-resource-class' to "Emacs".
4063
4064Setting this variable permanently is not a reasonable thing to do,
4065but binding this variable locally around a call to `x-get-resource'
4066is a reasonable practice. See also the variable `x-resource-name'. */);
4067 Vx_resource_class = build_string (EMACS_CLASS);
2731a0ad 4068#endif
972f4259
KS
4069
4070 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
4071 doc: /* Alist of default values for frame creation.
4072These may be set in your init file, like this:
5ff00c42 4073 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
972f4259
KS
4074These override values given in window system configuration data,
4075 including X Windows' defaults database.
4076For values specific to the first Emacs frame, see `initial-frame-alist'.
4077For values specific to the separate minibuffer frame, see
4078 `minibuffer-frame-alist'.
4079The `menu-bar-lines' element of the list controls whether new frames
4080 have menu bars; `menu-bar-mode' works by altering this element.
4081Setting this variable does not affect existing frames, only new ones. */);
4082 Vdefault_frame_alist = Qnil;
4083
6b61353c
KH
4084 DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
4085 doc: /* Default position of scroll bars on this window-system. */);
4086#ifdef HAVE_WINDOW_SYSTEM
b15325b2 4087#if defined(HAVE_NTGUI) || defined(MAC_OS)
6b61353c
KH
4088 /* MS-Windows has scroll bars on the right by default. */
4089 Vdefault_frame_scroll_bars = Qright;
4090#else
4091 Vdefault_frame_scroll_bars = Qleft;
4092#endif
4093#else
4094 Vdefault_frame_scroll_bars = Qnil;
4095#endif
4096
972f4259
KS
4097 Qinhibit_default_face_x_resources
4098 = intern ("inhibit-default-face-x-resources");
4099 staticpro (&Qinhibit_default_face_x_resources);
4100
4101 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
4102 doc: /* The initial frame-object, which represents Emacs's stdout. */);
4103
4104 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
4105 doc: /* Non-nil if all of emacs is iconified and frame updates are not needed. */);
4106 Vemacs_iconified = Qnil;
4107
4108 DEFVAR_LISP ("mouse-position-function", &Vmouse_position_function,
4109 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4110`mouse-position' calls this function, passing its usual return value as
4111argument, and returns whatever this function returns.
4112This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4113which need to do mouse handling at the Lisp level. */);
4114 Vmouse_position_function = Qnil;
4115
4116 DEFVAR_LISP ("mouse-highlight", &Vmouse_highlight,
4117 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4118If the value is an integer, highlighting is only shown after moving the
4119mouse, while keyboard input turns off the highlight even when the mouse
4120is over the clickable text. However, the mouse shape still indicates
4121when the mouse is over clickable text. */);
4122 Vmouse_highlight = Qt;
4123
4124 DEFVAR_LISP ("delete-frame-functions", &Vdelete_frame_functions,
4125 doc: /* Functions to be run before deleting a frame.
4126The functions are run with one arg, the frame to be deleted.
4127See `delete-frame'. */);
4128 Vdelete_frame_functions = Qnil;
4129
4130 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
4131 doc: /* Minibufferless frames use this frame's minibuffer.
4132
4133Emacs cannot create minibufferless frames unless this is set to an
4134appropriate surrogate.
4135
4136Emacs consults this variable only when creating minibufferless
4137frames; once the frame is created, it sticks with its assigned
4138minibuffer, no matter what this variable is set to. This means that
4139this variable doesn't necessarily say anything meaningful about the
4140current set of frames, or where the minibuffer is currently being
4141displayed.
4142
4143This variable is local to the current terminal and cannot be buffer-local. */);
4144
4145 staticpro (&Vframe_list);
4146
4147 defsubr (&Sactive_minibuffer_window);
4148 defsubr (&Sframep);
4149 defsubr (&Sframe_live_p);
4150 defsubr (&Smake_terminal_frame);
4151 defsubr (&Shandle_switch_frame);
972f4259
KS
4152 defsubr (&Sselect_frame);
4153 defsubr (&Sselected_frame);
4154 defsubr (&Swindow_frame);
4155 defsubr (&Sframe_root_window);
4156 defsubr (&Sframe_first_window);
4157 defsubr (&Sframe_selected_window);
4158 defsubr (&Sset_frame_selected_window);
4159 defsubr (&Sframe_list);
4160 defsubr (&Snext_frame);
4161 defsubr (&Sprevious_frame);
4162 defsubr (&Sdelete_frame);
4163 defsubr (&Smouse_position);
4164 defsubr (&Smouse_pixel_position);
4165 defsubr (&Sset_mouse_position);
4166 defsubr (&Sset_mouse_pixel_position);
4167#if 0
4168 defsubr (&Sframe_configuration);
4169 defsubr (&Srestore_frame_configuration);
4170#endif
4171 defsubr (&Smake_frame_visible);
4172 defsubr (&Smake_frame_invisible);
4173 defsubr (&Siconify_frame);
4174 defsubr (&Sframe_visible_p);
4175 defsubr (&Svisible_frame_list);
4176 defsubr (&Sraise_frame);
4177 defsubr (&Slower_frame);
4178 defsubr (&Sredirect_frame_focus);
4179 defsubr (&Sframe_focus);
4180 defsubr (&Sframe_parameters);
4181 defsubr (&Sframe_parameter);
4182 defsubr (&Smodify_frame_parameters);
4183 defsubr (&Sframe_char_height);
4184 defsubr (&Sframe_char_width);
4185 defsubr (&Sframe_pixel_height);
4186 defsubr (&Sframe_pixel_width);
4187 defsubr (&Sset_frame_height);
4188 defsubr (&Sset_frame_width);
4189 defsubr (&Sset_frame_size);
4190 defsubr (&Sset_frame_position);
4191
4192#ifdef HAVE_WINDOW_SYSTEM
4193 defsubr (&Sx_get_resource);
4194 defsubr (&Sx_parse_geometry);
4195#endif
4196
dc6f92b8 4197}
6b61353c
KH
4198
4199/* arch-tag: 7dbf2c69-9aad-45f8-8296-db893d6dd039
4200 (do not change this comment) */