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