*** empty log message ***
[bpt/emacs.git] / src / frame.c
CommitLineData
dc6f92b8 1/* Generic screen functions.
1113d9db 2 Copyright (C) 1989, 1992 Free Software Foundation.
dc6f92b8
JB
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
1113d9db 8the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
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 22#include "config.h"
e5d77022
JB
23
24#ifdef MULTI_SCREEN
25
dc6f92b8
JB
26#include "lisp.h"
27#include "screen.h"
28#include "window.h"
d5e7c279 29#include "termhooks.h"
dc6f92b8
JB
30
31Lisp_Object Vemacs_iconified;
32Lisp_Object Qscreenp;
f9898cc6 33Lisp_Object Qlive_screen_p;
dc6f92b8
JB
34Lisp_Object Vscreen_list;
35Lisp_Object Vterminal_screen;
f9898cc6 36Lisp_Object Vdefault_minibuffer_screen;
5bce042c 37Lisp_Object Vdefault_screen_alist;
bc93c097 38Lisp_Object Qminibuffer;
dc6f92b8
JB
39
40extern Lisp_Object Vminibuffer_list;
41extern Lisp_Object get_minibuffer ();
42\f
43DEFUN ("screenp", Fscreenp, Sscreenp, 1, 1, 0,
44 "Return non-nil if OBJECT is a screen.\n\
45Value is t for a termcap screen (a character-only terminal),\n\
f9898cc6 46`x' for an Emacs screen that is really an X window.\n\
ab17c3f2 47Also see `live-screen-p'.")
f9898cc6
JB
48 (object)
49 Lisp_Object object;
dc6f92b8 50{
f9898cc6 51 if (XTYPE (object) != Lisp_Screen)
dc6f92b8 52 return Qnil;
f9898cc6 53 switch (XSCREEN (object)->output_method)
dc6f92b8
JB
54 {
55 case output_termcap:
56 return Qt;
57 case output_x_window:
58 return intern ("x");
59 default:
60 abort ();
61 }
62}
63
f9898cc6
JB
64DEFUN ("live-screen-p", Flive_screen_p, Slive_screen_p, 1, 1, 0,
65 "Return non-nil if OBJECT is a screen which has not been deleted.\n\
66Value is nil if OBJECT is not a live screen. If object is a live\n\
67screen, the return value indicates what sort of output device it is\n\
68displayed on. Value is t for a termcap screen (a character-only\n\
69terminal), `x' for an Emacs screen being displayed in an X window.")
70 (object)
71 Lisp_Object object;
72{
73 return ((SCREENP (object)
74 && SCREEN_LIVE_P (XSCREEN (object)))
75 ? Fscreenp (object)
76 : Qnil);
77}
78
dc6f92b8
JB
79struct screen *
80make_screen (mini_p)
81 int mini_p;
82{
83 Lisp_Object screen;
84 register struct screen *s;
85 register Lisp_Object root_window;
86 register Lisp_Object mini_window;
87
d5e7c279
JB
88 screen = Fmake_vector (((sizeof (struct screen) - (sizeof (Lisp_Vector)
89 - sizeof (Lisp_Object)))
90 / sizeof (Lisp_Object)),
dc6f92b8
JB
91 make_number (0));
92 XSETTYPE (screen, Lisp_Screen);
93 s = XSCREEN (screen);
94
95 s->cursor_x = 0;
96 s->cursor_y = 0;
97 s->current_glyphs = 0;
98 s->desired_glyphs = 0;
99 s->visible = 0;
100 s->display.nothing = 0;
101 s->iconified = 0;
102 s->wants_modeline = 1;
103 s->auto_raise = 0;
104 s->auto_lower = 0;
105 s->no_split = 0;
106 s->garbaged = 0;
107 s->has_minibuffer = mini_p;
d5e7c279 108 s->focus_screen = screen;
dc6f92b8
JB
109
110 s->param_alist = Qnil;
111
112 root_window = make_window (0);
113 if (mini_p)
114 {
115 mini_window = make_window (0);
116 XWINDOW (root_window)->next = mini_window;
117 XWINDOW (mini_window)->prev = root_window;
118 XWINDOW (mini_window)->mini_p = Qt;
119 XWINDOW (mini_window)->screen = screen;
120 s->minibuffer_window = mini_window;
121 }
122 else
123 {
124 mini_window = Qnil;
125 XWINDOW (root_window)->next = Qnil;
126 s->minibuffer_window = Qnil;
127 }
128
129 XWINDOW (root_window)->screen = screen;
130
131 /* 10 is arbitrary,
132 just so that there is "something there."
133 Correct size will be set up later with change_screen_size. */
134
135 s->width = 10;
136 s->height = 10;
137
138 XFASTINT (XWINDOW (root_window)->width) = 10;
139 XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
140
141 if (mini_p)
142 {
143 XFASTINT (XWINDOW (mini_window)->width) = 10;
144 XFASTINT (XWINDOW (mini_window)->top) = 9;
145 XFASTINT (XWINDOW (mini_window)->height) = 1;
146 }
147
5bce042c
JB
148 /* Choose a buffer for the screen's root window. */
149 {
150 Lisp_Object buf;
151
152 XWINDOW (root_window)->buffer = Qt;
153 buf = Fcurrent_buffer ();
154 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
155 a space), try to find another one. */
156 if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
157 buf = Fother_buffer (buf);
158 Fset_window_buffer (root_window, buf);
159 }
160
dc6f92b8
JB
161 if (mini_p)
162 {
163 XWINDOW (mini_window)->buffer = Qt;
164 Fset_window_buffer (mini_window,
265a9e55 165 (NILP (Vminibuffer_list)
dc6f92b8
JB
166 ? get_minibuffer (0)
167 : Fcar (Vminibuffer_list)));
168 }
169
dc6f92b8 170 s->root_window = root_window;
d5e7c279
JB
171 s->selected_window = root_window;
172 /* Make sure this window seems more recently used than
173 a newly-created, never-selected window. */
174 XFASTINT (XWINDOW (s->selected_window)->use_time) = ++window_select_count;
dc6f92b8
JB
175
176 Vscreen_list = Fcons (screen, Vscreen_list);
177
178 return s;
179}
180\f
181/* Make a screen using a separate minibuffer window on another screen.
182 MINI_WINDOW is the minibuffer window to use. nil means use the
183 default (the global minibuffer). */
184
185struct screen *
186make_screen_without_minibuffer (mini_window)
187 register Lisp_Object mini_window;
188{
189 register struct screen *s;
190
191 /* Choose the minibuffer window to use. */
265a9e55 192 if (NILP (mini_window))
dc6f92b8 193 {
f9898cc6 194 if (XTYPE (Vdefault_minibuffer_screen) != Lisp_Screen)
1113d9db
JB
195 error ("default-minibuffer-screen must be set when creating minibufferless screens");
196 if (! SCREEN_LIVE_P (XSCREEN (Vdefault_minibuffer_screen)))
197 error ("default-minibuffer-screen must be a live screen");
f9898cc6 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 {
1113d9db
JB
495 Lisp_Object screens;
496
497 for (screens = Vscreen_list;
498 CONSP (screens);
499 screens = XCONS (screens)->cdr)
500 {
501 Lisp_Object this = XCONS (screens)->car;
502
503 if (! EQ (this, screen)
504 && EQ (screen,
505 (WINDOW_SCREEN
506 (XWINDOW
507 (SCREEN_MINIBUF_WINDOW
508 (XSCREEN (this)))))))
509 error ("Attempt to delete a surrogate minibuffer screen");
510 }
dc6f92b8
JB
511 }
512
d5e7c279
JB
513 /* Don't let the screen remain selected. */
514 if (s == selected_screen)
f9898cc6 515 Fselect_screen (next_screen (screen, Qt));
dc6f92b8
JB
516
517 /* Don't allow minibuf_window to remain on a deleted screen. */
518 if (EQ (s->minibuffer_window, minibuf_window))
519 {
520 Fset_window_buffer (selected_screen->minibuffer_window,
521 XWINDOW (minibuf_window)->buffer);
522 minibuf_window = selected_screen->minibuffer_window;
523 }
524
525 Vscreen_list = Fdelq (screen, Vscreen_list);
526 s->visible = 0;
527 displ = s->display;
528 s->display.nothing = 0;
529
d5e7c279 530#ifdef HAVE_X_WINDOWS
bc93c097 531 if (SCREEN_IS_X (s))
dc6f92b8 532 x_destroy_window (s, displ);
d5e7c279
JB
533#endif
534
535 /* If we've deleted the last_nonminibuf_screen, then try to find
536 another one. */
537 if (s == last_nonminibuf_screen)
538 {
1113d9db
JB
539 Lisp_Object screens;
540
d5e7c279
JB
541 last_nonminibuf_screen = 0;
542
1113d9db
JB
543 for (screens = Vscreen_list;
544 CONSP (screens);
d3aa5086 545 screens = XCONS (screens)->cdr)
d5e7c279 546 {
1113d9db 547 s = XSCREEN (XCONS (screens)->car);
f9898cc6 548 if (!SCREEN_MINIBUF_ONLY_P (s))
d5e7c279
JB
549 {
550 last_nonminibuf_screen = s;
551 break;
552 }
553 }
554 }
dc6f92b8 555
1113d9db
JB
556 /* If we've deleted Vdefault_minibuffer_screen, try to find another
557 one. Prefer minibuffer-only screens, but also notice screens
558 with other windows. */
559 if (EQ (screen, Vdefault_minibuffer_screen))
560 {
561 Lisp_Object screens;
562
563 /* The last screen we saw with a minibuffer, minibuffer-only or not. */
564 Lisp_Object screen_with_minibuf = Qnil;
565
566 for (screens = Vscreen_list;
567 CONSP (screens);
568 screens = XCONS (screens)->cdr)
569 {
570 Lisp_Object this = XCONS (screens)->car;
571
572 if (XTYPE (this) != Lisp_Screen)
573 abort ();
574 s = XSCREEN (this);
575
576 if (SCREEN_HAS_MINIBUF (s))
577 {
578 screen_with_minibuf = this;
579 if (SCREEN_MINIBUF_ONLY_P (s))
580 break;
581 }
582 }
583
584 /* We know that there must be some screen with a minibuffer out
585 there. If this were not true, all of the screens present
586 would have to be minibufferless, which implies that at some
587 point their minibuffer screens must have been deleted, but
588 that is prohibited at the top; you can't delete surrogate
589 minibuffer screens. */
590 if (NILP (screen_with_minibuf))
591 abort ();
592
593 Vdefault_minibuffer_screen = screen_with_minibuf;
594 }
595
dc6f92b8
JB
596 return Qnil;
597}
598\f
599/* Return mouse position in character cell units. */
600
f9898cc6
JB
601DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
602 "Return a list (SCREEN X . Y) giving the current mouse screen and position.\n\
603If Emacs is running on a mouseless terminal or hasn't been programmed\n\
604to read the mouse position, it returns the selected screen for SCREEN\n\
605and nil for X and Y.")
606 ()
dc6f92b8 607{
f9898cc6
JB
608 Lisp_Object x, y, dummy;
609 SCREEN_PTR s;
dc6f92b8 610
f9898cc6
JB
611 if (mouse_position_hook)
612 (*mouse_position_hook) (&s, &x, &y, &dummy);
613 else
614 {
615 s = selected_screen;
616 x = y = Qnil;
617 }
dc6f92b8 618
f9898cc6
JB
619 XSET (dummy, Lisp_Screen, s);
620 return Fcons (dummy, Fcons (make_number (x), make_number (y)));
dc6f92b8
JB
621}
622
623DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
624 "Move the mouse pointer to the center of cell (X,Y) in SCREEN.\n\
6869203e 625WARNING: If you use this under X, you should do `unfocus-screen' afterwards.")
dc6f92b8
JB
626 (screen, x, y)
627 Lisp_Object screen, x, y;
628{
f9898cc6 629 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
630 CHECK_NUMBER (x, 2);
631 CHECK_NUMBER (y, 1);
632
633#ifdef HAVE_X_WINDOWS
bc93c097 634 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
635 /* Warping the mouse will cause enternotify and focus events. */
636 x_set_mouse_position (XSCREEN (screen), x, y);
637#endif
638
639 return Qnil;
640}
641\f
642#if 0
643/* ??? Can this be replaced with a Lisp function?
644 It is used in minibuf.c. Can we get rid of that? */
645
646DEFUN ("screen-configuration", Fscreen_configuration, Sscreen_configuration,
647 0, 0, 0,
648 "Return object describing current screen configuration.\n\
649The screen configuration is the current mouse position and selected screen.\n\
650This object can be given to `restore-screen-configuration'\n\
651to restore this screen configuration.")
652 ()
653{
f9898cc6 654 Lisp_Object c, time;
dc6f92b8 655
f9898cc6
JB
656 c = Fmake_vector (make_number(4), Qnil);
657 XVECTOR (c)->contents[0] = Fselected_screen();
658 if (mouse_position_hook)
659 (*mouse_position_hook) (&XVECTOR (c)->contents[1]
660 &XVECTOR (c)->contents[2],
661 &XVECTOR (c)->contents[3],
662 &time);
dc6f92b8
JB
663 return c;
664}
665
666DEFUN ("restore-screen-configuration", Frestore_screen_configuration,
667 Srestore_screen_configuration,
668 1, 1, 0,
669 "Restores screen configuration CONFIGURATION.")
670 (config)
671 Lisp_Object config;
672{
673 Lisp_Object x_pos, y_pos, screen;
674
675 CHECK_VECTOR (config, 0);
676 if (XVECTOR (config)->size != 3)
677 {
678 error ("Wrong size vector passed to restore-screen-configuration");
679 }
680 screen = XVECTOR (config)->contents[0];
f9898cc6 681 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
682
683 Fselect_screen (screen, Qnil);
684
685#if 0
686 /* This seems to interfere with the screen selection mechanism. jla */
f9898cc6
JB
687 x_pos = XVECTOR (config)->contents[2];
688 y_pos = XVECTOR (config)->contents[3];
dc6f92b8
JB
689 set_mouse_position (screen, XINT (x_pos), XINT (y_pos));
690#endif
691
692 return screen;
693}
694#endif
695\f
696DEFUN ("make-screen-visible", Fmake_screen_visible, Smake_screen_visible,
697 1, 1, 0,
698 "Make the screen SCREEN visible (assuming it is an X-window).\n\
699Also raises the screen so that nothing obscures it.")
700 (screen)
701 Lisp_Object screen;
702{
f9898cc6 703 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8 704
bc93c097 705 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
706 x_make_screen_visible (XSCREEN (screen));
707
708 return screen;
709}
710
711DEFUN ("make-screen-invisible", Fmake_screen_invisible, Smake_screen_invisible,
712 1, 1, 0,
713 "Make the screen SCREEN invisible (assuming it is an X-window).")
714 (screen)
715 Lisp_Object screen;
716{
f9898cc6 717 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8 718
bc93c097 719 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
720 x_make_screen_invisible (XSCREEN (screen));
721
722 return Qnil;
723}
724
725DEFUN ("iconify-screen", Ficonify_screen, Siconify_screen,
726 1, 1, 0,
727 "Make the screen SCREEN into an icon.")
728 (screen)
729 Lisp_Object screen;
730{
f9898cc6 731 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8 732
bc93c097 733 if (SCREEN_IS_X (XSCREEN (screen)))
dc6f92b8
JB
734 x_iconify_screen (XSCREEN (screen));
735
736 return Qnil;
737}
738
dc6f92b8
JB
739DEFUN ("screen-visible-p", Fscreen_visible_p, Sscreen_visible_p,
740 1, 1, 0,
741 "Return t if SCREEN is now \"visible\" (actually in use for display).\n\
742A screen that is not \"visible\" is not updated and, if it works through\n\
743a window system, it may not show at all.\n\
744Return the symbol `icon' if window is visible only as an icon.")
745 (screen)
746 Lisp_Object screen;
747{
f9898cc6 748 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
749
750 if (XSCREEN (screen)->visible)
751 return Qt;
752 if (XSCREEN (screen)->iconified)
753 return intern ("icon");
754 return Qnil;
755}
756
757DEFUN ("visible-screen-list", Fvisible_screen_list, Svisible_screen_list,
758 0, 0, 0,
759 "Return a list of all screens now \"visible\" (being updated).")
760 ()
761{
762 Lisp_Object tail, screen;
763 struct screen *s;
764 Lisp_Object value;
765
766 value = Qnil;
767 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
768 {
769 screen = XCONS (tail)->car;
770 if (XTYPE (screen) != Lisp_Screen)
771 continue;
772 s = XSCREEN (screen);
773 if (s->visible)
774 value = Fcons (screen, value);
775 }
776 return value;
777}
d5e7c279
JB
778
779
780\f
781DEFUN ("redirect-screen-focus", Fredirect_screen_focus, Sredirect_screen_focus,
782 1, 2, 0,
783 "Arrange for keystrokes typed at SCREEN to be sent to FOCUS-SCREEN.\n\
784This means that, after reading a keystroke typed at SCREEN,\n\
6869203e 785`last-event-screen' will be FOCUS-SCREEN.\n\
d5e7c279
JB
786\n\
787If FOCUS-SCREEN is omitted or eq to SCREEN, any existing redirection is\n\
788cancelled, and the screen again receives its own keystrokes.\n\
789\n\
6869203e
RS
790The redirection lasts until the next call to `redirect-screen-focus'\n\
791or `select-screen'.\n\
d5e7c279
JB
792\n\
793This is useful for temporarily redirecting keystrokes to the minibuffer\n\
794window when a screen doesn't have its own minibuffer.")
795 (screen, focus_screen)
796 Lisp_Object screen, focus_screen;
797{
f9898cc6
JB
798 CHECK_LIVE_SCREEN (screen, 0);
799
265a9e55 800 if (NILP (focus_screen))
d5e7c279
JB
801 focus_screen = screen;
802 else
f9898cc6 803 CHECK_LIVE_SCREEN (focus_screen, 1);
d5e7c279
JB
804
805 XSCREEN (screen)->focus_screen = focus_screen;
806
807 if (screen_rehighlight_hook)
808 (*screen_rehighlight_hook) ();
809
810 return Qnil;
811}
812
813
814DEFUN ("screen-focus", Fscreen_focus, Sscreen_focus, 1, 1, 0,
815 "Return the screen to which SCREEN's keystrokes are currently being sent.\n\
6869203e 816See `redirect-screen-focus'.")
d5e7c279
JB
817 (screen)
818 Lisp_Object screen;
819{
f9898cc6 820 CHECK_LIVE_SCREEN (screen, 0);
d5e7c279
JB
821 return SCREEN_FOCUS_SCREEN (XSCREEN (screen));
822}
823
824
dc6f92b8
JB
825\f
826Lisp_Object
827get_screen_param (screen, prop)
828 register struct screen *screen;
829 Lisp_Object prop;
830{
831 register Lisp_Object tem;
832
833 tem = Fassq (prop, screen->param_alist);
834 if (EQ (tem, Qnil))
835 return tem;
836 return Fcdr (tem);
837}
838
839void
840store_in_alist (alistptr, propname, val)
841 Lisp_Object *alistptr, val;
842 char *propname;
843{
844 register Lisp_Object tem;
845 register Lisp_Object prop;
846
847 prop = intern (propname);
848 tem = Fassq (prop, *alistptr);
849 if (EQ (tem, Qnil))
850 *alistptr = Fcons (Fcons (prop, val), *alistptr);
851 else
852 Fsetcdr (tem, val);
853}
854
855void
856store_screen_param (s, prop, val)
857 struct screen *s;
858 Lisp_Object prop, val;
859{
860 register Lisp_Object tem;
861
862 tem = Fassq (prop, s->param_alist);
863 if (EQ (tem, Qnil))
864 s->param_alist = Fcons (Fcons (prop, val), s->param_alist);
865 else
866 Fsetcdr (tem, val);
bc93c097
JB
867
868 if (EQ (prop, Qminibuffer)
869 && XTYPE (val) == Lisp_Window)
870 {
871 if (! MINI_WINDOW_P (XWINDOW (val)))
872 error ("Surrogate minibuffer windows must be minibuffer windows.");
873
874 if (SCREEN_HAS_MINIBUF (s) || SCREEN_MINIBUF_ONLY_P (s))
875 error ("Can't change surrogate minibuffer on screens with their own minibuffers.");
876
877 /* Install the chosen minibuffer window, with proper buffer. */
878 s->minibuffer_window = val;
879 }
dc6f92b8
JB
880}
881
882DEFUN ("screen-parameters", Fscreen_parameters, Sscreen_parameters, 0, 1, 0,
883 "Return the parameters-alist of screen SCREEN.\n\
884It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
885The meaningful PARMs depend on the kind of screen.")
886 (screen)
887 Lisp_Object screen;
888{
889 Lisp_Object alist;
890 struct screen *s;
891
892 if (EQ (screen, Qnil))
893 s = selected_screen;
894 else
895 {
896 CHECK_SCREEN (screen, 0);
897 s = XSCREEN (screen);
898 }
899
900 if (s->display.nothing == 0)
901 return Qnil;
902
903 alist = Fcopy_alist (s->param_alist);
904 store_in_alist (&alist, "name", s->name);
905 store_in_alist (&alist, "height", make_number (s->height));
906 store_in_alist (&alist, "width", make_number (s->width));
907 store_in_alist (&alist, "modeline", (s->wants_modeline ? Qt : Qnil));
f9898cc6
JB
908 store_in_alist (&alist, "minibuffer",
909 (SCREEN_HAS_MINIBUF (s)
910 ? (SCREEN_MINIBUF_ONLY_P (s) ? intern ("only") : Qt)
bc93c097 911 : SCREEN_MINIBUF_WINDOW (s)));
dc6f92b8
JB
912 store_in_alist (&alist, "unsplittable", (s->no_split ? Qt : Qnil));
913
bc93c097 914 if (SCREEN_IS_X (s))
dc6f92b8
JB
915 x_report_screen_params (s, &alist);
916 return alist;
917}
918
919DEFUN ("modify-screen-parameters", Fmodify_screen_parameters,
920 Smodify_screen_parameters, 2, 2, 0,
921 "Modify the parameters of screen SCREEN according to ALIST.\n\
922ALIST is an alist of parameters to change and their new values.\n\
923Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
924The meaningful PARMs depend on the kind of screen; undefined PARMs are ignored.")
925 (screen, alist)
926 Lisp_Object screen, alist;
927{
928 register struct screen *s;
929 register Lisp_Object tail, elt, prop, val;
930
931 if (EQ (screen, Qnil))
932 s = selected_screen;
933 else
934 {
f9898cc6 935 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
936 s = XSCREEN (screen);
937 }
938
bc93c097 939 if (SCREEN_IS_X (s))
dc6f92b8
JB
940 for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
941 {
942 elt = Fcar (tail);
943 prop = Fcar (elt);
944 val = Fcdr (elt);
945 x_set_screen_param (s, prop, val,
946 get_screen_param (s, prop));
947 store_screen_param (s, prop, val);
948 }
949
950 return Qnil;
951}
952\f
953
954DEFUN ("screen-pixel-size", Fscreen_pixel_size,
955 Sscreen_pixel_size, 1, 1, 0,
f9898cc6 956 "Return a cons (width . height) of SCREEN's size in pixels.")
dc6f92b8
JB
957 (screen)
958 Lisp_Object screen;
959{
960 register struct screen *s;
961 int width, height;
962
f9898cc6 963 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
964 s = XSCREEN (screen);
965
966 return Fcons (make_number (x_pixel_width (s)),
967 make_number (x_pixel_height (s)));
968}
969
970DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
971 "Return number of lines available for display on selected screen.")
972 ()
973{
974 return make_number (SCREEN_HEIGHT (selected_screen));
975}
976
977DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
978 "Return number of columns available for display on selected screen.")
979 ()
980{
981 return make_number (SCREEN_WIDTH (selected_screen));
982}
983
984DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 2, 3, 0,
985 "Specify that the screen SCREEN has LINES lines.\n\
986Optional third arg non-nil means that redisplay should use LINES lines\n\
987but that the idea of the actual height of the screen should not be changed.")
988 (screen, rows, pretend)
989 Lisp_Object rows, pretend;
990{
991 register struct screen *s;
992
993 CHECK_NUMBER (rows, 0);
265a9e55 994 if (NILP (screen))
dc6f92b8
JB
995 s = selected_screen;
996 else
997 {
f9898cc6 998 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
999 s = XSCREEN (screen);
1000 }
1001
bc93c097 1002 if (SCREEN_IS_X (s))
dc6f92b8
JB
1003 {
1004 if (XINT (rows) != s->width)
1005 x_set_window_size (s, s->width, XINT (rows));
1006 }
1007 else
265a9e55 1008 change_screen_size (s, XINT (rows), 0, !NILP (pretend));
dc6f92b8
JB
1009 return Qnil;
1010}
1011
1012DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 2, 3, 0,
1013 "Specify that the screen SCREEN has COLS columns.\n\
1014Optional third arg non-nil means that redisplay should use COLS columns\n\
1015but that the idea of the actual width of the screen should not be changed.")
1016 (screen, cols, pretend)
1017 Lisp_Object cols, pretend;
1018{
1019 register struct screen *s;
1020 CHECK_NUMBER (cols, 0);
265a9e55 1021 if (NILP (screen))
dc6f92b8
JB
1022 s = selected_screen;
1023 else
1024 {
f9898cc6 1025 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
1026 s = XSCREEN (screen);
1027 }
1028
bc93c097 1029 if (SCREEN_IS_X (s))
dc6f92b8
JB
1030 {
1031 if (XINT (cols) != s->width)
1032 x_set_window_size (s, XINT (cols), s->height);
1033 }
1034 else
265a9e55 1035 change_screen_size (selected_screen, 0, XINT (cols), !NILP (pretend));
dc6f92b8
JB
1036 return Qnil;
1037}
1038
f9898cc6 1039DEFUN ("set-screen-size", Fset_screen_size, Sset_screen_size, 3, 3, 0,
dc6f92b8
JB
1040 "Sets size of SCREEN to COLS by ROWS, measured in characters.")
1041 (screen, cols, rows)
1042 Lisp_Object screen, cols, rows;
1043{
1044 register struct screen *s;
1045 int mask;
1046
f9898cc6 1047 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
1048 CHECK_NUMBER (cols, 2);
1049 CHECK_NUMBER (rows, 1);
1050 s = XSCREEN (screen);
1051
bc93c097 1052 if (SCREEN_IS_X (s))
dc6f92b8
JB
1053 {
1054 if (XINT (rows) != s->height || XINT (cols) != s->width)
1055 x_set_window_size (s, XINT (cols), XINT (rows));
1056 }
1057 else
1058 change_screen_size (s, XINT (rows), XINT (cols), 0);
1059
1060 return Qnil;
1061}
1062
1063DEFUN ("set-screen-position", Fset_screen_position,
1064 Sset_screen_position, 3, 3, 0,
f9898cc6
JB
1065 "Sets position of SCREEN in pixels to XOFFSET by YOFFSET.\n\
1066If XOFFSET or YOFFSET are negative, they are interpreted relative to\n\
1067the leftmost or bottommost position SCREEN could occupy without going\n\
1068off the screen.")
dc6f92b8
JB
1069 (screen, xoffset, yoffset)
1070 Lisp_Object screen, xoffset, yoffset;
1071{
1072 register struct screen *s;
1073 int mask;
1074
f9898cc6 1075 CHECK_LIVE_SCREEN (screen, 0);
dc6f92b8
JB
1076 CHECK_NUMBER (xoffset, 1);
1077 CHECK_NUMBER (yoffset, 2);
1078 s = XSCREEN (screen);
1079
bc93c097 1080 if (SCREEN_IS_X (s))
dc6f92b8
JB
1081 x_set_offset (s, XINT (xoffset), XINT (yoffset));
1082
1083 return Qt;
1084}
1085\f
dc6f92b8
JB
1086#ifndef HAVE_X11
1087DEFUN ("rubber-band-rectangle", Frubber_band_rectangle, Srubber_band_rectangle,
1088 3, 3, "",
1089 "Ask user to specify a window position and size on SCREEN with the mouse.\n\
1090Arguments are SCREEN, NAME and GEO. NAME is a name to be displayed as\n\
1091the purpose of this rectangle. GEO is an X-windows size spec that can\n\
1092specify defaults for some sizes/positions. If GEO specifies everything,\n\
1093the mouse is not used.\n\
1094Returns a list of five values: (SCREEN LEFT TOP WIDTH HEIGHT).")
1095 (screen, name, geo)
1096 Lisp_Object screen;
1097 Lisp_Object name;
1098 Lisp_Object geo;
1099{
1100 int vals[4];
1101 Lisp_Object nums[4];
1102 int i;
1103
1104 CHECK_SCREEN (screen, 0);
1105 CHECK_STRING (name, 1);
1106 CHECK_STRING (geo, 2);
1107
1108 switch (XSCREEN (screen)->output_method)
1109 {
1110 case output_x_window:
1111 x_rubber_band (XSCREEN (screen), &vals[0], &vals[1], &vals[2], &vals[3],
1112 XSTRING (geo)->data, XSTRING (name)->data);
1113 break;
1114
1115 default:
1116 return Qnil;
1117 }
1118
1119 for (i = 0; i < 4; i++)
1120 XFASTINT (nums[i]) = vals[i];
1121 return Fcons (screen, Flist (4, nums));
1122 return Qnil;
1123}
1124#endif /* not HAVE_X11 */
1125\f
1126choose_minibuf_screen ()
1127{
1128 /* For lowest-level minibuf, put it on currently selected screen
1129 if screen has a minibuffer. */
1130 if (minibuf_level == 0
1131 && selected_screen != 0
1132 && !EQ (minibuf_window, selected_screen->minibuffer_window)
1133 && !EQ (Qnil, selected_screen->minibuffer_window))
1134 {
1135 Fset_window_buffer (selected_screen->minibuffer_window,
1136 XWINDOW (minibuf_window)->buffer);
1137 minibuf_window = selected_screen->minibuffer_window;
1138 }
1139}
1140\f
1141syms_of_screen ()
1142{
1143 Qscreenp = intern ("screenp");
f9898cc6 1144 Qlive_screen_p = intern ("live_screen_p");
bc93c097 1145 Qminibuffer = intern ("minibuffer");
f9898cc6
JB
1146
1147 staticpro (&Qscreenp);
1148 staticpro (&Qlive_screen_p);
bc93c097 1149 staticpro (&Qminibuffer);
dc6f92b8
JB
1150
1151 staticpro (&Vscreen_list);
1152
1153 DEFVAR_LISP ("terminal-screen", &Vterminal_screen,
1154 "The initial screen-object, which represents Emacs's stdout.");
1155
1156 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
f9898cc6 1157 "Non-nil if all of emacs is iconified and screen updates are not needed.");
dc6f92b8
JB
1158 Vemacs_iconified = Qnil;
1159
f9898cc6
JB
1160 DEFVAR_LISP ("default-minibuffer-screen", &Vdefault_minibuffer_screen,
1161 "Minibufferless screens use this screen's minibuffer.\n\
1162\n\
1163Emacs cannot create minibufferless screens unless this is set to an\n\
1164appropriate surrogate.\n\
1165\n\
1166Emacs consults this variable only when creating minibufferless\n\
1167screens; once the screen is created, it sticks with its assigned\n\
1168minibuffer, no matter what this variable is set to. This means that\n\
1169this variable doesn't necessarily say anything meaningful about the\n\
1170current set of screens, or where the minibuffer is currently being\n\
1171displayed.");
1172 Vdefault_minibuffer_screen = Qnil;
dc6f92b8 1173
5bce042c
JB
1174 DEFVAR_LISP ("default-screen-alist", &Vdefault_screen_alist,
1175 "Alist of default values for screen creation.\n\
1176These may be set in your init file, like this:\n\
1177 (setq default-screen-alist '((width . 80) (height . 55)))\n\
1178These override values given in window system configuration data, like\n\
1179X Windows' defaults database.\n\
6869203e 1180For values specific to the first Emacs screen, see `initial-screen-alist'.\n\
5bce042c 1181For values specific to the separate minibuffer screen, see\n\
6869203e 1182`minibuffer-screen-alist'.");
5bce042c
JB
1183 Vdefault_screen_alist = Qnil;
1184
dc6f92b8 1185 defsubr (&Sscreenp);
f9898cc6 1186 defsubr (&Slive_screen_p);
dc6f92b8
JB
1187 defsubr (&Sselect_screen);
1188 defsubr (&Sselected_screen);
1189 defsubr (&Swindow_screen);
1190 defsubr (&Sscreen_root_window);
1191 defsubr (&Sscreen_selected_window);
1192 defsubr (&Sscreen_list);
1193 defsubr (&Snext_screen);
1194 defsubr (&Sdelete_screen);
f9898cc6 1195 defsubr (&Smouse_position);
dc6f92b8
JB
1196 defsubr (&Sset_mouse_position);
1197#if 0
1198 defsubr (&Sscreen_configuration);
1199 defsubr (&Srestore_screen_configuration);
1200#endif
1201 defsubr (&Smake_screen_visible);
1202 defsubr (&Smake_screen_invisible);
1203 defsubr (&Siconify_screen);
dc6f92b8
JB
1204 defsubr (&Sscreen_visible_p);
1205 defsubr (&Svisible_screen_list);
d5e7c279
JB
1206 defsubr (&Sredirect_screen_focus);
1207 defsubr (&Sscreen_focus);
dc6f92b8
JB
1208 defsubr (&Sscreen_parameters);
1209 defsubr (&Smodify_screen_parameters);
1210 defsubr (&Sscreen_pixel_size);
1211 defsubr (&Sscreen_height);
1212 defsubr (&Sscreen_width);
1213 defsubr (&Sset_screen_height);
1214 defsubr (&Sset_screen_width);
1215 defsubr (&Sset_screen_size);
1216 defsubr (&Sset_screen_position);
dc6f92b8
JB
1217#ifndef HAVE_X11
1218 defsubr (&Srubber_band_rectangle);
1219#endif /* HAVE_X11 */
1220}
e5d77022
JB
1221
1222#endif