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