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