-/* Generic screen functions.
- Copyright (C) 1989 Free Software Foundation.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <stdio.h>
-
-#include "config.h"
-#include "lisp.h"
-#include "screen.h"
-#include "window.h"
-#include "termhooks.h"
-
-Lisp_Object Vemacs_iconified;
-Lisp_Object Qscreenp;
-Lisp_Object Qlive_screen_p;
-Lisp_Object Vscreen_list;
-Lisp_Object Vterminal_screen;
-Lisp_Object Vdefault_minibuffer_screen;
-Lisp_Object Vdefault_screen_alist;
-
-/* A screen which is not just a minibuffer, or 0 if there are no
- such screens. This is usually the most recent such screen that
- was selected. */
-struct screen *last_nonminibuf_screen;
-
-extern Lisp_Object Vminibuffer_list;
-extern Lisp_Object get_minibuffer ();
-\f
-DEFUN ("screenp", Fscreenp, Sscreenp, 1, 1, 0,
- "Return non-nil if OBJECT is a screen.\n\
-Value is t for a termcap screen (a character-only terminal),\n\
-`x' for an Emacs screen that is really an X window.\n\
-Also see live-screen-p.")
- (object)
- Lisp_Object object;
-{
- if (XTYPE (object) != Lisp_Screen)
- return Qnil;
- switch (XSCREEN (object)->output_method)
- {
- case output_termcap:
- return Qt;
- case output_x_window:
- return intern ("x");
- default:
- abort ();
- }
-}
-
-DEFUN ("live-screen-p", Flive_screen_p, Slive_screen_p, 1, 1, 0,
- "Return non-nil if OBJECT is a screen which has not been deleted.\n\
-Value is nil if OBJECT is not a live screen. If object is a live\n\
-screen, the return value indicates what sort of output device it is\n\
-displayed on. Value is t for a termcap screen (a character-only\n\
-terminal), `x' for an Emacs screen being displayed in an X window.")
- (object)
- Lisp_Object object;
-{
- return ((SCREENP (object)
- && SCREEN_LIVE_P (XSCREEN (object)))
- ? Fscreenp (object)
- : Qnil);
-}
-
-struct screen *
-make_screen (mini_p)
- int mini_p;
-{
- Lisp_Object screen;
- register struct screen *s;
- register Lisp_Object root_window;
- register Lisp_Object mini_window;
-
- screen = Fmake_vector (((sizeof (struct screen) - (sizeof (Lisp_Vector)
- - sizeof (Lisp_Object)))
- / sizeof (Lisp_Object)),
- make_number (0));
- XSETTYPE (screen, Lisp_Screen);
- s = XSCREEN (screen);
-
- s->cursor_x = 0;
- s->cursor_y = 0;
- s->current_glyphs = 0;
- s->desired_glyphs = 0;
- s->visible = 0;
- s->display.nothing = 0;
- s->iconified = 0;
- s->wants_modeline = 1;
- s->auto_raise = 0;
- s->auto_lower = 0;
- s->no_split = 0;
- s->garbaged = 0;
- s->has_minibuffer = mini_p;
- s->focus_screen = screen;
-
- s->param_alist = Qnil;
-
- root_window = make_window (0);
- if (mini_p)
- {
- mini_window = make_window (0);
- XWINDOW (root_window)->next = mini_window;
- XWINDOW (mini_window)->prev = root_window;
- XWINDOW (mini_window)->mini_p = Qt;
- XWINDOW (mini_window)->screen = screen;
- s->minibuffer_window = mini_window;
- }
- else
- {
- mini_window = Qnil;
- XWINDOW (root_window)->next = Qnil;
- s->minibuffer_window = Qnil;
- }
-
- XWINDOW (root_window)->screen = screen;
-
- /* 10 is arbitrary,
- just so that there is "something there."
- Correct size will be set up later with change_screen_size. */
-
- s->width = 10;
- s->height = 10;
-
- XFASTINT (XWINDOW (root_window)->width) = 10;
- XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
-
- if (mini_p)
- {
- XFASTINT (XWINDOW (mini_window)->width) = 10;
- XFASTINT (XWINDOW (mini_window)->top) = 9;
- XFASTINT (XWINDOW (mini_window)->height) = 1;
- }
-
- /* Choose a buffer for the screen's root window. */
- {
- Lisp_Object buf;
-
- XWINDOW (root_window)->buffer = Qt;
- buf = Fcurrent_buffer ();
- /* If buf is a 'hidden' buffer (i.e. one whose name starts with
- a space), try to find another one. */
- if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
- buf = Fother_buffer (buf);
- Fset_window_buffer (root_window, buf);
- }
-
- if (mini_p)
- {
- XWINDOW (mini_window)->buffer = Qt;
- Fset_window_buffer (mini_window,
- (NILP (Vminibuffer_list)
- ? get_minibuffer (0)
- : Fcar (Vminibuffer_list)));
- }
-
- s->root_window = root_window;
- s->selected_window = root_window;
- /* Make sure this window seems more recently used than
- a newly-created, never-selected window. */
- XFASTINT (XWINDOW (s->selected_window)->use_time) = ++window_select_count;
-
- Vscreen_list = Fcons (screen, Vscreen_list);
-
- return s;
-}
-\f
-/* Make a screen using a separate minibuffer window on another screen.
- MINI_WINDOW is the minibuffer window to use. nil means use the
- default (the global minibuffer). */
-
-struct screen *
-make_screen_without_minibuffer (mini_window)
- register Lisp_Object mini_window;
-{
- register struct screen *s;
-
- /* Choose the minibuffer window to use. */
- if (NILP (mini_window))
- {
- if (XTYPE (Vdefault_minibuffer_screen) != Lisp_Screen)
- error ("default-minibuffer-screen must be set when creating minibufferless screens.");
- mini_window = XSCREEN (Vdefault_minibuffer_screen)->minibuffer_window;
- }
- else
- {
- CHECK_WINDOW (mini_window, 0);
- }
-
- /* Make a screen containing just a root window. */
- s = make_screen (0);
-
- /* Install the chosen minibuffer window, with proper buffer. */
- s->minibuffer_window = mini_window;
- Fset_window_buffer (mini_window,
- (NILP (Vminibuffer_list)
- ? get_minibuffer (0)
- : Fcar (Vminibuffer_list)));
- return s;
-}
-
-/* Make a screen containing only a minibuffer window. */
-
-struct screen *
-make_minibuffer_screen ()
-{
- /* First make a screen containing just a root window, no minibuffer. */
-
- register struct screen *s = make_screen (0);
- register Lisp_Object mini_window;
- register Lisp_Object screen;
-
- XSET (screen, Lisp_Screen, s);
-
- /* ??? Perhaps leave it to the user program to set auto_raise. */
- s->auto_raise = 1;
- s->auto_lower = 0;
- s->no_split = 1;
- s->wants_modeline = 0;
- s->has_minibuffer = 1;
-
- /* Now label the root window as also being the minibuffer.
- Avoid infinite looping on the window chain by marking next pointer
- as nil. */
-
- mini_window = s->minibuffer_window = s->root_window;
- XWINDOW (mini_window)->mini_p = Qt;
- XWINDOW (mini_window)->next = Qnil;
- XWINDOW (mini_window)->prev = mini_window;
- XWINDOW (mini_window)->screen = screen;
-
- /* Put the proper buffer in that window. */
-
- Fset_window_buffer (mini_window,
- (NILP (Vminibuffer_list)
- ? get_minibuffer (0)
- : Fcar (Vminibuffer_list)));
- return s;
-}
-\f
-/* Construct a screen that refers to the terminal (stdin and stdout). */
-
-struct screen *
-make_terminal_screen ()
-{
- register struct screen *s;
-
- Vscreen_list = Qnil;
- s = make_screen (1);
- s->name = build_string ("terminal");
- s->visible = 1;
- s->display.nothing = 1; /* Nonzero means screen isn't deleted. */
- XSET (Vterminal_screen, Lisp_Screen, s);
- return s;
-}
-\f
-DEFUN ("select-screen", Fselect_screen, Sselect_screen, 1, 2, 0,
- "Select the screen S. S's selected window becomes \"the\"\n\
-selected window. If the optional parameter NO-ENTER is non-nil, don't\n\
-focus on that screen.")
- (screen, no_enter)
- Lisp_Object screen, no_enter;
-{
- CHECK_LIVE_SCREEN (screen, 0);
-
- if (selected_screen == XSCREEN (screen))
- return screen;
-
- selected_screen = XSCREEN (screen);
- if (! SCREEN_MINIBUF_ONLY_P (selected_screen))
- last_nonminibuf_screen = selected_screen;
-
- Fselect_window (XSCREEN (screen)->selected_window);
-
-#ifdef HAVE_X_WINDOWS
-#ifdef MULTI_SCREEN
- if (XSCREEN (screen)->output_method == output_x_window
- && NILP (no_enter))
- {
- Ffocus_screen (screen);
- }
-#endif
-#endif
- choose_minibuf_screen ();
-
- return screen;
-}
-
-DEFUN ("selected-screen", Fselected_screen, Sselected_screen, 0, 0, 0,
- "Return the screen that is now selected.")
- ()
-{
- Lisp_Object tem;
- XSET (tem, Lisp_Screen, selected_screen);
- return tem;
-}
-
-DEFUN ("window-screen", Fwindow_screen, Swindow_screen, 1, 1, 0,
- "Return the screen object that window WINDOW is on.")
- (window)
- Lisp_Object window;
-{
- CHECK_WINDOW (window, 0);
- return XWINDOW (window)->screen;
-}
-
-DEFUN ("screen-root-window", Fscreen_root_window, Sscreen_root_window, 0, 1, 0,
- "Returns the root-window of SCREEN.")
- (screen)
- Lisp_Object screen;
-{
- if (NILP (screen))
- XSET (screen, Lisp_Screen, selected_screen);
- else
- CHECK_LIVE_SCREEN (screen, 0);
-
- return XSCREEN (screen)->root_window;
-}
-
-DEFUN ("screen-selected-window", Fscreen_selected_window,
- Sscreen_selected_window, 0, 1, 0,
- "Return the selected window of screen object SCREEN.")
- (screen)
- Lisp_Object screen;
-{
- if (NILP (screen))
- XSET (screen, Lisp_Screen, selected_screen);
- else
- CHECK_LIVE_SCREEN (screen, 0);
-
- return XSCREEN (screen)->selected_window;
-}
-
-DEFUN ("screen-list", Fscreen_list, Sscreen_list,
- 0, 0, 0,
- "Return a list of all screens.")
- ()
-{
- return Fcopy_sequence (Vscreen_list);
-}
-
-#ifdef MULTI_SCREEN
-
-/* Return the next screen in the screen list after SCREEN.
- If MINIBUF is non-nil, include all screens.
- If MINIBUF is nil, exclude minibuffer-only screens.
- If MINIBUF is a window, include only screens using that window for
- their minibuffer. */
-Lisp_Object
-next_screen (screen, minibuf)
- Lisp_Object screen;
- Lisp_Object minibuf;
-{
- Lisp_Object tail;
- int passed = 0;
-
- /* There must always be at least one screen in Vscreen_list. */
- if (! CONSP (Vscreen_list))
- abort ();
-
- while (1)
- for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- if (passed)
- {
- Lisp_Object s = XCONS (tail)->car;
-
- /* Decide whether this screen is eligible to be returned,
- according to minibuf. */
- if ((NILP (minibuf) && ! SCREEN_MINIBUF_ONLY_P (XSCREEN (s)))
- || XTYPE (minibuf) != Lisp_Window
- || EQ (SCREEN_MINIBUF_WINDOW (XSCREEN (s)), minibuf)
- || EQ (s, screen))
- return s;
- }
-
- if (EQ (screen, XCONS (tail)->car))
- passed++;
- }
-}
-
-/* Return the previous screen in the screen list before SCREEN.
- If MINIBUF is non-nil, include all screens.
- If MINIBUF is nil, exclude minibuffer-only screens.
- If MINIBUF is a window, include only screens using that window for
- their minibuffer. */
-Lisp_Object
-prev_screen (screen, minibuf)
- Lisp_Object screen;
- Lisp_Object minibuf;
-{
- Lisp_Object tail;
- Lisp_Object prev;
-
- /* There must always be at least one screen in Vscreen_list. */
- if (! CONSP (Vscreen_list))
- abort ();
-
- prev = Qnil;
- while (1)
- {
- for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object scr = XCONS (tail)->car;
-
- if (XTYPE (scr) != Lisp_Screen)
- abort ();
-
- if (EQ (screen, scr) && !NILP (prev))
- return prev;
-
- /* Decide whether this screen is eligible to be returned,
- according to minibuf. */
- if ((NILP (minibuf) && ! SCREEN_MINIBUF_ONLY_P (XSCREEN (scr)))
- || XTYPE (minibuf) != Lisp_Window
- || EQ (SCREEN_MINIBUF_WINDOW (XSCREEN (scr)), minibuf))
- prev = scr;
- }
-
- if (NILP (prev))
- /* We went through the whole screen list without finding a single
- acceptable screen. Return the original screen. */
- prev = screen;
- }
-
-}
-
-DEFUN ("next-screen", Fnext_screen, Snext_screen, 0, 2, 0,
- "Return the next screen in the screen list after SCREEN.\n\
-If optional argument MINIBUF is non-nil, include all screens. If\n\
-MINIBUF is nil or omitted, exclude minibuffer-only screens. If\n\
-MINIBUF is a window, include only screens using that window for their\n\
-minibuffer.")
- (screen, miniscreen)
-Lisp_Object screen, miniscreen;
-{
- Lisp_Object tail;
-
- if (NILP (screen))
- XSET (screen, Lisp_Screen, selected_screen);
- else
- CHECK_LIVE_SCREEN (screen, 0);
-
- return next_screen (screen, miniscreen);
-}
-#endif /* MULTI_SCREEN */
-\f
-DEFUN ("delete-screen", Fdelete_screen, Sdelete_screen, 0, 1, "",
- "Delete SCREEN, permanently eliminating it from use.\n\
-If omitted, SCREEN defaults to the selected screen.\n\
-A screen may not be deleted if its minibuffer is used by other screens.")
- (screen)
- Lisp_Object screen;
-{
- struct screen *s;
- union display displ;
-
- if (EQ (screen, Qnil))
- {
- s = selected_screen;
- XSET (screen, Lisp_Screen, s);
- }
- else
- {
- CHECK_SCREEN (screen, 0);
- s = XSCREEN (screen);
- }
-
- if (! SCREEN_LIVE_P (s))
- return;
-
- /* Are there any other screens besides this one? */
- if (s == selected_screen && EQ (next_screen (screen, Qt), screen))
- error ("Attempt to delete the only screen");
-
- /* Does this screen have a minibuffer, and is it the surrogate
- minibuffer for any other screen? */
- if (SCREEN_HAS_MINIBUF (XSCREEN (screen)))
- {
- Lisp_Object screen2;
-
- for (screen2 = Vscreen_list; CONSP (2); screen2 = XCONS (screen2)->cdr)
- if (! EQ (screen2, screen)
- && EQ (screen,
- (WINDOW_SCREEN
- (XWINDOW
- (SCREEN_MINIBUF_WINDOW
- (XSCREEN (screen2)))))))
- error ("Attempt to delete a surrogate minibuffer screen");
- }
-
- /* Don't let the screen remain selected. */
- if (s == selected_screen)
- Fselect_screen (next_screen (screen, Qt));
-
- /* Don't allow minibuf_window to remain on a deleted screen. */
- if (EQ (s->minibuffer_window, minibuf_window))
- {
- Fset_window_buffer (selected_screen->minibuffer_window,
- XWINDOW (minibuf_window)->buffer);
- minibuf_window = selected_screen->minibuffer_window;
- }
-
- Vscreen_list = Fdelq (screen, Vscreen_list);
- s->visible = 0;
- displ = s->display;
- s->display.nothing = 0;
-
-#ifdef HAVE_X_WINDOWS
- if (s->output_method == output_x_window)
- x_destroy_window (s, displ);
-#endif
-
- /* If we've deleted the last_nonminibuf_screen, then try to find
- another one. */
- if (s == last_nonminibuf_screen)
- {
- last_nonminibuf_screen = 0;
-
- for (screen = Vscreen_list; CONSP (screen); screen = XCONS (screen)->cdr)
- {
- s = XSCREEN (XCONS (screen)->car);
- if (!SCREEN_MINIBUF_ONLY_P (s))
- {
- last_nonminibuf_screen = s;
- break;
- }
- }
- }
-
- return Qnil;
-}
-\f
-/* Return mouse position in character cell units. */
-
-DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
- "Return a list (SCREEN X . Y) giving the current mouse screen and position.\n\
-If Emacs is running on a mouseless terminal or hasn't been programmed\n\
-to read the mouse position, it returns the selected screen for SCREEN\n\
-and nil for X and Y.")
- ()
-{
- Lisp_Object x, y, dummy;
- SCREEN_PTR s;
-
- if (mouse_position_hook)
- (*mouse_position_hook) (&s, &x, &y, &dummy);
- else
- {
- s = selected_screen;
- x = y = Qnil;
- }
-
- XSET (dummy, Lisp_Screen, s);
- return Fcons (dummy, Fcons (make_number (x), make_number (y)));
-}
-
-DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
- "Move the mouse pointer to the center of cell (X,Y) in SCREEN.\n\
-WARNING: If you use this under X, you should do unfocus-screen afterwards.")
- (screen, x, y)
- Lisp_Object screen, x, y;
-{
- CHECK_LIVE_SCREEN (screen, 0);
- CHECK_NUMBER (x, 2);
- CHECK_NUMBER (y, 1);
-
-#ifdef HAVE_X_WINDOWS
- if (XSCREEN (screen)->output_method == output_x_window)
- /* Warping the mouse will cause enternotify and focus events. */
- x_set_mouse_position (XSCREEN (screen), x, y);
-#endif
-
- return Qnil;
-}
-\f
-#if 0
-/* ??? Can this be replaced with a Lisp function?
- It is used in minibuf.c. Can we get rid of that? */
-
-DEFUN ("screen-configuration", Fscreen_configuration, Sscreen_configuration,
- 0, 0, 0,
- "Return object describing current screen configuration.\n\
-The screen configuration is the current mouse position and selected screen.\n\
-This object can be given to `restore-screen-configuration'\n\
-to restore this screen configuration.")
- ()
-{
- Lisp_Object c, time;
-
- c = Fmake_vector (make_number(4), Qnil);
- XVECTOR (c)->contents[0] = Fselected_screen();
- if (mouse_position_hook)
- (*mouse_position_hook) (&XVECTOR (c)->contents[1]
- &XVECTOR (c)->contents[2],
- &XVECTOR (c)->contents[3],
- &time);
- return c;
-}
-
-DEFUN ("restore-screen-configuration", Frestore_screen_configuration,
- Srestore_screen_configuration,
- 1, 1, 0,
- "Restores screen configuration CONFIGURATION.")
- (config)
- Lisp_Object config;
-{
- Lisp_Object x_pos, y_pos, screen;
-
- CHECK_VECTOR (config, 0);
- if (XVECTOR (config)->size != 3)
- {
- error ("Wrong size vector passed to restore-screen-configuration");
- }
- screen = XVECTOR (config)->contents[0];
- CHECK_LIVE_SCREEN (screen, 0);
-
- Fselect_screen (screen, Qnil);
-
-#if 0
- /* This seems to interfere with the screen selection mechanism. jla */
- x_pos = XVECTOR (config)->contents[2];
- y_pos = XVECTOR (config)->contents[3];
- set_mouse_position (screen, XINT (x_pos), XINT (y_pos));
-#endif
-
- return screen;
-}
-#endif
-\f
-DEFUN ("make-screen-visible", Fmake_screen_visible, Smake_screen_visible,
- 1, 1, 0,
- "Make the screen SCREEN visible (assuming it is an X-window).\n\
-Also raises the screen so that nothing obscures it.")
- (screen)
- Lisp_Object screen;
-{
- CHECK_LIVE_SCREEN (screen, 0);
-
- if (XSCREEN (screen)->output_method == output_x_window)
- x_make_screen_visible (XSCREEN (screen));
-
- return screen;
-}
-
-DEFUN ("make-screen-invisible", Fmake_screen_invisible, Smake_screen_invisible,
- 1, 1, 0,
- "Make the screen SCREEN invisible (assuming it is an X-window).")
- (screen)
- Lisp_Object screen;
-{
- CHECK_LIVE_SCREEN (screen, 0);
-
- if (XSCREEN (screen)->output_method == output_x_window)
- x_make_screen_invisible (XSCREEN (screen));
-
- return Qnil;
-}
-
-DEFUN ("iconify-screen", Ficonify_screen, Siconify_screen,
- 1, 1, 0,
- "Make the screen SCREEN into an icon.")
- (screen)
- Lisp_Object screen;
-{
- CHECK_LIVE_SCREEN (screen, 0);
-
- if (XSCREEN (screen)->output_method == output_x_window)
- x_iconify_screen (XSCREEN (screen));
-
- return Qnil;
-}
-
-DEFUN ("deiconify-screen", Fdeiconify_screen, Sdeiconify_screen,
- 1, 1, 0,
- "Open (de-iconify) the iconified screen SCREEN.")
- (screen)
- Lisp_Object screen;
-{
- CHECK_LIVE_SCREEN (screen, 0);
-
- if (XSCREEN (screen)->output_method == output_x_window)
- x_make_screen_visible (XSCREEN (screen));
-
- return screen;
-}
-
-DEFUN ("screen-visible-p", Fscreen_visible_p, Sscreen_visible_p,
- 1, 1, 0,
- "Return t if SCREEN is now \"visible\" (actually in use for display).\n\
-A screen that is not \"visible\" is not updated and, if it works through\n\
-a window system, it may not show at all.\n\
-Return the symbol `icon' if window is visible only as an icon.")
- (screen)
- Lisp_Object screen;
-{
- CHECK_LIVE_SCREEN (screen, 0);
-
- if (XSCREEN (screen)->visible)
- return Qt;
- if (XSCREEN (screen)->iconified)
- return intern ("icon");
- return Qnil;
-}
-
-DEFUN ("visible-screen-list", Fvisible_screen_list, Svisible_screen_list,
- 0, 0, 0,
- "Return a list of all screens now \"visible\" (being updated).")
- ()
-{
- Lisp_Object tail, screen;
- struct screen *s;
- Lisp_Object value;
-
- value = Qnil;
- for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- screen = XCONS (tail)->car;
- if (XTYPE (screen) != Lisp_Screen)
- continue;
- s = XSCREEN (screen);
- if (s->visible)
- value = Fcons (screen, value);
- }
- return value;
-}
-
-
-\f
-DEFUN ("redirect-screen-focus", Fredirect_screen_focus, Sredirect_screen_focus,
- 1, 2, 0,
- "Arrange for keystrokes typed at SCREEN to be sent to FOCUS-SCREEN.\n\
-This means that, after reading a keystroke typed at SCREEN,\n\
-last-event-screen will be FOCUS-SCREEN.\n\
-\n\
-If FOCUS-SCREEN is omitted or eq to SCREEN, any existing redirection is\n\
-cancelled, and the screen again receives its own keystrokes.\n\
-\n\
-The redirection lasts until the next call to redirect-screen-focus\n\
-or select-screen.\n\
-\n\
-This is useful for temporarily redirecting keystrokes to the minibuffer\n\
-window when a screen doesn't have its own minibuffer.")
- (screen, focus_screen)
- Lisp_Object screen, focus_screen;
-{
- CHECK_LIVE_SCREEN (screen, 0);
-
- if (NILP (focus_screen))
- focus_screen = screen;
- else
- CHECK_LIVE_SCREEN (focus_screen, 1);
-
- XSCREEN (screen)->focus_screen = focus_screen;
-
- if (screen_rehighlight_hook)
- (*screen_rehighlight_hook) ();
-
- return Qnil;
-}
-
-
-DEFUN ("screen-focus", Fscreen_focus, Sscreen_focus, 1, 1, 0,
- "Return the screen to which SCREEN's keystrokes are currently being sent.\n\
-See redirect-screen-focus.")
- (screen)
- Lisp_Object screen;
-{
- CHECK_LIVE_SCREEN (screen, 0);
- return SCREEN_FOCUS_SCREEN (XSCREEN (screen));
-}
-
-
-\f
-Lisp_Object
-get_screen_param (screen, prop)
- register struct screen *screen;
- Lisp_Object prop;
-{
- register Lisp_Object tem;
-
- tem = Fassq (prop, screen->param_alist);
- if (EQ (tem, Qnil))
- return tem;
- return Fcdr (tem);
-}
-
-void
-store_in_alist (alistptr, propname, val)
- Lisp_Object *alistptr, val;
- char *propname;
-{
- register Lisp_Object tem;
- register Lisp_Object prop;
-
- prop = intern (propname);
- tem = Fassq (prop, *alistptr);
- if (EQ (tem, Qnil))
- *alistptr = Fcons (Fcons (prop, val), *alistptr);
- else
- Fsetcdr (tem, val);
-}
-
-void
-store_screen_param (s, prop, val)
- struct screen *s;
- Lisp_Object prop, val;
-{
- register Lisp_Object tem;
-
- tem = Fassq (prop, s->param_alist);
- if (EQ (tem, Qnil))
- s->param_alist = Fcons (Fcons (prop, val), s->param_alist);
- else
- Fsetcdr (tem, val);
-}
-
-DEFUN ("screen-parameters", Fscreen_parameters, Sscreen_parameters, 0, 1, 0,
- "Return the parameters-alist of screen SCREEN.\n\
-It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
-The meaningful PARMs depend on the kind of screen.")
- (screen)
- Lisp_Object screen;
-{
- Lisp_Object alist;
- struct screen *s;
-
- if (EQ (screen, Qnil))
- s = selected_screen;
- else
- {
- CHECK_SCREEN (screen, 0);
- s = XSCREEN (screen);
- }
-
- if (s->display.nothing == 0)
- return Qnil;
-
- alist = Fcopy_alist (s->param_alist);
- store_in_alist (&alist, "name", s->name);
- store_in_alist (&alist, "height", make_number (s->height));
- store_in_alist (&alist, "width", make_number (s->width));
- store_in_alist (&alist, "modeline", (s->wants_modeline ? Qt : Qnil));
- store_in_alist (&alist, "minibuffer",
- (SCREEN_HAS_MINIBUF (s)
- ? (SCREEN_MINIBUF_ONLY_P (s) ? intern ("only") : Qt)
- : Qnil));
- store_in_alist (&alist, "unsplittable", (s->no_split ? Qt : Qnil));
-
- if (s->output_method == output_x_window)
- x_report_screen_params (s, &alist);
- return alist;
-}
-
-DEFUN ("modify-screen-parameters", Fmodify_screen_parameters,
- Smodify_screen_parameters, 2, 2, 0,
- "Modify the parameters of screen SCREEN according to ALIST.\n\
-ALIST is an alist of parameters to change and their new values.\n\
-Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
-The meaningful PARMs depend on the kind of screen; undefined PARMs are ignored.")
- (screen, alist)
- Lisp_Object screen, alist;
-{
- register struct screen *s;
- register Lisp_Object tail, elt, prop, val;
-
- if (EQ (screen, Qnil))
- s = selected_screen;
- else
- {
- CHECK_LIVE_SCREEN (screen, 0);
- s = XSCREEN (screen);
- }
-
- if (s->output_method == output_x_window)
- for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
- {
- elt = Fcar (tail);
- prop = Fcar (elt);
- val = Fcdr (elt);
- x_set_screen_param (s, prop, val,
- get_screen_param (s, prop));
- store_screen_param (s, prop, val);
- }
-
- return Qnil;
-}
-\f
-
-DEFUN ("screen-pixel-size", Fscreen_pixel_size,
- Sscreen_pixel_size, 1, 1, 0,
- "Return a cons (width . height) of SCREEN's size in pixels.")
- (screen)
- Lisp_Object screen;
-{
- register struct screen *s;
- int width, height;
-
- CHECK_LIVE_SCREEN (screen, 0);
- s = XSCREEN (screen);
-
- return Fcons (make_number (x_pixel_width (s)),
- make_number (x_pixel_height (s)));
-}
-
-DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
- "Return number of lines available for display on selected screen.")
- ()
-{
- return make_number (SCREEN_HEIGHT (selected_screen));
-}
-
-DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
- "Return number of columns available for display on selected screen.")
- ()
-{
- return make_number (SCREEN_WIDTH (selected_screen));
-}
-
-DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 2, 3, 0,
- "Specify that the screen SCREEN has LINES lines.\n\
-Optional third arg non-nil means that redisplay should use LINES lines\n\
-but that the idea of the actual height of the screen should not be changed.")
- (screen, rows, pretend)
- Lisp_Object rows, pretend;
-{
- register struct screen *s;
-
- CHECK_NUMBER (rows, 0);
- if (NILP (screen))
- s = selected_screen;
- else
- {
- CHECK_LIVE_SCREEN (screen, 0);
- s = XSCREEN (screen);
- }
-
- if (s->output_method == output_x_window)
- {
- if (XINT (rows) != s->width)
- x_set_window_size (s, s->width, XINT (rows));
- }
- else
- change_screen_size (s, XINT (rows), 0, !NILP (pretend));
- return Qnil;
-}
-
-DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 2, 3, 0,
- "Specify that the screen SCREEN has COLS columns.\n\
-Optional third arg non-nil means that redisplay should use COLS columns\n\
-but that the idea of the actual width of the screen should not be changed.")
- (screen, cols, pretend)
- Lisp_Object cols, pretend;
-{
- register struct screen *s;
- CHECK_NUMBER (cols, 0);
- if (NILP (screen))
- s = selected_screen;
- else
- {
- CHECK_LIVE_SCREEN (screen, 0);
- s = XSCREEN (screen);
- }
-
- if (s->output_method == output_x_window)
- {
- if (XINT (cols) != s->width)
- x_set_window_size (s, XINT (cols), s->height);
- }
- else
- change_screen_size (selected_screen, 0, XINT (cols), !NILP (pretend));
- return Qnil;
-}
-
-DEFUN ("set-screen-size", Fset_screen_size, Sset_screen_size, 3, 3, 0,
- "Sets size of SCREEN to COLS by ROWS, measured in characters.")
- (screen, cols, rows)
- Lisp_Object screen, cols, rows;
-{
- register struct screen *s;
- int mask;
-
- CHECK_LIVE_SCREEN (screen, 0);
- CHECK_NUMBER (cols, 2);
- CHECK_NUMBER (rows, 1);
- s = XSCREEN (screen);
-
- if (s->output_method == output_x_window)
- {
- if (XINT (rows) != s->height || XINT (cols) != s->width)
- x_set_window_size (s, XINT (cols), XINT (rows));
- }
- else
- change_screen_size (s, XINT (rows), XINT (cols), 0);
-
- return Qnil;
-}
-
-DEFUN ("set-screen-position", Fset_screen_position,
- Sset_screen_position, 3, 3, 0,
- "Sets position of SCREEN in pixels to XOFFSET by YOFFSET.\n\
-If XOFFSET or YOFFSET are negative, they are interpreted relative to\n\
-the leftmost or bottommost position SCREEN could occupy without going\n\
-off the screen.")
- (screen, xoffset, yoffset)
- Lisp_Object screen, xoffset, yoffset;
-{
- register struct screen *s;
- int mask;
-
- CHECK_LIVE_SCREEN (screen, 0);
- CHECK_NUMBER (xoffset, 1);
- CHECK_NUMBER (yoffset, 2);
- s = XSCREEN (screen);
-
- if (s->output_method == output_x_window)
- x_set_offset (s, XINT (xoffset), XINT (yoffset));
-
- return Qt;
-}
-\f
-#ifndef HAVE_X11
-DEFUN ("rubber-band-rectangle", Frubber_band_rectangle, Srubber_band_rectangle,
- 3, 3, "",
- "Ask user to specify a window position and size on SCREEN with the mouse.\n\
-Arguments are SCREEN, NAME and GEO. NAME is a name to be displayed as\n\
-the purpose of this rectangle. GEO is an X-windows size spec that can\n\
-specify defaults for some sizes/positions. If GEO specifies everything,\n\
-the mouse is not used.\n\
-Returns a list of five values: (SCREEN LEFT TOP WIDTH HEIGHT).")
- (screen, name, geo)
- Lisp_Object screen;
- Lisp_Object name;
- Lisp_Object geo;
-{
- int vals[4];
- Lisp_Object nums[4];
- int i;
-
- CHECK_SCREEN (screen, 0);
- CHECK_STRING (name, 1);
- CHECK_STRING (geo, 2);
-
- switch (XSCREEN (screen)->output_method)
- {
- case output_x_window:
- x_rubber_band (XSCREEN (screen), &vals[0], &vals[1], &vals[2], &vals[3],
- XSTRING (geo)->data, XSTRING (name)->data);
- break;
-
- default:
- return Qnil;
- }
-
- for (i = 0; i < 4; i++)
- XFASTINT (nums[i]) = vals[i];
- return Fcons (screen, Flist (4, nums));
- return Qnil;
-}
-#endif /* not HAVE_X11 */
-\f
-choose_minibuf_screen ()
-{
- /* For lowest-level minibuf, put it on currently selected screen
- if screen has a minibuffer. */
- if (minibuf_level == 0
- && selected_screen != 0
- && !EQ (minibuf_window, selected_screen->minibuffer_window)
- && !EQ (Qnil, selected_screen->minibuffer_window))
- {
- Fset_window_buffer (selected_screen->minibuffer_window,
- XWINDOW (minibuf_window)->buffer);
- minibuf_window = selected_screen->minibuffer_window;
- }
-}
-\f
-syms_of_screen ()
-{
- Qscreenp = intern ("screenp");
- Qlive_screen_p = intern ("live_screen_p");
-
- staticpro (&Qscreenp);
- staticpro (&Qlive_screen_p);
-
- staticpro (&Vscreen_list);
-
- DEFVAR_LISP ("terminal-screen", &Vterminal_screen,
- "The initial screen-object, which represents Emacs's stdout.");
-
- DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
- "Non-nil if all of emacs is iconified and screen updates are not needed.");
- Vemacs_iconified = Qnil;
-
- DEFVAR_LISP ("default-minibuffer-screen", &Vdefault_minibuffer_screen,
- "Minibufferless screens use this screen's minibuffer.\n\
-\n\
-Emacs cannot create minibufferless screens unless this is set to an\n\
-appropriate surrogate.\n\
-\n\
-Emacs consults this variable only when creating minibufferless\n\
-screens; once the screen is created, it sticks with its assigned\n\
-minibuffer, no matter what this variable is set to. This means that\n\
-this variable doesn't necessarily say anything meaningful about the\n\
-current set of screens, or where the minibuffer is currently being\n\
-displayed.");
- Vdefault_minibuffer_screen = Qnil;
-
- DEFVAR_LISP ("default-screen-alist", &Vdefault_screen_alist,
- "Alist of default values for screen creation.\n\
-These may be set in your init file, like this:\n\
- (setq default-screen-alist '((width . 80) (height . 55)))\n\
-These override values given in window system configuration data, like\n\
-X Windows' defaults database.\n\
-For values specific to the first emacs screen, see initial-screen-alist.\n\
-For values specific to the separate minibuffer screen, see\n\
-minibuffer-screen-alist.");
- Vdefault_screen_alist = Qnil;
-
- defsubr (&Sscreenp);
- defsubr (&Slive_screen_p);
- defsubr (&Sselect_screen);
- defsubr (&Sselected_screen);
- defsubr (&Swindow_screen);
- defsubr (&Sscreen_root_window);
- defsubr (&Sscreen_selected_window);
- defsubr (&Sscreen_list);
- defsubr (&Snext_screen);
- defsubr (&Sdelete_screen);
- defsubr (&Smouse_position);
- defsubr (&Sset_mouse_position);
-#if 0
- defsubr (&Sscreen_configuration);
- defsubr (&Srestore_screen_configuration);
-#endif
- defsubr (&Smake_screen_visible);
- defsubr (&Smake_screen_invisible);
- defsubr (&Siconify_screen);
- defsubr (&Sdeiconify_screen);
- defsubr (&Sscreen_visible_p);
- defsubr (&Svisible_screen_list);
- defsubr (&Sredirect_screen_focus);
- defsubr (&Sscreen_focus);
- defsubr (&Sscreen_parameters);
- defsubr (&Smodify_screen_parameters);
- defsubr (&Sscreen_pixel_size);
- defsubr (&Sscreen_height);
- defsubr (&Sscreen_width);
- defsubr (&Sset_screen_height);
- defsubr (&Sset_screen_width);
- defsubr (&Sset_screen_size);
- defsubr (&Sset_screen_position);
-#ifndef HAVE_X11
- defsubr (&Srubber_band_rectangle);
-#endif /* HAVE_X11 */
-}
+/* Generic frame functions.
+ Copyright (C) 1993 Free Software Foundation.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include <config.h>
+#include "lisp.h"
+#include "frame.h"
+#include "termhooks.h"
+
+#ifdef MULTI_FRAME
+
+#include "buffer.h"
+#include "window.h"
+
+/* These help us bind and responding to switch-frame events. */
+#include "commands.h"
+#include "keyboard.h"
+
+Lisp_Object Vemacs_iconified;
+Lisp_Object Vframe_list;
+Lisp_Object Vterminal_frame;
+Lisp_Object Vdefault_minibuffer_frame;
+Lisp_Object Vdefault_frame_alist;
+
+/* Evaluate this expression to rebuild the section of syms_of_frame
+ that initializes and staticpros the symbols declared below. Note
+ that Emacs 18 has a bug that keeps C-x C-e from being able to
+ evaluate this expression.
+
+(progn
+ ;; Accumulate a list of the symbols we want to initialize from the
+ ;; declarations at the top of the file.
+ (goto-char (point-min))
+ (search-forward "/\*&&& symbols declared here &&&*\/\n")
+ (let (symbol-list)
+ (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
+ (setq symbol-list
+ (cons (buffer-substring (match-beginning 1) (match-end 1))
+ symbol-list))
+ (forward-line 1))
+ (setq symbol-list (nreverse symbol-list))
+ ;; Delete the section of syms_of_... where we initialize the symbols.
+ (search-forward "\n /\*&&& init symbols here &&&*\/\n")
+ (let ((start (point)))
+ (while (looking-at "^ Q")
+ (forward-line 2))
+ (kill-region start (point)))
+ ;; Write a new symbol initialization section.
+ (while symbol-list
+ (insert (format " %s = intern (\"" (car symbol-list)))
+ (let ((start (point)))
+ (insert (substring (car symbol-list) 1))
+ (subst-char-in-region start (point) ?_ ?-))
+ (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
+ (setq symbol-list (cdr symbol-list)))))
+ */
+
+/*&&& symbols declared here &&&*/
+Lisp_Object Qframep;
+Lisp_Object Qframe_live_p;
+Lisp_Object Qheight;
+Lisp_Object Qicon;
+Lisp_Object Qminibuffer;
+Lisp_Object Qmodeline;
+Lisp_Object Qname;
+Lisp_Object Qonly;
+Lisp_Object Qunsplittable;
+Lisp_Object Qmenu_bar_lines;
+Lisp_Object Qwidth;
+Lisp_Object Qx;
+Lisp_Object Qvisible;
+
+extern Lisp_Object Vminibuffer_list;
+extern Lisp_Object get_minibuffer ();
+extern Lisp_Object Fhandle_switch_frame ();
+extern Lisp_Object Fredirect_frame_focus ();
+\f
+DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
+ "Return non-nil if OBJECT is a frame.\n\
+Value is t for a termcap frame (a character-only terminal),\n\
+`x' for an Emacs frame that is really an X window.\n\
+Also see `live-frame-p'.")
+ (object)
+ Lisp_Object object;
+{
+ if (XTYPE (object) != Lisp_Frame)
+ return Qnil;
+ switch (XFRAME (object)->output_method)
+ {
+ case output_termcap:
+ return Qt;
+ case output_x_window:
+ return Qx;
+ default:
+ abort ();
+ }
+}
+
+DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
+ "Return non-nil if OBJECT is a frame which has not been deleted.\n\
+Value is nil if OBJECT is not a live frame. If object is a live\n\
+frame, the return value indicates what sort of output device it is\n\
+displayed on. Value is t for a termcap frame (a character-only\n\
+terminal), `x' for an Emacs frame being displayed in an X window.")
+ (object)
+ Lisp_Object object;
+{
+ return ((FRAMEP (object)
+ && FRAME_LIVE_P (XFRAME (object)))
+ ? Fframep (object)
+ : Qnil);
+}
+
+struct frame *
+make_frame (mini_p)
+ int mini_p;
+{
+ Lisp_Object frame;
+ register struct frame *f;
+ register Lisp_Object root_window;
+ register Lisp_Object mini_window;
+
+ frame = Fmake_vector (((sizeof (struct frame) - (sizeof (Lisp_Vector)
+ - sizeof (Lisp_Object)))
+ / sizeof (Lisp_Object)),
+ make_number (0));
+ XSETTYPE (frame, Lisp_Frame);
+ f = XFRAME (frame);
+
+ f->cursor_x = 0;
+ f->cursor_y = 0;
+ f->current_glyphs = 0;
+ f->desired_glyphs = 0;
+ f->visible = 0;
+ f->async_visible = 0;
+ f->display.nothing = 0;
+ f->iconified = 0;
+ f->async_iconified = 0;
+ f->wants_modeline = 1;
+ f->auto_raise = 0;
+ f->auto_lower = 0;
+ f->no_split = 0;
+ f->garbaged = 0;
+ f->has_minibuffer = mini_p;
+ f->focus_frame = Qnil;
+ f->explicit_name = 0;
+ f->can_have_scroll_bars = 0;
+ f->has_vertical_scroll_bars = 0;
+ f->param_alist = Qnil;
+ f->scroll_bars = Qnil;
+ f->condemned_scroll_bars = Qnil;
+ f->face_alist = Qnil;
+ f->menu_bar_items = Qnil;
+
+ root_window = make_window ();
+ if (mini_p)
+ {
+ mini_window = make_window ();
+ XWINDOW (root_window)->next = mini_window;
+ XWINDOW (mini_window)->prev = root_window;
+ XWINDOW (mini_window)->mini_p = Qt;
+ XWINDOW (mini_window)->frame = frame;
+ f->minibuffer_window = mini_window;
+ }
+ else
+ {
+ mini_window = Qnil;
+ XWINDOW (root_window)->next = Qnil;
+ f->minibuffer_window = Qnil;
+ }
+
+ XWINDOW (root_window)->frame = frame;
+
+ /* 10 is arbitrary,
+ just so that there is "something there."
+ Correct size will be set up later with change_frame_size. */
+
+ f->width = 10;
+ f->height = 10;
+
+ XFASTINT (XWINDOW (root_window)->width) = 10;
+ XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
+
+ if (mini_p)
+ {
+ XFASTINT (XWINDOW (mini_window)->width) = 10;
+ XFASTINT (XWINDOW (mini_window)->top) = 9;
+ XFASTINT (XWINDOW (mini_window)->height) = 1;
+ }
+
+ /* Choose a buffer for the frame's root window. */
+ {
+ Lisp_Object buf;
+
+ XWINDOW (root_window)->buffer = Qt;
+ buf = Fcurrent_buffer ();
+ /* If buf is a 'hidden' buffer (i.e. one whose name starts with
+ a space), try to find another one. */
+ if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
+ buf = Fother_buffer (buf, Qnil);
+ Fset_window_buffer (root_window, buf);
+ }
+
+ if (mini_p)
+ {
+ XWINDOW (mini_window)->buffer = Qt;
+ Fset_window_buffer (mini_window,
+ (NILP (Vminibuffer_list)
+ ? get_minibuffer (0)
+ : Fcar (Vminibuffer_list)));
+ }
+
+ f->root_window = root_window;
+ f->selected_window = root_window;
+ /* Make sure this window seems more recently used than
+ a newly-created, never-selected window. */
+ XFASTINT (XWINDOW (f->selected_window)->use_time) = ++window_select_count;
+
+ return f;
+}
+\f
+/* Make a frame using a separate minibuffer window on another frame.
+ MINI_WINDOW is the minibuffer window to use. nil means use the
+ default (the global minibuffer). */
+
+struct frame *
+make_frame_without_minibuffer (mini_window)
+ register Lisp_Object mini_window;
+{
+ register struct frame *f;
+
+ /* Choose the minibuffer window to use. */
+ if (NILP (mini_window))
+ {
+ if (XTYPE (Vdefault_minibuffer_frame) != Lisp_Frame)
+ error ("default-minibuffer-frame must be set when creating minibufferless frames");
+ if (! FRAME_LIVE_P (XFRAME (Vdefault_minibuffer_frame)))
+ error ("default-minibuffer-frame must be a live frame");
+ mini_window = XFRAME (Vdefault_minibuffer_frame)->minibuffer_window;
+ }
+ else
+ {
+ CHECK_LIVE_WINDOW (mini_window, 0);
+ }
+
+ /* Make a frame containing just a root window. */
+ f = make_frame (0);
+
+ /* Install the chosen minibuffer window, with proper buffer. */
+ f->minibuffer_window = mini_window;
+ Fset_window_buffer (mini_window,
+ (NILP (Vminibuffer_list)
+ ? get_minibuffer (0)
+ : Fcar (Vminibuffer_list)));
+ return f;
+}
+
+/* Make a frame containing only a minibuffer window. */
+
+struct frame *
+make_minibuffer_frame ()
+{
+ /* First make a frame containing just a root window, no minibuffer. */
+
+ register struct frame *f = make_frame (0);
+ register Lisp_Object mini_window;
+ register Lisp_Object frame;
+
+ XSET (frame, Lisp_Frame, f);
+
+ f->auto_raise = 0;
+ f->auto_lower = 0;
+ f->no_split = 1;
+ f->wants_modeline = 0;
+ f->has_minibuffer = 1;
+
+ /* Now label the root window as also being the minibuffer.
+ Avoid infinite looping on the window chain by marking next pointer
+ as nil. */
+
+ mini_window = f->minibuffer_window = f->root_window;
+ XWINDOW (mini_window)->mini_p = Qt;
+ XWINDOW (mini_window)->next = Qnil;
+ XWINDOW (mini_window)->prev = Qnil;
+ XWINDOW (mini_window)->frame = frame;
+
+ /* Put the proper buffer in that window. */
+
+ Fset_window_buffer (mini_window,
+ (NILP (Vminibuffer_list)
+ ? get_minibuffer (0)
+ : Fcar (Vminibuffer_list)));
+ return f;
+}
+\f
+/* Construct a frame that refers to the terminal (stdin and stdout). */
+
+struct frame *
+make_terminal_frame ()
+{
+ register struct frame *f;
+ Lisp_Object frame;
+
+ Vframe_list = Qnil;
+ f = make_frame (1);
+
+ XSET (frame, Lisp_Frame, f);
+ Vframe_list = Fcons (frame, Vframe_list);
+
+ f->name = build_string ("terminal");
+ FRAME_SET_VISIBLE (f, 1);
+ f->display.nothing = 1; /* Nonzero means frame isn't deleted. */
+ XSET (Vterminal_frame, Lisp_Frame, f);
+ return f;
+}
+\f
+static Lisp_Object
+do_switch_frame (frame, no_enter, track)
+ Lisp_Object frame, no_enter;
+ int track;
+{
+ /* If FRAME is a switch-frame event, extract the frame we should
+ switch to. */
+ if (CONSP (frame)
+ && EQ (XCONS (frame)->car, Qswitch_frame)
+ && CONSP (XCONS (frame)->cdr))
+ frame = XCONS (XCONS (frame)->cdr)->car;
+
+ /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
+ a switch-frame event to arrive after a frame is no longer live,
+ especially when deleting the initial frame during startup. */
+ CHECK_FRAME (frame, 0);
+ if (! FRAME_LIVE_P (XFRAME (frame)))
+ return Qnil;
+
+ if (selected_frame == XFRAME (frame))
+ return frame;
+
+ /* This is too greedy; it causes inappropriate focus redirection
+ that's hard to get rid of. */
+#if 0
+ /* If a frame's focus has been redirected toward the currently
+ selected frame, we should change the redirection to point to the
+ newly selected frame. This means that if the focus is redirected
+ from a minibufferless frame to a surrogate minibuffer frame, we
+ can use `other-window' to switch between all the frames using
+ that minibuffer frame, and the focus redirection will follow us
+ around. */
+ if (track)
+ {
+ Lisp_Object tail;
+
+ for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ Lisp_Object focus;
+
+ if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
+ abort ();
+
+ focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
+
+ if (XTYPE (focus) == Lisp_Frame
+ && XFRAME (focus) == selected_frame)
+ Fredirect_frame_focus (XCONS (tail)->car, frame);
+ }
+ }
+#else /* ! 0 */
+ /* Instead, apply it only to the frame we're pointing to. */
+#ifdef HAVE_X_WINDOWS
+ if (track)
+ {
+ Lisp_Object focus, xfocus;
+
+ xfocus = x_get_focus_frame ();
+ if (FRAMEP (xfocus))
+ {
+ focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
+ if (FRAMEP (focus) && XFRAME (focus) == selected_frame)
+ Fredirect_frame_focus (xfocus, frame);
+ }
+ }
+#endif /* HAVE_X_WINDOWS */
+#endif /* ! 0 */
+
+ selected_frame = XFRAME (frame);
+ if (! FRAME_MINIBUF_ONLY_P (selected_frame))
+ last_nonminibuf_frame = selected_frame;
+
+ Fselect_window (XFRAME (frame)->selected_window);
+ choose_minibuf_frame ();
+
+ /* We want to make sure that the next event generates a frame-switch
+ event to the appropriate frame. This seems kludgy to me, but
+ before you take it out, make sure that evaluating something like
+ (select-window (frame-root-window (new-frame))) doesn't end up
+ with your typing being interpreted in the new frame instead of
+ the one you're actually typing in. */
+ internal_last_event_frame = Qnil;
+
+ return frame;
+}
+
+DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
+ "Select the frame FRAME.\n\
+Subsequent editing commands apply to its selected window.\n\
+The selection of FRAME lasts until the next time the user does\n\
+something to select a different frame, or until the next time this\n\
+function is called.")
+ (frame, no_enter)
+ Lisp_Object frame, no_enter;
+{
+ return do_switch_frame (frame, no_enter, 1);
+}
+
+
+DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
+ "Handle a switch-frame event EVENT.\n\
+Switch-frame events are usually bound to this function.\n\
+A switch-frame event tells Emacs that the window manager has requested\n\
+that the user's events be directed to the frame mentioned in the event.\n\
+This function selects the selected window of the frame of EVENT.\n\
+\n\
+If EVENT is frame object, handle it as if it were a switch-frame event\n\
+to that frame.")
+ (frame, no_enter)
+ Lisp_Object frame, no_enter;
+{
+ return do_switch_frame (frame, no_enter, 0);
+}
+
+
+DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
+ "Return the frame that is now selected.")
+ ()
+{
+ Lisp_Object tem;
+ XSET (tem, Lisp_Frame, selected_frame);
+ return tem;
+}
+
+DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
+ "Return the frame object that window WINDOW is on.")
+ (window)
+ Lisp_Object window;
+{
+ CHECK_LIVE_WINDOW (window, 0);
+ return XWINDOW (window)->frame;
+}
+
+DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
+ "Returns the root-window of FRAME.\n\
+If omitted, FRAME defaults to the currently selected frame.")
+ (frame)
+ Lisp_Object frame;
+{
+ if (NILP (frame))
+ XSET (frame, Lisp_Frame, selected_frame);
+ else
+ CHECK_LIVE_FRAME (frame, 0);
+
+ return XFRAME (frame)->root_window;
+}
+
+DEFUN ("frame-selected-window", Fframe_selected_window,
+ Sframe_selected_window, 0, 1, 0,
+ "Return the selected window of frame object FRAME.\n\
+If omitted, FRAME defaults to the currently selected frame.")
+ (frame)
+ Lisp_Object frame;
+{
+ if (NILP (frame))
+ XSET (frame, Lisp_Frame, selected_frame);
+ else
+ CHECK_LIVE_FRAME (frame, 0);
+
+ return XFRAME (frame)->selected_window;
+}
+
+DEFUN ("frame-list", Fframe_list, Sframe_list,
+ 0, 0, 0,
+ "Return a list of all frames.")
+ ()
+{
+ return Fcopy_sequence (Vframe_list);
+}
+
+/* Return the next frame in the frame list after FRAME.
+ If MINIBUF is nil, exclude minibuffer-only frames.
+ If MINIBUF is a window, include only frames using that window for
+ their minibuffer.
+ If MINIBUF is `visible', include all visible frames.
+ Otherwise, include all frames. */
+
+Lisp_Object
+next_frame (frame, minibuf)
+ Lisp_Object frame;
+ Lisp_Object minibuf;
+{
+ Lisp_Object tail;
+ int passed = 0;
+
+ /* There must always be at least one frame in Vframe_list. */
+ if (! CONSP (Vframe_list))
+ abort ();
+
+ /* If this frame is dead, it won't be in Vframe_list, and we'll loop
+ forever. Forestall that. */
+ CHECK_LIVE_FRAME (frame, 0);
+
+ while (1)
+ for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ Lisp_Object f;
+
+ f = XCONS (tail)->car;
+ if (passed)
+ {
+ /* Decide whether this frame is eligible to be returned. */
+
+ /* If we've looped all the way around without finding any
+ eligible frames, return the original frame. */
+ if (EQ (f, frame))
+ return f;
+
+ /* Let minibuf decide if this frame is acceptable. */
+ if (NILP (minibuf))
+ {
+ if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
+ return f;
+ }
+ else if (EQ (minibuf, Qvisible))
+ {
+ FRAME_SAMPLE_VISIBILITY (XFRAME (f));
+ if (FRAME_VISIBLE_P (XFRAME (f)))
+ return f;
+ }
+ else if (WINDOWP (minibuf))
+ {
+ if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
+ return f;
+ }
+ else
+ return f;
+ }
+
+ if (EQ (frame, f))
+ passed++;
+ }
+}
+
+/* Return the previous frame in the frame list before FRAME.
+ If MINIBUF is nil, exclude minibuffer-only frames.
+ If MINIBUF is a window, include only frames using that window for
+ their minibuffer.
+ If MINIBUF is `visible', include all visible frames.
+ Otherwise, include all frames. */
+
+Lisp_Object
+prev_frame (frame, minibuf)
+ Lisp_Object frame;
+ Lisp_Object minibuf;
+{
+ Lisp_Object tail;
+ Lisp_Object prev;
+
+ /* There must always be at least one frame in Vframe_list. */
+ if (! CONSP (Vframe_list))
+ abort ();
+
+ prev = Qnil;
+ for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ Lisp_Object f;
+
+ f = XCONS (tail)->car;
+ if (XTYPE (f) != Lisp_Frame)
+ abort ();
+
+ if (EQ (frame, f) && !NILP (prev))
+ return prev;
+
+ /* Decide whether this frame is eligible to be returned,
+ according to minibuf. */
+ if (NILP (minibuf))
+ {
+ if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
+ prev = f;
+ }
+ else if (XTYPE (minibuf) == Lisp_Window)
+ {
+ if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
+ prev = f;
+ }
+ else if (EQ (minibuf, Qvisible))
+ {
+ FRAME_SAMPLE_VISIBILITY (XFRAME (f));
+ if (FRAME_VISIBLE_P (XFRAME (f)))
+ prev = f;
+ }
+ else
+ prev = f;
+ }
+
+ /* We've scanned the entire list. */
+ if (NILP (prev))
+ /* We went through the whole frame list without finding a single
+ acceptable frame. Return the original frame. */
+ return frame;
+ else
+ /* There were no acceptable frames in the list before FRAME; otherwise,
+ we would have returned directly from the loop. Since PREV is the last
+ acceptable frame in the list, return it. */
+ return prev;
+}
+
+
+DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
+ "Return the next frame in the frame list after FRAME.\n\
+By default, skip minibuffer-only frames.\n\
+If omitted, FRAME defaults to the selected frame.\n\
+If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
+If MINIFRAME is a window, include only frames using that window for their\n\
+minibuffer.\n\
+If MINIFRAME is `visible', include all visible frames.\n\
+Otherwise, include all frames.")
+ (frame, miniframe)
+ Lisp_Object frame, miniframe;
+{
+ Lisp_Object tail;
+
+ if (NILP (frame))
+ XSET (frame, Lisp_Frame, selected_frame);
+ else
+ CHECK_LIVE_FRAME (frame, 0);
+
+ return next_frame (frame, miniframe);
+}
+
+DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
+ "Return the previous frame in the frame list before FRAME.\n\
+By default, skip minibuffer-only frames.\n\
+If omitted, FRAME defaults to the selected frame.\n\
+If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
+If MINIFRAME is a window, include only frames using that window for their\n\
+minibuffer.\n\
+If MINIFRAME is `visible', include all visible frames.\n\
+Otherwise, include all frames.")
+ (frame, miniframe)
+ Lisp_Object frame, miniframe;
+{
+ Lisp_Object tail;
+
+ if (NILP (frame))
+ XSET (frame, Lisp_Frame, selected_frame);
+ else
+ CHECK_LIVE_FRAME (frame, 0);
+
+ return prev_frame (frame, miniframe);
+}
+\f
+/* Return 1 if it is ok to delete frame F;
+ 0 if all frames aside from F are invisible.
+ (Exception: if F is the terminal frame, and we are using X, return 1.) */
+
+static int
+other_visible_frames (f)
+ FRAME_PTR f;
+{
+ /* We know the selected frame is visible,
+ so if F is some other frame, it can't be the sole visible one. */
+ if (f == selected_frame)
+ {
+ Lisp_Object frames;
+ int count = 0;
+
+ for (frames = Vframe_list;
+ CONSP (frames);
+ frames = XCONS (frames)->cdr)
+ {
+ Lisp_Object this;
+
+ this = XCONS (frames)->car;
+ /* Verify that the frame's window still exists
+ and we can still talk to it. And note any recent change
+ in visibility. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (XFRAME (this)))
+ {
+ x_sync (this);
+ FRAME_SAMPLE_VISIBILITY (XFRAME (this));
+ }
+#endif
+
+ if (FRAME_VISIBLE_P (XFRAME (this))
+ || FRAME_ICONIFIED_P (XFRAME (this))
+ /* Allow deleting the terminal frame when at least
+ one X frame exists! */
+ || (FRAME_X_P (XFRAME (this)) && !FRAME_X_P (f)))
+ count++;
+ }
+ return count > 1;
+ }
+ return 1;
+}
+
+DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
+ "Delete FRAME, permanently eliminating it from use.\n\
+If omitted, FRAME defaults to the selected frame.\n\
+A frame may not be deleted if its minibuffer is used by other frames.\n\
+Normally, you may not delete a frame if all other frames are invisible,\n\
+but if the second optional argument FORCE is non-nil, you may do so.")
+ (frame, force)
+ Lisp_Object frame, force;
+{
+ struct frame *f;
+
+ if (EQ (frame, Qnil))
+ {
+ f = selected_frame;
+ XSET (frame, Lisp_Frame, f);
+ }
+ else
+ {
+ CHECK_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+ if (! FRAME_LIVE_P (f))
+ return Qnil;
+
+ if (NILP (force) && !other_visible_frames (f))
+ error ("Attempt to delete the sole visible or iconified frame");
+
+ /* Does this frame have a minibuffer, and is it the surrogate
+ minibuffer for any other frame? */
+ if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
+ {
+ Lisp_Object frames;
+
+ for (frames = Vframe_list;
+ CONSP (frames);
+ frames = XCONS (frames)->cdr)
+ {
+ Lisp_Object this;
+ this = XCONS (frames)->car;
+
+ if (! EQ (this, frame)
+ && EQ (frame,
+ WINDOW_FRAME (XWINDOW
+ (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
+ error ("Attempt to delete a surrogate minibuffer frame");
+ }
+ }
+
+ /* Don't let the frame remain selected. */
+ if (f == selected_frame)
+ Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
+
+ /* Don't allow minibuf_window to remain on a deleted frame. */
+ if (EQ (f->minibuffer_window, minibuf_window))
+ {
+ Fset_window_buffer (selected_frame->minibuffer_window,
+ XWINDOW (minibuf_window)->buffer);
+ minibuf_window = selected_frame->minibuffer_window;
+ }
+
+ /* Mark all the windows that used to be on FRAME as deleted, and then
+ remove the reference to them. */
+ delete_all_subwindows (XWINDOW (f->root_window));
+ f->root_window = Qnil;
+
+ Vframe_list = Fdelq (frame, Vframe_list);
+ FRAME_SET_VISIBLE (f, 0);
+
+ /* Since some events are handled at the interrupt level, we may get
+ an event for f at any time; if we zero out the frame's display
+ now, then we may trip up the event-handling code. Instead, we'll
+ promise that the display of the frame must be valid until we have
+ called the window-system-dependent frame destruction routine. */
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ x_destroy_window (f);
+#endif
+
+ f->display.nothing = 0;
+
+ /* If we've deleted the last_nonminibuf_frame, then try to find
+ another one. */
+ if (f == last_nonminibuf_frame)
+ {
+ Lisp_Object frames;
+
+ last_nonminibuf_frame = 0;
+
+ for (frames = Vframe_list;
+ CONSP (frames);
+ frames = XCONS (frames)->cdr)
+ {
+ f = XFRAME (XCONS (frames)->car);
+ if (!FRAME_MINIBUF_ONLY_P (f))
+ {
+ last_nonminibuf_frame = f;
+ break;
+ }
+ }
+ }
+
+ /* If we've deleted Vdefault_minibuffer_frame, try to find another
+ one. Prefer minibuffer-only frames, but also notice frames
+ with other windows. */
+ if (EQ (frame, Vdefault_minibuffer_frame))
+ {
+ Lisp_Object frames;
+
+ /* The last frame we saw with a minibuffer, minibuffer-only or not. */
+ Lisp_Object frame_with_minibuf;
+
+ frame_with_minibuf = Qnil;
+ for (frames = Vframe_list;
+ CONSP (frames);
+ frames = XCONS (frames)->cdr)
+ {
+ Lisp_Object this;
+
+ this = XCONS (frames)->car;
+ if (XTYPE (this) != Lisp_Frame)
+ abort ();
+ f = XFRAME (this);
+
+ if (FRAME_HAS_MINIBUF_P (f))
+ {
+ frame_with_minibuf = this;
+ if (FRAME_MINIBUF_ONLY_P (f))
+ break;
+ }
+ }
+
+ /* We know that there must be some frame with a minibuffer out
+ there. If this were not true, all of the frames present
+ would have to be minibufferless, which implies that at some
+ point their minibuffer frames must have been deleted, but
+ that is prohibited at the top; you can't delete surrogate
+ minibuffer frames. */
+ if (NILP (frame_with_minibuf))
+ abort ();
+
+ Vdefault_minibuffer_frame = frame_with_minibuf;
+ }
+
+ return Qnil;
+}
+\f
+/* Return mouse position in character cell units. */
+
+DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
+ "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
+The position is given in character cells, where (0, 0) is the\n\
+upper-left corner.\n\
+If Emacs is running on a mouseless terminal or hasn't been programmed\n\
+to read the mouse position, it returns the selected frame for FRAME\n\
+and nil for X and Y.")
+ ()
+{
+ FRAME_PTR f;
+ Lisp_Object lispy_dummy;
+ enum scroll_bar_part party_dummy;
+ Lisp_Object x, y;
+ int col, row;
+ unsigned long long_dummy;
+
+ f = selected_frame;
+ x = y = Qnil;
+
+ /* It's okay for the hook to refrain from storing anything. */
+ if (mouse_position_hook)
+ (*mouse_position_hook) (&f,
+ &lispy_dummy, &party_dummy,
+ &x, &y,
+ &long_dummy);
+ col = XINT (x);
+ row = XINT (y);
+ glyph_to_pixel_coords (f, col, row, &col, &row);
+ XSETINT (x, col);
+ XSETINT (y, row);
+ XSET (lispy_dummy, Lisp_Frame, f);
+ return Fcons (lispy_dummy, Fcons (x, y));
+}
+
+DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
+ "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
+WARNING: If you use this under X, you should do `unfocus-frame' afterwards.")
+ (frame, x, y)
+ Lisp_Object frame, x, y;
+{
+ CHECK_LIVE_FRAME (frame, 0);
+ CHECK_NUMBER (x, 2);
+ CHECK_NUMBER (y, 1);
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (XFRAME (frame)))
+ /* Warping the mouse will cause enternotify and focus events. */
+ x_set_mouse_position (XFRAME (frame), x, y);
+#endif
+
+ return Qnil;
+}
+\f
+DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
+ 0, 1, "",
+ "Make the frame FRAME visible (assuming it is an X-window).\n\
+If omitted, FRAME defaults to the currently selected frame.")
+ (frame)
+ Lisp_Object frame;
+{
+ if (NILP (frame))
+ XSET (frame, Lisp_Frame, selected_frame);
+
+ CHECK_LIVE_FRAME (frame, 0);
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (XFRAME (frame)))
+ {
+ FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
+ x_make_frame_visible (XFRAME (frame));
+ }
+#endif
+
+ return frame;
+}
+
+DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
+ 0, 2, "",
+ "Make the frame FRAME invisible (assuming it is an X-window).\n\
+If omitted, FRAME defaults to the currently selected frame.\n\
+Normally you may not make FRAME invisible if all other frames are invisible,\n\
+but if the second optional argument FORCE is non-nil, you may do so.")
+ (frame, force)
+ Lisp_Object frame, force;
+{
+ if (NILP (frame))
+ XSET (frame, Lisp_Frame, selected_frame);
+
+ CHECK_LIVE_FRAME (frame, 0);
+
+ if (NILP (force) && !other_visible_frames (XFRAME (frame)))
+ error ("Attempt to make invisible the sole visible or iconified frame");
+
+ /* Don't let the frame remain selected. */
+ if (XFRAME (frame) == selected_frame)
+ Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
+
+ /* Don't allow minibuf_window to remain on a deleted frame. */
+ if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
+ {
+ Fset_window_buffer (selected_frame->minibuffer_window,
+ XWINDOW (minibuf_window)->buffer);
+ minibuf_window = selected_frame->minibuffer_window;
+ }
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (XFRAME (frame)))
+ x_make_frame_invisible (XFRAME (frame));
+#endif
+
+ return Qnil;
+}
+
+DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
+ 0, 1, "",
+ "Make the frame FRAME into an icon.\n\
+If omitted, FRAME defaults to the currently selected frame.")
+ (frame)
+ Lisp_Object frame;
+{
+ if (NILP (frame))
+ XSET (frame, Lisp_Frame, selected_frame);
+
+ CHECK_LIVE_FRAME (frame, 0);
+
+ /* Don't let the frame remain selected. */
+ if (XFRAME (frame) == selected_frame)
+ Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
+
+ /* Don't allow minibuf_window to remain on a deleted frame. */
+ if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
+ {
+ Fset_window_buffer (selected_frame->minibuffer_window,
+ XWINDOW (minibuf_window)->buffer);
+ minibuf_window = selected_frame->minibuffer_window;
+ }
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (XFRAME (frame)))
+ x_iconify_frame (XFRAME (frame));
+#endif
+
+ return Qnil;
+}
+
+DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
+ 1, 1, 0,
+ "Return t if FRAME is now \"visible\" (actually in use for display).\n\
+A frame that is not \"visible\" is not updated and, if it works through\n\
+a window system, it may not show at all.\n\
+Return the symbol `icon' if frame is visible only as an icon.")
+ (frame)
+ Lisp_Object frame;
+{
+ CHECK_LIVE_FRAME (frame, 0);
+
+ FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
+
+ if (FRAME_VISIBLE_P (XFRAME (frame)))
+ return Qt;
+ if (FRAME_ICONIFIED_P (XFRAME (frame)))
+ return Qicon;
+ return Qnil;
+}
+
+DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
+ 0, 0, 0,
+ "Return a list of all frames now \"visible\" (being updated).")
+ ()
+{
+ Lisp_Object tail, frame;
+ struct frame *f;
+ Lisp_Object value;
+
+ value = Qnil;
+ for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ frame = XCONS (tail)->car;
+ if (XTYPE (frame) != Lisp_Frame)
+ continue;
+ f = XFRAME (frame);
+ if (FRAME_VISIBLE_P (f))
+ value = Fcons (frame, value);
+ }
+ return value;
+}
+
+
+DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 1, 1, 0,
+ "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
+If FRAME is invisible, make it visible.\n\
+If Emacs is displaying on an ordinary terminal or some other device which\n\
+doesn't support multiple overlapping frames, this function does nothing.")
+ (frame)
+ Lisp_Object frame;
+{
+ CHECK_LIVE_FRAME (frame, 0);
+
+ /* Do like the documentation says. */
+ Fmake_frame_visible (frame);
+
+ if (frame_raise_lower_hook)
+ (*frame_raise_lower_hook) (XFRAME (frame), 1);
+
+ return Qnil;
+}
+
+/* Should we have a corresponding function called Flower_Power? */
+DEFUN ("lower-frame", Flower_frame, Slower_frame, 1, 1, 0,
+ "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
+If Emacs is displaying on an ordinary terminal or some other device which\n\
+doesn't support multiple overlapping frames, this function does nothing.")
+ (frame)
+ Lisp_Object frame;
+{
+ CHECK_LIVE_FRAME (frame, 0);
+
+ if (frame_raise_lower_hook)
+ (*frame_raise_lower_hook) (XFRAME (frame), 0);
+
+ return Qnil;
+}
+
+\f
+DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
+ 1, 2, 0,
+ "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
+In other words, switch-frame events caused by events in FRAME will\n\
+request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
+FOCUS-FRAME after reading an event typed at FRAME.\n\
+\n\
+If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
+cancelled, and the frame again receives its own keystrokes.\n\
+\n\
+Focus redirection is useful for temporarily redirecting keystrokes to\n\
+a surrogate minibuffer frame when a frame doesn't have its own\n\
+minibuffer window.\n\
+\n\
+A frame's focus redirection can be changed by select-frame. If frame\n\
+FOO is selected, and then a different frame BAR is selected, any\n\
+frames redirecting their focus to FOO are shifted to redirect their\n\
+focus to BAR. This allows focus redirection to work properly when the\n\
+user switches from one frame to another using `select-window'.\n\
+\n\
+This means that a frame whose focus is redirected to itself is treated\n\
+differently from a frame whose focus is redirected to nil; the former\n\
+is affected by select-frame, while the latter is not.\n\
+\n\
+The redirection lasts until `redirect-frame-focus' is called to change it.")
+ (frame, focus_frame)
+ Lisp_Object frame, focus_frame;
+{
+ /* Note that we don't check for a live frame here. It's reasonable
+ to redirect the focus of a frame you're about to delete, if you
+ know what other frame should receive those keystrokes. */
+ CHECK_FRAME (frame, 0);
+
+ if (! NILP (focus_frame))
+ CHECK_LIVE_FRAME (focus_frame, 1);
+
+ XFRAME (frame)->focus_frame = focus_frame;
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (!NILP (focus_frame) && ! EQ (focus_frame, frame)
+ && FRAME_X_P (XFRAME (focus_frame)))
+ Ffocus_frame (focus_frame);
+#endif
+
+ if (frame_rehighlight_hook)
+ (*frame_rehighlight_hook) ();
+
+ return Qnil;
+}
+
+
+DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
+ "Return the frame to which FRAME's keystrokes are currently being sent.\n\
+This returns nil if FRAME's focus is not redirected.\n\
+See `redirect-frame-focus'.")
+ (frame)
+ Lisp_Object frame;
+{
+ CHECK_LIVE_FRAME (frame, 0);
+
+ return FRAME_FOCUS_FRAME (XFRAME (frame));
+}
+
+
+\f
+Lisp_Object
+get_frame_param (frame, prop)
+ register struct frame *frame;
+ Lisp_Object prop;
+{
+ register Lisp_Object tem;
+
+ tem = Fassq (prop, frame->param_alist);
+ if (EQ (tem, Qnil))
+ return tem;
+ return Fcdr (tem);
+}
+
+void
+store_in_alist (alistptr, prop, val)
+ Lisp_Object *alistptr, val;
+ Lisp_Object prop;
+{
+ register Lisp_Object tem;
+
+ tem = Fassq (prop, *alistptr);
+ if (EQ (tem, Qnil))
+ *alistptr = Fcons (Fcons (prop, val), *alistptr);
+ else
+ Fsetcdr (tem, val);
+}
+
+void
+store_frame_param (f, prop, val)
+ struct frame *f;
+ Lisp_Object prop, val;
+{
+ register Lisp_Object tem;
+
+ tem = Fassq (prop, f->param_alist);
+ if (EQ (tem, Qnil))
+ f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
+ else
+ Fsetcdr (tem, val);
+
+ if (EQ (prop, Qminibuffer)
+ && XTYPE (val) == Lisp_Window)
+ {
+ if (! MINI_WINDOW_P (XWINDOW (val)))
+ error ("Surrogate minibuffer windows must be minibuffer windows.");
+
+ if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
+ error ("can't change the surrogate minibuffer of a frame with its own minibuffer");
+
+ /* Install the chosen minibuffer window, with proper buffer. */
+ f->minibuffer_window = val;
+ }
+}
+
+DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
+ "Return the parameters-alist of frame FRAME.\n\
+It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
+The meaningful PARMs depend on the kind of frame.\n\
+If FRAME is omitted, return information on the currently selected frame.")
+ (frame)
+ Lisp_Object frame;
+{
+ Lisp_Object alist;
+ struct frame *f;
+
+ if (EQ (frame, Qnil))
+ f = selected_frame;
+ else
+ {
+ CHECK_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+ if (f->display.nothing == 0)
+ return Qnil;
+
+ alist = Fcopy_alist (f->param_alist);
+ store_in_alist (&alist, Qname, f->name);
+ store_in_alist (&alist, Qheight, make_number (f->height));
+ store_in_alist (&alist, Qwidth, make_number (f->width));
+ store_in_alist (&alist, Qmodeline, (f->wants_modeline ? Qt : Qnil));
+ store_in_alist (&alist, Qminibuffer,
+ (! FRAME_HAS_MINIBUF_P (f) ? Qnil
+ : (FRAME_MINIBUF_ONLY_P (f) ? Qonly
+ : FRAME_MINIBUF_WINDOW (f))));
+ store_in_alist (&alist, Qunsplittable, (f->no_split ? Qt : Qnil));
+ store_in_alist (&alist, Qmenu_bar_lines, (FRAME_MENU_BAR_LINES (f)));
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ x_report_frame_params (f, &alist);
+#endif
+ return alist;
+}
+
+DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
+ Smodify_frame_parameters, 2, 2, 0,
+ "Modify the parameters of frame FRAME according to ALIST.\n\
+ALIST is an alist of parameters to change and their new values.\n\
+Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
+The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
+ (frame, alist)
+ Lisp_Object frame, alist;
+{
+ FRAME_PTR f;
+ register Lisp_Object tail, elt, prop, val;
+
+ if (EQ (frame, Qnil))
+ f = selected_frame;
+ else
+ {
+ CHECK_LIVE_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+#if 1
+ x_set_frame_parameters (f, alist);
+#else
+ for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
+ {
+ elt = Fcar (tail);
+ prop = Fcar (elt);
+ val = Fcdr (elt);
+ x_set_frame_param (f, prop, val, get_frame_param (f, prop));
+ store_frame_param (f, prop, val);
+ }
+#endif
+#endif
+
+ return Qnil;
+}
+\f
+DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
+ 0, 1, 0,
+ "Height in pixels of a line in the font in frame FRAME.\n\
+If FRAME is omitted, the selected frame is used.\n\
+For a terminal frame, the value is always 1.")
+ (frame)
+ Lisp_Object frame;
+{
+ struct frame *f;
+
+ if (NILP (frame))
+ f = selected_frame;
+ else
+ {
+ CHECK_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ return make_number (x_char_height (f));
+ else
+#endif
+ return make_number (1);
+}
+
+
+DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
+ 0, 1, 0,
+ "Width in pixels of characters in the font in frame FRAME.\n\
+If FRAME is omitted, the selected frame is used.\n\
+The width is the same for all characters, because\n\
+currently Emacs supports only fixed-width fonts.\n\
+For a terminal screen, the value is always 1.")
+ (frame)
+ Lisp_Object frame;
+{
+ struct frame *f;
+
+ if (NILP (frame))
+ f = selected_frame;
+ else
+ {
+ CHECK_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ return make_number (x_char_width (f));
+ else
+#endif
+ return make_number (1);
+}
+
+DEFUN ("frame-pixel-height", Fframe_pixel_height,
+ Sframe_pixel_height, 0, 1, 0,
+ "Return a FRAME's height in pixels.\n\
+For a terminal frame, the result really gives the height in characters.\n\
+If FRAME is omitted, the selected frame is used.")
+ (frame)
+ Lisp_Object frame;
+{
+ struct frame *f;
+
+ if (NILP (frame))
+ f = selected_frame;
+ else
+ {
+ CHECK_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ return make_number (x_pixel_height (f));
+ else
+#endif
+ return make_number (FRAME_HEIGHT (f));
+}
+
+DEFUN ("frame-pixel-width", Fframe_pixel_width,
+ Sframe_pixel_width, 0, 1, 0,
+ "Return FRAME's width in pixels.\n\
+For a terminal frame, the result really gives the width in characters.\n\
+If FRAME is omitted, the selected frame is used.")
+ (frame)
+ Lisp_Object frame;
+{
+ struct frame *f;
+
+ if (NILP (frame))
+ f = selected_frame;
+ else
+ {
+ CHECK_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ return make_number (x_pixel_width (f));
+ else
+#endif
+ return make_number (FRAME_WIDTH (f));
+}
+\f
+DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
+ "Specify that the frame FRAME has LINES lines.\n\
+Optional third arg non-nil means that redisplay should use LINES lines\n\
+but that the idea of the actual height of the frame should not be changed.")
+ (frame, rows, pretend)
+ Lisp_Object frame, rows, pretend;
+{
+ register struct frame *f;
+
+ CHECK_NUMBER (rows, 0);
+ if (NILP (frame))
+ f = selected_frame;
+ else
+ {
+ CHECK_LIVE_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ {
+ if (XINT (rows) != f->width)
+ x_set_window_size (f, 1, f->width, XINT (rows));
+ }
+ else
+#endif
+ change_frame_size (f, XINT (rows), 0, !NILP (pretend), 0);
+ return Qnil;
+}
+
+DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
+ "Specify that the frame FRAME has COLS columns.\n\
+Optional third arg non-nil means that redisplay should use COLS columns\n\
+but that the idea of the actual width of the frame should not be changed.")
+ (frame, cols, pretend)
+ Lisp_Object frame, cols, pretend;
+{
+ register struct frame *f;
+ CHECK_NUMBER (cols, 0);
+ if (NILP (frame))
+ f = selected_frame;
+ else
+ {
+ CHECK_LIVE_FRAME (frame, 0);
+ f = XFRAME (frame);
+ }
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ {
+ if (XINT (cols) != f->width)
+ x_set_window_size (f, 1, XINT (cols), f->height);
+ }
+ else
+#endif
+ change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0);
+ return Qnil;
+}
+
+DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
+ "Sets size of FRAME to COLS by ROWS, measured in characters.")
+ (frame, cols, rows)
+ Lisp_Object frame, cols, rows;
+{
+ register struct frame *f;
+ int mask;
+
+ CHECK_LIVE_FRAME (frame, 0);
+ CHECK_NUMBER (cols, 2);
+ CHECK_NUMBER (rows, 1);
+ f = XFRAME (frame);
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ {
+ if (XINT (rows) != f->height || XINT (cols) != f->width)
+ x_set_window_size (f, 1, XINT (cols), XINT (rows));
+ }
+ else
+#endif
+ change_frame_size (f, XINT (rows), XINT (cols), 0, 0);
+
+ return Qnil;
+}
+
+DEFUN ("set-frame-position", Fset_frame_position,
+ Sset_frame_position, 3, 3, 0,
+ "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
+This is actually the position of the upper left corner of the frame.\n\
+Negative values for XOFFSET or YOFFSET are interpreted relative to\n\
+the rightmost or bottommost possible position (that stays within the screen).")
+ (frame, xoffset, yoffset)
+ Lisp_Object frame, xoffset, yoffset;
+{
+ register struct frame *f;
+ int mask;
+
+ CHECK_LIVE_FRAME (frame, 0);
+ CHECK_NUMBER (xoffset, 1);
+ CHECK_NUMBER (yoffset, 2);
+ f = XFRAME (frame);
+
+ /* I think this should be done with a hook. */
+#ifdef HAVE_X_WINDOWS
+ if (FRAME_X_P (f))
+ x_set_offset (f, XINT (xoffset), XINT (yoffset));
+#endif
+
+ return Qt;
+}
+
+\f
+choose_minibuf_frame ()
+{
+ /* For lowest-level minibuf, put it on currently selected frame
+ if frame has a minibuffer. */
+
+ if (minibuf_level == 0
+ && selected_frame != 0
+ && !EQ (minibuf_window, selected_frame->minibuffer_window))
+ {
+ /* I don't think that any frames may validly have a null minibuffer
+ window anymore. */
+ if (NILP (selected_frame->minibuffer_window))
+ abort ();
+
+ Fset_window_buffer (selected_frame->minibuffer_window,
+ XWINDOW (minibuf_window)->buffer);
+ minibuf_window = selected_frame->minibuffer_window;
+ }
+}
+\f
+syms_of_frame ()
+{
+ /*&&& init symbols here &&&*/
+ Qframep = intern ("framep");
+ staticpro (&Qframep);
+ Qframe_live_p = intern ("frame-live-p");
+ staticpro (&Qframe_live_p);
+ Qheight = intern ("height");
+ staticpro (&Qheight);
+ Qicon = intern ("icon");
+ staticpro (&Qicon);
+ Qminibuffer = intern ("minibuffer");
+ staticpro (&Qminibuffer);
+ Qmodeline = intern ("modeline");
+ staticpro (&Qmodeline);
+ Qname = intern ("name");
+ staticpro (&Qname);
+ Qonly = intern ("only");
+ staticpro (&Qonly);
+ Qunsplittable = intern ("unsplittable");
+ staticpro (&Qunsplittable);
+ Qmenu_bar_lines = intern ("menu-bar-lines");
+ staticpro (&Qmenu_bar_lines);
+ Qwidth = intern ("width");
+ staticpro (&Qwidth);
+ Qx = intern ("x");
+ staticpro (&Qx);
+ Qvisible = intern ("visible");
+ staticpro (&Qvisible);
+
+ staticpro (&Vframe_list);
+
+ DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
+ "The initial frame-object, which represents Emacs's stdout.");
+
+ DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
+ "Non-nil if all of emacs is iconified and frame updates are not needed.");
+ Vemacs_iconified = Qnil;
+
+ DEFVAR_LISP ("default-minibuffer-frame", &Vdefault_minibuffer_frame,
+ "Minibufferless frames use this frame's minibuffer.\n\
+\n\
+Emacs cannot create minibufferless frames unless this is set to an\n\
+appropriate surrogate.\n\
+\n\
+Emacs consults this variable only when creating minibufferless\n\
+frames; once the frame is created, it sticks with its assigned\n\
+minibuffer, no matter what this variable is set to. This means that\n\
+this variable doesn't necessarily say anything meaningful about the\n\
+current set of frames, or where the minibuffer is currently being\n\
+displayed.");
+ Vdefault_minibuffer_frame = Qnil;
+
+ DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
+ "Alist of default values for frame creation.\n\
+These may be set in your init file, like this:\n\
+ (setq default-frame-alist '((width . 80) (height . 55)))\n\
+These override values given in window system configuration data, like\n\
+X Windows' defaults database.\n\
+For values specific to the first Emacs frame, see `initial-frame-alist'.\n\
+For values specific to the separate minibuffer frame, see\n\
+`minibuffer-frame-alist'.");
+ Vdefault_frame_alist = Qnil;
+
+ defsubr (&Sframep);
+ defsubr (&Sframe_live_p);
+ defsubr (&Shandle_switch_frame);
+ defsubr (&Sselect_frame);
+ defsubr (&Sselected_frame);
+ defsubr (&Swindow_frame);
+ defsubr (&Sframe_root_window);
+ defsubr (&Sframe_selected_window);
+ defsubr (&Sframe_list);
+ defsubr (&Snext_frame);
+ defsubr (&Sprevious_frame);
+ defsubr (&Sdelete_frame);
+ defsubr (&Smouse_position);
+ defsubr (&Sset_mouse_position);
+#if 0
+ defsubr (&Sframe_configuration);
+ defsubr (&Srestore_frame_configuration);
+#endif
+ defsubr (&Smake_frame_visible);
+ defsubr (&Smake_frame_invisible);
+ defsubr (&Siconify_frame);
+ defsubr (&Sframe_visible_p);
+ defsubr (&Svisible_frame_list);
+ defsubr (&Sraise_frame);
+ defsubr (&Slower_frame);
+ defsubr (&Sredirect_frame_focus);
+ defsubr (&Sframe_focus);
+ defsubr (&Sframe_parameters);
+ defsubr (&Smodify_frame_parameters);
+ defsubr (&Sframe_char_height);
+ defsubr (&Sframe_char_width);
+ defsubr (&Sframe_pixel_height);
+ defsubr (&Sframe_pixel_width);
+ defsubr (&Sset_frame_height);
+ defsubr (&Sset_frame_width);
+ defsubr (&Sset_frame_size);
+ defsubr (&Sset_frame_position);
+}
+
+keys_of_frame ()
+{
+ initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
+}
+\f
+#else /* not MULTI_FRAME */
+
+/* If we're not using multi-frame stuff, we still need to provide some
+ support functions. */
+
+Lisp_Object Vterminal_frame;
+
+/* Unless this function is defined, providing set-frame-height and
+ set-frame-width doesn't help compatibility any, since they both
+ want this as their first argument. */
+DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ ()
+{
+ Lisp_Object tem;
+ XFASTINT (tem) = 0;
+ return tem;
+}
+DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ (object)
+ Lisp_Object object;
+{
+ return Qnil;
+}
+
+DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ (frame, rows, pretend)
+ Lisp_Object frame, rows, pretend;
+{
+ CHECK_NUMBER (rows, 0);
+
+ change_frame_size (0, XINT (rows), 0, !NILP (pretend), 0);
+ return Qnil;
+}
+
+DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ (frame, cols, pretend)
+ Lisp_Object frame, cols, pretend;
+{
+ CHECK_NUMBER (cols, 0);
+
+ change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
+ return Qnil;
+}
+
+DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ (frame, cols, rows)
+ Lisp_Object frame, cols, rows;
+{
+ CHECK_NUMBER (cols, 2);
+ CHECK_NUMBER (rows, 1);
+
+ change_frame_size (0, XINT (rows), XINT (cols), 0, 0);
+
+ return Qnil;
+}
+
+DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 1, 0,
+ "Return number of lines available for display on FRAME.\n\
+If FRAME is omitted, describe the currently selected frame.")
+ (frame)
+ Lisp_Object frame;
+{
+ return make_number (FRAME_HEIGHT (selected_frame));
+}
+
+DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 1, 0,
+ "Return number of columns available for display on FRAME.\n\
+If FRAME is omitted, describe the currently selected frame.")
+ (frame)
+ Lisp_Object frame;
+{
+ return make_number (FRAME_WIDTH (selected_frame));
+}
+
+DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
+ 0, 1, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ (frame)
+ Lisp_Object frame;
+{
+ return make_number (1);
+}
+
+
+DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
+ 0, 1, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ (frame)
+ Lisp_Object frame;
+{
+ return make_number (1);
+}
+
+DEFUN ("frame-pixel-height", Fframe_pixel_height,
+ Sframe_pixel_height, 0, 1, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ (frame)
+ Lisp_Object frame;
+{
+ return make_number (FRAME_HEIGHT (f));
+}
+
+DEFUN ("frame-pixel-width", Fframe_pixel_width,
+ Sframe_pixel_width, 0, 1, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
+ (frame)
+ Lisp_Object frame;
+{
+ return make_number (FRAME_WIDTH (f));
+}
+
+/* These are for backward compatibility with Emacs 18. */
+
+DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
+ "Tell redisplay that the screen has LINES lines.\n\
+Optional second arg non-nil means that redisplay should use LINES lines\n\
+but that the idea of the actual height of the screen should not be changed.")
+ (lines, pretend)
+ Lisp_Object lines, pretend;
+{
+ CHECK_NUMBER (lines, 0);
+
+ change_frame_size (0, XINT (lines), 0, !NILP (pretend), 0);
+ return Qnil;
+}
+
+DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
+ "Tell redisplay that the screen has COLS columns.\n\
+Optional second arg non-nil means that redisplay should use COLS columns\n\
+but that the idea of the actual width of the screen should not be changed.")
+ (cols, pretend)
+ Lisp_Object cols, pretend;
+{
+ CHECK_NUMBER (cols, 0);
+
+ change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
+ return Qnil;
+}
+
+DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
+ "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
+The position is given in character cells, where (0, 0) is the\n\
+upper-left corner.\n\
+If Emacs is running on a mouseless terminal or hasn't been programmed\n\
+to read the mouse position, it returns the selected frame for FRAME\n\
+and nil for X and Y.")
+ ()
+{
+ FRAME_PTR f;
+ Lisp_Object lispy_dummy;
+ enum scroll_bar_part party_dummy;
+ Lisp_Object x, y;
+ unsigned long long_dummy;
+
+ f = selected_frame;
+ x = y = Qnil;
+
+ /* It's okay for the hook to refrain from storing anything. */
+ if (mouse_position_hook)
+ (*mouse_position_hook) (&f,
+ &lispy_dummy, &party_dummy,
+ &x, &y,
+ &long_dummy);
+
+ col = XINT (x);
+ row = XINT (y);
+ glyph_to_pixel_coords (f, col, row, &col, &row);
+ XSETINT (x, col);
+ XSETINT (y, row);
+ /* Always return nil for frame. */
+ return Fcons (Qnil, Fcons (x, y));
+}
+
+syms_of_frame ()
+{
+ DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
+ "The initial frame-object, which represents Emacs's stdout.");
+ XFASTINT (Vterminal_frame) = 0;
+
+ defsubr (&Sselected_frame);
+ defsubr (&Sframep);
+ defsubr (&Sframe_char_height);
+ defsubr (&Sframe_char_width);
+ defsubr (&Sframe_pixel_height);
+ defsubr (&Sframe_pixel_width);
+ defsubr (&Sset_frame_height);
+ defsubr (&Sset_frame_width);
+ defsubr (&Sset_frame_size);
+ defsubr (&Sset_screen_height);
+ defsubr (&Sset_screen_width);
+ defsubr (&Sframe_height);
+ Ffset (intern ("screen-height"), intern ("frame-height"));
+ defsubr (&Sframe_width);
+ Ffset (intern ("screen-width"), intern ("frame-width"));
+ defsubr (&Smouse_position);
+}
+
+keys_of_frame ()
+{
+}
+
+#endif /* not MULTI_FRAME */