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