f8b086196f8d88a62dd0f4d09ae2e0af65c507fa
[bpt/emacs.git] / src / frame.c
1 /* Generic frame functions.
2 Copyright (C) 1993, 1994, 1995, 1997, 1999 Free Software Foundation.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include "lisp.h"
25 #include "charset.h"
26 #ifdef HAVE_X_WINDOWS
27 #include "xterm.h"
28 #endif
29 #include "frame.h"
30 #ifdef HAVE_WINDOW_SYSTEM
31 #include "fontset.h"
32 #endif
33 #include "termhooks.h"
34 #include "dispextern.h"
35 #include "window.h"
36 #ifdef MSDOS
37 #include "msdos.h"
38 #include "dosfns.h"
39 #endif
40
41 #ifdef macintosh
42 extern struct mac_output *NewMacWindow ();
43 extern void DisposeMacWindow (struct mac_output *);
44 #endif
45
46 /* Evaluate this expression to rebuild the section of syms_of_frame
47 that initializes and staticpros the symbols declared below. Note
48 that Emacs 18 has a bug that keeps C-x C-e from being able to
49 evaluate this expression.
50
51 (progn
52 ;; Accumulate a list of the symbols we want to initialize from the
53 ;; declarations at the top of the file.
54 (goto-char (point-min))
55 (search-forward "/\*&&& symbols declared here &&&*\/\n")
56 (let (symbol-list)
57 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
58 (setq symbol-list
59 (cons (buffer-substring (match-beginning 1) (match-end 1))
60 symbol-list))
61 (forward-line 1))
62 (setq symbol-list (nreverse symbol-list))
63 ;; Delete the section of syms_of_... where we initialize the symbols.
64 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
65 (let ((start (point)))
66 (while (looking-at "^ Q")
67 (forward-line 2))
68 (kill-region start (point)))
69 ;; Write a new symbol initialization section.
70 (while symbol-list
71 (insert (format " %s = intern (\"" (car symbol-list)))
72 (let ((start (point)))
73 (insert (substring (car symbol-list) 1))
74 (subst-char-in-region start (point) ?_ ?-))
75 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
76 (setq symbol-list (cdr symbol-list)))))
77 */
78
79 /*&&& symbols declared here &&&*/
80 Lisp_Object Qframep;
81 Lisp_Object Qframe_live_p;
82 Lisp_Object Qheight;
83 Lisp_Object Qicon;
84 Lisp_Object Qminibuffer;
85 Lisp_Object Qmodeline;
86 Lisp_Object Qname;
87 Lisp_Object Qonly;
88 Lisp_Object Qunsplittable;
89 Lisp_Object Qmenu_bar_lines;
90 Lisp_Object Qtool_bar_lines;
91 Lisp_Object Qwidth;
92 Lisp_Object Qx;
93 Lisp_Object Qw32;
94 Lisp_Object Qpc;
95 Lisp_Object Qmac;
96 Lisp_Object Qvisible;
97 Lisp_Object Qbuffer_predicate;
98 Lisp_Object Qbuffer_list;
99 Lisp_Object Qtitle;
100
101 Lisp_Object Vterminal_frame;
102 Lisp_Object Vdefault_frame_alist;
103
104 static void
105 syms_of_frame_1 ()
106 {
107 /*&&& init symbols here &&&*/
108 Qframep = intern ("framep");
109 staticpro (&Qframep);
110 Qframe_live_p = intern ("frame-live-p");
111 staticpro (&Qframe_live_p);
112 Qheight = intern ("height");
113 staticpro (&Qheight);
114 Qicon = intern ("icon");
115 staticpro (&Qicon);
116 Qminibuffer = intern ("minibuffer");
117 staticpro (&Qminibuffer);
118 Qmodeline = intern ("modeline");
119 staticpro (&Qmodeline);
120 Qname = intern ("name");
121 staticpro (&Qname);
122 Qonly = intern ("only");
123 staticpro (&Qonly);
124 Qunsplittable = intern ("unsplittable");
125 staticpro (&Qunsplittable);
126 Qmenu_bar_lines = intern ("menu-bar-lines");
127 staticpro (&Qmenu_bar_lines);
128 Qtool_bar_lines = intern ("tool-bar-lines");
129 staticpro (&Qtool_bar_lines);
130 Qwidth = intern ("width");
131 staticpro (&Qwidth);
132 Qx = intern ("x");
133 staticpro (&Qx);
134 Qw32 = intern ("w32");
135 staticpro (&Qw32);
136 Qpc = intern ("pc");
137 staticpro (&Qpc);
138 Qmac = intern ("mac");
139 staticpro (&Qmac);
140 Qvisible = intern ("visible");
141 staticpro (&Qvisible);
142 Qbuffer_predicate = intern ("buffer-predicate");
143 staticpro (&Qbuffer_predicate);
144 Qbuffer_list = intern ("buffer-list");
145 staticpro (&Qbuffer_list);
146 Qtitle = intern ("title");
147 staticpro (&Qtitle);
148
149 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
150 "Alist of default values for frame creation.\n\
151 These may be set in your init file, like this:\n\
152 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1))\n\
153 These override values given in window system configuration data,\n\
154 including X Windows' defaults database.\n\
155 For values specific to the first Emacs frame, see `initial-frame-alist'.\n\
156 For values specific to the separate minibuffer frame, see\n\
157 `minibuffer-frame-alist'.\n\
158 The `menu-bar-lines' element of the list controls whether new frames\n\
159 have menu bars; `menu-bar-mode' works by altering this element.");
160 Vdefault_frame_alist = Qnil;
161 }
162 \f
163 static void
164 set_menu_bar_lines_1 (window, n)
165 Lisp_Object window;
166 int n;
167 {
168 struct window *w = XWINDOW (window);
169
170 XSETFASTINT (w->last_modified, 0);
171 XSETFASTINT (w->top, XFASTINT (w->top) + n);
172 XSETFASTINT (w->height, XFASTINT (w->height) - n);
173
174 /* Handle just the top child in a vertical split. */
175 if (!NILP (w->vchild))
176 set_menu_bar_lines_1 (w->vchild, n);
177
178 /* Adjust all children in a horizontal split. */
179 for (window = w->hchild; !NILP (window); window = w->next)
180 {
181 w = XWINDOW (window);
182 set_menu_bar_lines_1 (window, n);
183 }
184 }
185
186 void
187 set_menu_bar_lines (f, value, oldval)
188 struct frame *f;
189 Lisp_Object value, oldval;
190 {
191 int nlines;
192 int olines = FRAME_MENU_BAR_LINES (f);
193
194 /* Right now, menu bars don't work properly in minibuf-only frames;
195 most of the commands try to apply themselves to the minibuffer
196 frame itself, and get an error because you can't switch buffers
197 in or split the minibuffer window. */
198 if (FRAME_MINIBUF_ONLY_P (f))
199 return;
200
201 if (INTEGERP (value))
202 nlines = XINT (value);
203 else
204 nlines = 0;
205
206 if (nlines != olines)
207 {
208 windows_or_buffers_changed++;
209 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
210 FRAME_MENU_BAR_LINES (f) = nlines;
211 set_menu_bar_lines_1 (f->root_window, nlines - olines);
212 adjust_glyphs (f);
213 }
214 }
215 \f
216 #include "buffer.h"
217
218 /* These help us bind and responding to switch-frame events. */
219 #include "commands.h"
220 #include "keyboard.h"
221
222 Lisp_Object Vemacs_iconified;
223 Lisp_Object Vframe_list;
224
225 struct x_output tty_display;
226
227 extern Lisp_Object Vminibuffer_list;
228 extern Lisp_Object get_minibuffer ();
229 extern Lisp_Object Fhandle_switch_frame ();
230 extern Lisp_Object Fredirect_frame_focus ();
231 extern Lisp_Object x_get_focus_frame ();
232 \f
233 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
234 "Return non-nil if OBJECT is a frame.\n\
235 Value is t for a termcap frame (a character-only terminal),\n\
236 `x' for an Emacs frame that is really an X window,\n\
237 `w32' for an Emacs frame that is a window on MS-Windows display,\n\
238 `mac' for an Emacs frame on a Macintosh display,\n\
239 `pc' for a direct-write MS-DOS frame.\n\
240 See also `frame-live-p'.")
241 (object)
242 Lisp_Object object;
243 {
244 if (!FRAMEP (object))
245 return Qnil;
246 switch (XFRAME (object)->output_method)
247 {
248 case output_termcap:
249 return Qt;
250 case output_x_window:
251 return Qx;
252 case output_w32:
253 return Qw32;
254 case output_msdos_raw:
255 return Qpc;
256 case output_mac:
257 return Qmac;
258 default:
259 abort ();
260 }
261 }
262
263 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
264 "Return non-nil if OBJECT is a frame which has not been deleted.\n\
265 Value is nil if OBJECT is not a live frame. If object is a live\n\
266 frame, the return value indicates what sort of output device it is\n\
267 displayed on. Value is t for a termcap frame (a character-only\n\
268 terminal), `x' for an Emacs frame being displayed in an X window.")
269 (object)
270 Lisp_Object object;
271 {
272 return ((FRAMEP (object)
273 && FRAME_LIVE_P (XFRAME (object)))
274 ? Fframep (object)
275 : Qnil);
276 }
277
278 struct frame *
279 make_frame (mini_p)
280 int mini_p;
281 {
282 Lisp_Object frame;
283 register struct frame *f;
284 register Lisp_Object root_window;
285 register Lisp_Object mini_window;
286 register struct Lisp_Vector *vec;
287 int i;
288
289 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct frame));
290 for (i = 0; i < VECSIZE (struct frame); i++)
291 XSETFASTINT (vec->contents[i], 0);
292 vec->size = VECSIZE (struct frame);
293 f = (struct frame *)vec;
294 XSETFRAME (frame, f);
295
296 f->desired_matrix = 0;
297 f->current_matrix = 0;
298 f->desired_pool = 0;
299 f->current_pool = 0;
300 f->glyphs_initialized_p = 0;
301 f->decode_mode_spec_buffer = 0;
302 f->visible = 0;
303 f->async_visible = 0;
304 f->output_data.nothing = 0;
305 f->iconified = 0;
306 f->async_iconified = 0;
307 f->wants_modeline = 1;
308 f->auto_raise = 0;
309 f->auto_lower = 0;
310 f->no_split = 0;
311 f->garbaged = 0;
312 f->has_minibuffer = mini_p;
313 f->focus_frame = Qnil;
314 f->explicit_name = 0;
315 f->can_have_scroll_bars = 0;
316 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
317 f->param_alist = Qnil;
318 f->scroll_bars = Qnil;
319 f->condemned_scroll_bars = Qnil;
320 f->face_alist = Qnil;
321 f->face_cache = NULL;
322 f->menu_bar_items = Qnil;
323 f->menu_bar_vector = Qnil;
324 f->menu_bar_items_used = 0;
325 f->buffer_predicate = Qnil;
326 f->buffer_list = Qnil;
327 #ifdef MULTI_KBOARD
328 f->kboard = initial_kboard;
329 #endif
330 f->namebuf = 0;
331 f->title = Qnil;
332 f->menu_bar_window = Qnil;
333 f->tool_bar_window = Qnil;
334 f->desired_tool_bar_items = f->current_tool_bar_items = Qnil;
335 f->desired_tool_bar_string = f->current_tool_bar_string = Qnil;
336 f->n_desired_tool_bar_items = f->n_current_tool_bar_items = 0;
337
338 root_window = make_window ();
339 if (mini_p)
340 {
341 mini_window = make_window ();
342 XWINDOW (root_window)->next = mini_window;
343 XWINDOW (mini_window)->prev = root_window;
344 XWINDOW (mini_window)->mini_p = Qt;
345 XWINDOW (mini_window)->frame = frame;
346 f->minibuffer_window = mini_window;
347 }
348 else
349 {
350 mini_window = Qnil;
351 XWINDOW (root_window)->next = Qnil;
352 f->minibuffer_window = Qnil;
353 }
354
355 XWINDOW (root_window)->frame = frame;
356
357 /* 10 is arbitrary,
358 just so that there is "something there."
359 Correct size will be set up later with change_frame_size. */
360
361 SET_FRAME_WIDTH (f, 10);
362 f->height = 10;
363
364 XSETFASTINT (XWINDOW (root_window)->width, 10);
365 XSETFASTINT (XWINDOW (root_window)->height, (mini_p ? 9 : 10));
366
367 if (mini_p)
368 {
369 XSETFASTINT (XWINDOW (mini_window)->width, 10);
370 XSETFASTINT (XWINDOW (mini_window)->top, 9);
371 XSETFASTINT (XWINDOW (mini_window)->height, 1);
372 }
373
374 /* Choose a buffer for the frame's root window. */
375 {
376 Lisp_Object buf;
377
378 XWINDOW (root_window)->buffer = Qt;
379 buf = Fcurrent_buffer ();
380 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
381 a space), try to find another one. */
382 if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
383 buf = Fother_buffer (buf, Qnil, Qnil);
384
385 /* Use set_window_buffer, not Fset_window_buffer, and don't let
386 hooks be run by it. The reason is that the whole frame/window
387 arrangement is not yet fully intialized at this point. Windows
388 don't have the right size, glyph matrices aren't initialized
389 etc. Running Lisp functions at this point surely ends in a
390 SEGV. */
391 set_window_buffer (root_window, buf, 0);
392 f->buffer_list = Fcons (buf, Qnil);
393 }
394
395 if (mini_p)
396 {
397 XWINDOW (mini_window)->buffer = Qt;
398 set_window_buffer (mini_window,
399 (NILP (Vminibuffer_list)
400 ? get_minibuffer (0)
401 : Fcar (Vminibuffer_list)),
402 0);
403 }
404
405 f->root_window = root_window;
406 f->selected_window = root_window;
407 /* Make sure this window seems more recently used than
408 a newly-created, never-selected window. */
409 XSETFASTINT (XWINDOW (f->selected_window)->use_time, ++window_select_count);
410
411 #ifdef HAVE_WINDOW_SYSTEM
412 f->fontset_data = alloc_fontset_data ();
413 #endif
414
415 return f;
416 }
417 \f
418 #ifdef HAVE_WINDOW_SYSTEM
419 /* Make a frame using a separate minibuffer window on another frame.
420 MINI_WINDOW is the minibuffer window to use. nil means use the
421 default (the global minibuffer). */
422
423 struct frame *
424 make_frame_without_minibuffer (mini_window, kb, display)
425 register Lisp_Object mini_window;
426 KBOARD *kb;
427 Lisp_Object display;
428 {
429 register struct frame *f;
430 struct gcpro gcpro1;
431
432 if (!NILP (mini_window))
433 CHECK_LIVE_WINDOW (mini_window, 0);
434
435 #ifdef MULTI_KBOARD
436 if (!NILP (mini_window)
437 && XFRAME (XWINDOW (mini_window)->frame)->kboard != kb)
438 error ("frame and minibuffer must be on the same display");
439 #endif
440
441 /* Make a frame containing just a root window. */
442 f = make_frame (0);
443
444 if (NILP (mini_window))
445 {
446 /* Use default-minibuffer-frame if possible. */
447 if (!FRAMEP (kb->Vdefault_minibuffer_frame)
448 || ! FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame)))
449 {
450 Lisp_Object frame_dummy;
451
452 XSETFRAME (frame_dummy, f);
453 GCPRO1 (frame_dummy);
454 /* If there's no minibuffer frame to use, create one. */
455 kb->Vdefault_minibuffer_frame =
456 call1 (intern ("make-initial-minibuffer-frame"), display);
457 UNGCPRO;
458 }
459
460 mini_window = XFRAME (kb->Vdefault_minibuffer_frame)->minibuffer_window;
461 }
462
463 f->minibuffer_window = mini_window;
464
465 /* Make the chosen minibuffer window display the proper minibuffer,
466 unless it is already showing a minibuffer. */
467 if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
468 Fset_window_buffer (mini_window,
469 (NILP (Vminibuffer_list)
470 ? get_minibuffer (0)
471 : Fcar (Vminibuffer_list)));
472 return f;
473 }
474
475 /* Make a frame containing only a minibuffer window. */
476
477 struct frame *
478 make_minibuffer_frame ()
479 {
480 /* First make a frame containing just a root window, no minibuffer. */
481
482 register struct frame *f = make_frame (0);
483 register Lisp_Object mini_window;
484 register Lisp_Object frame;
485
486 XSETFRAME (frame, f);
487
488 f->auto_raise = 0;
489 f->auto_lower = 0;
490 f->no_split = 1;
491 f->wants_modeline = 0;
492 f->has_minibuffer = 1;
493
494 /* Now label the root window as also being the minibuffer.
495 Avoid infinite looping on the window chain by marking next pointer
496 as nil. */
497
498 mini_window = f->minibuffer_window = f->root_window;
499 XWINDOW (mini_window)->mini_p = Qt;
500 XWINDOW (mini_window)->next = Qnil;
501 XWINDOW (mini_window)->prev = Qnil;
502 XWINDOW (mini_window)->frame = frame;
503
504 /* Put the proper buffer in that window. */
505
506 Fset_window_buffer (mini_window,
507 (NILP (Vminibuffer_list)
508 ? get_minibuffer (0)
509 : Fcar (Vminibuffer_list)));
510 return f;
511 }
512 #endif /* HAVE_WINDOW_SYSTEM */
513 \f
514 /* Construct a frame that refers to the terminal (stdin and stdout). */
515
516 static int terminal_frame_count;
517
518 struct frame *
519 make_terminal_frame ()
520 {
521 register struct frame *f;
522 Lisp_Object frame;
523 char name[20];
524
525 #ifdef MULTI_KBOARD
526 if (!initial_kboard)
527 {
528 initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
529 init_kboard (initial_kboard);
530 initial_kboard->next_kboard = all_kboards;
531 all_kboards = initial_kboard;
532 }
533 #endif
534
535 /* The first call must initialize Vframe_list. */
536 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
537 Vframe_list = Qnil;
538
539 f = make_frame (1);
540
541 XSETFRAME (frame, f);
542 Vframe_list = Fcons (frame, Vframe_list);
543
544 terminal_frame_count++;
545 sprintf (name, "F%d", terminal_frame_count);
546 f->name = build_string (name);
547
548 f->visible = 1; /* FRAME_SET_VISIBLE wd set frame_garbaged. */
549 f->async_visible = 1; /* Don't let visible be cleared later. */
550 #ifdef MSDOS
551 f->output_data.x = &the_only_x_display;
552 if (!inhibit_window_system
553 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
554 || XFRAME (selected_frame)->output_method == output_msdos_raw))
555 f->output_method = output_msdos_raw;
556 else
557 f->output_method = output_termcap;
558 #else
559 #ifdef macintosh
560 f->output_data.mac = NewMacWindow(f);
561 f->output_data.mac->background_pixel = 0xffffff;
562 f->output_data.mac->foreground_pixel = 0;
563 f->output_data.mac->n_param_faces = 0;
564 f->output_data.mac->n_computed_faces = 0;
565 f->output_data.mac->size_computed_faces = 0;
566 f->output_method = output_mac;
567 f->auto_raise = 1;
568 f->auto_lower = 1;
569 init_frame_faces (f);
570 #else /* !macintosh */
571 f->output_data.x = &tty_display;
572 #endif /* !macintosh */
573 #endif /* MSDOS */
574
575 #ifndef macintosh
576 if (!noninteractive)
577 init_frame_faces (f);
578 #endif
579 return f;
580 }
581
582 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
583 1, 1, 0, "Create an additional terminal frame.\n\
584 You can create multiple frames on a text-only terminal in this way.\n\
585 Only the selected terminal frame is actually displayed.\n\
586 This function takes one argument, an alist specifying frame parameters.\n\
587 In practice, generally you don't need to specify any parameters.\n\
588 Note that changing the size of one terminal frame automatically affects all.")
589 (parms)
590 Lisp_Object parms;
591 {
592 struct frame *f;
593 Lisp_Object frame, tem;
594 struct frame *sf = SELECTED_FRAME ();
595
596 #ifdef MSDOS
597 if (sf->output_method != output_msdos_raw
598 && sf->output_method != output_termcap)
599 abort ();
600 #else /* not MSDOS */
601
602 #ifdef macintosh
603 if (sf->output_method != output_mac)
604 error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
605 #else
606 if (sf->output_method != output_termcap)
607 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
608 #endif
609 #endif /* not MSDOS */
610
611 f = make_terminal_frame ();
612
613 change_frame_size (f, FRAME_HEIGHT (sf),
614 FRAME_WIDTH (sf), 0, 0, 0);
615 adjust_glyphs (f);
616 calculate_costs (f);
617 XSETFRAME (frame, f);
618 Fmodify_frame_parameters (frame, Vdefault_frame_alist);
619 Fmodify_frame_parameters (frame, parms);
620
621 /* Make the frame face alist be frame-specific, so that each
622 frame could change its face definitions independently. */
623 f->face_alist = Fcopy_alist (sf->face_alist);
624 /* Simple Fcopy_alist isn't enough, because we need the contents of
625 the vectors which are the CDRs of associations in face_alist to
626 be copied as well. */
627 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
628 XCDR (XCAR (tem)) = Fcopy_sequence (XCDR (XCAR (tem)));
629 return frame;
630 }
631 \f
632 Lisp_Object
633 do_switch_frame (frame, no_enter, track)
634 Lisp_Object frame, no_enter;
635 int track;
636 {
637 struct frame *sf = SELECTED_FRAME ();
638
639 /* If FRAME is a switch-frame event, extract the frame we should
640 switch to. */
641 if (CONSP (frame)
642 && EQ (XCAR (frame), Qswitch_frame)
643 && CONSP (XCDR (frame)))
644 frame = XCAR (XCDR (frame));
645
646 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
647 a switch-frame event to arrive after a frame is no longer live,
648 especially when deleting the initial frame during startup. */
649 CHECK_FRAME (frame, 0);
650 if (! FRAME_LIVE_P (XFRAME (frame)))
651 return Qnil;
652
653 if (sf == XFRAME (frame))
654 return frame;
655
656 /* This is too greedy; it causes inappropriate focus redirection
657 that's hard to get rid of. */
658 #if 0
659 /* If a frame's focus has been redirected toward the currently
660 selected frame, we should change the redirection to point to the
661 newly selected frame. This means that if the focus is redirected
662 from a minibufferless frame to a surrogate minibuffer frame, we
663 can use `other-window' to switch between all the frames using
664 that minibuffer frame, and the focus redirection will follow us
665 around. */
666 if (track)
667 {
668 Lisp_Object tail;
669
670 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
671 {
672 Lisp_Object focus;
673
674 if (!FRAMEP (XCAR (tail)))
675 abort ();
676
677 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
678
679 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
680 Fredirect_frame_focus (XCAR (tail), frame);
681 }
682 }
683 #else /* ! 0 */
684 /* Instead, apply it only to the frame we're pointing to. */
685 #ifdef HAVE_WINDOW_SYSTEM
686 if (track && (FRAME_WINDOW_P (XFRAME (frame))))
687 {
688 Lisp_Object focus, xfocus;
689
690 xfocus = x_get_focus_frame (XFRAME (frame));
691 if (FRAMEP (xfocus))
692 {
693 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
694 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
695 Fredirect_frame_focus (xfocus, frame);
696 }
697 }
698 #endif /* HAVE_X_WINDOWS */
699 #endif /* ! 0 */
700
701 selected_frame = frame;
702 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
703 last_nonminibuf_frame = XFRAME (selected_frame);
704
705 Fselect_window (XFRAME (frame)->selected_window);
706
707 /* We want to make sure that the next event generates a frame-switch
708 event to the appropriate frame. This seems kludgy to me, but
709 before you take it out, make sure that evaluating something like
710 (select-window (frame-root-window (new-frame))) doesn't end up
711 with your typing being interpreted in the new frame instead of
712 the one you're actually typing in. */
713 internal_last_event_frame = Qnil;
714
715 return frame;
716 }
717
718 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
719 "Select the frame FRAME.\n\
720 Subsequent editing commands apply to its selected window.\n\
721 The selection of FRAME lasts until the next time the user does\n\
722 something to select a different frame, or until the next time this\n\
723 function is called.")
724 (frame, no_enter)
725 Lisp_Object frame, no_enter;
726 {
727 return do_switch_frame (frame, no_enter, 1);
728 }
729
730
731 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
732 "Handle a switch-frame event EVENT.\n\
733 Switch-frame events are usually bound to this function.\n\
734 A switch-frame event tells Emacs that the window manager has requested\n\
735 that the user's events be directed to the frame mentioned in the event.\n\
736 This function selects the selected window of the frame of EVENT.\n\
737 \n\
738 If EVENT is frame object, handle it as if it were a switch-frame event\n\
739 to that frame.")
740 (event, no_enter)
741 Lisp_Object event, no_enter;
742 {
743 /* Preserve prefix arg that the command loop just cleared. */
744 current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
745 call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
746 return do_switch_frame (event, no_enter, 0);
747 }
748
749 DEFUN ("ignore-event", Fignore_event, Signore_event, 0, 0, "",
750 "Do nothing, but preserve any prefix argument already specified.\n\
751 This is a suitable binding for iconify-frame and make-frame-visible.")
752 ()
753 {
754 current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
755 return Qnil;
756 }
757
758 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
759 "Return the frame that is now selected.")
760 ()
761 {
762 return selected_frame;
763 }
764 \f
765 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
766 "Return the frame object that window WINDOW is on.")
767 (window)
768 Lisp_Object window;
769 {
770 CHECK_LIVE_WINDOW (window, 0);
771 return XWINDOW (window)->frame;
772 }
773
774 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
775 "Returns the topmost, leftmost window of FRAME.\n\
776 If omitted, FRAME defaults to the currently selected frame.")
777 (frame)
778 Lisp_Object frame;
779 {
780 Lisp_Object w;
781
782 if (NILP (frame))
783 w = SELECTED_FRAME ()->root_window;
784 else
785 {
786 CHECK_LIVE_FRAME (frame, 0);
787 w = XFRAME (frame)->root_window;
788 }
789 while (NILP (XWINDOW (w)->buffer))
790 {
791 if (! NILP (XWINDOW (w)->hchild))
792 w = XWINDOW (w)->hchild;
793 else if (! NILP (XWINDOW (w)->vchild))
794 w = XWINDOW (w)->vchild;
795 else
796 abort ();
797 }
798 return w;
799 }
800
801 DEFUN ("active-minibuffer-window", Factive_minibuffer_window,
802 Sactive_minibuffer_window, 0, 0, 0,
803 "Return the currently active minibuffer window, or nil if none.")
804 ()
805 {
806 return minibuf_level ? minibuf_window : Qnil;
807 }
808
809 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
810 "Returns the root-window of FRAME.\n\
811 If omitted, FRAME defaults to the currently selected frame.")
812 (frame)
813 Lisp_Object frame;
814 {
815 Lisp_Object window;
816
817 if (NILP (frame))
818 window = SELECTED_FRAME ()->root_window;
819 else
820 {
821 CHECK_LIVE_FRAME (frame, 0);
822 window = XFRAME (frame)->root_window;
823 }
824
825 return window;
826 }
827
828 DEFUN ("frame-selected-window", Fframe_selected_window,
829 Sframe_selected_window, 0, 1, 0,
830 "Return the selected window of frame object FRAME.\n\
831 If omitted, FRAME defaults to the currently selected frame.")
832 (frame)
833 Lisp_Object frame;
834 {
835 Lisp_Object window;
836
837 if (NILP (frame))
838 window = SELECTED_FRAME ()->selected_window;
839 else
840 {
841 CHECK_LIVE_FRAME (frame, 0);
842 window = XFRAME (frame)->selected_window;
843 }
844
845 return window;
846 }
847
848 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
849 Sset_frame_selected_window, 2, 2, 0,
850 "Set the selected window of frame object FRAME to WINDOW.\n\
851 If FRAME is nil, the selected frame is used.\n\
852 If FRAME is the selected frame, this makes WINDOW the selected window.")
853 (frame, window)
854 Lisp_Object frame, window;
855 {
856 if (NILP (frame))
857 frame = selected_frame;
858
859 CHECK_LIVE_FRAME (frame, 0);
860 CHECK_LIVE_WINDOW (window, 1);
861
862 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
863 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
864
865 if (EQ (frame, selected_frame))
866 return Fselect_window (window);
867
868 return XFRAME (frame)->selected_window = window;
869 }
870 \f
871 DEFUN ("frame-list", Fframe_list, Sframe_list,
872 0, 0, 0,
873 "Return a list of all frames.")
874 ()
875 {
876 return Fcopy_sequence (Vframe_list);
877 }
878
879 /* Return the next frame in the frame list after FRAME.
880 If MINIBUF is nil, exclude minibuffer-only frames.
881 If MINIBUF is a window, include only its own frame
882 and any frame now using that window as the minibuffer.
883 If MINIBUF is `visible', include all visible frames.
884 If MINIBUF is 0, include all visible and iconified frames.
885 Otherwise, include all frames. */
886
887 Lisp_Object
888 next_frame (frame, minibuf)
889 Lisp_Object frame;
890 Lisp_Object minibuf;
891 {
892 Lisp_Object tail;
893 int passed = 0;
894
895 /* There must always be at least one frame in Vframe_list. */
896 if (! CONSP (Vframe_list))
897 abort ();
898
899 /* If this frame is dead, it won't be in Vframe_list, and we'll loop
900 forever. Forestall that. */
901 CHECK_LIVE_FRAME (frame, 0);
902
903 while (1)
904 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
905 {
906 Lisp_Object f;
907
908 f = XCAR (tail);
909
910 if (passed
911 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
912 {
913 /* Decide whether this frame is eligible to be returned. */
914
915 /* If we've looped all the way around without finding any
916 eligible frames, return the original frame. */
917 if (EQ (f, frame))
918 return f;
919
920 /* Let minibuf decide if this frame is acceptable. */
921 if (NILP (minibuf))
922 {
923 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
924 return f;
925 }
926 else if (EQ (minibuf, Qvisible))
927 {
928 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
929 if (FRAME_VISIBLE_P (XFRAME (f)))
930 return f;
931 }
932 else if (XFASTINT (minibuf) == 0)
933 {
934 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
935 if (FRAME_VISIBLE_P (XFRAME (f))
936 || FRAME_ICONIFIED_P (XFRAME (f)))
937 return f;
938 }
939 else if (WINDOWP (minibuf))
940 {
941 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
942 /* Check that F either is, or has forwarded its focus to,
943 MINIBUF's frame. */
944 && (EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
945 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
946 FRAME_FOCUS_FRAME (XFRAME (f)))))
947 return f;
948 }
949 else
950 return f;
951 }
952
953 if (EQ (frame, f))
954 passed++;
955 }
956 }
957
958 /* Return the previous frame in the frame list before FRAME.
959 If MINIBUF is nil, exclude minibuffer-only frames.
960 If MINIBUF is a window, include only its own frame
961 and any frame now using that window as the minibuffer.
962 If MINIBUF is `visible', include all visible frames.
963 If MINIBUF is 0, include all visible and iconified frames.
964 Otherwise, include all frames. */
965
966 Lisp_Object
967 prev_frame (frame, minibuf)
968 Lisp_Object frame;
969 Lisp_Object minibuf;
970 {
971 Lisp_Object tail;
972 Lisp_Object prev;
973
974 /* There must always be at least one frame in Vframe_list. */
975 if (! CONSP (Vframe_list))
976 abort ();
977
978 prev = Qnil;
979 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
980 {
981 Lisp_Object f;
982
983 f = XCAR (tail);
984 if (!FRAMEP (f))
985 abort ();
986
987 if (EQ (frame, f) && !NILP (prev))
988 return prev;
989
990 if (FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
991 {
992 /* Decide whether this frame is eligible to be returned,
993 according to minibuf. */
994 if (NILP (minibuf))
995 {
996 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
997 prev = f;
998 }
999 else if (WINDOWP (minibuf))
1000 {
1001 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
1002 /* Check that F either is, or has forwarded its focus to,
1003 MINIBUF's frame. */
1004 && (EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
1005 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1006 FRAME_FOCUS_FRAME (XFRAME (f)))))
1007 prev = f;
1008 }
1009 else if (EQ (minibuf, Qvisible))
1010 {
1011 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
1012 if (FRAME_VISIBLE_P (XFRAME (f)))
1013 prev = f;
1014 }
1015 else if (XFASTINT (minibuf) == 0)
1016 {
1017 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
1018 if (FRAME_VISIBLE_P (XFRAME (f))
1019 || FRAME_ICONIFIED_P (XFRAME (f)))
1020 prev = f;
1021 }
1022 else
1023 prev = f;
1024 }
1025 }
1026
1027 /* We've scanned the entire list. */
1028 if (NILP (prev))
1029 /* We went through the whole frame list without finding a single
1030 acceptable frame. Return the original frame. */
1031 return frame;
1032 else
1033 /* There were no acceptable frames in the list before FRAME; otherwise,
1034 we would have returned directly from the loop. Since PREV is the last
1035 acceptable frame in the list, return it. */
1036 return prev;
1037 }
1038
1039
1040 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1041 "Return the next frame in the frame list after FRAME.\n\
1042 It considers only frames on the same terminal as FRAME.\n\
1043 By default, skip minibuffer-only frames.\n\
1044 If omitted, FRAME defaults to the selected frame.\n\
1045 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
1046 If MINIFRAME is a window, include only its own frame\n\
1047 and any frame now using that window as the minibuffer.\n\
1048 If MINIFRAME is `visible', include all visible frames.\n\
1049 If MINIFRAME is 0, include all visible and iconified frames.\n\
1050 Otherwise, include all frames.")
1051 (frame, miniframe)
1052 Lisp_Object frame, miniframe;
1053 {
1054 if (NILP (frame))
1055 frame = selected_frame;
1056
1057 CHECK_LIVE_FRAME (frame, 0);
1058 return next_frame (frame, miniframe);
1059 }
1060
1061 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1062 "Return the previous frame in the frame list before FRAME.\n\
1063 It considers only frames on the same terminal as FRAME.\n\
1064 By default, skip minibuffer-only frames.\n\
1065 If omitted, FRAME defaults to the selected frame.\n\
1066 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
1067 If MINIFRAME is a window, include only its own frame\n\
1068 and any frame now using that window as the minibuffer.\n\
1069 If MINIFRAME is `visible', include all visible frames.\n\
1070 If MINIFRAME is 0, include all visible and iconified frames.\n\
1071 Otherwise, include all frames.")
1072 (frame, miniframe)
1073 Lisp_Object frame, miniframe;
1074 {
1075 if (NILP (frame))
1076 frame = selected_frame;
1077 CHECK_LIVE_FRAME (frame, 0);
1078 return prev_frame (frame, miniframe);
1079 }
1080 \f
1081 /* Return 1 if it is ok to delete frame F;
1082 0 if all frames aside from F are invisible.
1083 (Exception: if F is the terminal frame, and we are using X, return 1.) */
1084
1085 int
1086 other_visible_frames (f)
1087 FRAME_PTR f;
1088 {
1089 /* We know the selected frame is visible,
1090 so if F is some other frame, it can't be the sole visible one. */
1091 if (f == SELECTED_FRAME ())
1092 {
1093 Lisp_Object frames;
1094 int count = 0;
1095
1096 for (frames = Vframe_list;
1097 CONSP (frames);
1098 frames = XCDR (frames))
1099 {
1100 Lisp_Object this;
1101
1102 this = XCAR (frames);
1103 /* Verify that the frame's window still exists
1104 and we can still talk to it. And note any recent change
1105 in visibility. */
1106 #ifdef HAVE_WINDOW_SYSTEM
1107 if (FRAME_WINDOW_P (XFRAME (this)))
1108 {
1109 x_sync (XFRAME (this));
1110 FRAME_SAMPLE_VISIBILITY (XFRAME (this));
1111 }
1112 #endif
1113
1114 if (FRAME_VISIBLE_P (XFRAME (this))
1115 || FRAME_ICONIFIED_P (XFRAME (this))
1116 /* Allow deleting the terminal frame when at least
1117 one X frame exists! */
1118 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
1119 count++;
1120 }
1121 return count > 1;
1122 }
1123 return 1;
1124 }
1125
1126 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
1127 "Delete FRAME, permanently eliminating it from use.\n\
1128 If omitted, FRAME defaults to the selected frame.\n\
1129 A frame may not be deleted if its minibuffer is used by other frames.\n\
1130 Normally, you may not delete a frame if all other frames are invisible,\n\
1131 but if the second optional argument FORCE is non-nil, you may do so.")
1132 (frame, force)
1133 Lisp_Object frame, force;
1134 {
1135 struct frame *f;
1136 struct frame *sf = SELECTED_FRAME ();
1137 int minibuffer_selected;
1138
1139 if (EQ (frame, Qnil))
1140 {
1141 f = sf;
1142 XSETFRAME (frame, f);
1143 }
1144 else
1145 {
1146 CHECK_FRAME (frame, 0);
1147 f = XFRAME (frame);
1148 }
1149
1150 if (! FRAME_LIVE_P (f))
1151 return Qnil;
1152
1153 if (NILP (force) && !other_visible_frames (f))
1154 error ("Attempt to delete the sole visible or iconified frame");
1155
1156 #if 0
1157 /* This is a nice idea, but x_connection_closed needs to be able
1158 to delete the last frame, if it is gone. */
1159 if (NILP (XCDR (Vframe_list)))
1160 error ("Attempt to delete the only frame");
1161 #endif
1162
1163 /* Does this frame have a minibuffer, and is it the surrogate
1164 minibuffer for any other frame? */
1165 if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
1166 {
1167 Lisp_Object frames;
1168
1169 for (frames = Vframe_list;
1170 CONSP (frames);
1171 frames = XCDR (frames))
1172 {
1173 Lisp_Object this;
1174 this = XCAR (frames);
1175
1176 if (! EQ (this, frame)
1177 && EQ (frame,
1178 WINDOW_FRAME (XWINDOW
1179 (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
1180 error ("Attempt to delete a surrogate minibuffer frame");
1181 }
1182 }
1183
1184 minibuffer_selected = EQ (minibuf_window, selected_window);
1185
1186 /* Don't let the frame remain selected. */
1187 if (f == sf)
1188 {
1189 Lisp_Object tail, frame1;
1190
1191 /* Look for another visible frame on the same terminal. */
1192 frame1 = next_frame (frame, Qvisible);
1193
1194 /* If there is none, find *some* other frame. */
1195 if (NILP (frame1) || EQ (frame1, frame))
1196 {
1197 FOR_EACH_FRAME (tail, frame1)
1198 {
1199 if (! EQ (frame, frame1))
1200 break;
1201 }
1202 }
1203
1204 do_switch_frame (frame1, Qnil, 0);
1205 sf = SELECTED_FRAME ();
1206 }
1207
1208 /* Don't allow minibuf_window to remain on a deleted frame. */
1209 if (EQ (f->minibuffer_window, minibuf_window))
1210 {
1211 Fset_window_buffer (sf->minibuffer_window,
1212 XWINDOW (minibuf_window)->buffer);
1213 minibuf_window = sf->minibuffer_window;
1214
1215 /* If the dying minibuffer window was selected,
1216 select the new one. */
1217 if (minibuffer_selected)
1218 Fselect_window (minibuf_window);
1219 }
1220
1221 /* Clear any X selections for this frame. */
1222 #ifdef HAVE_X_WINDOWS
1223 if (FRAME_X_P (f))
1224 x_clear_frame_selections (f);
1225 #endif
1226
1227 /* Free glyphs.
1228 This function must be called before the window tree of the
1229 frame is deleted because windows contain dynamically allocated
1230 memory. */
1231 free_glyphs (f);
1232
1233 /* Mark all the windows that used to be on FRAME as deleted, and then
1234 remove the reference to them. */
1235 delete_all_subwindows (XWINDOW (f->root_window));
1236 f->root_window = Qnil;
1237
1238 Vframe_list = Fdelq (frame, Vframe_list);
1239 FRAME_SET_VISIBLE (f, 0);
1240
1241 if (f->namebuf)
1242 xfree (f->namebuf);
1243 if (FRAME_INSERT_COST (f))
1244 xfree (FRAME_INSERT_COST (f));
1245 if (FRAME_DELETEN_COST (f))
1246 xfree (FRAME_DELETEN_COST (f));
1247 if (FRAME_INSERTN_COST (f))
1248 xfree (FRAME_INSERTN_COST (f));
1249 if (FRAME_DELETE_COST (f))
1250 xfree (FRAME_DELETE_COST (f));
1251 if (FRAME_MESSAGE_BUF (f))
1252 xfree (FRAME_MESSAGE_BUF (f));
1253
1254 #ifdef HAVE_WINDOW_SYSTEM
1255 /* Free all fontset data. */
1256 free_fontset_data (FRAME_FONTSET_DATA (f));
1257 #endif
1258
1259 /* Since some events are handled at the interrupt level, we may get
1260 an event for f at any time; if we zero out the frame's display
1261 now, then we may trip up the event-handling code. Instead, we'll
1262 promise that the display of the frame must be valid until we have
1263 called the window-system-dependent frame destruction routine. */
1264
1265 /* I think this should be done with a hook. */
1266 #ifdef HAVE_WINDOW_SYSTEM
1267 if (FRAME_WINDOW_P (f))
1268 x_destroy_window (f);
1269 #endif
1270
1271 /* Done by x_destroy_window above already */
1272 #if 0
1273 #ifdef macintosh
1274 if (FRAME_MAC_P (f))
1275 DisposeMacWindow (f->output_data.mac);
1276 #endif
1277 #endif
1278
1279 f->output_data.nothing = 0;
1280
1281 /* If we've deleted the last_nonminibuf_frame, then try to find
1282 another one. */
1283 if (f == last_nonminibuf_frame)
1284 {
1285 Lisp_Object frames;
1286
1287 last_nonminibuf_frame = 0;
1288
1289 for (frames = Vframe_list;
1290 CONSP (frames);
1291 frames = XCDR (frames))
1292 {
1293 f = XFRAME (XCAR (frames));
1294 if (!FRAME_MINIBUF_ONLY_P (f))
1295 {
1296 last_nonminibuf_frame = f;
1297 break;
1298 }
1299 }
1300 }
1301
1302 /* If we've deleted this keyboard's default_minibuffer_frame, try to
1303 find another one. Prefer minibuffer-only frames, but also notice
1304 frames with other windows. */
1305 if (EQ (frame, FRAME_KBOARD (f)->Vdefault_minibuffer_frame))
1306 {
1307 Lisp_Object frames;
1308
1309 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
1310 Lisp_Object frame_with_minibuf;
1311 /* Some frame we found on the same kboard, or nil if there are none. */
1312 Lisp_Object frame_on_same_kboard;
1313
1314 frame_on_same_kboard = Qnil;
1315 frame_with_minibuf = Qnil;
1316
1317 for (frames = Vframe_list;
1318 CONSP (frames);
1319 frames = XCDR (frames))
1320 {
1321 Lisp_Object this;
1322 struct frame *f1;
1323
1324 this = XCAR (frames);
1325 if (!FRAMEP (this))
1326 abort ();
1327 f1 = XFRAME (this);
1328
1329 /* Consider only frames on the same kboard
1330 and only those with minibuffers. */
1331 if (FRAME_KBOARD (f) == FRAME_KBOARD (f1)
1332 && FRAME_HAS_MINIBUF_P (f1))
1333 {
1334 frame_with_minibuf = this;
1335 if (FRAME_MINIBUF_ONLY_P (f1))
1336 break;
1337 }
1338
1339 if (FRAME_KBOARD (f) == FRAME_KBOARD (f1))
1340 frame_on_same_kboard = this;
1341 }
1342
1343 if (!NILP (frame_on_same_kboard))
1344 {
1345 /* We know that there must be some frame with a minibuffer out
1346 there. If this were not true, all of the frames present
1347 would have to be minibufferless, which implies that at some
1348 point their minibuffer frames must have been deleted, but
1349 that is prohibited at the top; you can't delete surrogate
1350 minibuffer frames. */
1351 if (NILP (frame_with_minibuf))
1352 abort ();
1353
1354 FRAME_KBOARD (f)->Vdefault_minibuffer_frame = frame_with_minibuf;
1355 }
1356 else
1357 /* No frames left on this kboard--say no minibuffer either. */
1358 FRAME_KBOARD (f)->Vdefault_minibuffer_frame = Qnil;
1359 }
1360
1361 /* Cause frame titles to update--necessary if we now have just one frame. */
1362 update_mode_lines = 1;
1363
1364 return Qnil;
1365 }
1366 \f
1367 /* Return mouse position in character cell units. */
1368
1369 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
1370 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
1371 The position is given in character cells, where (0, 0) is the\n\
1372 upper-left corner.\n\
1373 If Emacs is running on a mouseless terminal or hasn't been programmed\n\
1374 to read the mouse position, it returns the selected frame for FRAME\n\
1375 and nil for X and Y.")
1376 ()
1377 {
1378 FRAME_PTR f;
1379 Lisp_Object lispy_dummy;
1380 enum scroll_bar_part party_dummy;
1381 Lisp_Object x, y;
1382 int col, row;
1383 unsigned long long_dummy;
1384
1385 f = SELECTED_FRAME ();
1386 x = y = Qnil;
1387
1388 #ifdef HAVE_MOUSE
1389 /* It's okay for the hook to refrain from storing anything. */
1390 if (mouse_position_hook)
1391 (*mouse_position_hook) (&f, -1,
1392 &lispy_dummy, &party_dummy,
1393 &x, &y,
1394 &long_dummy);
1395 if (! NILP (x))
1396 {
1397 col = XINT (x);
1398 row = XINT (y);
1399 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
1400 XSETINT (x, col);
1401 XSETINT (y, row);
1402 }
1403 #endif
1404 XSETFRAME (lispy_dummy, f);
1405 return Fcons (lispy_dummy, Fcons (x, y));
1406 }
1407
1408 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
1409 Smouse_pixel_position, 0, 0, 0,
1410 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
1411 The position is given in pixel units, where (0, 0) is the\n\
1412 upper-left corner.\n\
1413 If Emacs is running on a mouseless terminal or hasn't been programmed\n\
1414 to read the mouse position, it returns the selected frame for FRAME\n\
1415 and nil for X and Y.")
1416 ()
1417 {
1418 FRAME_PTR f;
1419 Lisp_Object lispy_dummy;
1420 enum scroll_bar_part party_dummy;
1421 Lisp_Object x, y;
1422 unsigned long long_dummy;
1423
1424 f = SELECTED_FRAME ();
1425 x = y = Qnil;
1426
1427 #ifdef HAVE_MOUSE
1428 /* It's okay for the hook to refrain from storing anything. */
1429 if (mouse_position_hook)
1430 (*mouse_position_hook) (&f, -1,
1431 &lispy_dummy, &party_dummy,
1432 &x, &y,
1433 &long_dummy);
1434 #endif
1435 XSETFRAME (lispy_dummy, f);
1436 return Fcons (lispy_dummy, Fcons (x, y));
1437 }
1438
1439 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
1440 "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
1441 Coordinates are relative to the frame, not a window,\n\
1442 so the coordinates of the top left character in the frame\n\
1443 may be nonzero due to left-hand scroll bars or the menu bar.\n\
1444 \n\
1445 This function is a no-op for an X frame that is not visible.\n\
1446 If you have just created a frame, you must wait for it to become visible\n\
1447 before calling this function on it, like this.\n\
1448 (while (not (frame-visible-p frame)) (sleep-for .5))")
1449 (frame, x, y)
1450 Lisp_Object frame, x, y;
1451 {
1452 CHECK_LIVE_FRAME (frame, 0);
1453 CHECK_NUMBER (x, 2);
1454 CHECK_NUMBER (y, 1);
1455
1456 /* I think this should be done with a hook. */
1457 #ifdef HAVE_WINDOW_SYSTEM
1458 if (FRAME_WINDOW_P (XFRAME (frame)))
1459 /* Warping the mouse will cause enternotify and focus events. */
1460 x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
1461 #else
1462 #if defined (MSDOS) && defined (HAVE_MOUSE)
1463 if (FRAME_MSDOS_P (XFRAME (frame)))
1464 {
1465 Fselect_frame (frame, Qnil);
1466 mouse_moveto (XINT (x), XINT (y));
1467 }
1468 #endif
1469 #endif
1470
1471 return Qnil;
1472 }
1473
1474 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
1475 Sset_mouse_pixel_position, 3, 3, 0,
1476 "Move the mouse pointer to pixel position (X,Y) in FRAME.\n\
1477 Note, this is a no-op for an X frame that is not visible.\n\
1478 If you have just created a frame, you must wait for it to become visible\n\
1479 before calling this function on it, like this.\n\
1480 (while (not (frame-visible-p frame)) (sleep-for .5))")
1481 (frame, x, y)
1482 Lisp_Object frame, x, y;
1483 {
1484 CHECK_LIVE_FRAME (frame, 0);
1485 CHECK_NUMBER (x, 2);
1486 CHECK_NUMBER (y, 1);
1487
1488 /* I think this should be done with a hook. */
1489 #ifdef HAVE_WINDOW_SYSTEM
1490 if (FRAME_WINDOW_P (XFRAME (frame)))
1491 /* Warping the mouse will cause enternotify and focus events. */
1492 x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
1493 #else
1494 #if defined (MSDOS) && defined (HAVE_MOUSE)
1495 if (FRAME_MSDOS_P (XFRAME (frame)))
1496 {
1497 Fselect_frame (frame, Qnil);
1498 mouse_moveto (XINT (x), XINT (y));
1499 }
1500 #endif
1501 #endif
1502
1503 return Qnil;
1504 }
1505 \f
1506 static void make_frame_visible_1 P_ ((Lisp_Object));
1507
1508 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
1509 0, 1, "",
1510 "Make the frame FRAME visible (assuming it is an X-window).\n\
1511 If omitted, FRAME defaults to the currently selected frame.")
1512 (frame)
1513 Lisp_Object frame;
1514 {
1515 if (NILP (frame))
1516 frame = selected_frame;
1517
1518 CHECK_LIVE_FRAME (frame, 0);
1519
1520 /* I think this should be done with a hook. */
1521 #ifdef HAVE_WINDOW_SYSTEM
1522 if (FRAME_WINDOW_P (XFRAME (frame)))
1523 {
1524 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1525 x_make_frame_visible (XFRAME (frame));
1526 }
1527 #endif
1528
1529 make_frame_visible_1 (XFRAME (frame)->root_window);
1530
1531 /* Make menu bar update for the Buffers and Frams menus. */
1532 windows_or_buffers_changed++;
1533
1534 return frame;
1535 }
1536
1537 /* Update the display_time slot of the buffers shown in WINDOW
1538 and all its descendents. */
1539
1540 static void
1541 make_frame_visible_1 (window)
1542 Lisp_Object window;
1543 {
1544 struct window *w;
1545
1546 for (;!NILP (window); window = w->next)
1547 {
1548 w = XWINDOW (window);
1549
1550 if (!NILP (w->buffer))
1551 XBUFFER (w->buffer)->display_time = Fcurrent_time ();
1552
1553 if (!NILP (w->vchild))
1554 make_frame_visible_1 (w->vchild);
1555 if (!NILP (w->hchild))
1556 make_frame_visible_1 (w->hchild);
1557 }
1558 }
1559
1560 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
1561 0, 2, "",
1562 "Make the frame FRAME invisible (assuming it is an X-window).\n\
1563 If omitted, FRAME defaults to the currently selected frame.\n\
1564 Normally you may not make FRAME invisible if all other frames are invisible,\n\
1565 but if the second optional argument FORCE is non-nil, you may do so.")
1566 (frame, force)
1567 Lisp_Object frame, force;
1568 {
1569 if (NILP (frame))
1570 frame = selected_frame;
1571
1572 CHECK_LIVE_FRAME (frame, 0);
1573
1574 if (NILP (force) && !other_visible_frames (XFRAME (frame)))
1575 error ("Attempt to make invisible the sole visible or iconified frame");
1576
1577 #if 0 /* This isn't logically necessary, and it can do GC. */
1578 /* Don't let the frame remain selected. */
1579 if (EQ (frame, selected_frame))
1580 do_switch_frame (next_frame (frame, Qt), Qnil, 0)
1581 #endif
1582
1583 /* Don't allow minibuf_window to remain on a deleted frame. */
1584 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
1585 {
1586 struct frame *sf = XFRAME (selected_frame);
1587 Fset_window_buffer (sf->minibuffer_window,
1588 XWINDOW (minibuf_window)->buffer);
1589 minibuf_window = sf->minibuffer_window;
1590 }
1591
1592 /* I think this should be done with a hook. */
1593 #ifdef HAVE_WINDOW_SYSTEM
1594 if (FRAME_WINDOW_P (XFRAME (frame)))
1595 x_make_frame_invisible (XFRAME (frame));
1596 #endif
1597
1598 /* Make menu bar update for the Buffers and Frams menus. */
1599 windows_or_buffers_changed++;
1600
1601 return Qnil;
1602 }
1603
1604 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
1605 0, 1, "",
1606 "Make the frame FRAME into an icon.\n\
1607 If omitted, FRAME defaults to the currently selected frame.")
1608 (frame)
1609 Lisp_Object frame;
1610 {
1611 if (NILP (frame))
1612 frame = selected_frame;
1613
1614 CHECK_LIVE_FRAME (frame, 0);
1615
1616 #if 0 /* This isn't logically necessary, and it can do GC. */
1617 /* Don't let the frame remain selected. */
1618 if (EQ (frame, selected_frame))
1619 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
1620 #endif
1621
1622 /* Don't allow minibuf_window to remain on a deleted frame. */
1623 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
1624 {
1625 struct frame *sf = XFRAME (selected_frame);
1626 Fset_window_buffer (sf->minibuffer_window,
1627 XWINDOW (minibuf_window)->buffer);
1628 minibuf_window = sf->minibuffer_window;
1629 }
1630
1631 /* I think this should be done with a hook. */
1632 #ifdef HAVE_WINDOW_SYSTEM
1633 if (FRAME_WINDOW_P (XFRAME (frame)))
1634 x_iconify_frame (XFRAME (frame));
1635 #endif
1636
1637 /* Make menu bar update for the Buffers and Frams menus. */
1638 windows_or_buffers_changed++;
1639
1640 return Qnil;
1641 }
1642
1643 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
1644 1, 1, 0,
1645 "Return t if FRAME is now \"visible\" (actually in use for display).\n\
1646 A frame that is not \"visible\" is not updated and, if it works through\n\
1647 a window system, it may not show at all.\n\
1648 Return the symbol `icon' if frame is visible only as an icon.")
1649 (frame)
1650 Lisp_Object frame;
1651 {
1652 CHECK_LIVE_FRAME (frame, 0);
1653
1654 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1655
1656 if (FRAME_VISIBLE_P (XFRAME (frame)))
1657 return Qt;
1658 if (FRAME_ICONIFIED_P (XFRAME (frame)))
1659 return Qicon;
1660 return Qnil;
1661 }
1662
1663 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
1664 0, 0, 0,
1665 "Return a list of all frames now \"visible\" (being updated).")
1666 ()
1667 {
1668 Lisp_Object tail, frame;
1669 struct frame *f;
1670 Lisp_Object value;
1671
1672 value = Qnil;
1673 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1674 {
1675 frame = XCAR (tail);
1676 if (!FRAMEP (frame))
1677 continue;
1678 f = XFRAME (frame);
1679 if (FRAME_VISIBLE_P (f))
1680 value = Fcons (frame, value);
1681 }
1682 return value;
1683 }
1684
1685
1686 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
1687 "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
1688 If FRAME is invisible, make it visible.\n\
1689 If you don't specify a frame, the selected frame is used.\n\
1690 If Emacs is displaying on an ordinary terminal or some other device which\n\
1691 doesn't support multiple overlapping frames, this function does nothing.")
1692 (frame)
1693 Lisp_Object frame;
1694 {
1695 if (NILP (frame))
1696 frame = selected_frame;
1697
1698 CHECK_LIVE_FRAME (frame, 0);
1699
1700 /* Do like the documentation says. */
1701 Fmake_frame_visible (frame);
1702
1703 if (frame_raise_lower_hook)
1704 (*frame_raise_lower_hook) (XFRAME (frame), 1);
1705
1706 return Qnil;
1707 }
1708
1709 /* Should we have a corresponding function called Flower_Power? */
1710 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
1711 "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
1712 If you don't specify a frame, the selected frame is used.\n\
1713 If Emacs is displaying on an ordinary terminal or some other device which\n\
1714 doesn't support multiple overlapping frames, this function does nothing.")
1715 (frame)
1716 Lisp_Object frame;
1717 {
1718 if (NILP (frame))
1719 frame = selected_frame;
1720
1721 CHECK_LIVE_FRAME (frame, 0);
1722
1723 if (frame_raise_lower_hook)
1724 (*frame_raise_lower_hook) (XFRAME (frame), 0);
1725
1726 return Qnil;
1727 }
1728
1729 \f
1730 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
1731 1, 2, 0,
1732 "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
1733 In other words, switch-frame events caused by events in FRAME will\n\
1734 request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
1735 FOCUS-FRAME after reading an event typed at FRAME.\n\
1736 \n\
1737 If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
1738 cancelled, and the frame again receives its own keystrokes.\n\
1739 \n\
1740 Focus redirection is useful for temporarily redirecting keystrokes to\n\
1741 a surrogate minibuffer frame when a frame doesn't have its own\n\
1742 minibuffer window.\n\
1743 \n\
1744 A frame's focus redirection can be changed by select-frame. If frame\n\
1745 FOO is selected, and then a different frame BAR is selected, any\n\
1746 frames redirecting their focus to FOO are shifted to redirect their\n\
1747 focus to BAR. This allows focus redirection to work properly when the\n\
1748 user switches from one frame to another using `select-window'.\n\
1749 \n\
1750 This means that a frame whose focus is redirected to itself is treated\n\
1751 differently from a frame whose focus is redirected to nil; the former\n\
1752 is affected by select-frame, while the latter is not.\n\
1753 \n\
1754 The redirection lasts until `redirect-frame-focus' is called to change it.")
1755 (frame, focus_frame)
1756 Lisp_Object frame, focus_frame;
1757 {
1758 /* Note that we don't check for a live frame here. It's reasonable
1759 to redirect the focus of a frame you're about to delete, if you
1760 know what other frame should receive those keystrokes. */
1761 CHECK_FRAME (frame, 0);
1762
1763 if (! NILP (focus_frame))
1764 CHECK_LIVE_FRAME (focus_frame, 1);
1765
1766 XFRAME (frame)->focus_frame = focus_frame;
1767
1768 if (frame_rehighlight_hook)
1769 (*frame_rehighlight_hook) (XFRAME (frame));
1770
1771 return Qnil;
1772 }
1773
1774
1775 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
1776 "Return the frame to which FRAME's keystrokes are currently being sent.\n\
1777 This returns nil if FRAME's focus is not redirected.\n\
1778 See `redirect-frame-focus'.")
1779 (frame)
1780 Lisp_Object frame;
1781 {
1782 CHECK_LIVE_FRAME (frame, 0);
1783
1784 return FRAME_FOCUS_FRAME (XFRAME (frame));
1785 }
1786
1787
1788 \f
1789 /* Return the value of frame parameter PROP in frame FRAME. */
1790
1791 Lisp_Object
1792 get_frame_param (frame, prop)
1793 register struct frame *frame;
1794 Lisp_Object prop;
1795 {
1796 register Lisp_Object tem;
1797
1798 tem = Fassq (prop, frame->param_alist);
1799 if (EQ (tem, Qnil))
1800 return tem;
1801 return Fcdr (tem);
1802 }
1803
1804 /* Return the buffer-predicate of the selected frame. */
1805
1806 Lisp_Object
1807 frame_buffer_predicate (frame)
1808 Lisp_Object frame;
1809 {
1810 return XFRAME (frame)->buffer_predicate;
1811 }
1812
1813 /* Return the buffer-list of the selected frame. */
1814
1815 Lisp_Object
1816 frame_buffer_list (frame)
1817 Lisp_Object frame;
1818 {
1819 return XFRAME (frame)->buffer_list;
1820 }
1821
1822 /* Set the buffer-list of the selected frame. */
1823
1824 void
1825 set_frame_buffer_list (frame, list)
1826 Lisp_Object frame, list;
1827 {
1828 XFRAME (frame)->buffer_list = list;
1829 }
1830
1831 /* Discard BUFFER from the buffer-list of each frame. */
1832
1833 void
1834 frames_discard_buffer (buffer)
1835 Lisp_Object buffer;
1836 {
1837 Lisp_Object frame, tail;
1838
1839 FOR_EACH_FRAME (tail, frame)
1840 {
1841 XFRAME (frame)->buffer_list
1842 = Fdelq (buffer, XFRAME (frame)->buffer_list);
1843 }
1844 }
1845
1846 /* Move BUFFER to the end of the buffer-list of each frame. */
1847
1848 void
1849 frames_bury_buffer (buffer)
1850 Lisp_Object buffer;
1851 {
1852 Lisp_Object frame, tail;
1853
1854 FOR_EACH_FRAME (tail, frame)
1855 {
1856 XFRAME (frame)->buffer_list
1857 = nconc2 (Fdelq (buffer, XFRAME (frame)->buffer_list),
1858 Fcons (buffer, Qnil));
1859 }
1860 }
1861
1862 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
1863 If the alist already has an element for PROP, we change it. */
1864
1865 void
1866 store_in_alist (alistptr, prop, val)
1867 Lisp_Object *alistptr, val;
1868 Lisp_Object prop;
1869 {
1870 register Lisp_Object tem;
1871
1872 tem = Fassq (prop, *alistptr);
1873 if (EQ (tem, Qnil))
1874 *alistptr = Fcons (Fcons (prop, val), *alistptr);
1875 else
1876 Fsetcdr (tem, val);
1877 }
1878
1879 static int
1880 frame_name_fnn_p (str, len)
1881 char *str;
1882 int len;
1883 {
1884 if (len > 1 && str[0] == 'F')
1885 {
1886 char *end_ptr;
1887
1888 strtol (str + 1, &end_ptr, 10);
1889
1890 if (end_ptr == str + len)
1891 return 1;
1892 }
1893 return 0;
1894 }
1895
1896 /* Set the name of the terminal frame. Also used by MSDOS frames.
1897 Modeled after x_set_name which is used for WINDOW frames. */
1898
1899 void
1900 set_term_frame_name (f, name)
1901 struct frame *f;
1902 Lisp_Object name;
1903 {
1904 f->explicit_name = ! NILP (name);
1905
1906 /* If NAME is nil, set the name to F<num>. */
1907 if (NILP (name))
1908 {
1909 char namebuf[20];
1910
1911 /* Check for no change needed in this very common case
1912 before we do any consing. */
1913 if (frame_name_fnn_p (XSTRING (f->name)->data,
1914 STRING_BYTES (XSTRING (f->name))))
1915 return;
1916
1917 terminal_frame_count++;
1918 sprintf (namebuf, "F%d", terminal_frame_count);
1919 name = build_string (namebuf);
1920 }
1921 else
1922 {
1923 CHECK_STRING (name, 0);
1924
1925 /* Don't change the name if it's already NAME. */
1926 if (! NILP (Fstring_equal (name, f->name)))
1927 return;
1928
1929 /* Don't allow the user to set the frame name to F<num>, so it
1930 doesn't clash with the names we generate for terminal frames. */
1931 if (frame_name_fnn_p (XSTRING (name)->data, STRING_BYTES (XSTRING (name))))
1932 error ("Frame names of the form F<num> are usurped by Emacs");
1933 }
1934
1935 f->name = name;
1936 update_mode_lines = 1;
1937 }
1938
1939 void
1940 store_frame_param (f, prop, val)
1941 struct frame *f;
1942 Lisp_Object prop, val;
1943 {
1944 register Lisp_Object tem;
1945
1946 if (EQ (prop, Qbuffer_list))
1947 {
1948 f->buffer_list = val;
1949 return;
1950 }
1951
1952 tem = Fassq (prop, f->param_alist);
1953 if (EQ (tem, Qnil))
1954 f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
1955 else
1956 Fsetcdr (tem, val);
1957
1958 if (EQ (prop, Qbuffer_predicate))
1959 f->buffer_predicate = val;
1960
1961 if (! FRAME_WINDOW_P (f))
1962 {
1963 if (EQ (prop, Qmenu_bar_lines))
1964 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
1965 else if (EQ (prop, Qname))
1966 set_term_frame_name (f, val);
1967 }
1968
1969 if (EQ (prop, Qminibuffer) && WINDOWP (val))
1970 {
1971 if (! MINI_WINDOW_P (XWINDOW (val)))
1972 error ("Surrogate minibuffer windows must be minibuffer windows.");
1973
1974 if ((FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
1975 && !EQ (val, f->minibuffer_window))
1976 error ("Can't change the surrogate minibuffer of a frame with its own minibuffer");
1977
1978 /* Install the chosen minibuffer window, with proper buffer. */
1979 f->minibuffer_window = val;
1980 }
1981 }
1982
1983 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
1984 "Return the parameters-alist of frame FRAME.\n\
1985 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
1986 The meaningful PARMs depend on the kind of frame.\n\
1987 If FRAME is omitted, return information on the currently selected frame.")
1988 (frame)
1989 Lisp_Object frame;
1990 {
1991 Lisp_Object alist;
1992 FRAME_PTR f;
1993 int height, width;
1994 struct gcpro gcpro1;
1995
1996 if (EQ (frame, Qnil))
1997 frame = selected_frame;
1998
1999 CHECK_FRAME (frame, 0);
2000 f = XFRAME (frame);
2001
2002 if (!FRAME_LIVE_P (f))
2003 return Qnil;
2004
2005 alist = Fcopy_alist (f->param_alist);
2006 GCPRO1 (alist);
2007
2008 if (!FRAME_WINDOW_P (f))
2009 {
2010 int fg = FRAME_FOREGROUND_PIXEL (f);
2011 int bg = FRAME_BACKGROUND_PIXEL (f);
2012
2013 store_in_alist (&alist, intern ("foreground-color"),
2014 tty_color_name (f, fg));
2015 store_in_alist (&alist, intern ("background-color"),
2016 tty_color_name (f, bg));
2017 store_in_alist (&alist, intern ("font"),
2018 build_string (FRAME_MSDOS_P (f)
2019 ? "ms-dos"
2020 : FRAME_W32_P (f) ? "w32term" : "tty"));
2021 }
2022 store_in_alist (&alist, Qname, f->name);
2023 height = (FRAME_NEW_HEIGHT (f) ? FRAME_NEW_HEIGHT (f) : FRAME_HEIGHT (f));
2024 store_in_alist (&alist, Qheight, make_number (height));
2025 width = (FRAME_NEW_WIDTH (f) ? FRAME_NEW_WIDTH (f) : FRAME_WIDTH (f));
2026 store_in_alist (&alist, Qwidth, make_number (width));
2027 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
2028 store_in_alist (&alist, Qminibuffer,
2029 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
2030 : FRAME_MINIBUF_ONLY_P (f) ? Qonly
2031 : FRAME_MINIBUF_WINDOW (f)));
2032 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
2033 store_in_alist (&alist, Qbuffer_list,
2034 frame_buffer_list (selected_frame));
2035
2036 /* I think this should be done with a hook. */
2037 #ifdef HAVE_WINDOW_SYSTEM
2038 if (FRAME_WINDOW_P (f))
2039 x_report_frame_params (f, &alist);
2040 else
2041 #endif
2042 {
2043 /* This ought to be correct in f->param_alist for an X frame. */
2044 Lisp_Object lines;
2045 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
2046 store_in_alist (&alist, Qmenu_bar_lines, lines);
2047 }
2048
2049 UNGCPRO;
2050 return alist;
2051 }
2052
2053 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
2054 Smodify_frame_parameters, 2, 2, 0,
2055 "Modify the parameters of frame FRAME according to ALIST.\n\
2056 ALIST is an alist of parameters to change and their new values.\n\
2057 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
2058 The meaningful PARMs depend on the kind of frame.\n\
2059 Undefined PARMs are ignored, but stored in the frame's parameter list\n\
2060 so that `frame-parameters' will return them.")
2061 (frame, alist)
2062 Lisp_Object frame, alist;
2063 {
2064 FRAME_PTR f;
2065 register Lisp_Object tail, prop, val;
2066
2067 if (EQ (frame, Qnil))
2068 frame = selected_frame;
2069 CHECK_LIVE_FRAME (frame, 0);
2070 f = XFRAME (frame);
2071
2072 /* I think this should be done with a hook. */
2073 #ifdef HAVE_WINDOW_SYSTEM
2074 if (FRAME_WINDOW_P (f))
2075 x_set_frame_parameters (f, alist);
2076 else
2077 #endif
2078 #ifdef MSDOS
2079 if (FRAME_MSDOS_P (f))
2080 IT_set_frame_parameters (f, alist);
2081 else
2082 #endif
2083 #ifdef macintosh
2084 if (FRAME_MAC_P (f))
2085 mac_set_frame_parameters (f, alist);
2086 else
2087 #endif
2088
2089 {
2090 int length = XINT (Flength (alist));
2091 int i;
2092 Lisp_Object *parms
2093 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2094 Lisp_Object *values
2095 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2096
2097 /* Extract parm names and values into those vectors. */
2098
2099 i = 0;
2100 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2101 {
2102 Lisp_Object elt;
2103
2104 elt = Fcar (tail);
2105 parms[i] = Fcar (elt);
2106 values[i] = Fcdr (elt);
2107 i++;
2108 }
2109
2110 /* Now process them in reverse of specified order. */
2111 for (i--; i >= 0; i--)
2112 {
2113 prop = parms[i];
2114 val = values[i];
2115 store_frame_param (f, prop, val);
2116 }
2117 }
2118
2119 return Qnil;
2120 }
2121 \f
2122 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
2123 0, 1, 0,
2124 "Height in pixels of a line in the font in frame FRAME.\n\
2125 If FRAME is omitted, the selected frame is used.\n\
2126 For a terminal frame, the value is always 1.")
2127 (frame)
2128 Lisp_Object frame;
2129 {
2130 struct frame *f;
2131
2132 if (NILP (frame))
2133 frame = selected_frame;
2134 CHECK_FRAME (frame, 0);
2135 f = XFRAME (frame);
2136
2137 #ifdef HAVE_WINDOW_SYSTEM
2138 if (FRAME_WINDOW_P (f))
2139 return make_number (x_char_height (f));
2140 else
2141 #endif
2142 return make_number (1);
2143 }
2144
2145
2146 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
2147 0, 1, 0,
2148 "Width in pixels of characters in the font in frame FRAME.\n\
2149 If FRAME is omitted, the selected frame is used.\n\
2150 The width is the same for all characters, because\n\
2151 currently Emacs supports only fixed-width fonts.\n\
2152 For a terminal screen, the value is always 1.")
2153 (frame)
2154 Lisp_Object frame;
2155 {
2156 struct frame *f;
2157
2158 if (NILP (frame))
2159 frame = selected_frame;
2160 CHECK_FRAME (frame, 0);
2161 f = XFRAME (frame);
2162
2163 #ifdef HAVE_WINDOW_SYSTEM
2164 if (FRAME_WINDOW_P (f))
2165 return make_number (x_char_width (f));
2166 else
2167 #endif
2168 return make_number (1);
2169 }
2170
2171 DEFUN ("frame-pixel-height", Fframe_pixel_height,
2172 Sframe_pixel_height, 0, 1, 0,
2173 "Return a FRAME's height in pixels.\n\
2174 This counts only the height available for text lines,\n\
2175 not menu bars on window-system Emacs frames.\n\
2176 For a terminal frame, the result really gives the height in characters.\n\
2177 If FRAME is omitted, the selected frame is used.")
2178 (frame)
2179 Lisp_Object frame;
2180 {
2181 struct frame *f;
2182
2183 if (NILP (frame))
2184 frame = selected_frame;
2185 CHECK_FRAME (frame, 0);
2186 f = XFRAME (frame);
2187
2188 #ifdef HAVE_WINDOW_SYSTEM
2189 if (FRAME_WINDOW_P (f))
2190 return make_number (x_pixel_height (f));
2191 else
2192 #endif
2193 return make_number (FRAME_HEIGHT (f));
2194 }
2195
2196 DEFUN ("frame-pixel-width", Fframe_pixel_width,
2197 Sframe_pixel_width, 0, 1, 0,
2198 "Return FRAME's width in pixels.\n\
2199 For a terminal frame, the result really gives the width in characters.\n\
2200 If FRAME is omitted, the selected frame is used.")
2201 (frame)
2202 Lisp_Object frame;
2203 {
2204 struct frame *f;
2205
2206 if (NILP (frame))
2207 frame = selected_frame;
2208 CHECK_FRAME (frame, 0);
2209 f = XFRAME (frame);
2210
2211 #ifdef HAVE_WINDOW_SYSTEM
2212 if (FRAME_WINDOW_P (f))
2213 return make_number (x_pixel_width (f));
2214 else
2215 #endif
2216 return make_number (FRAME_WIDTH (f));
2217 }
2218 \f
2219 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
2220 "Specify that the frame FRAME has LINES lines.\n\
2221 Optional third arg non-nil means that redisplay should use LINES lines\n\
2222 but that the idea of the actual height of the frame should not be changed.")
2223 (frame, lines, pretend)
2224 Lisp_Object frame, lines, pretend;
2225 {
2226 register struct frame *f;
2227
2228 CHECK_NUMBER (lines, 0);
2229 if (NILP (frame))
2230 frame = selected_frame;
2231 CHECK_LIVE_FRAME (frame, 0);
2232 f = XFRAME (frame);
2233
2234 /* I think this should be done with a hook. */
2235 #ifdef HAVE_WINDOW_SYSTEM
2236 if (FRAME_WINDOW_P (f))
2237 {
2238 if (XINT (lines) != f->height)
2239 x_set_window_size (f, 1, f->width, XINT (lines));
2240 do_pending_window_change (0);
2241 }
2242 else
2243 #endif
2244 change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0, 0);
2245 return Qnil;
2246 }
2247
2248 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
2249 "Specify that the frame FRAME has COLS columns.\n\
2250 Optional third arg non-nil means that redisplay should use COLS columns\n\
2251 but that the idea of the actual width of the frame should not be changed.")
2252 (frame, cols, pretend)
2253 Lisp_Object frame, cols, pretend;
2254 {
2255 register struct frame *f;
2256 CHECK_NUMBER (cols, 0);
2257 if (NILP (frame))
2258 frame = selected_frame;
2259 CHECK_LIVE_FRAME (frame, 0);
2260 f = XFRAME (frame);
2261
2262 /* I think this should be done with a hook. */
2263 #ifdef HAVE_WINDOW_SYSTEM
2264 if (FRAME_WINDOW_P (f))
2265 {
2266 if (XINT (cols) != f->width)
2267 x_set_window_size (f, 1, XINT (cols), f->height);
2268 do_pending_window_change (0);
2269 }
2270 else
2271 #endif
2272 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0, 0);
2273 return Qnil;
2274 }
2275
2276 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
2277 "Sets size of FRAME to COLS by ROWS, measured in characters.")
2278 (frame, cols, rows)
2279 Lisp_Object frame, cols, rows;
2280 {
2281 register struct frame *f;
2282
2283 CHECK_LIVE_FRAME (frame, 0);
2284 CHECK_NUMBER (cols, 2);
2285 CHECK_NUMBER (rows, 1);
2286 f = XFRAME (frame);
2287
2288 /* I think this should be done with a hook. */
2289 #ifdef HAVE_WINDOW_SYSTEM
2290 if (FRAME_WINDOW_P (f))
2291 {
2292 if (XINT (rows) != f->height || XINT (cols) != f->width
2293 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
2294 x_set_window_size (f, 1, XINT (cols), XINT (rows));
2295 do_pending_window_change (0);
2296 }
2297 else
2298 #endif
2299 change_frame_size (f, XINT (rows), XINT (cols), 0, 0, 0);
2300
2301 return Qnil;
2302 }
2303
2304 DEFUN ("set-frame-position", Fset_frame_position,
2305 Sset_frame_position, 3, 3, 0,
2306 "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
2307 This is actually the position of the upper left corner of the frame.\n\
2308 Negative values for XOFFSET or YOFFSET are interpreted relative to\n\
2309 the rightmost or bottommost possible position (that stays within the screen).")
2310 (frame, xoffset, yoffset)
2311 Lisp_Object frame, xoffset, yoffset;
2312 {
2313 register struct frame *f;
2314
2315 CHECK_LIVE_FRAME (frame, 0);
2316 CHECK_NUMBER (xoffset, 1);
2317 CHECK_NUMBER (yoffset, 2);
2318 f = XFRAME (frame);
2319
2320 /* I think this should be done with a hook. */
2321 #ifdef HAVE_WINDOW_SYSTEM
2322 if (FRAME_WINDOW_P (f))
2323 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
2324 #endif
2325
2326 return Qt;
2327 }
2328
2329 \f
2330 void
2331 syms_of_frame ()
2332 {
2333 syms_of_frame_1 ();
2334
2335 staticpro (&Vframe_list);
2336
2337 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
2338 "The initial frame-object, which represents Emacs's stdout.");
2339
2340 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
2341 "Non-nil if all of emacs is iconified and frame updates are not needed.");
2342 Vemacs_iconified = Qnil;
2343
2344 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
2345 "Minibufferless frames use this frame's minibuffer.\n\
2346 \n\
2347 Emacs cannot create minibufferless frames unless this is set to an\n\
2348 appropriate surrogate.\n\
2349 \n\
2350 Emacs consults this variable only when creating minibufferless\n\
2351 frames; once the frame is created, it sticks with its assigned\n\
2352 minibuffer, no matter what this variable is set to. This means that\n\
2353 this variable doesn't necessarily say anything meaningful about the\n\
2354 current set of frames, or where the minibuffer is currently being\n\
2355 displayed.");
2356
2357 defsubr (&Sactive_minibuffer_window);
2358 defsubr (&Sframep);
2359 defsubr (&Sframe_live_p);
2360 defsubr (&Smake_terminal_frame);
2361 defsubr (&Shandle_switch_frame);
2362 defsubr (&Signore_event);
2363 defsubr (&Sselect_frame);
2364 defsubr (&Sselected_frame);
2365 defsubr (&Swindow_frame);
2366 defsubr (&Sframe_root_window);
2367 defsubr (&Sframe_first_window);
2368 defsubr (&Sframe_selected_window);
2369 defsubr (&Sset_frame_selected_window);
2370 defsubr (&Sframe_list);
2371 defsubr (&Snext_frame);
2372 defsubr (&Sprevious_frame);
2373 defsubr (&Sdelete_frame);
2374 defsubr (&Smouse_position);
2375 defsubr (&Smouse_pixel_position);
2376 defsubr (&Sset_mouse_position);
2377 defsubr (&Sset_mouse_pixel_position);
2378 #if 0
2379 defsubr (&Sframe_configuration);
2380 defsubr (&Srestore_frame_configuration);
2381 #endif
2382 defsubr (&Smake_frame_visible);
2383 defsubr (&Smake_frame_invisible);
2384 defsubr (&Siconify_frame);
2385 defsubr (&Sframe_visible_p);
2386 defsubr (&Svisible_frame_list);
2387 defsubr (&Sraise_frame);
2388 defsubr (&Slower_frame);
2389 defsubr (&Sredirect_frame_focus);
2390 defsubr (&Sframe_focus);
2391 defsubr (&Sframe_parameters);
2392 defsubr (&Smodify_frame_parameters);
2393 defsubr (&Sframe_char_height);
2394 defsubr (&Sframe_char_width);
2395 defsubr (&Sframe_pixel_height);
2396 defsubr (&Sframe_pixel_width);
2397 defsubr (&Sset_frame_height);
2398 defsubr (&Sset_frame_width);
2399 defsubr (&Sset_frame_size);
2400 defsubr (&Sset_frame_position);
2401 }
2402
2403 void
2404 keys_of_frame ()
2405 {
2406 initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
2407 initial_define_lispy_key (global_map, "delete-frame", "handle-delete-frame");
2408 initial_define_lispy_key (global_map, "iconify-frame", "ignore-event");
2409 initial_define_lispy_key (global_map, "make-frame-visible", "ignore-event");
2410 }