Initial revision
[bpt/emacs.git] / src / frame.c
CommitLineData
dc6f92b8
JB
1/* Generic screen functions.
2 Copyright (C) 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
d5e7c279
JB
20#include <stdio.h>
21
dc6f92b8
JB
22#include "config.h"
23#include "lisp.h"
24#include "screen.h"
25#include "window.h"
d5e7c279 26#include "termhooks.h"
dc6f92b8
JB
27
28Lisp_Object Vemacs_iconified;
29Lisp_Object Qscreenp;
f9898cc6 30Lisp_Object Qlive_screen_p;
dc6f92b8
JB
31Lisp_Object Vscreen_list;
32Lisp_Object Vterminal_screen;
f9898cc6 33Lisp_Object Vdefault_minibuffer_screen;
5bce042c 34Lisp_Object Vdefault_screen_alist;
bc93c097 35Lisp_Object Qminibuffer;
dc6f92b8 36
d5e7c279
JB
37/* A screen which is not just a minibuffer, or 0 if there are no
38 such screens. This is usually the most recent such screen that
39 was selected. */
40struct screen *last_nonminibuf_screen;
41
dc6f92b8
JB
42extern Lisp_Object Vminibuffer_list;
43extern Lisp_Object get_minibuffer ();
44\f
45DEFUN ("screenp", Fscreenp, Sscreenp, 1, 1, 0,
46 "Return non-nil if OBJECT is a screen.\n\
47Value is t for a termcap screen (a character-only terminal),\n\
f9898cc6
JB
48`x' for an Emacs screen that is really an X window.\n\
49Also see live-screen-p.")
50 (object)
51 Lisp_Object object;
dc6f92b8 52{
f9898cc6 53 if (XTYPE (object) != Lisp_Screen)
dc6f92b8 54 return Qnil;
f9898cc6 55 switch (XSCREEN (object)->output_method)
dc6f92b8
JB
56 {
57 case output_termcap:
58 return Qt;
59 case output_x_window:
60 return intern ("x");
61 default:
62 abort ();
63 }
64}
65
f9898cc6
JB
66DEFUN ("live-screen-p", Flive_screen_p, Slive_screen_p, 1, 1, 0,
67 "Return non-nil if OBJECT is a screen which has not been deleted.\n\
68Value is nil if OBJECT is not a live screen. If object is a live\n\
69screen, the return value indicates what sort of output device it is\n\
70displayed on. Value is t for a termcap screen (a character-only\n\
71terminal), `x' for an Emacs screen being displayed in an X window.")
72 (object)
73 Lisp_Object object;
74{
75 return ((SCREENP (object)
76 && SCREEN_LIVE_P (XSCREEN (object)))
77 ? Fscreenp (object)
78 : Qnil);
79}
80
dc6f92b8
JB
81struct screen *
82make_screen (mini_p)
83 int mini_p;
84{
85 Lisp_Object screen;
86 register struct screen *s;
87 register Lisp_Object root_window;
88 register Lisp_Object mini_window;
89
d5e7c279
JB
90 screen = Fmake_vector (((sizeof (struct screen) - (sizeof (Lisp_Vector)
91 - sizeof (Lisp_Object)))
92 / sizeof (Lisp_Object)),
dc6f92b8
JB
93 make_number (0));
94 XSETTYPE (screen, Lisp_Screen);
95 s = XSCREEN (screen);
96
97 s->cursor_x = 0;
98 s->cursor_y = 0;
99 s->current_glyphs = 0;
100 s->desired_glyphs = 0;
101 s->visible = 0;
102 s->display.nothing = 0;
103 s->iconified = 0;
104 s->wants_modeline = 1;
105 s->auto_raise = 0;
106 s->auto_lower = 0;
107 s->no_split = 0;
108 s->garbaged = 0;
109 s->has_minibuffer = mini_p;
d5e7c279 110 s->focus_screen = screen;
dc6f92b8
JB
111
112 s->param_alist = Qnil;
113
114 root_window = make_window (0);
115 if (mini_p)
116 {
117 mini_window = make_window (0);
118 XWINDOW (root_window)->next = mini_window;
119 XWINDOW (mini_window)->prev = root_window;
120 XWINDOW (mini_window)->mini_p = Qt;
121 XWINDOW (mini_window)->screen = screen;
122 s->minibuffer_window = mini_window;
123 }
124 else
125 {
126 mini_window = Qnil;
127 XWINDOW (root_window)->next = Qnil;
128 s->minibuffer_window = Qnil;
129 }
130
131 XWINDOW (root_window)->screen = screen;
132
133 /* 10 is arbitrary,
134 just so that there is "something there."
135 Correct size will be set up later with change_screen_size. */
136
137 s->width = 10;
138 s->height = 10;
139
140 XFASTINT (XWINDOW (root_window)->width) = 10;
141 XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
142
143 if (mini_p)
144 {
145 XFASTINT (XWINDOW (mini_window)->width) = 10;
146 XFASTINT (XWINDOW (mini_window)->top) = 9;
147 XFASTINT (XWINDOW (mini_window)->height) = 1;
148 }
149
5bce042c
JB
150 /* Choose a buffer for the screen's root window. */
151 {
152 Lisp_Object buf;
153
154 XWINDOW (root_window)->buffer = Qt;
155 buf = Fcurrent_buffer ();
156 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
157 a space), try to find another one. */
158 if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
159 buf = Fother_buffer (buf);
160 Fset_window_buffer (root_window, buf);
161 }
162
dc6f92b8
JB
163 if (mini_p)
164 {
165 XWINDOW (mini_window)->buffer = Qt;
166 Fset_window_buffer (mini_window,
265a9e55 167 (NILP (Vminibuffer_list)
dc6f92b8
JB
168 ? get_minibuffer (0)
169 : Fcar (Vminibuffer_list)));
170 }
171
dc6f92b8 172 s->root_window = root_window;
d5e7c279
JB
173 s->selected_window = root_window;
174 /* Make sure this window seems more recently used than
175 a newly-created, never-selected window. */
176 XFASTINT (XWINDOW (s->selected_window)->use_time) = ++window_select_count;
dc6f92b8
JB
177
178 Vscreen_list = Fcons (screen, Vscreen_list);
179
180 return s;
181}
182\f
183/* Make a screen using a separate minibuffer window on another screen.
184 MINI_WINDOW is the minibuffer window to use. nil means use the
185 default (the global minibuffer). */
186
187struct screen *
188make_screen_without_minibuffer (mini_window)
189 register Lisp_Object mini_window;
190{
191 register struct screen *s;
192
193 /* Choose the minibuffer window to use. */
265a9e55 194 if (NILP (mini_window))
dc6f92b8 195 {
f9898cc6
JB
196 if (XTYPE (Vdefault_minibuffer_screen) != Lisp_Screen)
197 error ("default-minibuffer-screen must be set when creating minibufferless screens.");
198 mini_window = XSCREEN (Vdefault_minibuffer_screen)->minibuffer_window;
dc6f92b8
JB
199 }
200 else
201 {
202 CHECK_WINDOW (mini_window, 0);
203 }
204
205 /* Make a screen containing just a root window. */
206 s = make_screen (0);
207
208 /* Install the chosen minibuffer window, with proper buffer. */
209 s->minibuffer_window = mini_window;
210 Fset_window_buffer (mini_window,
265a9e55 211 (NILP (Vminibuffer_list)
dc6f92b8
JB
212 ? get_minibuffer (0)
213 : Fcar (Vminibuffer_list)));
214 return s;
215}
216
217/* Make a screen containing only a minibuffer window. */
218
219struct screen *
220make_minibuffer_screen ()
221{
222 /* First make a screen containing just a root window, no minibuffer. */
223
224 register struct screen *s = make_screen (0);
225 register Lisp_Object mini_window;
226 register Lisp_Object screen;
227
228 XSET (screen, Lisp_Screen, s);
229
230 /* ??? Perhaps leave it to the user program to set auto_raise. */
231 s->auto_raise = 1;
232 s->auto_lower = 0;
233 s->no_split = 1;
234 s->wants_modeline = 0;
f9898cc6 235 s->has_minibuffer = 1;
dc6f92b8
JB
236
237 /* Now label the root window as also being the minibuffer.
238 Avoid infinite looping on the window chain by marking next pointer
239 as nil. */
240
241 mini_window = s->minibuffer_window = s->root_window;
242 XWINDOW (mini_window)->mini_p = Qt;
243 XWINDOW (mini_window)->next = Qnil;
244 XWINDOW (mini_window)->prev = mini_window;
245 XWINDOW (mini_window)->screen = screen;
246
247 /* Put the proper buffer in that window. */
248
249 Fset_window_buffer (mini_window,
265a9e55 250 (NILP (Vminibuffer_list)
dc6f92b8
JB
251 ? get_minibuffer (0)
252 : Fcar (Vminibuffer_list)));
253 return s;
254}
255\f
256/* Construct a screen that refers to the terminal (stdin and stdout). */
257
258struct screen *
259make_terminal_screen ()
260{
261 register struct screen *s;
262
263 Vscreen_list = Qnil;
264 s = make_screen (1);
265 s->name = build_string ("terminal");
266 s->visible = 1;
267 s->display.nothing = 1; /* Nonzero means screen isn't deleted. */
268 XSET (Vterminal_screen, Lisp_Screen, s);
269 return s;
270}
271\f
272DEFUN ("select-screen", Fselect_screen, Sselect_screen, 1, 2, 0,
273 "Select the screen S. S's selected window becomes \"the\"\n\
d5e7c279 274selected window. If the optional parameter NO-ENTER is non-nil, don't\n\
dc6f92b8
JB
275focus on that screen.")
276 (screen, no_enter)
277 Lisp_Object screen, no_enter;
278{
f9898cc6 279 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
280
281 if (selected_screen == XSCREEN (screen))
282 return screen;
283
284 selected_screen = XSCREEN (screen);
f9898cc6 285 if (! SCREEN_MINIBUF_ONLY_P (selected_screen))
d5e7c279
JB
286 last_nonminibuf_screen = selected_screen;
287
dc6f92b8
JB
288 Fselect_window (XSCREEN (screen)->selected_window);
289
290#ifdef HAVE_X_WINDOWS
291#ifdef MULTI_SCREEN
bc93c097 292 if (SCREEN_IS_X (XSCREEN (screen))
265a9e55 293 && NILP (no_enter))
dc6f92b8
JB
294 {
295 Ffocus_screen (screen);
296 }
297#endif
298#endif
299 choose_minibuf_screen ();
300
301 return screen;
302}
303
304DEFUN ("selected-screen", Fselected_screen, Sselected_screen, 0, 0, 0,
305 "Return the screen that is now selected.")
306 ()
307{
308 Lisp_Object tem;
309 XSET (tem, Lisp_Screen, selected_screen);
310 return tem;
311}
312
313DEFUN ("window-screen", Fwindow_screen, Swindow_screen, 1, 1, 0,
314 "Return the screen object that window WINDOW is on.")
315 (window)
316 Lisp_Object window;
317{
318 CHECK_WINDOW (window, 0);
319 return XWINDOW (window)->screen;
320}
321
322DEFUN ("screen-root-window", Fscreen_root_window, Sscreen_root_window, 0, 1, 0,
323 "Returns the root-window of SCREEN.")
324 (screen)
325 Lisp_Object screen;
326{
265a9e55 327 if (NILP (screen))
dc6f92b8 328 XSET (screen, Lisp_Screen, selected_screen);
f9898cc6
JB
329 else
330 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
331
332 return XSCREEN (screen)->root_window;
333}
334
335DEFUN ("screen-selected-window", Fscreen_selected_window,
336 Sscreen_selected_window, 0, 1, 0,
337 "Return the selected window of screen object SCREEN.")
338 (screen)
339 Lisp_Object screen;
340{
265a9e55 341 if (NILP (screen))
dc6f92b8 342 XSET (screen, Lisp_Screen, selected_screen);
f9898cc6
JB
343 else
344 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
345
346 return XSCREEN (screen)->selected_window;
347}
348
349DEFUN ("screen-list", Fscreen_list, Sscreen_list,
350 0, 0, 0,
351 "Return a list of all screens.")
352 ()
353{
354 return Fcopy_sequence (Vscreen_list);
355}
356
357#ifdef MULTI_SCREEN
f9898cc6
JB
358
359/* Return the next screen in the screen list after SCREEN.
360 If MINIBUF is non-nil, include all screens.
361 If MINIBUF is nil, exclude minibuffer-only screens.
362 If MINIBUF is a window, include only screens using that window for
363 their minibuffer. */
dc6f92b8 364Lisp_Object
f9898cc6 365next_screen (screen, minibuf)
dc6f92b8 366 Lisp_Object screen;
f9898cc6 367 Lisp_Object minibuf;
dc6f92b8
JB
368{
369 Lisp_Object tail;
370 int passed = 0;
371
f9898cc6
JB
372 /* There must always be at least one screen in Vscreen_list. */
373 if (! CONSP (Vscreen_list))
374 abort ();
375
dc6f92b8
JB
376 while (1)
377 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
378 {
379 if (passed)
d5e7c279 380 {
f9898cc6
JB
381 Lisp_Object s = XCONS (tail)->car;
382
383 /* Decide whether this screen is eligible to be returned,
384 according to minibuf. */
265a9e55 385 if ((NILP (minibuf) && ! SCREEN_MINIBUF_ONLY_P (XSCREEN (s)))
f9898cc6
JB
386 || XTYPE (minibuf) != Lisp_Window
387 || EQ (SCREEN_MINIBUF_WINDOW (XSCREEN (s)), minibuf)
388 || EQ (s, screen))
389 return s;
d5e7c279 390 }
dc6f92b8
JB
391
392 if (EQ (screen, XCONS (tail)->car))
393 passed++;
394 }
395}
396
f9898cc6
JB
397/* Return the previous screen in the screen list before SCREEN.
398 If MINIBUF is non-nil, include all screens.
399 If MINIBUF is nil, exclude minibuffer-only screens.
400 If MINIBUF is a window, include only screens using that window for
401 their minibuffer. */
dc6f92b8 402Lisp_Object
f9898cc6 403prev_screen (screen, minibuf)
dc6f92b8 404 Lisp_Object screen;
f9898cc6 405 Lisp_Object minibuf;
dc6f92b8
JB
406{
407 Lisp_Object tail;
408 Lisp_Object prev;
409
f9898cc6
JB
410 /* There must always be at least one screen in Vscreen_list. */
411 if (! CONSP (Vscreen_list))
412 abort ();
413
dc6f92b8
JB
414 prev = Qnil;
415 while (1)
f9898cc6
JB
416 {
417 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
418 {
419 Lisp_Object scr = XCONS (tail)->car;
420
421 if (XTYPE (scr) != Lisp_Screen)
422 abort ();
423
265a9e55 424 if (EQ (screen, scr) && !NILP (prev))
f9898cc6
JB
425 return prev;
426
427 /* Decide whether this screen is eligible to be returned,
428 according to minibuf. */
265a9e55 429 if ((NILP (minibuf) && ! SCREEN_MINIBUF_ONLY_P (XSCREEN (scr)))
f9898cc6
JB
430 || XTYPE (minibuf) != Lisp_Window
431 || EQ (SCREEN_MINIBUF_WINDOW (XSCREEN (scr)), minibuf))
432 prev = scr;
433 }
434
265a9e55 435 if (NILP (prev))
f9898cc6
JB
436 /* We went through the whole screen list without finding a single
437 acceptable screen. Return the original screen. */
438 prev = screen;
439 }
440
dc6f92b8
JB
441}
442
f9898cc6
JB
443DEFUN ("next-screen", Fnext_screen, Snext_screen, 0, 2, 0,
444 "Return the next screen in the screen list after SCREEN.\n\
445If optional argument MINIBUF is non-nil, include all screens. If\n\
446MINIBUF is nil or omitted, exclude minibuffer-only screens. If\n\
447MINIBUF is a window, include only screens using that window for their\n\
448minibuffer.")
dc6f92b8
JB
449 (screen, miniscreen)
450Lisp_Object screen, miniscreen;
451{
452 Lisp_Object tail;
453
265a9e55 454 if (NILP (screen))
dc6f92b8 455 XSET (screen, Lisp_Screen, selected_screen);
f9898cc6
JB
456 else
457 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8 458
f9898cc6 459 return next_screen (screen, miniscreen);
dc6f92b8
JB
460}
461#endif /* MULTI_SCREEN */
462\f
f9898cc6
JB
463DEFUN ("delete-screen", Fdelete_screen, Sdelete_screen, 0, 1, "",
464 "Delete SCREEN, permanently eliminating it from use.\n\
465If omitted, SCREEN defaults to the selected screen.\n\
466A screen may not be deleted if its minibuffer is used by other screens.")
dc6f92b8
JB
467 (screen)
468 Lisp_Object screen;
469{
470 struct screen *s;
471 union display displ;
472
473 if (EQ (screen, Qnil))
474 {
475 s = selected_screen;
476 XSET (screen, Lisp_Screen, s);
477 }
478 else
479 {
480 CHECK_SCREEN (screen, 0);
481 s = XSCREEN (screen);
482 }
483
f9898cc6
JB
484 if (! SCREEN_LIVE_P (s))
485 return;
486
d5e7c279 487 /* Are there any other screens besides this one? */
f9898cc6 488 if (s == selected_screen && EQ (next_screen (screen, Qt), screen))
d5e7c279
JB
489 error ("Attempt to delete the only screen");
490
491 /* Does this screen have a minibuffer, and is it the surrogate
492 minibuffer for any other screen? */
f9898cc6 493 if (SCREEN_HAS_MINIBUF (XSCREEN (screen)))
dc6f92b8 494 {
d5e7c279 495 Lisp_Object screen2;
dc6f92b8 496
d5e7c279
JB
497 for (screen2 = Vscreen_list; CONSP (2); screen2 = XCONS (screen2)->cdr)
498 if (! EQ (screen2, screen)
499 && EQ (screen,
f9898cc6
JB
500 (WINDOW_SCREEN
501 (XWINDOW
502 (SCREEN_MINIBUF_WINDOW
503 (XSCREEN (screen2)))))))
d5e7c279 504 error ("Attempt to delete a surrogate minibuffer screen");
dc6f92b8
JB
505 }
506
d5e7c279
JB
507 /* Don't let the screen remain selected. */
508 if (s == selected_screen)
f9898cc6 509 Fselect_screen (next_screen (screen, Qt));
dc6f92b8
JB
510
511 /* Don't allow minibuf_window to remain on a deleted screen. */
512 if (EQ (s->minibuffer_window, minibuf_window))
513 {
514 Fset_window_buffer (selected_screen->minibuffer_window,
515 XWINDOW (minibuf_window)->buffer);
516 minibuf_window = selected_screen->minibuffer_window;
517 }
518
519 Vscreen_list = Fdelq (screen, Vscreen_list);
520 s->visible = 0;
521 displ = s->display;
522 s->display.nothing = 0;
523
d5e7c279 524#ifdef HAVE_X_WINDOWS
bc93c097 525 if (SCREEN_IS_X (s))
dc6f92b8 526 x_destroy_window (s, displ);
d5e7c279
JB
527#endif
528
529 /* If we've deleted the last_nonminibuf_screen, then try to find
530 another one. */
531 if (s == last_nonminibuf_screen)
532 {
533 last_nonminibuf_screen = 0;
534
535 for (screen = Vscreen_list; CONSP (screen); screen = XCONS (screen)->cdr)
536 {
f9898cc6
JB
537 s = XSCREEN (XCONS (screen)->car);
538 if (!SCREEN_MINIBUF_ONLY_P (s))
d5e7c279
JB
539 {
540 last_nonminibuf_screen = s;
541 break;
542 }
543 }
544 }
dc6f92b8
JB
545
546 return Qnil;
547}
548\f
549/* Return mouse position in character cell units. */
550
f9898cc6
JB
551DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
552 "Return a list (SCREEN X . Y) giving the current mouse screen and position.\n\
553If Emacs is running on a mouseless terminal or hasn't been programmed\n\
554to read the mouse position, it returns the selected screen for SCREEN\n\
555and nil for X and Y.")
556 ()
dc6f92b8 557{
f9898cc6
JB
558 Lisp_Object x, y, dummy;
559 SCREEN_PTR s;
dc6f92b8 560
f9898cc6
JB
561 if (mouse_position_hook)
562 (*mouse_position_hook) (&s, &x, &y, &dummy);
563 else
564 {
565 s = selected_screen;
566 x = y = Qnil;
567 }
dc6f92b8 568
f9898cc6
JB
569 XSET (dummy, Lisp_Screen, s);
570 return Fcons (dummy, Fcons (make_number (x), make_number (y)));
dc6f92b8
JB
571}
572
573DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
574 "Move the mouse pointer to the center of cell (X,Y) in SCREEN.\n\
575WARNING: If you use this under X, you should do unfocus-screen afterwards.")
576 (screen, x, y)
577 Lisp_Object screen, x, y;
578{
f9898cc6 579 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
580 CHECK_NUMBER (x, 2);
581 CHECK_NUMBER (y, 1);
582
583#ifdef HAVE_X_WINDOWS
bc93c097 584 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
585 /* Warping the mouse will cause enternotify and focus events. */
586 x_set_mouse_position (XSCREEN (screen), x, y);
587#endif
588
589 return Qnil;
590}
591\f
592#if 0
593/* ??? Can this be replaced with a Lisp function?
594 It is used in minibuf.c. Can we get rid of that? */
595
596DEFUN ("screen-configuration", Fscreen_configuration, Sscreen_configuration,
597 0, 0, 0,
598 "Return object describing current screen configuration.\n\
599The screen configuration is the current mouse position and selected screen.\n\
600This object can be given to `restore-screen-configuration'\n\
601to restore this screen configuration.")
602 ()
603{
f9898cc6 604 Lisp_Object c, time;
dc6f92b8 605
f9898cc6
JB
606 c = Fmake_vector (make_number(4), Qnil);
607 XVECTOR (c)->contents[0] = Fselected_screen();
608 if (mouse_position_hook)
609 (*mouse_position_hook) (&XVECTOR (c)->contents[1]
610 &XVECTOR (c)->contents[2],
611 &XVECTOR (c)->contents[3],
612 &time);
dc6f92b8
JB
613 return c;
614}
615
616DEFUN ("restore-screen-configuration", Frestore_screen_configuration,
617 Srestore_screen_configuration,
618 1, 1, 0,
619 "Restores screen configuration CONFIGURATION.")
620 (config)
621 Lisp_Object config;
622{
623 Lisp_Object x_pos, y_pos, screen;
624
625 CHECK_VECTOR (config, 0);
626 if (XVECTOR (config)->size != 3)
627 {
628 error ("Wrong size vector passed to restore-screen-configuration");
629 }
630 screen = XVECTOR (config)->contents[0];
f9898cc6 631 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
632
633 Fselect_screen (screen, Qnil);
634
635#if 0
636 /* This seems to interfere with the screen selection mechanism. jla */
f9898cc6
JB
637 x_pos = XVECTOR (config)->contents[2];
638 y_pos = XVECTOR (config)->contents[3];
dc6f92b8
JB
639 set_mouse_position (screen, XINT (x_pos), XINT (y_pos));
640#endif
641
642 return screen;
643}
644#endif
645\f
646DEFUN ("make-screen-visible", Fmake_screen_visible, Smake_screen_visible,
647 1, 1, 0,
648 "Make the screen SCREEN visible (assuming it is an X-window).\n\
649Also raises the screen so that nothing obscures it.")
650 (screen)
651 Lisp_Object screen;
652{
f9898cc6 653 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8 654
bc93c097 655 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
656 x_make_screen_visible (XSCREEN (screen));
657
658 return screen;
659}
660
661DEFUN ("make-screen-invisible", Fmake_screen_invisible, Smake_screen_invisible,
662 1, 1, 0,
663 "Make the screen SCREEN invisible (assuming it is an X-window).")
664 (screen)
665 Lisp_Object screen;
666{
f9898cc6 667 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8 668
bc93c097 669 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
670 x_make_screen_invisible (XSCREEN (screen));
671
672 return Qnil;
673}
674
675DEFUN ("iconify-screen", Ficonify_screen, Siconify_screen,
676 1, 1, 0,
677 "Make the screen SCREEN into an icon.")
678 (screen)
679 Lisp_Object screen;
680{
f9898cc6 681 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8 682
bc93c097 683 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
684 x_iconify_screen (XSCREEN (screen));
685
686 return Qnil;
687}
688
689DEFUN ("deiconify-screen", Fdeiconify_screen, Sdeiconify_screen,
690 1, 1, 0,
691 "Open (de-iconify) the iconified screen SCREEN.")
692 (screen)
693 Lisp_Object screen;
694{
f9898cc6 695 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8 696
bc93c097 697 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
698 x_make_screen_visible (XSCREEN (screen));
699
700 return screen;
701}
702
703DEFUN ("screen-visible-p", Fscreen_visible_p, Sscreen_visible_p,
704 1, 1, 0,
705 "Return t if SCREEN is now \"visible\" (actually in use for display).\n\
706A screen that is not \"visible\" is not updated and, if it works through\n\
707a window system, it may not show at all.\n\
708Return the symbol `icon' if window is visible only as an icon.")
709 (screen)
710 Lisp_Object screen;
711{
f9898cc6 712 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
713
714 if (XSCREEN (screen)->visible)
715 return Qt;
716 if (XSCREEN (screen)->iconified)
717 return intern ("icon");
718 return Qnil;
719}
720
721DEFUN ("visible-screen-list", Fvisible_screen_list, Svisible_screen_list,
722 0, 0, 0,
723 "Return a list of all screens now \"visible\" (being updated).")
724 ()
725{
726 Lisp_Object tail, screen;
727 struct screen *s;
728 Lisp_Object value;
729
730 value = Qnil;
731 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
732 {
733 screen = XCONS (tail)->car;
734 if (XTYPE (screen) != Lisp_Screen)
735 continue;
736 s = XSCREEN (screen);
737 if (s->visible)
738 value = Fcons (screen, value);
739 }
740 return value;
741}
d5e7c279
JB
742
743
744\f
745DEFUN ("redirect-screen-focus", Fredirect_screen_focus, Sredirect_screen_focus,
746 1, 2, 0,
747 "Arrange for keystrokes typed at SCREEN to be sent to FOCUS-SCREEN.\n\
748This means that, after reading a keystroke typed at SCREEN,\n\
749last-event-screen will be FOCUS-SCREEN.\n\
750\n\
751If FOCUS-SCREEN is omitted or eq to SCREEN, any existing redirection is\n\
752cancelled, and the screen again receives its own keystrokes.\n\
753\n\
754The redirection lasts until the next call to redirect-screen-focus\n\
755or select-screen.\n\
756\n\
757This is useful for temporarily redirecting keystrokes to the minibuffer\n\
758window when a screen doesn't have its own minibuffer.")
759 (screen, focus_screen)
760 Lisp_Object screen, focus_screen;
761{
f9898cc6
JB
762 CHECK_LIVE_SCREEN (screen, 0);
763
265a9e55 764 if (NILP (focus_screen))
d5e7c279
JB
765 focus_screen = screen;
766 else
f9898cc6 767 CHECK_LIVE_SCREEN (focus_screen, 1);
d5e7c279
JB
768
769 XSCREEN (screen)->focus_screen = focus_screen;
770
771 if (screen_rehighlight_hook)
772 (*screen_rehighlight_hook) ();
773
774 return Qnil;
775}
776
777
778DEFUN ("screen-focus", Fscreen_focus, Sscreen_focus, 1, 1, 0,
779 "Return the screen to which SCREEN's keystrokes are currently being sent.\n\
780See redirect-screen-focus.")
781 (screen)
782 Lisp_Object screen;
783{
f9898cc6 784 CHECK_LIVE_SCREEN (screen, 0);
d5e7c279
JB
785 return SCREEN_FOCUS_SCREEN (XSCREEN (screen));
786}
787
788
dc6f92b8
JB
789\f
790Lisp_Object
791get_screen_param (screen, prop)
792 register struct screen *screen;
793 Lisp_Object prop;
794{
795 register Lisp_Object tem;
796
797 tem = Fassq (prop, screen->param_alist);
798 if (EQ (tem, Qnil))
799 return tem;
800 return Fcdr (tem);
801}
802
803void
804store_in_alist (alistptr, propname, val)
805 Lisp_Object *alistptr, val;
806 char *propname;
807{
808 register Lisp_Object tem;
809 register Lisp_Object prop;
810
811 prop = intern (propname);
812 tem = Fassq (prop, *alistptr);
813 if (EQ (tem, Qnil))
814 *alistptr = Fcons (Fcons (prop, val), *alistptr);
815 else
816 Fsetcdr (tem, val);
817}
818
819void
820store_screen_param (s, prop, val)
821 struct screen *s;
822 Lisp_Object prop, val;
823{
824 register Lisp_Object tem;
825
826 tem = Fassq (prop, s->param_alist);
827 if (EQ (tem, Qnil))
828 s->param_alist = Fcons (Fcons (prop, val), s->param_alist);
829 else
830 Fsetcdr (tem, val);
bc93c097
JB
831
832 if (EQ (prop, Qminibuffer)
833 && XTYPE (val) == Lisp_Window)
834 {
835 if (! MINI_WINDOW_P (XWINDOW (val)))
836 error ("Surrogate minibuffer windows must be minibuffer windows.");
837
838 if (SCREEN_HAS_MINIBUF (s) || SCREEN_MINIBUF_ONLY_P (s))
839 error ("Can't change surrogate minibuffer on screens with their own minibuffers.");
840
841 /* Install the chosen minibuffer window, with proper buffer. */
842 s->minibuffer_window = val;
843 }
dc6f92b8
JB
844}
845
846DEFUN ("screen-parameters", Fscreen_parameters, Sscreen_parameters, 0, 1, 0,
847 "Return the parameters-alist of screen SCREEN.\n\
848It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
849The meaningful PARMs depend on the kind of screen.")
850 (screen)
851 Lisp_Object screen;
852{
853 Lisp_Object alist;
854 struct screen *s;
855
856 if (EQ (screen, Qnil))
857 s = selected_screen;
858 else
859 {
860 CHECK_SCREEN (screen, 0);
861 s = XSCREEN (screen);
862 }
863
864 if (s->display.nothing == 0)
865 return Qnil;
866
867 alist = Fcopy_alist (s->param_alist);
868 store_in_alist (&alist, "name", s->name);
869 store_in_alist (&alist, "height", make_number (s->height));
870 store_in_alist (&alist, "width", make_number (s->width));
871 store_in_alist (&alist, "modeline", (s->wants_modeline ? Qt : Qnil));
f9898cc6
JB
872 store_in_alist (&alist, "minibuffer",
873 (SCREEN_HAS_MINIBUF (s)
874 ? (SCREEN_MINIBUF_ONLY_P (s) ? intern ("only") : Qt)
bc93c097 875 : SCREEN_MINIBUF_WINDOW (s)));
dc6f92b8
JB
876 store_in_alist (&alist, "unsplittable", (s->no_split ? Qt : Qnil));
877
bc93c097 878 if (SCREEN_IS_X (s))
dc6f92b8
JB
879 x_report_screen_params (s, &alist);
880 return alist;
881}
882
883DEFUN ("modify-screen-parameters", Fmodify_screen_parameters,
884 Smodify_screen_parameters, 2, 2, 0,
885 "Modify the parameters of screen SCREEN according to ALIST.\n\
886ALIST is an alist of parameters to change and their new values.\n\
887Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
888The meaningful PARMs depend on the kind of screen; undefined PARMs are ignored.")
889 (screen, alist)
890 Lisp_Object screen, alist;
891{
892 register struct screen *s;
893 register Lisp_Object tail, elt, prop, val;
894
895 if (EQ (screen, Qnil))
896 s = selected_screen;
897 else
898 {
f9898cc6 899 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
900 s = XSCREEN (screen);
901 }
902
bc93c097 903 if (SCREEN_IS_X (s))
dc6f92b8
JB
904 for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
905 {
906 elt = Fcar (tail);
907 prop = Fcar (elt);
908 val = Fcdr (elt);
909 x_set_screen_param (s, prop, val,
910 get_screen_param (s, prop));
911 store_screen_param (s, prop, val);
912 }
913
914 return Qnil;
915}
916\f
917
918DEFUN ("screen-pixel-size", Fscreen_pixel_size,
919 Sscreen_pixel_size, 1, 1, 0,
f9898cc6 920 "Return a cons (width . height) of SCREEN's size in pixels.")
dc6f92b8
JB
921 (screen)
922 Lisp_Object screen;
923{
924 register struct screen *s;
925 int width, height;
926
f9898cc6 927 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
928 s = XSCREEN (screen);
929
930 return Fcons (make_number (x_pixel_width (s)),
931 make_number (x_pixel_height (s)));
932}
933
934DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
935 "Return number of lines available for display on selected screen.")
936 ()
937{
938 return make_number (SCREEN_HEIGHT (selected_screen));
939}
940
941DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
942 "Return number of columns available for display on selected screen.")
943 ()
944{
945 return make_number (SCREEN_WIDTH (selected_screen));
946}
947
948DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 2, 3, 0,
949 "Specify that the screen SCREEN has LINES lines.\n\
950Optional third arg non-nil means that redisplay should use LINES lines\n\
951but that the idea of the actual height of the screen should not be changed.")
952 (screen, rows, pretend)
953 Lisp_Object rows, pretend;
954{
955 register struct screen *s;
956
957 CHECK_NUMBER (rows, 0);
265a9e55 958 if (NILP (screen))
dc6f92b8
JB
959 s = selected_screen;
960 else
961 {
f9898cc6 962 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
963 s = XSCREEN (screen);
964 }
965
bc93c097 966 if (SCREEN_IS_X (s))
dc6f92b8
JB
967 {
968 if (XINT (rows) != s->width)
969 x_set_window_size (s, s->width, XINT (rows));
970 }
971 else
265a9e55 972 change_screen_size (s, XINT (rows), 0, !NILP (pretend));
dc6f92b8
JB
973 return Qnil;
974}
975
976DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 2, 3, 0,
977 "Specify that the screen SCREEN has COLS columns.\n\
978Optional third arg non-nil means that redisplay should use COLS columns\n\
979but that the idea of the actual width of the screen should not be changed.")
980 (screen, cols, pretend)
981 Lisp_Object cols, pretend;
982{
983 register struct screen *s;
984 CHECK_NUMBER (cols, 0);
265a9e55 985 if (NILP (screen))
dc6f92b8
JB
986 s = selected_screen;
987 else
988 {
f9898cc6 989 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
990 s = XSCREEN (screen);
991 }
992
bc93c097 993 if (SCREEN_IS_X (s))
dc6f92b8
JB
994 {
995 if (XINT (cols) != s->width)
996 x_set_window_size (s, XINT (cols), s->height);
997 }
998 else
265a9e55 999 change_screen_size (selected_screen, 0, XINT (cols), !NILP (pretend));
dc6f92b8
JB
1000 return Qnil;
1001}
1002
f9898cc6 1003DEFUN ("set-screen-size", Fset_screen_size, Sset_screen_size, 3, 3, 0,
dc6f92b8
JB
1004 "Sets size of SCREEN to COLS by ROWS, measured in characters.")
1005 (screen, cols, rows)
1006 Lisp_Object screen, cols, rows;
1007{
1008 register struct screen *s;
1009 int mask;
1010
f9898cc6 1011 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
1012 CHECK_NUMBER (cols, 2);
1013 CHECK_NUMBER (rows, 1);
1014 s = XSCREEN (screen);
1015
bc93c097 1016 if (SCREEN_IS_X (s))
dc6f92b8
JB
1017 {
1018 if (XINT (rows) != s->height || XINT (cols) != s->width)
1019 x_set_window_size (s, XINT (cols), XINT (rows));
1020 }
1021 else
1022 change_screen_size (s, XINT (rows), XINT (cols), 0);
1023
1024 return Qnil;
1025}
1026
1027DEFUN ("set-screen-position", Fset_screen_position,
1028 Sset_screen_position, 3, 3, 0,
f9898cc6
JB
1029 "Sets position of SCREEN in pixels to XOFFSET by YOFFSET.\n\
1030If XOFFSET or YOFFSET are negative, they are interpreted relative to\n\
1031the leftmost or bottommost position SCREEN could occupy without going\n\
1032off the screen.")
dc6f92b8
JB
1033 (screen, xoffset, yoffset)
1034 Lisp_Object screen, xoffset, yoffset;
1035{
1036 register struct screen *s;
1037 int mask;
1038
f9898cc6 1039 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
1040 CHECK_NUMBER (xoffset, 1);
1041 CHECK_NUMBER (yoffset, 2);
1042 s = XSCREEN (screen);
1043
bc93c097 1044 if (SCREEN_IS_X (s))
dc6f92b8
JB
1045 x_set_offset (s, XINT (xoffset), XINT (yoffset));
1046
1047 return Qt;
1048}
1049\f
dc6f92b8
JB
1050#ifndef HAVE_X11
1051DEFUN ("rubber-band-rectangle", Frubber_band_rectangle, Srubber_band_rectangle,
1052 3, 3, "",
1053 "Ask user to specify a window position and size on SCREEN with the mouse.\n\
1054Arguments are SCREEN, NAME and GEO. NAME is a name to be displayed as\n\
1055the purpose of this rectangle. GEO is an X-windows size spec that can\n\
1056specify defaults for some sizes/positions. If GEO specifies everything,\n\
1057the mouse is not used.\n\
1058Returns a list of five values: (SCREEN LEFT TOP WIDTH HEIGHT).")
1059 (screen, name, geo)
1060 Lisp_Object screen;
1061 Lisp_Object name;
1062 Lisp_Object geo;
1063{
1064 int vals[4];
1065 Lisp_Object nums[4];
1066 int i;
1067
1068 CHECK_SCREEN (screen, 0);
1069 CHECK_STRING (name, 1);
1070 CHECK_STRING (geo, 2);
1071
1072 switch (XSCREEN (screen)->output_method)
1073 {
1074 case output_x_window:
1075 x_rubber_band (XSCREEN (screen), &vals[0], &vals[1], &vals[2], &vals[3],
1076 XSTRING (geo)->data, XSTRING (name)->data);
1077 break;
1078
1079 default:
1080 return Qnil;
1081 }
1082
1083 for (i = 0; i < 4; i++)
1084 XFASTINT (nums[i]) = vals[i];
1085 return Fcons (screen, Flist (4, nums));
1086 return Qnil;
1087}
1088#endif /* not HAVE_X11 */
1089\f
1090choose_minibuf_screen ()
1091{
1092 /* For lowest-level minibuf, put it on currently selected screen
1093 if screen has a minibuffer. */
1094 if (minibuf_level == 0
1095 && selected_screen != 0
1096 && !EQ (minibuf_window, selected_screen->minibuffer_window)
1097 && !EQ (Qnil, selected_screen->minibuffer_window))
1098 {
1099 Fset_window_buffer (selected_screen->minibuffer_window,
1100 XWINDOW (minibuf_window)->buffer);
1101 minibuf_window = selected_screen->minibuffer_window;
1102 }
1103}
1104\f
1105syms_of_screen ()
1106{
1107 Qscreenp = intern ("screenp");
f9898cc6 1108 Qlive_screen_p = intern ("live_screen_p");
bc93c097 1109 Qminibuffer = intern ("minibuffer");
f9898cc6
JB
1110
1111 staticpro (&Qscreenp);
1112 staticpro (&Qlive_screen_p);
bc93c097 1113 staticpro (&Qminibuffer);
dc6f92b8
JB
1114
1115 staticpro (&Vscreen_list);
1116
1117 DEFVAR_LISP ("terminal-screen", &Vterminal_screen,
1118 "The initial screen-object, which represents Emacs's stdout.");
1119
1120 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
f9898cc6 1121 "Non-nil if all of emacs is iconified and screen updates are not needed.");
dc6f92b8
JB
1122 Vemacs_iconified = Qnil;
1123
f9898cc6
JB
1124 DEFVAR_LISP ("default-minibuffer-screen", &Vdefault_minibuffer_screen,
1125 "Minibufferless screens use this screen's minibuffer.\n\
1126\n\
1127Emacs cannot create minibufferless screens unless this is set to an\n\
1128appropriate surrogate.\n\
1129\n\
1130Emacs consults this variable only when creating minibufferless\n\
1131screens; once the screen is created, it sticks with its assigned\n\
1132minibuffer, no matter what this variable is set to. This means that\n\
1133this variable doesn't necessarily say anything meaningful about the\n\
1134current set of screens, or where the minibuffer is currently being\n\
1135displayed.");
1136 Vdefault_minibuffer_screen = Qnil;
dc6f92b8 1137
5bce042c
JB
1138 DEFVAR_LISP ("default-screen-alist", &Vdefault_screen_alist,
1139 "Alist of default values for screen creation.\n\
1140These may be set in your init file, like this:\n\
1141 (setq default-screen-alist '((width . 80) (height . 55)))\n\
1142These override values given in window system configuration data, like\n\
1143X Windows' defaults database.\n\
1144For values specific to the first emacs screen, see initial-screen-alist.\n\
1145For values specific to the separate minibuffer screen, see\n\
1146minibuffer-screen-alist.");
1147 Vdefault_screen_alist = Qnil;
1148
dc6f92b8 1149 defsubr (&Sscreenp);
f9898cc6 1150 defsubr (&Slive_screen_p);
dc6f92b8
JB
1151 defsubr (&Sselect_screen);
1152 defsubr (&Sselected_screen);
1153 defsubr (&Swindow_screen);
1154 defsubr (&Sscreen_root_window);
1155 defsubr (&Sscreen_selected_window);
1156 defsubr (&Sscreen_list);
1157 defsubr (&Snext_screen);
1158 defsubr (&Sdelete_screen);
f9898cc6 1159 defsubr (&Smouse_position);
dc6f92b8
JB
1160 defsubr (&Sset_mouse_position);
1161#if 0
1162 defsubr (&Sscreen_configuration);
1163 defsubr (&Srestore_screen_configuration);
1164#endif
1165 defsubr (&Smake_screen_visible);
1166 defsubr (&Smake_screen_invisible);
1167 defsubr (&Siconify_screen);
1168 defsubr (&Sdeiconify_screen);
1169 defsubr (&Sscreen_visible_p);
1170 defsubr (&Svisible_screen_list);
d5e7c279
JB
1171 defsubr (&Sredirect_screen_focus);
1172 defsubr (&Sscreen_focus);
dc6f92b8
JB
1173 defsubr (&Sscreen_parameters);
1174 defsubr (&Smodify_screen_parameters);
1175 defsubr (&Sscreen_pixel_size);
1176 defsubr (&Sscreen_height);
1177 defsubr (&Sscreen_width);
1178 defsubr (&Sset_screen_height);
1179 defsubr (&Sset_screen_width);
1180 defsubr (&Sset_screen_size);
1181 defsubr (&Sset_screen_position);
dc6f92b8
JB
1182#ifndef HAVE_X11
1183 defsubr (&Srubber_band_rectangle);
1184#endif /* HAVE_X11 */
1185}