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