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