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