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