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