aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJim Blandy1991-05-25 06:46:10 +0000
committerJim Blandy1991-05-25 06:46:10 +0000
commitdc6f92b83455e13fba9ee1c88122fcc9453e79cd (patch)
treea0d069609f2a4afcf80f484c5c2d822006c591df /src
parentecca85de5679824b489852bade75738310a7fcba (diff)
downloademacs-dc6f92b83455e13fba9ee1c88122fcc9453e79cd.tar.gz
emacs-dc6f92b83455e13fba9ee1c88122fcc9453e79cd.zip
Initial revision
Diffstat (limited to 'src')
-rw-r--r--src/frame.c1056
-rw-r--r--src/xterm.c3798
2 files changed, 4854 insertions, 0 deletions
diff --git a/src/frame.c b/src/frame.c
new file mode 100644
index 00000000000..8f07e71d893
--- /dev/null
+++ b/src/frame.c
@@ -0,0 +1,1056 @@
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
20#include "config.h"
21#include "lisp.h"
22#include "screen.h"
23#include "window.h"
24
25Lisp_Object Vemacs_iconified;
26Lisp_Object Qscreenp;
27Lisp_Object Vscreen_list;
28Lisp_Object Vterminal_screen;
29Lisp_Object Vglobal_minibuffer_screen;
30
31extern Lisp_Object Vminibuffer_list;
32extern Lisp_Object get_minibuffer ();
33
34DEFUN ("screenp", Fscreenp, Sscreenp, 1, 1, 0,
35 "Return non-nil if OBJECT is a screen.\n\
36Value is t for a termcap screen (a character-only terminal),\n\
37`x' for an Emacs screen that is really an X window.")
38 (screen)
39 Lisp_Object screen;
40{
41 if (XTYPE (screen) != Lisp_Screen)
42 return Qnil;
43 switch (XSCREEN (screen)->output_method)
44 {
45 case output_termcap:
46 return Qt;
47 case output_x_window:
48 return intern ("x");
49 default:
50 abort ();
51 }
52}
53
54struct screen *
55make_screen (mini_p)
56 int mini_p;
57{
58 Lisp_Object screen;
59 register struct screen *s;
60 register Lisp_Object root_window;
61 register Lisp_Object mini_window;
62
63 screen = Fmake_vector (sizeof (struct screen) - sizeof (Lisp_Vector) + 1,
64 make_number (0));
65 XSETTYPE (screen, Lisp_Screen);
66 s = XSCREEN (screen);
67
68 s->cursor_x = 0;
69 s->cursor_y = 0;
70 s->current_glyphs = 0;
71 s->desired_glyphs = 0;
72 s->visible = 0;
73 s->display.nothing = 0;
74 s->iconified = 0;
75 s->wants_modeline = 1;
76 s->auto_raise = 0;
77 s->auto_lower = 0;
78 s->no_split = 0;
79 s->garbaged = 0;
80 s->has_minibuffer = mini_p;
81
82 s->param_alist = Qnil;
83
84 root_window = make_window (0);
85 if (mini_p)
86 {
87 mini_window = make_window (0);
88 XWINDOW (root_window)->next = mini_window;
89 XWINDOW (mini_window)->prev = root_window;
90 XWINDOW (mini_window)->mini_p = Qt;
91 XWINDOW (mini_window)->screen = screen;
92 s->minibuffer_window = mini_window;
93 }
94 else
95 {
96 mini_window = Qnil;
97 XWINDOW (root_window)->next = Qnil;
98 s->minibuffer_window = Qnil;
99 }
100
101 XWINDOW (root_window)->screen = screen;
102
103 /* 10 is arbitrary,
104 just so that there is "something there."
105 Correct size will be set up later with change_screen_size. */
106
107 s->width = 10;
108 s->height = 10;
109
110 XFASTINT (XWINDOW (root_window)->width) = 10;
111 XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
112
113 if (mini_p)
114 {
115 XFASTINT (XWINDOW (mini_window)->width) = 10;
116 XFASTINT (XWINDOW (mini_window)->top) = 9;
117 XFASTINT (XWINDOW (mini_window)->height) = 1;
118 }
119
120 XWINDOW (root_window)->buffer = Qt;
121 Fset_window_buffer (root_window, Fcurrent_buffer ());
122 if (mini_p)
123 {
124 XWINDOW (mini_window)->buffer = Qt;
125 Fset_window_buffer (mini_window,
126 (NULL (Vminibuffer_list)
127 ? get_minibuffer (0)
128 : Fcar (Vminibuffer_list)));
129 }
130
131 s->selected_window = root_window;
132 s->root_window = root_window;
133
134 Vscreen_list = Fcons (screen, Vscreen_list);
135
136 return s;
137}
138
139/* Make a screen using a separate minibuffer window on another screen.
140 MINI_WINDOW is the minibuffer window to use. nil means use the
141 default (the global minibuffer). */
142
143struct screen *
144make_screen_without_minibuffer (mini_window)
145 register Lisp_Object mini_window;
146{
147 register struct screen *s;
148
149 /* Choose the minibuffer window to use. */
150 if (NULL (mini_window))
151 {
152 CHECK_SCREEN (Vglobal_minibuffer_screen, 0);
153 mini_window = XSCREEN (Vglobal_minibuffer_screen)->minibuffer_window;
154 }
155 else
156 {
157 CHECK_WINDOW (mini_window, 0);
158 }
159
160 /* Make a screen containing just a root window. */
161 s = make_screen (0);
162
163 /* Install the chosen minibuffer window, with proper buffer. */
164 s->minibuffer_window = mini_window;
165 Fset_window_buffer (mini_window,
166 (NULL (Vminibuffer_list)
167 ? get_minibuffer (0)
168 : Fcar (Vminibuffer_list)));
169 return s;
170}
171
172/* Make a screen containing only a minibuffer window. */
173
174struct screen *
175make_minibuffer_screen ()
176{
177 /* First make a screen containing just a root window, no minibuffer. */
178
179 register struct screen *s = make_screen (0);
180 register Lisp_Object mini_window;
181 register Lisp_Object screen;
182
183 XSET (screen, Lisp_Screen, s);
184
185 /* ??? Perhaps leave it to the user program to set auto_raise. */
186 s->auto_raise = 1;
187 s->auto_lower = 0;
188 s->no_split = 1;
189 s->wants_modeline = 0;
190 /* Note we leave has_minibuffer as 0. This is a little strange. */
191
192 /* Now label the root window as also being the minibuffer.
193 Avoid infinite looping on the window chain by marking next pointer
194 as nil. */
195
196 mini_window = s->minibuffer_window = s->root_window;
197 XWINDOW (mini_window)->mini_p = Qt;
198 XWINDOW (mini_window)->next = Qnil;
199 XWINDOW (mini_window)->prev = mini_window;
200 XWINDOW (mini_window)->screen = screen;
201
202 /* Put the proper buffer in that window. */
203
204 Fset_window_buffer (mini_window,
205 (NULL (Vminibuffer_list)
206 ? get_minibuffer (0)
207 : Fcar (Vminibuffer_list)));
208 return s;
209}
210
211/* Construct a screen that refers to the terminal (stdin and stdout). */
212
213struct screen *
214make_terminal_screen ()
215{
216 register struct screen *s;
217
218 Vscreen_list = Qnil;
219 s = make_screen (1);
220 s->name = build_string ("terminal");
221 s->visible = 1;
222 s->display.nothing = 1; /* Nonzero means screen isn't deleted. */
223 XSET (Vterminal_screen, Lisp_Screen, s);
224 return s;
225}
226
227DEFUN ("select-screen", Fselect_screen, Sselect_screen, 1, 2, 0,
228 "Select the screen S. S's selected window becomes \"the\"\n\
229selected window. If the optional parameter NO-ENTER is non-nil, don't
230focus on that screen.")
231 (screen, no_enter)
232 Lisp_Object screen, no_enter;
233{
234 CHECK_SCREEN (screen, 0);
235
236 if (selected_screen == XSCREEN (screen))
237 return screen;
238
239 selected_screen = XSCREEN (screen);
240 Fselect_window (XSCREEN (screen)->selected_window);
241
242#ifdef HAVE_X_WINDOWS
243#ifdef MULTI_SCREEN
244 if (XSCREEN (screen)->output_method == output_x_window
245 && NULL (no_enter))
246 {
247 Ffocus_screen (screen);
248 }
249#endif
250#endif
251 choose_minibuf_screen ();
252
253 return screen;
254}
255
256DEFUN ("selected-screen", Fselected_screen, Sselected_screen, 0, 0, 0,
257 "Return the screen that is now selected.")
258 ()
259{
260 Lisp_Object tem;
261 XSET (tem, Lisp_Screen, selected_screen);
262 return tem;
263}
264
265DEFUN ("window-screen", Fwindow_screen, Swindow_screen, 1, 1, 0,
266 "Return the screen object that window WINDOW is on.")
267 (window)
268 Lisp_Object window;
269{
270 CHECK_WINDOW (window, 0);
271 return XWINDOW (window)->screen;
272}
273
274DEFUN ("screen-root-window", Fscreen_root_window, Sscreen_root_window, 0, 1, 0,
275 "Returns the root-window of SCREEN.")
276 (screen)
277 Lisp_Object screen;
278{
279 if (NULL (screen))
280 XSET (screen, Lisp_Screen, selected_screen);
281 CHECK_SCREEN (screen, 0);
282
283 return XSCREEN (screen)->root_window;
284}
285
286DEFUN ("screen-selected-window", Fscreen_selected_window,
287 Sscreen_selected_window, 0, 1, 0,
288 "Return the selected window of screen object SCREEN.")
289 (screen)
290 Lisp_Object screen;
291{
292 if (NULL (screen))
293 XSET (screen, Lisp_Screen, selected_screen);
294 CHECK_SCREEN (screen, 0);
295
296 return XSCREEN (screen)->selected_window;
297}
298
299DEFUN ("screen-list", Fscreen_list, Sscreen_list,
300 0, 0, 0,
301 "Return a list of all screens.")
302 ()
303{
304 return Fcopy_sequence (Vscreen_list);
305}
306
307#ifdef MULTI_SCREEN
308Lisp_Object
309next_screen (screen, mini_screen)
310 Lisp_Object screen;
311 int mini_screen;
312{
313 Lisp_Object tail;
314 int passed = 0;
315
316 while (1)
317 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
318 {
319 if (passed)
320 if (!mini_screen
321 && EQ (XCONS (tail)->car, Vglobal_minibuffer_screen))
322 continue;
323 else
324 return XCONS (tail)->car;
325
326 if (EQ (screen, XCONS (tail)->car))
327 passed++;
328 }
329}
330
331Lisp_Object
332prev_screen (screen, mini_screen)
333 Lisp_Object screen;
334 int mini_screen;
335{
336 Lisp_Object tail;
337 Lisp_Object prev;
338
339 prev = Qnil;
340 while (1)
341 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
342 {
343 if (EQ (screen, XCONS (tail)->car))
344 {
345 if (!NULL (prev) && (mini_screen
346 || !EQ (XCONS (tail)->car,
347 Vglobal_minibuffer_screen)))
348 return prev;
349 }
350 prev = XCONS (tail)->car;
351 }
352}
353
354DEFUN ("next-screen", Fnext_screen, Snext_screen,
355 0, 2, 0,
356 "Return the next screen in the screen list after SCREEN.\n\
357If MINISCREEN is non-nil, include the global-minibuffer-screen if it\n\
358has its own screen.")
359 (screen, miniscreen)
360Lisp_Object screen, miniscreen;
361{
362 Lisp_Object tail;
363
364 if (NULL (screen))
365 XSET (screen, Lisp_Screen, selected_screen);
366 CHECK_SCREEN (screen, 0);
367
368 return next_screen (screen, (NULL (miniscreen) ? 0 : 1));
369}
370#endif /* MULTI_SCREEN */
371
372DEFUN ("delete-screen", Fdelete_screen, Sdelete_screen,
373 0, 1, "",
374 "Delete SCREEN, permanently eliminating it from use.\n\
375Default is current screen.")
376 (screen)
377 Lisp_Object screen;
378{
379 struct screen *s;
380 union display displ;
381
382 if (EQ (screen, Qnil))
383 {
384 s = selected_screen;
385 XSET (screen, Lisp_Screen, s);
386 }
387 else
388 {
389 CHECK_SCREEN (screen, 0);
390 s = XSCREEN (screen);
391 }
392
393 /* Don't allow deleted screen to remain selected. */
394 if (s == selected_screen)
395 {
396 Lisp_Object next;
397
398 next = next_screen (screen, 0);
399 if (EQ (next, screen))
400 error ("Attempt to delete the only screen");
401 Fselect_screen (next, Qnil);
402 }
403
404 /* Don't allow the global minibuffer screen to be deleted */
405 if (s == XSCREEN (Vglobal_minibuffer_screen))
406 error ("Attempt to delete the global minibuffer screen");
407
408 /* Don't allow minibuf_window to remain on a deleted screen. */
409 if (EQ (s->minibuffer_window, minibuf_window))
410 {
411 Fset_window_buffer (selected_screen->minibuffer_window,
412 XWINDOW (minibuf_window)->buffer);
413 minibuf_window = selected_screen->minibuffer_window;
414 }
415
416 Vscreen_list = Fdelq (screen, Vscreen_list);
417 s->visible = 0;
418 displ = s->display;
419 s->display.nothing = 0;
420
421 if (s->output_method == output_x_window)
422 x_destroy_window (s, displ);
423
424 return Qnil;
425}
426
427/* Return mouse position in character cell units. */
428
429static
430read_mouse_position (screen, x, y)
431 Lisp_Object screen;
432 int *x, *y;
433{
434 CHECK_SCREEN (screen, 0);
435
436 *x = 1;
437 *y = 1;
438
439#ifdef HAVE_X_WINDOWS
440 if (XSCREEN (screen)->output_method == output_x_window)
441 x_read_mouse_position (XSCREEN (screen), x, y);
442#endif
443}
444
445DEFUN ("read-mouse-position", Fread_mouse_position, Sread_mouse_position, 1, 1, 0,
446 "Return a cons (x . y) which represents the position of the mouse.")
447 (screen)
448 Lisp_Object screen;
449{
450 int x, y;
451 struct screen *s;
452
453 CHECK_SCREEN (screen, 0);
454
455 read_mouse_position (screen, &x, &y);
456 return Fcons (make_number (x), make_number (y));
457}
458
459DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
460 "Move the mouse pointer to the center of cell (X,Y) in SCREEN.\n\
461WARNING: If you use this under X, you should do unfocus-screen afterwards.")
462 (screen, x, y)
463 Lisp_Object screen, x, y;
464{
465 CHECK_SCREEN (screen, 0);
466 CHECK_NUMBER (x, 2);
467 CHECK_NUMBER (y, 1);
468
469#ifdef HAVE_X_WINDOWS
470 if (XSCREEN (screen)->output_method == output_x_window)
471 /* Warping the mouse will cause enternotify and focus events. */
472 x_set_mouse_position (XSCREEN (screen), x, y);
473#endif
474
475 return Qnil;
476}
477
478#if 0
479/* ??? Can this be replaced with a Lisp function?
480 It is used in minibuf.c. Can we get rid of that? */
481
482DEFUN ("screen-configuration", Fscreen_configuration, Sscreen_configuration,
483 0, 0, 0,
484 "Return object describing current screen configuration.\n\
485The screen configuration is the current mouse position and selected screen.\n\
486This object can be given to `restore-screen-configuration'\n\
487to restore this screen configuration.")
488 ()
489{
490 int x, y;
491 Lisp_Object c, screen;
492 struct screen *s;
493
494 c = Fmake_vector (make_number(3), Qnil);
495 XVECTOR (c)->contents[0] = screen = Fselected_screen();
496 read_mouse_position (screen, &x, &y);
497 XVECTOR (c)->contents[1] = make_number (x);
498 XVECTOR (c)->contents[2] = make_number (y);
499
500 return c;
501}
502
503DEFUN ("restore-screen-configuration", Frestore_screen_configuration,
504 Srestore_screen_configuration,
505 1, 1, 0,
506 "Restores screen configuration CONFIGURATION.")
507 (config)
508 Lisp_Object config;
509{
510 Lisp_Object x_pos, y_pos, screen;
511
512 CHECK_VECTOR (config, 0);
513 if (XVECTOR (config)->size != 3)
514 {
515 error ("Wrong size vector passed to restore-screen-configuration");
516 }
517 screen = XVECTOR (config)->contents[0];
518 CHECK_SCREEN (screen, 0);
519
520 Fselect_screen (screen, Qnil);
521
522#if 0
523 /* This seems to interfere with the screen selection mechanism. jla */
524 x_pos = XVECTOR (config)->contents[1];
525 y_pos = XVECTOR (config)->contents[2];
526 set_mouse_position (screen, XINT (x_pos), XINT (y_pos));
527#endif
528
529 return screen;
530}
531#endif
532
533DEFUN ("make-screen-visible", Fmake_screen_visible, Smake_screen_visible,
534 1, 1, 0,
535 "Make the screen SCREEN visible (assuming it is an X-window).\n\
536Also raises the screen so that nothing obscures it.")
537 (screen)
538 Lisp_Object screen;
539{
540 CHECK_SCREEN (screen, 0);
541
542 if (XSCREEN (screen)->display.nothing == 0)
543 error ("Cannot make a dead screen object visible");
544
545 if (XSCREEN (screen)->output_method == output_x_window)
546 x_make_screen_visible (XSCREEN (screen));
547
548 return screen;
549}
550
551DEFUN ("make-screen-invisible", Fmake_screen_invisible, Smake_screen_invisible,
552 1, 1, 0,
553 "Make the screen SCREEN invisible (assuming it is an X-window).")
554 (screen)
555 Lisp_Object screen;
556{
557 CHECK_SCREEN (screen, 0);
558
559 if (XSCREEN (screen)->output_method == output_x_window)
560 x_make_screen_invisible (XSCREEN (screen));
561
562 return Qnil;
563}
564
565DEFUN ("iconify-screen", Ficonify_screen, Siconify_screen,
566 1, 1, 0,
567 "Make the screen SCREEN into an icon.")
568 (screen)
569 Lisp_Object screen;
570{
571 CHECK_SCREEN (screen, 0);
572
573 if (XSCREEN (screen)->display.nothing == 0)
574 error ("Cannot make a dead screen object iconified.");
575
576 if (XSCREEN (screen)->output_method == output_x_window)
577 x_iconify_screen (XSCREEN (screen));
578
579 return Qnil;
580}
581
582DEFUN ("deiconify-screen", Fdeiconify_screen, Sdeiconify_screen,
583 1, 1, 0,
584 "Open (de-iconify) the iconified screen SCREEN.")
585 (screen)
586 Lisp_Object screen;
587{
588 CHECK_SCREEN (screen, 0);
589
590 if (XSCREEN (screen)->display.nothing == 0)
591 error ("Cannot deiconify a dead screen object.");
592
593 if (XSCREEN (screen)->output_method == output_x_window)
594 x_make_screen_visible (XSCREEN (screen));
595
596 return screen;
597}
598
599DEFUN ("screen-visible-p", Fscreen_visible_p, Sscreen_visible_p,
600 1, 1, 0,
601 "Return t if SCREEN is now \"visible\" (actually in use for display).\n\
602A screen that is not \"visible\" is not updated and, if it works through\n\
603a window system, it may not show at all.\n\
604Return the symbol `icon' if window is visible only as an icon.")
605 (screen)
606 Lisp_Object screen;
607{
608 CHECK_SCREEN (screen, 0);
609
610 if (XSCREEN (screen)->visible)
611 return Qt;
612 if (XSCREEN (screen)->iconified)
613 return intern ("icon");
614 return Qnil;
615}
616
617DEFUN ("visible-screen-list", Fvisible_screen_list, Svisible_screen_list,
618 0, 0, 0,
619 "Return a list of all screens now \"visible\" (being updated).")
620 ()
621{
622 Lisp_Object tail, screen;
623 struct screen *s;
624 Lisp_Object value;
625
626 value = Qnil;
627 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
628 {
629 screen = XCONS (tail)->car;
630 if (XTYPE (screen) != Lisp_Screen)
631 continue;
632 s = XSCREEN (screen);
633 if (s->visible)
634 value = Fcons (screen, value);
635 }
636 return value;
637}
638
639Lisp_Object
640get_screen_param (screen, prop)
641 register struct screen *screen;
642 Lisp_Object prop;
643{
644 register Lisp_Object tem;
645
646 tem = Fassq (prop, screen->param_alist);
647 if (EQ (tem, Qnil))
648 return tem;
649 return Fcdr (tem);
650}
651
652void
653store_in_alist (alistptr, propname, val)
654 Lisp_Object *alistptr, val;
655 char *propname;
656{
657 register Lisp_Object tem;
658 register Lisp_Object prop;
659
660 prop = intern (propname);
661 tem = Fassq (prop, *alistptr);
662 if (EQ (tem, Qnil))
663 *alistptr = Fcons (Fcons (prop, val), *alistptr);
664 else
665 Fsetcdr (tem, val);
666}
667
668void
669store_screen_param (s, prop, val)
670 struct screen *s;
671 Lisp_Object prop, val;
672{
673 register Lisp_Object tem;
674
675 tem = Fassq (prop, s->param_alist);
676 if (EQ (tem, Qnil))
677 s->param_alist = Fcons (Fcons (prop, val), s->param_alist);
678 else
679 Fsetcdr (tem, val);
680}
681
682DEFUN ("screen-parameters", Fscreen_parameters, Sscreen_parameters, 0, 1, 0,
683 "Return the parameters-alist of screen SCREEN.\n\
684It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
685The meaningful PARMs depend on the kind of screen.")
686 (screen)
687 Lisp_Object screen;
688{
689 Lisp_Object alist;
690 struct screen *s;
691
692 if (EQ (screen, Qnil))
693 s = selected_screen;
694 else
695 {
696 CHECK_SCREEN (screen, 0);
697 s = XSCREEN (screen);
698 }
699
700 if (s->display.nothing == 0)
701 return Qnil;
702
703 alist = Fcopy_alist (s->param_alist);
704 store_in_alist (&alist, "name", s->name);
705 store_in_alist (&alist, "height", make_number (s->height));
706 store_in_alist (&alist, "width", make_number (s->width));
707 store_in_alist (&alist, "modeline", (s->wants_modeline ? Qt : Qnil));
708 store_in_alist (&alist, "minibuffer", (s->has_minibuffer ? Qt : Qnil));
709 store_in_alist (&alist, "unsplittable", (s->no_split ? Qt : Qnil));
710
711 if (s->output_method == output_x_window)
712 x_report_screen_params (s, &alist);
713 return alist;
714}
715
716DEFUN ("modify-screen-parameters", Fmodify_screen_parameters,
717 Smodify_screen_parameters, 2, 2, 0,
718 "Modify the parameters of screen SCREEN according to ALIST.\n\
719ALIST is an alist of parameters to change and their new values.\n\
720Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
721The meaningful PARMs depend on the kind of screen; undefined PARMs are ignored.")
722 (screen, alist)
723 Lisp_Object screen, alist;
724{
725 register struct screen *s;
726 register Lisp_Object tail, elt, prop, val;
727
728 if (EQ (screen, Qnil))
729 s = selected_screen;
730 else
731 {
732 CHECK_SCREEN (screen, 0);
733 s = XSCREEN (screen);
734 }
735
736 if (s->display.nothing == 0)
737 error ("Cannot modify parameters of a deleted screen");
738
739 if (s->output_method == output_x_window)
740 for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
741 {
742 elt = Fcar (tail);
743 prop = Fcar (elt);
744 val = Fcdr (elt);
745 x_set_screen_param (s, prop, val,
746 get_screen_param (s, prop));
747 store_screen_param (s, prop, val);
748 }
749
750 return Qnil;
751}
752
753
754DEFUN ("screen-pixel-size", Fscreen_pixel_size,
755 Sscreen_pixel_size, 1, 1, 0,
756 "Return a cons (width . height) of screen SCREEN's dimensions.")
757 (screen)
758 Lisp_Object screen;
759{
760 register struct screen *s;
761 int width, height;
762
763 CHECK_SCREEN (screen, 0);
764 s = XSCREEN (screen);
765
766 return Fcons (make_number (x_pixel_width (s)),
767 make_number (x_pixel_height (s)));
768}
769
770DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
771 "Return number of lines available for display on selected screen.")
772 ()
773{
774 return make_number (SCREEN_HEIGHT (selected_screen));
775}
776
777DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
778 "Return number of columns available for display on selected screen.")
779 ()
780{
781 return make_number (SCREEN_WIDTH (selected_screen));
782}
783
784DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 2, 3, 0,
785 "Specify that the screen SCREEN has LINES lines.\n\
786Optional third arg non-nil means that redisplay should use LINES lines\n\
787but that the idea of the actual height of the screen should not be changed.")
788 (screen, rows, pretend)
789 Lisp_Object rows, pretend;
790{
791 register struct screen *s;
792
793 CHECK_NUMBER (rows, 0);
794 if (NULL (screen))
795 s = selected_screen;
796 else
797 {
798 CHECK_SCREEN (screen, 0);
799 s = XSCREEN (screen);
800 }
801
802 if (s->output_method == output_x_window)
803 {
804 if (XINT (rows) != s->width)
805 x_set_window_size (s, s->width, XINT (rows));
806 }
807 else
808 change_screen_size (s, XINT (rows), 0, !NULL (pretend));
809 return Qnil;
810}
811
812DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 2, 3, 0,
813 "Specify that the screen SCREEN has COLS columns.\n\
814Optional third arg non-nil means that redisplay should use COLS columns\n\
815but that the idea of the actual width of the screen should not be changed.")
816 (screen, cols, pretend)
817 Lisp_Object cols, pretend;
818{
819 register struct screen *s;
820 CHECK_NUMBER (cols, 0);
821 if (NULL (screen))
822 s = selected_screen;
823 else
824 {
825 CHECK_SCREEN (screen, 0);
826 s = XSCREEN (screen);
827 }
828
829 if (s->output_method == output_x_window)
830 {
831 if (XINT (cols) != s->width)
832 x_set_window_size (s, XINT (cols), s->height);
833 }
834 else
835 change_screen_size (selected_screen, 0, XINT (cols), !NULL (pretend));
836 return Qnil;
837}
838
839DEFUN ("set-screen-size", Fset_screen_size,
840 Sset_screen_size, 3, 3, 0,
841 "Sets size of SCREEN to COLS by ROWS, measured in characters.")
842 (screen, cols, rows)
843 Lisp_Object screen, cols, rows;
844{
845 register struct screen *s;
846 int mask;
847
848 CHECK_SCREEN (screen, 0);
849 CHECK_NUMBER (cols, 2);
850 CHECK_NUMBER (rows, 1);
851 s = XSCREEN (screen);
852
853 if (s->output_method == output_x_window)
854 {
855 if (XINT (rows) != s->height || XINT (cols) != s->width)
856 x_set_window_size (s, XINT (cols), XINT (rows));
857 }
858 else
859 change_screen_size (s, XINT (rows), XINT (cols), 0);
860
861 return Qnil;
862}
863
864DEFUN ("set-screen-position", Fset_screen_position,
865 Sset_screen_position, 3, 3, 0,
866 "Sets size of SCREEN in pixels to XOFFSET by YOFFSET.")
867 (screen, xoffset, yoffset)
868 Lisp_Object screen, xoffset, yoffset;
869{
870 register struct screen *s;
871 int mask;
872
873 CHECK_SCREEN (screen, 0);
874 CHECK_NUMBER (xoffset, 1);
875 CHECK_NUMBER (yoffset, 2);
876 s = XSCREEN (screen);
877
878 if (s->output_method == output_x_window)
879 x_set_offset (s, XINT (xoffset), XINT (yoffset));
880
881 return Qt;
882}
883
884/* Test if column *x, row *y is within window *w. If they are not,
885 return 0; if they are on the window's modeline, return -1; if
886 they are in the window's text area (the only other alternative)
887 set *x and *y to their locations relative to the upper left
888 corner of the window, and return 1. */
889int
890coordinates_in_window (w, x, y)
891 register struct window *w;
892 register int *x, *y;
893{
894 register int left = XINT (w->left);
895 register int width = XINT (w->width);
896 register int screen_height = XINT ((XSCREEN (w->screen)->height));
897 register int window_height = XINT (w->height);
898 register int top = XFASTINT (w->top);
899
900 if (*x < left || *x >= left + width
901 || *y == screen_height || *y < top || *y > top + window_height - 1)
902 return 0;
903
904 if (*y == top + window_height - 1
905 && window_height > 1) /* 1 line => minibuffer */
906 /* in modeline */
907 return -1;
908
909 *x -= left;
910 *y -= top;
911 return 1;
912}
913
914DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
915 Scoordinates_in_window_p, 2, 2, 0,
916 "Return non-nil if COORDINATES are in WINDOW.\n\
917COORDINATES is a cons of the form (X Y), X and Y being screen-relative.\n\
918If COORDINATES are in the text portion of WINDOW, the coordinates relative\n\
919to the window are returned. If they are in the modeline of WINDOW, t is\n\
920returned.")
921 (coordinates, window)
922 register Lisp_Object coordinates, window;
923{
924 int x, y;
925
926 CHECK_WINDOW (window, 0);
927 CHECK_CONS (coordinates, 1);
928 x = XINT (Fcar (coordinates));
929 y = XINT (Fcar (Fcdr (coordinates)));
930
931 switch (coordinates_in_window (XWINDOW (window), &x, &y))
932 {
933 case -1: /* In modeline of window. */
934 return Qt;
935
936 case 0: /* NOT in window at all. */
937 return Qnil;
938
939 case 1: /* In text part of window. */
940 return Fcons (x, Fcons (y, Qnil));
941
942 default:
943 abort ();
944 }
945}
946
947#ifndef HAVE_X11
948DEFUN ("rubber-band-rectangle", Frubber_band_rectangle, Srubber_band_rectangle,
949 3, 3, "",
950 "Ask user to specify a window position and size on SCREEN with the mouse.\n\
951Arguments are SCREEN, NAME and GEO. NAME is a name to be displayed as\n\
952the purpose of this rectangle. GEO is an X-windows size spec that can\n\
953specify defaults for some sizes/positions. If GEO specifies everything,\n\
954the mouse is not used.\n\
955Returns a list of five values: (SCREEN LEFT TOP WIDTH HEIGHT).")
956 (screen, name, geo)
957 Lisp_Object screen;
958 Lisp_Object name;
959 Lisp_Object geo;
960{
961 int vals[4];
962 Lisp_Object nums[4];
963 int i;
964
965 CHECK_SCREEN (screen, 0);
966 CHECK_STRING (name, 1);
967 CHECK_STRING (geo, 2);
968
969 switch (XSCREEN (screen)->output_method)
970 {
971 case output_x_window:
972 x_rubber_band (XSCREEN (screen), &vals[0], &vals[1], &vals[2], &vals[3],
973 XSTRING (geo)->data, XSTRING (name)->data);
974 break;
975
976 default:
977 return Qnil;
978 }
979
980 for (i = 0; i < 4; i++)
981 XFASTINT (nums[i]) = vals[i];
982 return Fcons (screen, Flist (4, nums));
983 return Qnil;
984}
985#endif /* not HAVE_X11 */
986
987choose_minibuf_screen ()
988{
989 /* For lowest-level minibuf, put it on currently selected screen
990 if screen has a minibuffer. */
991 if (minibuf_level == 0
992 && selected_screen != 0
993 && !EQ (minibuf_window, selected_screen->minibuffer_window)
994 && !EQ (Qnil, selected_screen->minibuffer_window))
995 {
996 Fset_window_buffer (selected_screen->minibuffer_window,
997 XWINDOW (minibuf_window)->buffer);
998 minibuf_window = selected_screen->minibuffer_window;
999 }
1000}
1001
1002syms_of_screen ()
1003{
1004 Qscreenp = intern ("screenp");
1005
1006 staticpro (&Vscreen_list);
1007
1008 DEFVAR_LISP ("terminal-screen", &Vterminal_screen,
1009 "The initial screen-object, which represents Emacs's stdout.");
1010
1011 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
1012 "Non-nil if all of emacs is iconified and not screen updates are needed.");
1013 Vemacs_iconified = Qnil;
1014
1015 DEFVAR_LISP ("global-minibuffer-screen", &Vglobal_minibuffer_screen,
1016 "A screen whose minibuffer is used by minibufferless screens.\n\
1017When you create a minibufferless screen, by default it will use the\n\
1018minibuffer of this screen. It is up to you to create a suitable screen\n\
1019and store it in this variable.");
1020 Vglobal_minibuffer_screen = Qnil;
1021
1022 defsubr (&Sscreenp);
1023 defsubr (&Sselect_screen);
1024 defsubr (&Sselected_screen);
1025 defsubr (&Swindow_screen);
1026 defsubr (&Sscreen_root_window);
1027 defsubr (&Sscreen_selected_window);
1028 defsubr (&Sscreen_list);
1029 defsubr (&Snext_screen);
1030 defsubr (&Sdelete_screen);
1031 defsubr (&Sread_mouse_position);
1032 defsubr (&Sset_mouse_position);
1033#if 0
1034 defsubr (&Sscreen_configuration);
1035 defsubr (&Srestore_screen_configuration);
1036#endif
1037 defsubr (&Smake_screen_visible);
1038 defsubr (&Smake_screen_invisible);
1039 defsubr (&Siconify_screen);
1040 defsubr (&Sdeiconify_screen);
1041 defsubr (&Sscreen_visible_p);
1042 defsubr (&Svisible_screen_list);
1043 defsubr (&Sscreen_parameters);
1044 defsubr (&Smodify_screen_parameters);
1045 defsubr (&Sscreen_pixel_size);
1046 defsubr (&Sscreen_height);
1047 defsubr (&Sscreen_width);
1048 defsubr (&Sset_screen_height);
1049 defsubr (&Sset_screen_width);
1050 defsubr (&Sset_screen_size);
1051 defsubr (&Sset_screen_position);
1052 defsubr (&Scoordinates_in_window_p);
1053#ifndef HAVE_X11
1054 defsubr (&Srubber_band_rectangle);
1055#endif /* HAVE_X11 */
1056}
diff --git a/src/xterm.c b/src/xterm.c
new file mode 100644
index 00000000000..c99899d3d0a
--- /dev/null
+++ b/src/xterm.c
@@ -0,0 +1,3798 @@
1/* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989 Free Software Foundation, Inc.
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
20/* Serious problems:
21
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
25
26*/
27
28#include "config.h"
29
30#ifdef HAVE_X_WINDOWS
31
32#include "lisp.h"
33#undef NULL
34
35/* On 4.3 this loses if it comes after xterm.h. */
36#include <signal.h>
37
38/* This may include sys/types.h, and that somehow loses
39 if this is not done before the other system files. */
40#include "xterm.h"
41
42/* Load sys/types.h if not already loaded.
43 In some systems loading it twice is suicidal. */
44#ifndef makedev
45#include <sys/types.h>
46#endif
47
48#ifdef BSD
49#include <sys/ioctl.h>
50#include <strings.h>
51#else
52#include <sys/termio.h>
53#include <string.h>
54#endif
55
56/* Allow m- file to inhibit use of FIONREAD. */
57#ifdef BROKEN_FIONREAD
58#undef FIONREAD
59#endif
60
61/* We are unable to use interrupts if FIONREAD is not available,
62 so flush SIGIO so we won't try. */
63#ifndef FIONREAD
64#ifdef SIGIO
65#undef SIGIO
66#endif
67#endif
68
69#ifdef NEED_TIME_H
70#include <time.h>
71#else /* not NEED_TIME_H */
72#ifdef HAVE_TIMEVAL
73#include <sys/time.h>
74#endif /* HAVE_TIMEVAL */
75#endif /* not NEED_TIME_H */
76
77#include <fcntl.h>
78#include <stdio.h>
79#include <ctype.h>
80#include <errno.h>
81#include <setjmp.h>
82#include <sys/stat.h>
83#include <sys/param.h>
84
85#include "dispextern.h"
86#include "termhooks.h"
87#include "termopts.h"
88#include "termchar.h"
89#if 0
90#include "sink.h"
91#include "sinkmask.h"
92#endif
93#include "gnu.h"
94#include "screen.h"
95#include "disptab.h"
96#include "window.h"
97#include "buffer.h"
98#include "xfns.h"
99
100#ifdef HAVE_X11
101#define XMapWindow XMapRaised /* Raise them when mapping. */
102#else
103#include <X/Xkeyboard.h>
104/*#include <X/Xproto.h> */
105#endif /* HAVE_X11 */
106
107/* For sending Meta-characters. Do we need this? */
108#define METABIT 0200
109
110#define min(a,b) ((a)<(b) ? (a) : (b))
111#define max(a,b) ((a)>(b) ? (a) : (b))
112
113/* Nonzero means we must reprint all windows
114 because 1) we received an ExposeWindow event
115 or 2) we received too many ExposeRegion events to record. */
116
117static int expose_all_windows;
118
119/* Nonzero means we must reprint all icon windows. */
120
121static int expose_all_icons;
122
123#ifndef HAVE_X11
124/* ExposeRegion events, when received, are copied into this queue
125 for later processing. */
126
127static struct event_queue x_expose_queue;
128
129/* ButtonPressed and ButtonReleased events, when received,
130 are copied into this queue for later processing. */
131
132struct event_queue x_mouse_queue;
133#endif
134
135/* Nonzero after BLOCK_INPUT; prevents input events from being
136 processed until later. */
137
138int x_input_blocked;
139
140#if defined (SIGIO) && defined (FIONREAD)
141int BLOCK_INPUT_mask;
142#endif
143
144/* Nonzero if input events came in while x_input_blocked was nonzero.
145 UNBLOCK_INPUT checks for this. */
146
147int x_pending_input;
148
149/* Nonzero if in redisplay (); prevents us from calling it recursively */
150
151int in_display;
152
153/* The id of a bitmap used for icon windows.
154 One such map is shared by all Emacs icon windows.
155 This is zero if we have not yet had a need to create the bitmap. */
156
157static Bitmap icon_bitmap;
158
159/* Font used for text icons. */
160
161static FONT_TYPE *icon_font_info;
162
163/* Stuff for dealing with the main icon title. */
164
165extern Lisp_Object Vcommand_line_args;
166char *hostname, *id_name, *invocation_name;
167
168/* This is the X connection that we are using. */
169
170Display *x_current_display;
171
172/* Screen being updated by update_screen. */
173/* This is set by XTupdate_begin and looked at by all the
174 XT functions. It is zero while not inside an update.
175 In that case, the XT functions assume that `selected_screen'
176 is the screen to apply to. */
177
178static struct screen *updating_screen;
179
180/* The screen (if any) which has the X window that has keyboard focus.
181 Zero if none. This is examined by Ffocus_screen in screen.c */
182
183struct screen *x_focus_screen;
184
185/* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
186 mouse is moved to inside of screen when screen is de-iconified. */
187
188static int warp_mouse_on_deiconify;
189
190/* During an update, maximum vpos for ins/del line operations to affect. */
191
192static int flexlines;
193
194/* During an update, nonzero if chars output now should be highlighted. */
195
196static int highlight;
197
198/* Nominal cursor position -- where to draw output.
199 During an update, these are different from the cursor-box position. */
200
201static int curs_x;
202static int curs_y;
203
204#ifdef HAVE_X11
205/* `t' if a mouse button is depressed. */
206
207extern Lisp_Object Vmouse_depressed;
208
209/* Tells if a window manager is present or not. */
210
211extern Lisp_Object Vx_no_window_manager;
212
213/* Timestamp that we requested selection data was made. */
214extern Time requestor_time;
215
216/* ID of the window requesting selection data. */
217extern Window requestor_window;
218
219/* Nonzero enables some debugging for the X interface code. */
220extern int _Xdebug;
221
222#else /* X10 stuff */
223
224/* Bit patterns for the mouse cursor. */
225
226short MouseCursor[] = {
227 0x0000, 0x0008, 0x0018, 0x0038,
228 0x0078, 0x00f8, 0x01f8, 0x03f8,
229 0x07f8, 0x00f8, 0x00d8, 0x0188,
230 0x0180, 0x0300, 0x0300, 0x0000};
231
232short MouseMask[] = {
233 0x000c, 0x001c, 0x003c, 0x007c,
234 0x00fc, 0x01fc, 0x03fc, 0x07fc,
235 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
236 0x03cc, 0x0780, 0x0780, 0x0300};
237
238static short grey_bits[] = {
239 0x0005, 0x000a, 0x0005, 0x000a};
240
241static Pixmap GreyPixmap = 0;
242#endif /* X10 stuff */
243
244/* From time to time we get info on an Emacs window, here. */
245
246static WINDOWINFO_TYPE windowinfo;
247
248extern int errno;
249
250extern Lisp_Object Vglobal_minibuffer_screen;
251
252extern Display *XOpenDisplay ();
253extern Window XCreateWindow ();
254
255extern Cursor XCreateCursor ();
256extern FONT_TYPE *XOpenFont ();
257
258static void flashback ();
259
260#ifndef HAVE_X11
261static void dumpqueue ();
262#endif
263
264void dumpborder ();
265static XTcursor_to ();
266static XTclear_end_of_line ();
267
268/* These hooks are called by update_screen at the beginning and end
269 of a screen update. We record in `updating_screen' the identity
270 of the screen being updated, so that the XT... functions do not
271 need to take a screen as argument. Most of the XT... functions
272 should never be called except during an update, the only exceptions
273 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
274
275extern int mouse_track_top, mouse_track_left, mouse_track_width;
276
277static
278XTupdate_begin (s)
279 struct screen *s;
280{
281 int mask;
282
283 if (s == 0)
284 abort ();
285
286 updating_screen = s;
287 flexlines = s->height;
288 highlight = 0;
289
290#if 0
291 if (mouse_track_width != 0)
292 {
293 x_rectangle (s, s->display.x->reverse_gc,
294 mouse_track_top, mouse_track_left, mouse_track_width, 1);
295 mouse_track_width = 0;
296 }
297#endif
298 BLOCK_INPUT;
299#ifndef HAVE_X11
300 dumpqueue ();
301#endif
302 UNBLOCK_INPUT;
303}
304
305static void x_do_pending_expose ();
306
307static
308XTupdate_end (s)
309 struct screen *s;
310{
311 int mask;
312
313 if (updating_screen == 0
314 || updating_screen != s)
315 abort ();
316
317 BLOCK_INPUT;
318#ifndef HAVE_X11
319 dumpqueue ();
320#endif
321 adjust_scrollbars (s);
322 x_do_pending_expose ();
323
324 x_display_cursor (s, 1);
325
326 updating_screen = 0;
327 XFlushQueue ();
328 UNBLOCK_INPUT;
329}
330
331/* External interface to control of standout mode.
332 Call this when about to modify line at position VPOS
333 and not change whether it is highlighted. */
334
335XTreassert_line_highlight (new, vpos)
336 int new, vpos;
337{
338 highlight = new;
339}
340
341/* Call this when about to modify line at position VPOS
342 and change whether it is highlighted. */
343
344static
345XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
346 int new_highlight, vpos, first_unused_hpos;
347{
348 highlight = new_highlight;
349 XTcursor_to (vpos, 0);
350 XTclear_end_of_line (updating_screen->width);
351}
352
353/* This is used when starting Emacs and when restarting after suspend.
354 When starting Emacs, no X window is mapped. And nothing must be done
355 to Emacs's own window if it is suspended (though that rarely happens). */
356
357static
358XTset_terminal_modes ()
359{
360}
361
362/* This is called when exiting or suspending Emacs.
363 Exiting will make the X-windows go away, and suspending
364 requires no action. */
365
366static
367XTreset_terminal_modes ()
368{
369/* XTclear_screen (); */
370}
371
372/* Set the nominal cursor position of the screen:
373 where display update commands will take effect.
374 This does not affect the place where the cursor-box is displayed. */
375
376XTcursor_to (row, col)
377 register int row, col;
378{
379 int mask;
380 int orow = row;
381
382 curs_x = col;
383 curs_y = row;
384
385 if (updating_screen == 0)
386 {
387 BLOCK_INPUT;
388 x_display_cursor (selected_screen, 1);
389 XFlushQueue ();
390 UNBLOCK_INPUT;
391 }
392}
393
394/* Display a sequence of N glyphs found at GP.
395 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
396 HL is 1 if this text is highlighted, 2 if the cursor is on it.
397
398 FONT is the default font to use (for glyphs whose font-code is 0). */
399
400static void
401dumpglyphs (s, left, top, gp, n, hl, font)
402 struct screen *s;
403 int left, top;
404 register GLYPH *gp; /* Points to first GLYPH. */
405 register int n; /* Number of glyphs to display. */
406 int hl;
407 FONT_TYPE *font;
408{
409 char buf[s->width];
410 register char *cp = buf;
411 register int len;
412 Window window = s->display.x->window_desc;
413 GC drawing_gc = (hl == 2 ? s->display.x->cursor_gc
414 : (hl ? s->display.x->reverse_gc
415 : s->display.x->normal_gc));
416
417 XDrawImageString16 (x_current_display, window, drawing_gc,
418 left, top + FONT_BASE (font), (XChar2b *) gp, n);
419}
420
421#if 0
422static void
423dumpglyphs (s, left, top, gp, n, hl, font)
424 struct screen *s;
425 int left, top;
426 register GLYPH *gp; /* Points to first GLYPH. */
427 register int n; /* Number of glyphs to display. */
428 int hl;
429 FONT_TYPE *font;
430{
431 char buf[s->width]; /* Holds characters to be displayed. */
432 register char *cp; /* Steps through buf[]. */
433 register int tlen = GLYPH_TABLE_LENGTH;
434 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
435 Window window = s->display.x->window_desc;
436 int cursor_pixel = s->display.x->cursor_pixel;
437 int fg_pixel = s->display.x->foreground_pixel;
438 int bg_pixel = s->display.x->background_pixel;
439 int intborder = s->display.x->internal_border_width;
440
441 while (n)
442 {
443 /* Get the face-code of the next GLYPH. */
444 int cf, len;
445 int g = *gp;
446
447 while (GLYPH_ALIAS_P (tbase, tlen, g))
448 g = GLYPH_ALIAS (tbase, g);
449
450 cf = g >> 8;
451
452 /* Find the run of consecutive glyphs with the same face-code.
453 Extract their character codes into BUF. */
454 cp = buf;
455 while (n > 0)
456 {
457 g = *gp;
458 while (GLYPH_ALIAS_P (tbase, tlen, g))
459 g = GLYPH_ALIAS (tbase, g);
460 if ((g >> 8) != cf)
461 break;
462
463 *cp++ = 0377 & g;
464 --n;
465 ++gp;
466 }
467
468 /* LEN gets the length of the run. */
469 len = cp - buf;
470
471 /* Now output this run of chars, with the font and pixel values
472 determined by the face code CF. */
473 if (cf == 0)
474 {
475#ifdef HAVE_X11
476 GC GC_cursor = s->display.x->cursor_gc;
477 GC GC_reverse = s->display.x->reverse_gc;
478 GC GC_normal = s->display.x->normal_gc;
479
480 XDrawImageString (x_current_display, window,
481 (hl == 2
482 ? GC_cursor
483 : (hl ? GC_reverse : GC_normal)),
484 left, top + FONT_BASE (font), buf, len);
485#else
486 XText (window, left, top,
487 buf,
488 len,
489 font->id,
490 (hl == 2
491 ? (cursor_pixel == fg_pixel ? bg_pixel : fg_pixel)
492 : hl ? bg_pixel : fg_pixel),
493 (hl == 2 ? cursor_pixel
494 : hl ? fg_pixel : bg_pixel));
495#endif /* HAVE_X11 */
496 }
497 else
498 {
499#ifdef HAVE_X11
500 if (FACE_IS_FONT (cf))
501 XDrawImageString (x_current_display, s->display.x->window_desc,
502 FACE_GC (cf),
503 left, top + FONT_BASE (FACE_FONT (cf)),
504 buf, len);
505 else if (FACE_IS_IMAGE (cf))
506 XCopyPlane (x_current_display, FACE_IMAGE (cf),
507 s->display.x->window_desc,
508 s->display.x->normal_gc,
509 0, 0,
510 FACE_IMAGE_WIDTH (cf),
511 FACE_IMAGE_HEIGHT (cf), left, top);
512 else
513 abort ();
514#else
515 register struct face *fp = x_face_table[cf];
516
517 XText (window, left, top,
518 buf,
519 len,
520 fp->font->id,
521 (hl == 2
522 ? (cursor_pixel == fp->fg ? fp->bg : fp->fg)
523 : hl ? fp->bg : fp->fg),
524 (hl == 2 ? cursor_pixel
525 : hl ? fp->fg : fp->bg));
526#endif /* HAVE_X11 */
527 }
528 left += len * FONT_WIDTH (font);
529 }
530}
531#endif
532
533/* Output some text at the nominal screen cursor position,
534 advancing the cursor over the text.
535 Output LEN glyphs at START.
536
537 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
538 controls the pixel values used for foreground and background. */
539
540static
541XTwrite_glyphs (start, len)
542 register GLYPH *start;
543 int len;
544{
545 register int temp_length;
546 int mask;
547 struct screen *s;
548
549 BLOCK_INPUT;
550
551 s = updating_screen;
552 if (s == 0)
553 {
554 s = selected_screen;
555 /* If not within an update,
556 output at the screen's visible cursor. */
557 curs_x = s->cursor_x;
558 curs_y = s->cursor_y;
559 }
560
561 /* Clear the cursor if it appears on this line. */
562 if (curs_y == s->cursor_y)
563 x_display_cursor (s, 0);
564
565 dumpglyphs (s,
566 (curs_x * FONT_WIDTH (s->display.x->font)
567 + s->display.x->internal_border_width),
568 (curs_y * FONT_HEIGHT (s->display.x->font)
569 + s->display.x->internal_border_width),
570 start, len, highlight, s->display.x->font);
571
572 if (updating_screen == 0)
573 {
574 s->cursor_x += len;
575 x_display_cursor (s, 1);
576 s->cursor_x -= len;
577 }
578 else
579 curs_x += len;
580
581 UNBLOCK_INPUT;
582}
583
584/* Erase the current text line from the nominal cursor position (inclusive)
585 to column FIRST_UNUSED (exclusive). The idea is that everything
586 from FIRST_UNUSED onward is already erased. */
587
588static
589XTclear_end_of_line (first_unused)
590 register int first_unused;
591{
592 struct screen *s = updating_screen;
593 int mask;
594
595 if (s == 0)
596 abort ();
597
598 if (curs_y < 0 || curs_y >= s->height)
599 return;
600 if (first_unused <= 0)
601 return;
602
603 if (first_unused >= s->width)
604 first_unused = s->width;
605
606 BLOCK_INPUT;
607
608 /* Clear the cursor if it appears on this line. */
609 if (curs_y == s->cursor_y)
610 x_display_cursor (s, 0);
611
612#ifdef HAVE_X11
613 XClearArea (x_current_display, s->display.x->window_desc,
614 curs_x * FONT_WIDTH (s->display.x->font)
615 + s->display.x->internal_border_width,
616 curs_y * FONT_HEIGHT (s->display.x->font)
617 + s->display.x->internal_border_width,
618 FONT_WIDTH (s->display.x->font) * (first_unused - curs_x),
619 FONT_HEIGHT (s->display.x->font), False);
620
621#else
622 XPixSet (s->display.x->window_desc,
623 curs_x * FONT_WIDTH (s->display.x->font) + s->display.x->internal_border_width,
624 curs_y * FONT_HEIGHT (s->display.x->font) + s->display.x->internal_border_width,
625 FONT_WIDTH (s->display.x->font) * (first_unused - curs_x),
626 FONT_HEIGHT (s->display.x->font),
627 s->display.x->background_pixel);
628#endif /* HAVE_X11 */
629
630 UNBLOCK_INPUT;
631}
632
633static
634XTclear_screen ()
635{
636 int mask;
637 struct screen *s = updating_screen;
638
639 if (s == 0)
640 s = selected_screen;
641
642 s->phys_cursor_x = -1; /* Cursor not visible. */
643 curs_x = 0; /* Nominal cursor position is top left. */
644 curs_y = 0;
645
646 BLOCK_INPUT;
647 XClear (s->display.x->window_desc);
648#ifndef HAVE_X11
649 dumpborder (s, 0);
650#endif
651 XFlushQueue ();
652 UNBLOCK_INPUT;
653}
654
655/* Paint horzontal bars down the screen for a visible bell.
656 Note that this may be way too slow on some machines. */
657
658XTflash (s)
659 struct screen *s;
660{
661 register struct screen_glyphs *active_screen = SCREEN_CURRENT_GLYPHS (s);
662 register int i;
663 int x, y;
664
665 if (updating_screen != 0)
666 abort ();
667
668 BLOCK_INPUT;
669#ifdef HAVE_X11
670#if 0
671 for (i = s->height * FONT_HEIGHT (s->display.x->font) - 10;
672 i >= 0;
673 i -= 100) /* Should be NO LOWER than 75 for speed reasons. */
674 XFillRectangle (x_current_display, s->display.x->window_desc,
675 s->display.x->cursor_gc,
676 0, i, s->width * FONT_WIDTH (s->display.x->font)
677 + 2 * s->display.x->internal_border_width, 25);
678#endif
679
680 x = (s->width * FONT_WIDTH (s->display.x->font)) / 4;
681 y = (s->height * FONT_HEIGHT (s->display.x->font)) / 4;
682 XFillRectangle (x_current_display, s->display.x->window_desc,
683 s->display.x->cursor_gc,
684 x, y, 2 * x, 2 * y);
685 dumpglyphs (s, (x + s->display.x->internal_border_width),
686 (y + s->display.x->internal_border_width),
687 &active_screen->glyphs[(s->height / 4) + 1][(s->width / 4)],
688 1, 0, s->display.x->font);
689
690#else /* X10 */
691 for (i = s->height * FONT_HEIGHT (s->display.x->font) - 10;
692 i >= 0;
693 i -= 50)
694 XPixFill (s->display.x->window_desc, 0, i,
695 s->width * FONT_WIDTH (s->display.x->font)
696 + 2 * s->display.x->internal_border_width, 10,
697 WHITE_PIX_DEFAULT, ClipModeClipped, GXinvert, AllPlanes);
698#endif /* X10 */
699
700 XFlushQueue ();
701 UNBLOCK_INPUT;
702}
703
704/* Flip background and forground colors of the screen. */
705
706x_invert_screen (s)
707 struct screen *s;
708{
709#ifdef HAVE_X11
710 GC temp;
711 unsigned long pix_temp;
712
713 x_display_cursor (s, 0);
714 XClearWindow (x_current_display, s->display.x->window_desc);
715 temp = s->display.x->normal_gc;
716 s->display.x->normal_gc = s->display.x->reverse_gc;
717 s->display.x->reverse_gc = temp;
718 pix_temp = s->display.x->foreground_pixel;
719 s->display.x->foreground_pixel = s->display.x->background_pixel;
720 s->display.x->background_pixel = pix_temp;
721
722 XSetWindowBackground (x_current_display, s->display.x->window_desc,
723 s->display.x->background_pixel);
724 if (s->display.x->background_pixel == s->display.x->cursor_pixel)
725 {
726 s->display.x->cursor_pixel = s->display.x->foreground_pixel;
727 XSetBackground (x_current_display, s->display.x->cursor_gc,
728 s->display.x->cursor_pixel);
729 XSetForeground (x_current_display, s->display.x->cursor_gc,
730 s->display.x->background_pixel);
731 }
732 redraw_screen (s);
733#endif /* X11 */
734}
735
736/* Make audible bell. */
737
738#ifdef HAVE_X11
739#define XRINGBELL XBell(x_current_display, 0)
740#else
741#define XRINGBELL XFeep(0);
742#endif
743
744XTring_bell ()
745{
746 if (visible_bell)
747#if 0
748 XTflash (selected_screen);
749#endif
750 {
751 x_invert_screen (selected_screen);
752 x_invert_screen (selected_screen);
753 }
754 else
755 {
756 BLOCK_INPUT;
757 XRINGBELL;
758 XFlushQueue ();
759 UNBLOCK_INPUT;
760 }
761}
762
763/* Insert and delete character are not supposed to be used
764 because we are supposed to turn off the feature of using them. */
765
766static
767XTinsert_glyphs (start, len)
768 register char *start;
769 register int len;
770{
771 abort ();
772}
773
774static
775XTdelete_glyphs (n)
776 register int n;
777{
778 abort ();
779}
780
781/* Specify how many text lines, from the top of the window,
782 should be affected by insert-lines and delete-lines operations.
783 This, and those operations, are used only within an update
784 that is bounded by calls to XTupdate_begin and XTupdate_end. */
785
786static
787XTset_terminal_window (n)
788 register int n;
789{
790 if (updating_screen == 0)
791 abort ();
792
793 if ((n <= 0) || (n > updating_screen->height))
794 flexlines = updating_screen->height;
795 else
796 flexlines = n;
797}
798
799/* Perform an insert-lines operation, inserting N lines
800 at a vertical position curs_y. */
801
802static void
803stufflines (n)
804 register int n;
805{
806 register int topregion, bottomregion;
807 register int length, newtop, mask;
808 register struct screen *s = updating_screen;
809 int intborder = s->display.x->internal_border_width;
810
811 if (curs_y >= flexlines)
812 return;
813
814 topregion = curs_y;
815 bottomregion = flexlines - (n + 1);
816 newtop = topregion + n;
817 length = (bottomregion - topregion) + 1;
818
819#ifndef HAVE_X11
820 dumpqueue ();
821#endif
822
823 if ((length > 0) && (newtop <= flexlines))
824 {
825#ifdef HAVE_X11
826 XCopyArea (x_current_display, s->display.x->window_desc,
827 s->display.x->window_desc, s->display.x->normal_gc,
828 intborder, topregion * FONT_HEIGHT (s->display.x->font) + intborder,
829 s->width * FONT_WIDTH (s->display.x->font),
830 length * FONT_HEIGHT (s->display.x->font), intborder,
831 newtop * FONT_HEIGHT (s->display.x->font) + intborder);
832#else
833 XMoveArea (s->display.x->window_desc,
834 intborder, topregion * FONT_HEIGHT (s->display.x->font) + intborder,
835 intborder, newtop * FONT_HEIGHT (s->display.x->font) + intborder,
836 s->width * FONT_WIDTH (s->display.x->font),
837 length * FONT_HEIGHT (s->display.x->font));
838 /* Now we must process any ExposeRegion events that occur
839 if the area being copied from is obscured.
840 We can't let it wait because further i/d operations
841 may want to copy this area to another area. */
842 x_read_exposes ();
843#endif /* HAVE_X11 */
844 }
845
846 newtop = min (newtop, (flexlines - 1));
847 length = newtop - topregion;
848 if (length > 0)
849 {
850#ifdef HAVE_X11
851 XClearArea (x_current_display, s->display.x->window_desc, intborder,
852 topregion * FONT_HEIGHT (s->display.x->font) + intborder,
853 s->width * FONT_WIDTH (s->display.x->font),
854 n * FONT_HEIGHT (s->display.x->font), False);
855#else
856 XPixSet (s->display.x->window_desc,
857 intborder,
858 topregion * FONT_HEIGHT (s->display.x->font) + intborder,
859 s->width * FONT_WIDTH (s->display.x->font),
860 n * FONT_HEIGHT (s->display.x->font),
861 s->display.x->background_pixel);
862#endif /* HAVE_X11 */
863 }
864}
865
866/* Perform a delete-lines operation, deleting N lines
867 at a vertical position curs_y. */
868
869static void
870scraplines (n)
871 register int n;
872{
873 int mask;
874 register struct screen *s = updating_screen;
875 int intborder = s->display.x->internal_border_width;
876
877 if (curs_y >= flexlines)
878 return;
879
880#ifndef HAVE_X11
881 dumpqueue ();
882#endif
883
884 if ((curs_y + n) >= flexlines)
885 {
886 if (flexlines >= (curs_y + 1))
887 {
888#ifdef HAVE_X11
889 XClearArea (x_current_display, s->display.x->window_desc, intborder,
890 curs_y * FONT_HEIGHT (s->display.x->font) + intborder,
891 s->width * FONT_WIDTH (s->display.x->font),
892 (flexlines - curs_y) * FONT_HEIGHT (s->display.x->font), False);
893#else
894 XPixSet (s->display.x->window_desc,
895 intborder, curs_y * FONT_HEIGHT (s->display.x->font) + intborder,
896 s->width * FONT_WIDTH (s->display.x->font),
897 (flexlines - curs_y) * FONT_HEIGHT (s->display.x->font),
898 s->display.x->background_pixel);
899#endif /* HAVE_X11 */
900 }
901 }
902 else
903 {
904#ifdef HAVE_X11
905 XCopyArea (x_current_display, s->display.x->window_desc,
906 s->display.x->window_desc, s->display.x->normal_gc,
907 intborder,
908 (curs_y + n) * FONT_HEIGHT (s->display.x->font) + intborder,
909 s->width * FONT_WIDTH (s->display.x->font),
910 (flexlines - (curs_y + n)) * FONT_HEIGHT (s->display.x->font),
911 intborder, curs_y * FONT_HEIGHT (s->display.x->font) + intborder);
912 XClearArea (x_current_display, s->display.x->window_desc,
913 intborder,
914 (flexlines - n) * FONT_HEIGHT (s->display.x->font) + intborder,
915 s->width * FONT_WIDTH (s->display.x->font),
916 n * FONT_HEIGHT (s->display.x->font), False);
917#else
918 XMoveArea (s->display.x->window_desc,
919 intborder,
920 (curs_y + n) * FONT_HEIGHT (s->display.x->font) + intborder,
921 intborder, curs_y * FONT_HEIGHT (s->display.x->font) + intborder,
922 s->width * FONT_WIDTH (s->display.x->font),
923 (flexlines - (curs_y + n)) * FONT_HEIGHT (s->display.x->font));
924 /* Now we must process any ExposeRegion events that occur
925 if the area being copied from is obscured.
926 We can't let it wait because further i/d operations
927 may want to copy this area to another area. */
928 x_read_exposes ();
929 XPixSet (s->display.x->window_desc, intborder,
930 (flexlines - n) * FONT_HEIGHT (s->display.x->font) + intborder,
931 s->width * FONT_WIDTH (s->display.x->font),
932 n * FONT_HEIGHT (s->display.x->font), s->display.x->background_pixel);
933#endif /* HAVE_X11 */
934 }
935}
936
937/* Perform an insert-lines or delete-lines operation,
938 inserting N lines or deleting -N lines at vertical position VPOS. */
939
940XTins_del_lines (vpos, n)
941 int vpos, n;
942{
943 if (updating_screen == 0)
944 abort ();
945
946 /* Clear the cursor. */
947 x_display_cursor (updating_screen, 0);
948
949 XTcursor_to (vpos, 0);
950
951 BLOCK_INPUT;
952 if (n >= 0)
953 stufflines (n);
954 else
955 scraplines (-n);
956 XFlushQueue ();
957 UNBLOCK_INPUT;
958}
959
960static void clear_cursor ();
961
962/* Output into a rectangle of an X-window (for screen S)
963 the characters in s->phys_lines that overlap that rectangle.
964 TOP and LEFT are the position of the upper left corner of the rectangle.
965 ROWS and COLS are the size of the rectangle. */
966
967static void
968dumprectangle (s, left, top, cols, rows)
969 struct screen *s;
970 register int left, top, cols, rows;
971{
972 register struct screen_glyphs *active_screen = SCREEN_CURRENT_GLYPHS (s);
973 int cursor_cleared = 0;
974 int bottom, right;
975 register int y;
976
977 if (SCREEN_GARBAGED_P (s))
978 return;
979
980 top -= s->display.x->internal_border_width;
981 left -= s->display.x->internal_border_width;
982
983 /* Express rectangle as four edges, instead of position-and-size. */
984 bottom = top + rows;
985 right = left + cols;
986
987#ifndef HAVE_X11 /* Window manger does this for X11. */
988 /* If the rectangle includes any of the internal border area,
989 redisplay the border emphasis. */
990 if (top < 0 || left < 0
991 || bottom > s->height * FONT_HEIGHT (s->display.x->font)
992 || right > s->width * FONT_WIDTH (s->display.x->font))
993 dumpborder (s, 0);
994#endif /* HAVE_X11 */
995
996 /* Convert rectangle edges in pixels to edges in chars.
997 Round down for left and top, up for right and bottom. */
998 top /= FONT_HEIGHT (s->display.x->font);
999 left /= FONT_WIDTH (s->display.x->font);
1000 bottom += (FONT_HEIGHT (s->display.x->font) - 1);
1001 right += (FONT_WIDTH (s->display.x->font) - 1);
1002 bottom /= FONT_HEIGHT (s->display.x->font);
1003 right /= FONT_WIDTH (s->display.x->font);
1004
1005 /* Clip the rectangle to what can be visible. */
1006 if (left < 0)
1007 left = 0;
1008 if (top < 0)
1009 top = 0;
1010 if (right > s->width)
1011 right = s->width;
1012 if (bottom > s->height)
1013 bottom = s->height;
1014
1015 /* Get size in chars of the rectangle. */
1016 cols = right - left;
1017 rows = bottom - top;
1018
1019 /* If rectangle has zero area, return. */
1020 if (rows <= 0) return;
1021 if (cols <= 0) return;
1022
1023 /* Turn off the cursor if it is in the rectangle.
1024 We will turn it back on afterward. */
1025 if ((s->phys_cursor_x >= left) && (s->phys_cursor_x < right)
1026 && (s->phys_cursor_y >= top) && (s->phys_cursor_y < bottom))
1027 {
1028 clear_cursor (s);
1029 cursor_cleared = 1;
1030 }
1031
1032 /* Display the text in the rectangle, one text line at a time. */
1033
1034 for (y = top; y < bottom; y++)
1035 {
1036 GLYPH *line = &active_screen->glyphs[y][left];
1037
1038 if (! active_screen->enable[y] || left > active_screen->used[y])
1039 continue;
1040
1041 dumpglyphs (s,
1042 (left * FONT_WIDTH (s->display.x->font)
1043 + s->display.x->internal_border_width),
1044 (y * FONT_HEIGHT (s->display.x->font)
1045 + s->display.x->internal_border_width),
1046 line, min (cols, active_screen->used[y] - left),
1047 active_screen->highlight[y], s->display.x->font);
1048 }
1049
1050 /* Turn the cursor on if we turned it off. */
1051
1052 if (cursor_cleared)
1053 x_display_cursor (s, 1);
1054 XFlushQueue ();
1055}
1056
1057#ifndef HAVE_X11
1058/* Process all queued ExposeRegion events. */
1059
1060static void
1061dumpqueue ()
1062{
1063 register int i;
1064 XExposeRegionEvent r;
1065
1066 while (dequeue_event (&r, &x_expose_queue))
1067 {
1068 struct screen *s = x_window_to_screen (r.window);
1069 if (s->display.x->icon_desc == r.window)
1070 refreshicon (s);
1071 else
1072 dumprectangle (s, r.x, r.y, r.width, r.height);
1073 }
1074 XFlushQueue ();
1075}
1076#endif
1077
1078/* Process all expose events that are pending.
1079 Redraws the cursor if necessary on any screen that
1080 is not in the process of being updated with update_screen. */
1081
1082static void
1083x_do_pending_expose ()
1084{
1085 int mask;
1086 struct screen *s;
1087 Lisp_Object tail, screen;
1088
1089 if (expose_all_windows)
1090 {
1091 expose_all_windows = 0;
1092 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
1093 {
1094 register int temp_width, temp_height;
1095 int intborder;
1096
1097 screen = XCONS (tail)->car;
1098 if (XTYPE (screen) != Lisp_Screen)
1099 continue;
1100 s = XSCREEN (screen);
1101 if (s->output_method != output_x_window)
1102 continue;
1103 if (!s->visible)
1104 continue;
1105 if (!s->display.x->needs_exposure)
1106 continue;
1107
1108 intborder = s->display.x->internal_border_width;
1109
1110 clear_cursor (s);
1111 XGetWindowInfo (s->display.x->window_desc, &windowinfo);
1112 temp_width = ((windowinfo.width - 2 * intborder
1113 - s->display.x->v_scrollbar_width)
1114 / FONT_WIDTH (s->display.x->font));
1115 temp_height = ((windowinfo.height- 2 * intborder
1116 - s->display.x->h_scrollbar_height)
1117 / FONT_HEIGHT (s->display.x->font));
1118 if (temp_width != s->width || temp_height != s->height)
1119 {
1120 change_screen_size (s, max (1, temp_height),
1121 max (1, temp_width), 0);
1122 x_resize_scrollbars (s);
1123 }
1124 s->display.x->left_pos = windowinfo.x;
1125 s->display.x->top_pos = windowinfo.y;
1126 dumprectangle (s, 0, 0, PIXEL_WIDTH (s), PIXEL_HEIGHT (s));
1127#if 0
1128 dumpborder (s, 0);
1129#endif
1130 s->display.x->needs_exposure = 0;
1131 if (updating_screen != s)
1132 x_display_cursor (s, 1);
1133 XFlushQueue ();
1134 }
1135 }
1136 else
1137 /* Handle any individual-rectangle expose events queued
1138 for various windows. */
1139#ifdef HAVE_X11
1140 ;
1141#else
1142 dumpqueue ();
1143#endif
1144}
1145
1146#ifdef HAVE_X11
1147static void
1148screen_highlight (screen)
1149 struct screen *screen;
1150{
1151 if (! EQ (Vx_no_window_manager, Qnil))
1152 XSetWindowBorder (x_current_display, screen->display.x->window_desc,
1153 screen->display.x->border_pixel);
1154 x_display_cursor (screen, 1);
1155}
1156
1157static void
1158screen_unhighlight (screen)
1159 struct screen *screen;
1160{
1161 if (! EQ (Vx_no_window_manager, Qnil))
1162 XSetWindowBorderPixmap (x_current_display, screen->display.x->window_desc,
1163 screen->display.x->border_tile);
1164 x_display_cursor (screen, 1);
1165}
1166#else /* X10 */
1167/* Dump the border-emphasis of screen S.
1168 If S is selected, this is a lining of the same color as the border,
1169 just within the border, occupying a portion of the internal border.
1170 If S is not selected, it is background in the same place.
1171 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1172
1173 ALWAYS = 1 is used when a screen becomes selected or deselected.
1174 In that case, we also turn the cursor off and on again
1175 so it will appear in the proper shape (solid if selected; else hollow.) */
1176
1177static void
1178dumpborder (s, always)
1179 struct screen *s;
1180 int always;
1181{
1182 int thickness = s->display.x->internal_border_width / 2;
1183 int width = PIXEL_WIDTH (s);
1184 int height = PIXEL_HEIGHT (s);
1185 int pixel;
1186
1187 if (s != selected_screen)
1188 {
1189 if (!always)
1190 return;
1191
1192 pixel = s->display.x->background_pixel;
1193 }
1194 else
1195 {
1196 pixel = s->display.x->border_pixel;
1197 }
1198
1199 XPixSet (s->display.x->window_desc, 0, 0, width, thickness, pixel);
1200 XPixSet (s->display.x->window_desc, 0, 0, thickness, height, pixel);
1201 XPixSet (s->display.x->window_desc, 0, height - thickness, width,
1202 thickness, pixel);
1203 XPixSet (s->display.x->window_desc, width - thickness, 0, thickness,
1204 height, pixel);
1205
1206 if (always)
1207 x_display_cursor (s, 1);
1208}
1209#endif /* X10 */
1210
1211/* The focus has changed. Update the screens as necessary to reflect
1212 the new situation. Note that we can't change the selected screen
1213 here, because the lisp code we are interrupting might become confused.
1214 For that, we enqueue a screen_selected event.
1215
1216 Return the number of events stored at bufp. */
1217static int
1218x_new_focus_screen (screen, bufp, buf_free)
1219 struct screen *screen;
1220 struct input_event *bufp;
1221 int buf_free;
1222{
1223 struct screen *old_focus = x_focus_screen;
1224 int events_enqueued = 0;
1225
1226 if (screen == x_focus_screen)
1227 return 0;
1228
1229 /* Set this before calling screen_{un,}highlight, so that they see
1230 the correct value of x_focus_screen. */
1231 x_focus_screen = screen;
1232
1233 if (old_focus)
1234 {
1235 if (old_focus->auto_lower)
1236 x_lower_screen (old_focus);
1237 screen_unhighlight (old_focus);
1238 }
1239
1240#if 0
1241 selected_screen = screen;
1242 XSET (XWINDOW (selected_screen->selected_window)->screen,
1243 Lisp_Screen, selected_screen);
1244 Fselect_window (selected_screen->selected_window);
1245 choose_minibuf_screen ();
1246#endif
1247
1248 if (x_focus_screen)
1249 {
1250 if (x_focus_screen->auto_raise)
1251 x_raise_screen (x_focus_screen);
1252 screen_highlight (x_focus_screen);
1253
1254 /* Enqueue an event. It's kind of important not to drop these
1255 events, but the event queue's fixed size is a real pain in the butt
1256 anyway. */
1257 if (buf_free > 0)
1258 {
1259 bufp->kind = screen_selected;
1260 bufp->screen = screen;
1261 events_enqueued++;
1262 }
1263 }
1264
1265 return events_enqueued;
1266}
1267
1268enum window_type
1269{
1270 no_window,
1271 scrollbar_window,
1272 text_window,
1273};
1274
1275/* Symbol returned in input stream to indicate mouse movement. */
1276Lisp_Object Qmouse_moved;
1277
1278/* Position of the mouse in characters */
1279unsigned int x_mouse_x, x_mouse_y;
1280
1281/* Emacs window the mouse is in, if any. */
1282extern Lisp_Object Vmouse_window;
1283
1284/* Offset in buffer of character under the pointer, or 0. */
1285extern int mouse_buffer_offset;
1286
1287/* Part of the screen the mouse is in. */
1288extern Lisp_Object Vmouse_screen_part;
1289
1290extern void pixel_to_glyph_translation ();
1291extern int buffer_posn_from_coords ();
1292
1293/* Symbols from xfns.c to denote the different parts of a window. */
1294extern Lisp_Object Qmodeline_part, Qtext_part;
1295
1296#if 0
1297/* Set *RESULT to an emacs input_event corresponding to MOTION_EVENT.
1298 S is the screen in which the event occurred.
1299
1300 WINDOW_TYPE says whether the event happened in a scrollbar window
1301 or a text window, affecting the format of the event created.
1302
1303 PART specifies which part of the scrollbar the event happened in,
1304 if WINDOW_TYPE == scrollbar_window.
1305
1306 If the mouse is over the same character as the last time we checked,
1307 don't return an event; set result->kind to no_event. */
1308
1309static void
1310notice_mouse_movement (result, motion_event, s, window_type, part)
1311 struct input_event *result;
1312 XMotionEvent motion_event;
1313 struct screen *s;
1314 int window_type;
1315 Lisp_Object part;
1316{
1317 int x, y, root_x, root_y, pix_x, pix_y;
1318 unsigned int keys_and_buttons;
1319 Window w, root_window;
1320
1321 /* Unless we decide otherwise below, return a non-event. */
1322 result->kind = no_event;
1323
1324 if (XQueryPointer (x_current_display,
1325 s->display.x->window_desc,
1326 &root_window, &w,
1327 &root_x, &root_y, &pix_x, &pix_y,
1328 &keys_and_buttons)
1329 == False)
1330 return;
1331
1332#if 0
1333 if (w == None) /* Mouse no longer in window. */
1334 return Qnil;
1335#endif
1336
1337 pixel_to_glyph_translation (s, pix_x, pix_y, &x, &y);
1338 if (x == x_mouse_x && y == x_mouse_y)
1339 return;
1340
1341 x_mouse_x = x;
1342 x_mouse_y = y;
1343
1344 /* What sort of window are we in now? */
1345 if (window_type == text_window) /* Text part */
1346 {
1347 int modeline_p;
1348
1349 Vmouse_window = window_from_coordinates (s, x, y, &modeline_p);
1350
1351 if (XTYPE (Vmouse_window) == Lisp_Window)
1352 mouse_buffer_offset
1353 = buffer_posn_from_coords (XWINDOW (Vmouse_window), x, y);
1354 else
1355 mouse_buffer_offset = 0;
1356
1357 if (EQ (Vmouse_window, Qnil))
1358 Vmouse_screen_part = Qnil;
1359 else if (modeline_p)
1360 Vmouse_screen_part = Qmodeline_part;
1361 else
1362 Vmouse_screen_part = Qtext_part;
1363
1364 result->kind = window_sys_event;
1365 result->code = Qmouse_moved;
1366
1367 return;
1368 }
1369 else if (window_type == scrollbar_window) /* Scrollbar */
1370 {
1371 Vmouse_window = s->selected_window;
1372 mouse_buffer_offset = 0;
1373 Vmouse_screen_part = part;
1374
1375 result->kind = window_sys_event;
1376 result->code = Qmouse_moved;
1377
1378 return;
1379 }
1380
1381 return;
1382}
1383#endif
1384
1385/* Given a pixel position (pix_x, pix_y) on the screen s, return
1386 character co-ordinates in (*x, *y). */
1387void
1388pixel_to_glyph_translation (s, pix_x, pix_y, x, y)
1389 SCREEN_PTR s;
1390 register unsigned int pix_x, pix_y;
1391 register int *x, *y;
1392{
1393 register struct screen_glyphs *s_glyphs = SCREEN_CURRENT_GLYPHS (s);
1394 register int line = SCREEN_HEIGHT (s) - 1;
1395 int ibw = s->display.x->internal_border_width;
1396
1397 /* What line is it on? */
1398 line = SCREEN_HEIGHT (s) - 1;
1399 while (s_glyphs->top_left_y[line] > pix_y)
1400 line--;
1401 *y = line;
1402
1403 /* Horizontally, is it in the border? */
1404 if (pix_x < ibw)
1405 *x = 0;
1406
1407 /* If it's off the right edge, clip it. */
1408 else if (pix_x > s->display.x->pixel_width - ibw)
1409 *x = SCREEN_WIDTH (s) - 1;
1410
1411 /* It's in the midst of the screen; assume all the characters are
1412 the same width, and figure the column. */
1413 else
1414 *x = (pix_x - ibw) / FONT_WIDTH (s->display.x->font);
1415}
1416
1417#ifdef HAVE_X11
1418
1419/* Any buttons grabbed. */
1420unsigned int x_mouse_grabbed;
1421
1422/* Convert a set of X modifier bits to the proper form for a
1423 struct input_event modifiers value. */
1424
1425static Lisp_Object
1426x_convert_modifiers (state)
1427 unsigned int state;
1428{
1429 return ( ((state & (ShiftMask | LockMask)) ? shift_modifier : 0)
1430 | ((state & ControlMask) ? ctrl_modifier : 0)
1431 | ((state & Mod1Mask) ? meta_modifier : 0));
1432}
1433
1434extern struct screen *x_window_to_scrollbar ();
1435extern Lisp_Object Vmouse_event;
1436
1437/* Prepare a mouse-event in *RESULT for placement in the input queue.
1438
1439 If the event is a button press, then note that we have grabbed
1440 the mouse.
1441
1442 If PART and PREFIX are 0, then the event occurred in the text part;
1443 otherwise it happened in a scrollbar. */
1444
1445static Lisp_Object
1446construct_mouse_click (result, event, s, part, prefix)
1447 struct input_event *result;
1448 XButtonEvent *event;
1449 struct screen *s;
1450 int prefix;
1451 Lisp_Object part;
1452{
1453 /* Initialize those fields text and scrollbar clicks hold in common.
1454 Make the event type no_event; we'll change that when we decide
1455 otherwise. */
1456 result->kind = no_event;
1457 XSET (result->code, Lisp_Int, event->button);
1458 result->modifiers = (x_convert_modifiers (event->state)
1459 | (event->type == ButtonRelease ? up_modifier : 0));
1460 XSET (result->timestamp, Lisp_Int, (event->time & 0x7fffff));
1461
1462 /* Notice if the mouse is still grabbed. */
1463 if (event->type == ButtonPress)
1464 {
1465 if (! x_mouse_grabbed)
1466 Vmouse_depressed = Qt;
1467 x_mouse_grabbed |= event->button;
1468 }
1469 else if (event->type == ButtonRelease)
1470 {
1471 x_mouse_grabbed &= ~(event->button);
1472 if (!x_mouse_grabbed)
1473 Vmouse_depressed = Qnil;
1474 }
1475
1476 if (part) /* Scrollbar event */
1477 {
1478 int pos, len;
1479
1480 pos = event->y - (s->display.x->v_scrollbar_width - 2);
1481 XSET (x_mouse_x, Lisp_Int, pos);
1482 len = ((FONT_HEIGHT (s->display.x->font) * s->height)
1483 + s->display.x->internal_border_width
1484 - (2 * (s->display.x->v_scrollbar_width - 2)));
1485 XSET (x_mouse_y, Lisp_Int, len);
1486
1487 result->kind = scrollbar_click;
1488 result->part = part;
1489 XSET (result->x, Lisp_Int, (s->display.x->top_pos - event->y));
1490 XSET (result->y, Lisp_Int, s->display.x->pixel_height);
1491 result->screen = s;
1492 }
1493 else /* Text Window Event */
1494 {
1495 int row, column;
1496
1497 pixel_to_glyph_translation (s,
1498 event->x, event->y,
1499 &column, &row);
1500
1501 result->kind = mouse_click;
1502 result->x = column;
1503 result->y = row;
1504 result->screen = s;
1505 }
1506}
1507
1508
1509static char *events[] =
1510{
1511 "0: ERROR!",
1512 "1: REPLY",
1513 "KeyPress",
1514 "KeyRelease",
1515 "ButtonPress",
1516 "ButtonRelease",
1517 "MotionNotify",
1518 "EnterNotify",
1519 "LeaveNotify",
1520 "FocusIn",
1521 "FocusOut",
1522 "KeymapNotify",
1523 "Expose",
1524 "GraphicsExpose",
1525 "NoExpose",
1526 "VisibilityNotify",
1527 "CreateNotify",
1528 "DestroyNotify",
1529 "UnmapNotify",
1530 "MapNotify",
1531 "MapRequest",
1532 "ReparentNotify",
1533 "ConfigureNotify",
1534 "ConfigureRequest",
1535 "GravityNotify",
1536 "ResizeRequest",
1537 "CirculateNotify",
1538 "CirculateRequest",
1539 "PropertyNotify",
1540 "SelectionClear",
1541 "SelectionRequest",
1542 "SelectionNotify",
1543 "ColormapNotify",
1544 "ClientMessage",
1545 "MappingNotify",
1546 "LASTEvent"
1547};
1548#else /* X10 */
1549#define XEvent XKeyPressedEvent
1550#endif /* HAVE_X11 */
1551
1552/* Symbols returned in the input stream to indicate various X events. */
1553Lisp_Object Qmapped_screen;
1554Lisp_Object Qunmapped_screen;
1555Lisp_Object Qexited_scrollbar;
1556Lisp_Object Qexited_window;
1557Lisp_Object Qredraw_screen;
1558Lisp_Object Qmouse_click;
1559Lisp_Object Qscrollbar_click;
1560
1561/* Timestamp of enter window event. This is only used by XTread_socket,
1562 but we have to put it out here, since static variables within functions
1563 sometimes don't work. */
1564static Time enter_timestamp;
1565
1566/* Read events coming from the X server.
1567 This routine is called by the SIGIO handler.
1568 We return as soon as there are no more events to be read.
1569
1570 Events representing keys are stored in buffer BUFP,
1571 which can hold up to NUMCHARS characters.
1572 We return the number of characters stored into the buffer,
1573 thus pretending to be `read'.
1574
1575 WAITP is nonzero if we should block until input arrives.
1576 EXPECTED is nonzero if the caller knows input is available. */
1577
1578Lisp_Object
1579XTread_socket (sd, bufp, numchars, waitp, expected)
1580 register int sd;
1581 register struct input_event *bufp;
1582 register int numchars;
1583 int waitp;
1584 int expected;
1585{
1586 int count = 0;
1587 int nbytes = 0;
1588 int mask;
1589 int items_pending; /* How many items are in the X queue. */
1590 XEvent event;
1591 struct screen *s;
1592 int event_found;
1593 int prefix;
1594 Lisp_Object part;
1595
1596 if (x_input_blocked)
1597 {
1598 x_pending_input = 1;
1599 return -1;
1600 }
1601
1602 x_pending_input = 0;
1603 BLOCK_INPUT;
1604
1605 if (numchars <= 0)
1606 abort (); /* Don't think this happens. */
1607
1608#ifdef FIOSNBIO
1609 /* If available, Xlib uses FIOSNBIO to make the socket
1610 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
1611 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
1612 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
1613 fcntl (fileno (stdin), F_SETFL, 0);
1614#endif
1615
1616#ifndef SIGIO
1617#ifndef HAVE_SELECT
1618 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
1619 {
1620 extern int read_alarm_should_throw;
1621 read_alarm_should_throw = 1;
1622 XPeekEvent (XDISPLAY &event);
1623 read_alarm_should_throw = 0;
1624 }
1625#endif
1626#endif
1627
1628 while (XStuffPending () != 0)
1629 {
1630 XNextEvent (XDISPLAY &event);
1631 event_found = 1;
1632
1633 switch (event.type)
1634 {
1635#ifdef HAVE_X11
1636
1637 case SelectionClear: /* Someone has grabbed ownership. */
1638 x_disown_selection (event.xselectionclear.window,
1639 event.xselectionclear.selection,
1640 event.xselectionclear.time);
1641 break;
1642
1643 case SelectionRequest: /* Someone wants our selection. */
1644 x_answer_selection_request (event);
1645 break;
1646
1647 case PropertyNotify:
1648 /* If we were to do this synchronously, there'd be no worry
1649 about re-selecting. */
1650 x_send_incremental (event);
1651 break;
1652
1653 case Expose:
1654 s = x_window_to_screen (event.xexpose.window);
1655 if (s)
1656 {
1657 if (s->visible == 0)
1658 {
1659 s->visible = 1;
1660 s->iconified = 0;
1661 SET_SCREEN_GARBAGED (s);
1662 }
1663 else
1664 dumprectangle (x_window_to_screen (event.xexpose.window),
1665 event.xexpose.x, event.xexpose.y,
1666 event.xexpose.width, event.xexpose.height);
1667 }
1668 break;
1669
1670 case GraphicsExpose: /* This occurs when an XCopyArea's
1671 source area was obscured or not
1672 available.*/
1673 dumprectangle (x_window_to_screen (event.xgraphicsexpose.drawable),
1674 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
1675 event.xgraphicsexpose.width,
1676 event.xgraphicsexpose.height);
1677 break;
1678
1679 case NoExpose: /* This occurs when an XCopyArea's
1680 source area was completely
1681 available */
1682 break;
1683#else /* not HAVE_X11 */
1684 case ExposeWindow:
1685 if (event.subwindow != 0)
1686 break; /* duplicate event */
1687 s = x_window_to_screen (event.window);
1688 if (event.window == s->display.x->icon_desc)
1689 {
1690 refreshicon (s);
1691 s->iconified = 1;
1692 }
1693 if (event.window == s->display.x->window_desc)
1694 {
1695 /* Say must check all windows' needs_exposure flags. */
1696 expose_all_windows = 1;
1697 s->display.x->needs_exposure = 1;
1698 s->visible = 1;
1699 }
1700 break;
1701
1702 case ExposeRegion:
1703 if (event.subwindow != 0)
1704 break; /* duplicate event */
1705 s = x_window_to_screen (event.window);
1706 if (event.window == s->display.x->icon_desc)
1707 {
1708 refreshicon (s);
1709 break;
1710 }
1711 /* If window already needs full redraw, ignore this rectangle. */
1712 if (expose_all_windows && s->display.x->needs_exposure)
1713 break;
1714 /* Put the event on the queue of rectangles to redraw. */
1715 if (enqueue_event (&event, &x_expose_queue))
1716 /* If it is full, we can't record the rectangle,
1717 so redraw this entire window. */
1718 {
1719 /* Say must check all windows' needs_exposure flags. */
1720 expose_all_windows = 1;
1721 s->display.x->needs_exposure = 1;
1722 }
1723 break;
1724
1725 case ExposeCopy:
1726 /* This should happen only when we are expecting it,
1727 in x_read_exposes. */
1728 abort ();
1729#endif /* not HAVE_X11 */
1730
1731#ifdef HAVE_X11
1732 case UnmapNotify:
1733 {
1734 XWMHints *hints;
1735
1736 s = x_window_to_screen (event.xunmap.window);
1737 if (s) /* S may no longer exist if
1738 the screen was deleted. */
1739 {
1740 /* While a screen is unmapped, display generation is
1741 disabled; you don't want to spend time updating a
1742 display that won't ever be seen. */
1743 s->visible = 0;
1744 Vmouse_window = Vmouse_screen_part = Qnil;
1745 x_mouse_x = x_mouse_y = -1;
1746 }
1747 }
1748 break;
1749
1750 case MapNotify:
1751 s = x_window_to_screen (event.xmap.window);
1752 if (s)
1753 {
1754 s->visible = 1;
1755 s->iconified = 0;
1756
1757 /* wait_reading_process_input will notice this and update
1758 the screen's display structures. */
1759 SET_SCREEN_GARBAGED (s);
1760 }
1761 break;
1762
1763 /* Turn off processing if we become fully obscured. */
1764 case VisibilityNotify:
1765 break;
1766
1767#else
1768 case UnmapWindow:
1769 s = x_window_to_screen (event.window);
1770 if (event.window == s->display.x->icon_desc)
1771 s->iconified = 0;
1772 if (event.window == s->display.x->window_desc)
1773 s->visible = 0;
1774 break;
1775#endif /* HAVE_X11 */
1776
1777#ifdef HAVE_X11
1778 case KeyPress:
1779 s = x_window_to_screen (event.xkey.window);
1780 if (s != 0)
1781 {
1782 KeySym keysym;
1783 XComposeStatus status;
1784 char copy_buffer[80];
1785
1786 /* This will have to go some day... */
1787 nbytes = XLookupString (&event.xkey,
1788 copy_buffer,
1789 80,
1790 &keysym,
1791 &status);
1792
1793 if (numchars > 1)
1794 {
1795 if (IsCursorKey (keysym) /* >= 0xff50 < 0xff60 */
1796 || IsMiscFunctionKey (keysym) /* >= 0xff60 < 0xff80 */
1797 || IsKeypadKey (keysym) /* >= 0xff80 <= 0xffbd */
1798 || IsFunctionKey (keysym)) /* >= 0xffbe <= 0xffe0 */
1799 {
1800 bufp->kind = non_ascii_keystroke;
1801 bufp->code = (unsigned) keysym - 0xff50;
1802 bufp->modifiers = x_convert_modifiers (event.xkey.state);
1803 bufp++;
1804 count++;
1805 numchars--;
1806 }
1807 else if (numchars > nbytes)
1808 {
1809 register int i;
1810
1811 if (nbytes == 1)
1812 {
1813 if (event.xkey.state & Mod1Mask)
1814 *copy_buffer |= METABIT;
1815 bufp->kind = ascii_keystroke;
1816 XSET (bufp->code, Lisp_Int, *copy_buffer);
1817 bufp++;
1818 }
1819 else
1820 for (i = nbytes - 1; i > 1; i--)
1821 {
1822 bufp->kind = ascii_keystroke;
1823 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
1824 bufp++;
1825 }
1826
1827 count += nbytes;
1828 numchars -= nbytes;
1829 }
1830 }
1831 }
1832 break;
1833#else
1834 case KeyPressed:
1835 {
1836 register char *where_mapping;
1837
1838 s = x_window_to_screen (event.window);
1839 /* Ignore keys typed on icon windows. */
1840 if (s != 0 && event.window == s->display.x->icon_desc)
1841 break;
1842 where_mapping = XLookupMapping (&event, &nbytes);
1843 /* Nasty fix for arrow keys */
1844 if (!nbytes && IsCursorKey (event.detail & 0xff))
1845 {
1846 switch (event.detail & 0xff)
1847 {
1848 case KC_CURSOR_LEFT:
1849 where_mapping = "\002";
1850 break;
1851 case KC_CURSOR_RIGHT:
1852 where_mapping = "\006";
1853 break;
1854 case KC_CURSOR_UP:
1855 where_mapping = "\020";
1856 break;
1857 case KC_CURSOR_DOWN:
1858 where_mapping = "\016";
1859 break;
1860 }
1861 nbytes = 1;
1862 }
1863 if (numchars - nbytes > 0)
1864 {
1865 register int i;
1866
1867 for (i = 0; i < nbytes; i++)
1868 {
1869 bufp->kind = ascii_keystroke;
1870 XSET (bufp->code, Lisp_Int, where_mapping[i]);
1871 bufp++;
1872 }
1873 count += nbytes;
1874 numchars -= nbytes;
1875 }
1876 }
1877 break;
1878#endif /* HAVE_X11 */
1879
1880#ifdef HAVE_X11
1881 case EnterNotify:
1882 if (event.xcrossing.detail == NotifyInferior) /* Left Scrollbar */
1883 ;
1884 else if (event.xcrossing.focus) /* Entered Window */
1885 {
1886 /* If we decide we want to generate an event to be seen
1887 by the rest of Emacs, we put it here. */
1888 struct input_event emacs_event;
1889 emacs_event.kind = no_event;
1890
1891 s = x_window_to_screen (event.xcrossing.window);
1892
1893 /* Avoid nasty pop/raise loops. */
1894 if (s && (!(s->auto_raise)
1895 || !(s->auto_lower)
1896 || (event.xcrossing.time - enter_timestamp) > 500))
1897 {
1898 int n = x_new_focus_screen (s, bufp, numchars);
1899 bufp += n;
1900 numchars -= n;
1901 enter_timestamp = event.xcrossing.time;
1902 }
1903#if 0
1904 else if ((s = x_window_to_scrollbar (event.xcrossing.window,
1905 &part, &prefix)))
1906 /* Fake a motion event */
1907 notice_mouse_movement (&emacs_event,
1908 event.xmotion, s, scrollbar_window,
1909 part);
1910#endif
1911
1912#if 0
1913 if (! EQ (Vx_send_mouse_movement_events, Qnil)
1914 && numchars >= 1
1915 && emacs_event.kind != no_event)
1916 {
1917 bcopy (&emacs_event, bufp, sizeof (struct input_event));
1918 bufp++;
1919 count++;
1920 numchars--;
1921 }
1922#endif
1923 }
1924#if 0
1925 else if (s = x_window_to_screen (event.xcrossing.window))
1926 x_mouse_screen = s;
1927#endif
1928
1929 break;
1930
1931 case FocusIn:
1932 s = x_window_to_screen (event.xfocus.window);
1933 if (s)
1934 {
1935 int n = x_new_focus_screen (s, bufp, numchars);
1936 bufp += n;
1937 numchars -= n;
1938 }
1939 break;
1940
1941 case LeaveNotify:
1942 if (event.xcrossing.detail != NotifyInferior
1943 && event.xcrossing.subwindow == None
1944 && event.xcrossing.mode == NotifyNormal)
1945 {
1946 if (event.xcrossing.focus
1947 && (x_focus_screen
1948 == x_window_to_screen (event.xcrossing.window)))
1949 {
1950 int n = x_new_focus_screen (0, bufp, numchars);
1951 bufp += n;
1952 numchars -= n;
1953 }
1954 }
1955 break;
1956
1957 case FocusOut:
1958 s = x_window_to_screen (event.xfocus.window);
1959 if (s && s == x_focus_screen)
1960 {
1961 int n = x_new_focus_screen (0, bufp, numchars);
1962 bufp += n;
1963 numchars -= n;
1964 }
1965 break;
1966
1967#else /* not HAVE_X11 */
1968
1969 case EnterWindow:
1970 if ((event.detail & 0xFF) == 1)
1971 break; /* Coming from our own subwindow */
1972 if (event.subwindow != 0)
1973 break; /* Entering our own subwindow. */
1974
1975 {
1976 extern int waiting_for_input;
1977 struct screen *old_s = x_input_screen;
1978
1979 s = x_window_to_screen (event.window);
1980 x_mouse_screen = s;
1981
1982 if (waiting_for_input && x_focus_screen == 0)
1983 x_new_selected_screen (s);
1984 }
1985 break;
1986
1987 case LeaveWindow:
1988 if ((event.detail & 0xFF) == 1)
1989 break; /* Entering our own subwindow */
1990 if (event.subwindow != 0)
1991 break; /* Leaving our own subwindow. */
1992
1993 x_mouse_screen = 0;
1994 if (x_focus_screen == 0
1995 && x_input_screen != 0
1996 && x_input_screen == x_window_to_screen (event.window)
1997 && event.window == x_input_screen->display.x->window_desc)
1998 {
1999 s = x_input_screen;
2000 x_input_screen = 0;
2001 if (s)
2002 screen_unhighlight (s);
2003 }
2004 break;
2005#endif /* not HAVE_X11 */
2006
2007#ifdef HAVE_X11
2008 case MotionNotify:
2009 {
2010 s = x_window_to_screen (event.xmotion.window);
2011 if (s)
2012 {
2013 int row, column;
2014
2015 pixel_to_glyph_translation (s,
2016 event.xmotion.x, event.xmotion.y,
2017 &column, &row);
2018
2019 note_mouse_position (s, column, row, event.xmotion.time);
2020 }
2021#if 0
2022 else if ((s = x_window_to_scrollbar (event.xmotion.window,
2023 &part, &prefix)))
2024 {
2025 What should go here?
2026 }
2027#endif
2028 }
2029 break;
2030
2031 case ConfigureNotify:
2032 {
2033 int rows, columns;
2034 s = x_window_to_screen (event.xconfigure.window);
2035 if (!s)
2036 break;
2037
2038 columns = ((event.xconfigure.width -
2039 (2 * s->display.x->internal_border_width)
2040 - s->display.x->v_scrollbar_width)
2041 / FONT_WIDTH (s->display.x->font));
2042 rows = ((event.xconfigure.height -
2043 (2 * s->display.x->internal_border_width)
2044 - s->display.x->h_scrollbar_height)
2045 / FONT_HEIGHT (s->display.x->font));
2046
2047 if (columns != s->width || rows != s->height)
2048 {
2049 XEvent ignored_event;
2050
2051 change_screen_size (s, rows, columns, 0);
2052 x_resize_scrollbars (s);
2053 SET_SCREEN_GARBAGED (s);
2054#if 0
2055 dumprectangle (s, 0, 0, PIXEL_WIDTH (s), PIXEL_HEIGHT (s));
2056 /* Throw away the exposures generated by this reconfigure. */
2057 while (XCheckWindowEvent (x_current_display,
2058 event.xconfigure.window,
2059 ExposureMask, &ignored_event)
2060 == True);
2061#endif
2062 }
2063
2064 s->display.x->left_pos = event.xconfigure.x;
2065 s->display.x->top_pos = event.xconfigure.y;
2066 s->display.x->pixel_width = event.xconfigure.width;
2067 s->display.x->pixel_height = event.xconfigure.height;
2068 break;
2069 }
2070
2071 case ButtonPress:
2072 case ButtonRelease:
2073 {
2074 /* If we decide we want to generate an event to be seen
2075 by the rest of Emacs, we put it here. */
2076 struct input_event emacs_event;
2077 emacs_event.kind = no_event;
2078
2079 s = x_window_to_screen (event.xbutton.window);
2080 if (s)
2081 if (!x_focus_screen || (s == x_focus_screen))
2082 construct_mouse_click (&emacs_event,
2083 &event, s, 0, 0);
2084 else
2085 continue;
2086 else
2087 if ((s = x_window_to_scrollbar (event.xbutton.window,
2088 &part, &prefix)))
2089 {
2090 if (!x_focus_screen || (selected_screen == x_focus_screen))
2091 construct_mouse_click (&emacs_event,
2092 &event, s, part, prefix);
2093 else
2094 continue;
2095 }
2096
2097 if (numchars >= 1 && emacs_event.kind != no_event)
2098 {
2099 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2100 bufp++;
2101 count++;
2102 numchars--;
2103 }
2104 }
2105 break;
2106
2107#else /* not HAVE_X11 */
2108 case ButtonPressed:
2109 case ButtonReleased:
2110 s = x_window_to_screen (event.window);
2111 if (s)
2112 {
2113 if (event.window == s->display.x->icon_desc)
2114 {
2115 x_make_screen_visible (s);
2116
2117 if (warp_mouse_on_deiconify)
2118 XWarpMouse (s->display.x->window_desc, 10, 10);
2119 break;
2120 }
2121 if (event.window == s->display.x->window_desc)
2122 {
2123 if (s->auto_raise)
2124 x_raise_screen (s);
2125 }
2126 }
2127 enqueue_event (&event, &x_mouse_queue);
2128 if (numchars >= 2)
2129 {
2130 bufp->kind = ascii_keystroke;
2131 bufp->code = (char) 'X' & 037; /* C-x */
2132 bufp++;
2133
2134 bufp->kind = ascii_keystroke;
2135 bufp->code = (char) 0; /* C-@ */
2136 bufp++;
2137
2138 count += 2;
2139 numchars -= 2;
2140 }
2141 break;
2142#endif /* not HAVE_X11 */
2143
2144#ifdef HAVE_X11
2145
2146 case CirculateNotify:
2147 break;
2148 case CirculateRequest:
2149 break;
2150
2151#endif /* HAVE_X11 */
2152
2153 case MappingNotify:
2154 if (event.xmapping.request == MappingKeyboard)
2155 /* Someone has changed the keyboard mapping - flush the
2156 local cache. */
2157 XRefreshKeyboardMapping (&event.xmapping);
2158 break;
2159
2160 default:
2161 break;
2162 }
2163 }
2164
2165#if 0
2166#ifdef HAVE_SELECT
2167 if (expected && ! event_found)
2168 {
2169 /* AOJ 880406: if select returns true but XPending doesn't, it means that
2170 there is an EOF condition; in other words, that X has died.
2171 Act as if there had been a hangup. */
2172
2173 int fd = ConnectionNumber (x_current_display);
2174 int mask = 1 << fd;
2175
2176 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
2177 (struct timeval *) 0)
2178 && !XStuffPending ())
2179 kill (getpid (), SIGHUP);
2180 }
2181#endif /* HAVE_SELECT */
2182#endif
2183
2184 if (updating_screen == 0)
2185 x_do_pending_expose ();
2186
2187 UNBLOCK_INPUT;
2188 return count;
2189}
2190
2191#ifndef HAVE_X11
2192/* Read and process only Expose events
2193 until we get an ExposeCopy event; then return.
2194 This is used in insert/delete line.
2195 We assume input is already blocked. */
2196
2197static void
2198x_read_exposes ()
2199{
2200 struct screen *s;
2201 XKeyPressedEvent event;
2202
2203 while (1)
2204 {
2205 /* while there are more events*/
2206 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
2207 switch (event.type)
2208 {
2209 case ExposeWindow:
2210 if (event.subwindow != 0)
2211 break; /* duplicate event */
2212 s = x_window_to_screen (event.window);
2213 if (event.window == s->display.x->icon_desc)
2214 {
2215 refreshicon (s);
2216 break;
2217 }
2218 if (event.window == s->display.x->window_desc)
2219 {
2220 expose_all_windows = 1;
2221 s->display.x->needs_exposure = 1;
2222 break;
2223 }
2224 break;
2225
2226 case ExposeRegion:
2227 if (event.subwindow != 0)
2228 break; /* duplicate event */
2229 s = x_window_to_screen (event.window);
2230 if (event.window == s->display.x->icon_desc)
2231 {
2232 refreshicon (s);
2233 break;
2234 }
2235 /* If window already needs full redraw, ignore this rectangle. */
2236 if (expose_all_windows && s->display.x->needs_exposure)
2237 break;
2238 /* Put the event on the queue of rectangles to redraw. */
2239 if (enqueue_event (&event, &x_expose_queue))
2240 /* If it is full, we can't record the rectangle,
2241 so redraw this entire window. */
2242 {
2243 /* Say must check all windows' needs_exposure flags. */
2244 expose_all_windows = 1;
2245 s->display.x->needs_exposure = 1;
2246 }
2247 break;
2248
2249 case ExposeCopy:
2250 return;
2251 }
2252 }
2253}
2254#endif /* HAVE_X11 */
2255
2256static int
2257XTmouse_tracking_enable (enable)
2258 int enable;
2259{
2260 Lisp_Object tail;
2261
2262 /* Go through the list of screens and turn on/off mouse tracking for
2263 each of them. */
2264 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
2265 {
2266 if (XTYPE (XCONS (tail)->car) != Lisp_Screen)
2267 abort ();
2268 if (XSCREEN (XCONS (tail)->car)->output_method == output_x_window)
2269 XSelectInput (x_current_display,
2270 XSCREEN (XCONS (tail)->car)->display.x->window_desc,
2271 (enable
2272 ? (STANDARD_EVENT_SET
2273 | PointerMotionMask
2274 | ButtonReleaseMask)
2275 : STANDARD_EVENT_SET));
2276 }
2277}
2278
2279
2280static Lisp_Object
2281XTmouse_position ()
2282{
2283
2284}
2285
2286
2287
2288/* Draw a hollow box cursor. Don't change the inside of the box. */
2289
2290static void
2291x_draw_box (s)
2292 struct screen *s;
2293{
2294 int left = s->cursor_x * FONT_WIDTH (s->display.x->font)
2295 + s->display.x->internal_border_width;
2296 int top = s->cursor_y * FONT_HEIGHT (s->display.x->font)
2297 + s->display.x->internal_border_width;
2298 int width = FONT_WIDTH (s->display.x->font);
2299 int height = FONT_HEIGHT (s->display.x->font);
2300
2301#ifdef HAVE_X11
2302 /* Perhaps we should subtract 1 from width and height... */
2303 XDrawRectangle (x_current_display, s->display.x->window_desc,
2304 s->display.x->cursor_gc,
2305 left, top, width - 1, height - 1);
2306#else
2307 XPixSet (s->display.x->window_desc,
2308 left, top, width, 1,
2309 s->display.x->cursor_pixel);
2310
2311 XPixSet (s->display.x->window_desc,
2312 left, top, 1, height,
2313 s->display.x->cursor_pixel);
2314
2315 XPixSet (s->display.x->window_desc,
2316 left+width-1, top, 1, height,
2317 s->display.x->cursor_pixel);
2318
2319 XPixSet (s->display.x->window_desc,
2320 left, top+height-1, width, 1,
2321 s->display.x->cursor_pixel);
2322#endif /* HAVE_X11 */
2323}
2324
2325/* Clear the cursor of screen S to background color,
2326 and mark the cursor as not shown.
2327 This is used when the text where the cursor is
2328 is about to be rewritten. */
2329
2330static void
2331clear_cursor (s)
2332 struct screen *s;
2333{
2334 int mask;
2335
2336 if (! s->visible
2337 || s->phys_cursor_x < 0)
2338 return;
2339
2340#ifdef HAVE_X11
2341 x_display_cursor (s, 0);
2342#if 0
2343 XClearArea (x_current_display, s->display.x->window_desc,
2344 s->phys_cursor_x * FONT_WIDTH (s->display.x->font)
2345 + s->display.x->internal_border_width,
2346 s->phys_cursor_y * FONT_HEIGHT (s->display.x->font)
2347 + s->display.x->internal_border_width,
2348 FONT_WIDTH (s->display.x->font) + 1, FONT_HEIGHT (s->display.x->font) + 1, False);
2349#endif
2350#else
2351 XPixSet (s->display.x->window_desc,
2352 s->phys_cursor_x * FONT_WIDTH (s->display.x->font) + s->display.x->internal_border_width,
2353 s->phys_cursor_y * FONT_HEIGHT (s->display.x->font) + s->display.x->internal_border_width,
2354 FONT_WIDTH (s->display.x->font), FONT_HEIGHT (s->display.x->font),
2355 s->display.x->background_pixel);
2356#endif /* HAVE_X11 */
2357 s->phys_cursor_x = -1;
2358}
2359
2360x_display_bar_cursor (s, on)
2361 struct screen *s;
2362 int on;
2363{
2364 register int phys_x = s->phys_cursor_x;
2365 register int phys_y = s->phys_cursor_y;
2366 register int x1;
2367 register int y1;
2368 register int y2;
2369
2370 if (! s->visible || (! on && s->phys_cursor_x < 0))
2371 return;
2372
2373#ifdef HAVE_X11
2374 if (phys_x >= 0 &&
2375 (!on || phys_x != s->cursor_x || phys_y != s->cursor_y))
2376 {
2377 x1 = phys_x * FONT_WIDTH (s->display.x->font)
2378 + s->display.x->internal_border_width;
2379 y1 = phys_y * FONT_HEIGHT (s->display.x->font)
2380 + s->display.x->internal_border_width - 1;
2381 y2 = y1 + FONT_HEIGHT (s->display.x->font) + 1;
2382
2383 XDrawLine (x_current_display, s->display.x->window_desc,
2384 s->display.x->reverse_gc, x1, y1, x1, y2);
2385
2386 s->phys_cursor_x = phys_x = -1;
2387 }
2388
2389 if (on && s == x_focus_screen)
2390 {
2391 x1 = s->cursor_x * FONT_WIDTH (s->display.x->font)
2392 + s->display.x->internal_border_width;
2393 y1 = s->cursor_y * FONT_HEIGHT (s->display.x->font)
2394 + s->display.x->internal_border_width - 1;
2395 y2 = y1 + FONT_HEIGHT (s->display.x->font) + 1;
2396
2397 XDrawLine (x_current_display, s->display.x->window_desc,
2398 s->display.x->cursor_gc, x1, y1, x1, y2);
2399
2400 s->phys_cursor_x = s->cursor_x;
2401 s->phys_cursor_y = s->cursor_y;
2402 }
2403#else /* X10 */
2404 Give it up, dude.
2405#endif /* X10 */
2406}
2407
2408
2409/* Redraw the glyph at ROW, COLUMN on screen S, in the style HIGHLIGHT.
2410 If there is no character there, erase the area. HIGHLIGHT is as
2411 defined for dumpglyphs. */
2412
2413static void
2414x_draw_single_glyph (s, row, column, highlight)
2415 struct screen *s;
2416 int row, column;
2417 int highlight;
2418{
2419 register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (s);
2420
2421 /* If there is supposed to be a character there, redraw it
2422 in that line's normal video. */
2423 if (current_screen->enable[row]
2424 && column < current_screen->used[row])
2425 dumpglyphs (s,
2426 (column * FONT_WIDTH (s->display.x->font)
2427 + s->display.x->internal_border_width),
2428 (row * FONT_HEIGHT (s->display.x->font)
2429 + s->display.x->internal_border_width),
2430 &current_screen->glyphs[row][column],
2431 1, highlight, s->display.x->font);
2432 else
2433 {
2434#ifdef HAVE_X11
2435 static GLYPH a_space_glyph = SPACEGLYPH;
2436 dumpglyphs (s,
2437 (column * FONT_WIDTH (s->display.x->font)
2438 + s->display.x->internal_border_width),
2439 (row * FONT_HEIGHT (s->display.x->font)
2440 + s->display.x->internal_border_width),
2441 &a_space_glyph, 1, highlight, s->display.x->font);
2442#else
2443 XPixSet (s->display.x->window_desc,
2444 (column * FONT_WIDTH (s->display.x->font)
2445 + s->display.x->internal_border_width),
2446 (row * FONT_HEIGHT (s->display.x->font)
2447 + s->display.x->internal_border_width),
2448 FONT_WIDTH (s->display.x->font),
2449 FONT_HEIGHT (s->display.x->font),
2450 (highlight == 0
2451 ? s->display.x->background_pixel
2452 : (highlight == 1
2453 ? s->display.x->foreground_pixel
2454 : s->display.x->cursor_pixel)));
2455#endif /* HAVE_X11 */
2456 }
2457}
2458
2459/* Turn the displayed cursor of screen S on or off according to ON.
2460 If ON is nonzero, where to put the cursor is specified
2461 by S->cursor_x and S->cursor_y. */
2462
2463static void
2464x_display_box_cursor (s, on)
2465 struct screen *s;
2466 int on;
2467{
2468 if (! s->visible)
2469 return;
2470
2471 /* If cursor is off and we want it off, return quickly. */
2472
2473 if (!on && s->phys_cursor_x < 0)
2474 return;
2475
2476 /* If cursor is currently being shown and we don't want it to be
2477 or it is in the wrong place,
2478 or we want a hollow box and it's not so, (pout!)
2479 erase it. */
2480 if (s->phys_cursor_x >= 0
2481 && (!on
2482 || s->phys_cursor_x != s->cursor_x
2483 || s->phys_cursor_y != s->cursor_y
2484 || (s->display.x->text_cursor_kind != hollow_box_cursor
2485 && (s != x_focus_screen))))
2486 {
2487 /* Erase the cursor by redrawing the character underneath it. */
2488 x_draw_single_glyph (s, s->phys_cursor_y, s->phys_cursor_x,
2489 (SCREEN_CURRENT_GLYPHS (s)
2490 ->highlight[s->phys_cursor_y]));
2491
2492 s->phys_cursor_x = -1;
2493 }
2494
2495 /* If we want to show a cursor,
2496 or we want a box cursor and it's not so,
2497 write it in the right place. */
2498 if (on
2499 && (s->phys_cursor_x < 0
2500 || (s->display.x->text_cursor_kind != filled_box_cursor
2501 && s == x_focus_screen)))
2502 {
2503 if (s != x_focus_screen)
2504 {
2505 x_draw_box (s);
2506 s->display.x->text_cursor_kind = hollow_box_cursor;
2507 }
2508 else
2509 {
2510 x_draw_single_glyph (s, s->cursor_y, s->cursor_x, 2);
2511 s->display.x->text_cursor_kind = filled_box_cursor;
2512 }
2513
2514 s->phys_cursor_x = s->cursor_x;
2515 s->phys_cursor_y = s->cursor_y;
2516 }
2517
2518 if (updating_screen != s)
2519 XFlushQueue ();
2520}
2521
2522#if 0
2523This code has been rewritten to use x_draw_single_glyph and draw
2524box cursors successfully. Once that code is working, this can go away.
2525
2526/* Turn the displayed cursor of screen S on or off according to ON.
2527 If ON is nonzero, where to put the cursor is specified
2528 by S->cursor_x and S->cursor_y. */
2529
2530static void
2531x_display_box_cursor (s, on)
2532 struct screen *s;
2533 int on;
2534{
2535 register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (s);
2536
2537 if (! s->visible)
2538 return;
2539
2540 /* If cursor is off and we want it off, return quickly. */
2541
2542 if (!on && s->phys_cursor_x < 0)
2543 return;
2544
2545 /* If cursor is currently being shown and we don't want it to be
2546 or it is in the wrong place, erase it. */
2547
2548 if (s->phys_cursor_x >= 0
2549 && (!on || s->phys_cursor_x != s->cursor_x
2550 || s->phys_cursor_y != s->cursor_y))
2551 {
2552 /* If there is supposed to be a character there, redraw it
2553 in that line's normal video. */
2554 if (current_screen->enable[s->phys_cursor_y]
2555 && s->phys_cursor_x < current_screen->used[s->phys_cursor_y])
2556 dumpglyphs (s,
2557 (s->phys_cursor_x * FONT_WIDTH (s->display.x->font)
2558 + s->display.x->internal_border_width),
2559 (s->phys_cursor_y * FONT_HEIGHT (s->display.x->font)
2560 + s->display.x->internal_border_width),
2561 &current_screen->glyphs[s->phys_cursor_y][s->phys_cursor_x],
2562 1, current_screen->highlight[s->phys_cursor_y],
2563 s->display.x->font);
2564 /* Otherwise just erase the space. */
2565 else
2566#ifdef HAVE_X11
2567 XClearArea (x_current_display, s->display.x->window_desc,
2568 s->phys_cursor_x * FONT_WIDTH (s->display.x->font)
2569 + s->display.x->internal_border_width,
2570 s->phys_cursor_y * FONT_HEIGHT (s->display.x->font)
2571 + s->display.x->internal_border_width,
2572 FONT_WIDTH (s->display.x->font),
2573 FONT_HEIGHT (s->display.x->font), False);
2574#else
2575 XPixSet (s->display.x->window_desc,
2576 s->phys_cursor_x * FONT_WIDTH (s->display.x->font)
2577 + s->display.x->internal_border_width,
2578 s->phys_cursor_y * FONT_HEIGHT (s->display.x->font)
2579 + s->display.x->internal_border_width,
2580 FONT_WIDTH (s->display.x->font),
2581 FONT_HEIGHT (s->display.x->font),
2582 s->display.x->background_pixel);
2583#endif /* HAVE_X11 */
2584
2585 s->phys_cursor_x = -1;
2586 }
2587
2588 /* If we want to show a cursor, write it in the right place. */
2589
2590 if (on && s->phys_cursor_x < 0)
2591 {
2592 if (s != selected_screen || s != x_input_screen)
2593 x_draw_box (s);
2594 else if (current_screen->enable[s->cursor_y]
2595 && s->cursor_x < current_screen->used[s->cursor_y])
2596 /* There is a character there: draw the character with
2597 cursor coloration. */
2598 dumpglyphs (s,
2599 (s->cursor_x * FONT_WIDTH (s->display.x->font)
2600 + s->display.x->internal_border_width),
2601 (s->cursor_y * FONT_HEIGHT (s->display.x->font)
2602 + s->display.x->internal_border_width),
2603 &current_screen->glyphs[s->cursor_y][s->cursor_x],
2604 1, 2, s->display.x->font);
2605 else
2606#ifdef HAVE_X11
2607 {
2608 GLYPH space = SPACEGLYPH;
2609 dumpglyphs (s,
2610 (s->cursor_x * FONT_WIDTH (s->display.x->font)
2611 + s->display.x->internal_border_width),
2612 (s->cursor_y * FONT_HEIGHT (s->display.x->font)
2613 + s->display.x->internal_border_width),
2614 &space, 1,
2615 2, s->display.x->font);
2616 }
2617#if 0
2618 /* This kills the HP-BSD X11R3 server... */
2619 XFillRectangle (x_current_display, s->display.x->window_desc,
2620 s->display.x->cursor_gc,
2621 s->cursor_x * FONT_WIDTH (s->display.x->font)
2622 + s->display.x->internal_border_width,
2623 s->cursor_y * FONT_HEIGHT (s->display.x->font)
2624 + s->display.x->internal_border_width,
2625 FONT_WIDTH (s->display.x->font), FONT_HEIGHT (s->display.x->font));
2626#endif
2627#else
2628 XPixSet (s->display.x->window_desc,
2629 s->cursor_x * FONT_WIDTH (s->display.x->font)+s->display.x->internal_border_width,
2630 s->cursor_y * FONT_HEIGHT (s->display.x->font)+s->display.x->internal_border_width,
2631 FONT_WIDTH (s->display.x->font), FONT_HEIGHT (s->display.x->font), s->display.x->cursor_pixel);
2632#endif /* HAVE_X11 */
2633
2634 s->phys_cursor_x = s->cursor_x;
2635 s->phys_cursor_y = s->cursor_y;
2636 }
2637
2638 if (updating_screen != s)
2639 XFlushQueue ();
2640}
2641#endif
2642
2643extern Lisp_Object Vbar_cursor;
2644
2645x_display_cursor (s, on)
2646 struct screen *s;
2647 int on;
2648{
2649 if (EQ (Vbar_cursor, Qnil))
2650 x_display_box_cursor (s, on);
2651 else
2652 x_display_bar_cursor (s, on);
2653}
2654
2655/* Icons. */
2656
2657/* Refresh bitmap kitchen sink icon for screen S
2658 when we get an expose event for it. */
2659
2660refreshicon (s)
2661 struct screen *s;
2662{
2663#ifdef HAVE_X11
2664 /* Normally, the window manager handles this function. */
2665#else
2666 int mask;
2667
2668 if (s->display.x->icon_bitmap_flag)
2669 XBitmapBitsPut (s->display.x->icon_desc, 0, 0, sink_width, sink_height,
2670 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
2671 icon_bitmap, GXcopy, AllPlanes);
2672 else
2673 {
2674 extern struct screen *selected_screen;
2675 struct Lisp_String *str;
2676 unsigned char *string;
2677
2678 string
2679 = XSTRING (XBUFFER (XWINDOW (s->selected_window)->buffer)->name)->data;
2680
2681 if (s->display.x->icon_label != string)
2682 {
2683 s->display.x->icon_label = string;
2684 XChangeWindow (s->display.x->icon_desc,
2685 XQueryWidth (string, icon_font_info->id) + 10,
2686 icon_font_info->height + 10);
2687 }
2688
2689 XText (s->display.x->icon_desc, 5, 5, string,
2690 str->size, icon_font_info->id,
2691 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
2692 }
2693 XFlushQueue ();
2694#endif /* HAVE_X11 */
2695}
2696
2697/* Make the x-window of screen S use the kitchen-sink icon
2698 that's a window generated by Emacs. */
2699
2700int
2701x_bitmap_icon (s)
2702 struct screen *s;
2703{
2704 int mask;
2705 Window icon_window;
2706
2707 if (s->display.x->window_desc == 0)
2708 return 1;
2709
2710#ifdef HAVE_X11
2711 if (icon_bitmap)
2712 XFreePixmap (x_current_display, icon_bitmap);
2713
2714 icon_bitmap =
2715 XCreateBitmapFromData (x_current_display, s->display.x->window_desc,
2716 gnu_bits, gnu_width, gnu_height);
2717 x_wm_set_icon_pixmap (s, icon_bitmap);
2718 s->display.x->icon_bitmap_flag = 1;
2719#else
2720 if (s->display.x->icon_desc)
2721 {
2722 XClearIconWindow (s->display.x->window_desc);
2723 XDestroyWindow (s->display.x->icon_desc);
2724 }
2725
2726 icon_window = XCreateWindow (s->display.x->parent_desc,
2727 0, 0, sink_width, sink_height,
2728 2, WhitePixmap, (Pixmap) NULL);
2729
2730 if (icon_window == 0)
2731 return 1;
2732
2733 XSetIconWindow (s->display.x->window_desc, icon_window);
2734 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
2735
2736 s->display.x->icon_desc = icon_window;
2737 s->display.x->icon_bitmap_flag = 1;
2738
2739 if (icon_bitmap == 0)
2740 icon_bitmap
2741 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
2742#endif /* HAVE_X11 */
2743
2744 return 0;
2745}
2746
2747
2748/* Make the x-window of screen S use a rectangle with text. */
2749
2750int
2751x_text_icon (s, icon_name)
2752 struct screen *s;
2753 char *icon_name;
2754{
2755#ifndef HAVE_X11
2756 int mask;
2757 int width;
2758 Window icon_window;
2759 char *X_DefaultValue;
2760 Bitmap b1;
2761
2762#if 0 /* This doesn't seem to be used, but I can't quite believe it. */
2763 static Pixmap grey_pixmap;
2764#endif
2765
2766#ifndef WhitePixel
2767#define WhitePixel 1
2768#endif
2769
2770#ifndef BlackPixel
2771#define BlackPixel 0
2772#endif
2773#endif /* not HAVE_X11 */
2774
2775 if (s->display.x->window_desc == 0)
2776 return 1;
2777
2778 if (icon_font_info == 0)
2779 icon_font_info
2780 = XGetFont (XGetDefault (XDISPLAY invocation_name, "BodyFont"));
2781
2782#ifdef HAVE_X11
2783 if (icon_name)
2784 s->display.x->icon_label = icon_name;
2785 else
2786 if (! s->display.x->icon_label)
2787 s->display.x->icon_label = " *emacs* ";
2788
2789 XSetIconName (x_current_display, s->display.x->window_desc,
2790 (char *) s->display.x->icon_label);
2791
2792 s->display.x->icon_bitmap_flag = 0;
2793#else
2794 if (s->display.x->icon_desc)
2795 {
2796 XClearIconWindow (XDISPLAY s->display.x->window_desc);
2797 XDestroyWindow (XDISPLAY s->display.x->icon_desc);
2798 }
2799
2800 if (icon_name)
2801 s->display.x->icon_label = (unsigned char *) icon_name;
2802 else
2803 if (! s->display.x->icon_label)
2804 s->display.x->icon_label = XSTRING (s->name)->data;
2805
2806 width = XStringWidth (s->display.x->icon_label, icon_font_info, 0, 0);
2807 icon_window = XCreateWindow (s->display.x->parent_desc,
2808 s->display.x->left_pos,
2809 s->display.x->top_pos,
2810 width + 10, icon_font_info->height + 10,
2811 2, BlackPixmap, WhitePixmap);
2812
2813 if (icon_window == 0)
2814 return 1;
2815
2816 XSetIconWindow (s->display.x->window_desc, icon_window);
2817 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
2818
2819 s->display.x->icon_desc = icon_window;
2820 s->display.x->icon_bitmap_flag = 0;
2821 s->display.x->icon_label = 0;
2822#endif /* HAVE_X11 */
2823
2824 return 0;
2825}
2826
2827static char *x_proto_requests[] =
2828{
2829 "CreateWindow",
2830 "ChangeWindowAttributes",
2831 "GetWindowAttributes",
2832 "DestroyWindow",
2833 "DestroySubwindows",
2834 "ChangeSaveSet",
2835 "ReparentWindow",
2836 "MapWindow",
2837 "MapSubwindows",
2838 "UnmapWindow",
2839 "UnmapSubwindows",
2840 "ConfigureWindow",
2841 "CirculateWindow",
2842 "GetGeometry",
2843 "QueryTree",
2844 "InternAtom",
2845 "GetAtomName",
2846 "ChangeProperty",
2847 "DeleteProperty",
2848 "GetProperty",
2849 "ListProperties",
2850 "SetSelectionOwner",
2851 "GetSelectionOwner",
2852 "ConvertSelection",
2853 "SendEvent",
2854 "GrabPointer",
2855 "UngrabPointer",
2856 "GrabButton",
2857 "UngrabButton",
2858 "ChangeActivePointerGrab",
2859 "GrabKeyboard",
2860 "UngrabKeyboard",
2861 "GrabKey",
2862 "UngrabKey",
2863 "AllowEvents",
2864 "GrabServer",
2865 "UngrabServer",
2866 "QueryPointer",
2867 "GetMotionEvents",
2868 "TranslateCoords",
2869 "WarpPointer",
2870 "SetInputFocus",
2871 "GetInputFocus",
2872 "QueryKeymap",
2873 "OpenFont",
2874 "CloseFont",
2875 "QueryFont",
2876 "QueryTextExtents",
2877 "ListFonts",
2878 "ListFontsWithInfo",
2879 "SetFontPath",
2880 "GetFontPath",
2881 "CreatePixmap",
2882 "FreePixmap",
2883 "CreateGC",
2884 "ChangeGC",
2885 "CopyGC",
2886 "SetDashes",
2887 "SetClipRectangles",
2888 "FreeGC",
2889 "ClearArea",
2890 "CopyArea",
2891 "CopyPlane",
2892 "PolyPoint",
2893 "PolyLine",
2894 "PolySegment",
2895 "PolyRectangle",
2896 "PolyArc",
2897 "FillPoly",
2898 "PolyFillRectangle",
2899 "PolyFillArc",
2900 "PutImage",
2901 "GetImage",
2902 "PolyText",
2903 "PolyText",
2904 "ImageText",
2905 "ImageText",
2906 "CreateColormap",
2907 "FreeColormap",
2908 "CopyColormapAndFree",
2909 "InstallColormap",
2910 "UninstallColormap",
2911 "ListInstalledColormaps",
2912 "AllocColor",
2913 "AllocNamedColor",
2914 "AllocColorCells",
2915 "AllocColorPlanes",
2916 "FreeColors",
2917 "StoreColors",
2918 "StoreNamedColor",
2919 "QueryColors",
2920 "LookupColor",
2921 "CreateCursor",
2922 "CreateGlyphCursor",
2923 "FreeCursor",
2924 "RecolorCursor",
2925 "QueryBestSize",
2926 "QueryExtension",
2927 "ListExtensions",
2928 "ChangeKeyboardMapping",
2929 "GetKeyboardMapping",
2930 "ChangeKeyboardControl",
2931 "GetKeyboardControl",
2932 "Bell",
2933 "ChangePointerControl",
2934 "GetPointerControl",
2935 "SetScreenSaver",
2936 "GetScreenSaver",
2937 "ChangeHosts",
2938 "ListHosts",
2939 "SetAccessControl",
2940 "SetCloseDownMode",
2941 "KillClient",
2942 "RotateProperties",
2943 "ForceScreenSaver",
2944 "SetPointerMapping",
2945 "GetPointerMapping",
2946 "SetModifierMapping",
2947 "GetModifierMapping",
2948 "NoOperation"
2949};
2950
2951#define acceptable_x_error_p(type) ((type) == 94)
2952
2953x_handle_error_gracefully (event)
2954 XErrorEvent *event;
2955{
2956 char error_ptr[128];
2957 char *proto_ptr = x_proto_requests[event->request_code];
2958 char str[128];
2959
2960 XGetErrorText (x_current_display, event->error_code, error_ptr, 128);
2961 sprintf (str, "X Protocol Error: %s on request: %s", error_ptr, proto_ptr);
2962 TOTALLY_UNBLOCK_INPUT;
2963 error (str);
2964}
2965
2966#if 0
2967extern int x_selection_alloc_error;
2968extern int x_converting_selection;
2969#endif
2970
2971/* Handle X Errors. If the error is not traumatic,
2972 just call error (). Otherwise print a (hopefully) interesting
2973 message and quit.
2974
2975 The arg to Fkill_emacs is an exit status value
2976 and also prevents any questions. */
2977
2978x_error_handler (disp, event)
2979 Display *disp;
2980#ifdef HAVE_X11
2981 XErrorEvent *event;
2982
2983#define XlibDisplayIOError (1L << 0)
2984
2985#else
2986 struct _XErrorEvent *event;
2987#endif
2988{
2989 /* Here we use the standard X handlers. */
2990
2991 BLOCK_INPUT;
2992 if (event && event->type == 0) /* 0 is the XError Event type. */
2993 {
2994#if 0
2995#ifdef HAVE_X11
2996 if (event->request_code == BadAlloc && x_converting_selection)
2997 x_selection_alloc_error = 1;
2998 else
2999#endif
3000#endif
3001 if (acceptable_x_error_p (event->request_code))
3002 x_handle_error_gracefully (event);
3003 else
3004 _XDefaultError (disp, event);
3005 }
3006 else
3007 {
3008 disp->flags |= XlibDisplayIOError;
3009 _XDefaultIOError (disp);
3010 }
3011 UNBLOCK_INPUT;
3012
3013 if (_Xdebug)
3014 abort ();
3015 else
3016 Fkill_emacs (make_number (70));
3017}
3018
3019/* Initialize communication with the X window server. */
3020
3021#if 0
3022static unsigned int x_wire_count;
3023x_trace_wire ()
3024{
3025 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3026}
3027#endif
3028
3029
3030/* Set the font of the x-window specified by screen S
3031 to the font named NEWNAME. This is safe to use
3032 even before S has an actual x-window. */
3033
3034#ifdef HAVE_X11
3035
3036/* A table of all the fonts we have already loaded. */
3037static XFontStruct **x_font_table;
3038
3039/* The current capacity of x_font_table. */
3040static int x_font_table_size;
3041
3042/* The number of fonts actually stored in x_font_table.
3043 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3044 0 <= n_fonts <= x_font_table_size. */
3045static int n_fonts;
3046
3047x_new_font (s, fontname)
3048 struct screen *s;
3049 register char *fontname;
3050{
3051 XFontStruct *temp;
3052 int already_loaded;
3053 int n_matching_fonts;
3054 XFontStruct *font_info;
3055 char **font_names;
3056
3057 /* Get a list of all the fonts that match this name. Once we
3058 have a list of matching fonts, we compare them against the fonts
3059 we already have by comparing font ids. */
3060 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3061 1024, &n_matching_fonts,
3062 &font_info);
3063 /* If the server couldn't find any fonts whose named matched fontname,
3064 return an error code. */
3065 if (n_matching_fonts == 0)
3066 return 1;
3067
3068 /* See if we've already loaded this font. */
3069 {
3070 int i, j;
3071
3072 already_loaded = 0;
3073 for (i = 0; i < n_fonts; i++)
3074 for (j = 0; j < n_matching_fonts; j++)
3075 if (x_font_table[i]->fid == font_info[j].fid)
3076 {
3077 already_loaded = i;
3078 goto found_font;
3079 }
3080 }
3081 found_font:
3082
3083 /* If we have, just return it from the table. */
3084 if (already_loaded)
3085 {
3086 s->display.x->font = x_font_table[already_loaded];
3087 }
3088
3089 /* Otherwise, load the font and add it to the table. */
3090 else
3091 {
3092 XFontStruct *font;
3093
3094 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
3095 if (! font)
3096 return 1;
3097
3098 /* Do we need to create the table? */
3099 if (x_font_table_size == 0)
3100 {
3101 x_font_table_size = 16;
3102 x_font_table
3103 = (XFontStruct **) xmalloc (x_font_table_size
3104 * sizeof (x_font_table[0]));
3105 }
3106 /* Do we need to grow the table? */
3107 else if (n_fonts >= x_font_table_size)
3108 {
3109 x_font_table_size <<= 1;
3110 x_font_table
3111 = (XFontStruct **) xrealloc (x_font_table,
3112 (x_font_table_size
3113 * sizeof (x_font_table[0])));
3114 }
3115
3116 s->display.x->font = x_font_table[n_fonts++] = font;
3117 }
3118
3119 /* Free the information from XListFontsWithInfo. The data
3120 we actually retain comes from XLoadQueryFont. */
3121 XFreeFontInfo (font_names, font_info, n_matching_fonts);
3122
3123 /* Now make the screen display the given font. */
3124 if (s->display.x->window_desc != 0)
3125 {
3126 XSetFont (x_current_display, s->display.x->normal_gc,
3127 s->display.x->font->fid);
3128 XSetFont (x_current_display, s->display.x->reverse_gc,
3129 s->display.x->font->fid);
3130 XSetFont (x_current_display, s->display.x->cursor_gc,
3131 s->display.x->font->fid);
3132
3133 x_set_window_size (s, s->width, s->height);
3134 }
3135
3136 return 0;
3137}
3138#else
3139x_new_font (s, newname)
3140 struct screen *s;
3141 register char *newname;
3142{
3143 FONT_TYPE *temp;
3144 int mask;
3145
3146 temp = XGetFont (newname);
3147 if (temp == (FONT_TYPE *) 0)
3148 return 1;
3149
3150 if (s->display.x->font)
3151 XLoseFont (s->display.x->font);
3152
3153 s->display.x->font = temp;
3154
3155 if (s->display.x->window_desc != 0)
3156 x_set_window_size (s, s->width, s->height);
3157
3158 return 0;
3159}
3160#endif
3161
3162x_calc_absolute_position (s)
3163 struct screen *s;
3164{
3165#ifdef HAVE_X11
3166 if (s->display.x->left_pos < 0)
3167 s->display.x->left_pos
3168 = XINT (x_screen_width) - PIXEL_WIDTH (s) + s->display.x->left_pos;
3169
3170 if (s->display.x->top_pos < 0)
3171 s->display.x->top_pos
3172 = XINT (x_screen_height) - PIXEL_HEIGHT (s) + s->display.x->top_pos;
3173#else /* X10 */
3174 WINDOWINFO_TYPE parentinfo;
3175
3176 XGetWindowInfo (s->display.x->window_desc, &parentinfo);
3177
3178 if (s->display.x->left_pos < 0)
3179 s->display.x->left_pos = parentinfo.width + (s->display.x->left_pos + 1)
3180 - PIXEL_WIDTH (s) - 2 * s->display.x->internal_border_width;
3181
3182 if (s->display.x->top_pos < 0)
3183 s->display.x->top_pos = parentinfo.height + (s->display.x->top_pos + 1)
3184 - PIXEL_HEIGHT (s) - 2 * s->display.x->internal_border_width;
3185#endif /* X10 */
3186}
3187
3188x_set_offset (s, xoff, yoff)
3189 struct screen *s;
3190 register int xoff, yoff;
3191{
3192 s->display.x->top_pos = yoff;
3193 s->display.x->left_pos = xoff;
3194 x_calc_absolute_position (s);
3195
3196 BLOCK_INPUT;
3197 XMoveWindow (XDISPLAY s->display.x->window_desc,
3198 s->display.x->left_pos, s->display.x->top_pos);
3199#ifdef HAVE_X11
3200 x_wm_set_size_hint (s, 0);
3201#endif
3202 UNBLOCK_INPUT;
3203}
3204
3205/* Call this to change the size of screen S's x-window. */
3206
3207x_set_window_size (s, cols, rows)
3208 struct screen *s;
3209 register int cols, rows;
3210{
3211 int pixelwidth, pixelheight;
3212 int mask;
3213 int ibw = s->display.x->internal_border_width;
3214
3215 BLOCK_INPUT;
3216
3217 /* ??? Who DOES worry about minimum reasonable sizes? */
3218 pixelwidth = (cols * FONT_WIDTH (s->display.x->font) + 2 * ibw
3219 + s->display.x->v_scrollbar_width);
3220 pixelheight = (rows * FONT_HEIGHT (s->display.x->font) + 2 * ibw
3221 + s->display.x->h_scrollbar_height);
3222
3223#ifdef HAVE_X11
3224 x_wm_set_size_hint (s, 0);
3225#endif /* HAVE_X11 */
3226 XChangeWindowSize (s->display.x->window_desc, pixelwidth, pixelheight);
3227 XFlushQueue ();
3228 UNBLOCK_INPUT;
3229}
3230
3231#ifndef HAVE_X11
3232x_set_resize_hint (s)
3233 struct screen *s;
3234{
3235
3236 XSetResizeHint (s->display.x->window_desc, 2 * s->display.x->internal_border_width,
3237 2 * s->display.x->internal_border_width,
3238 FONT_WIDTH (s->display.x->font), FONT_HEIGHT (s->display.x->font));
3239}
3240#endif /* not HAVE_X11 */
3241
3242
3243x_set_mouse_position (s, x, y)
3244 struct screen *s;
3245 int x, y;
3246{
3247 int pix_x, pix_y;
3248
3249 x_raise_screen (s);
3250
3251 if (x < 0)
3252 pix_x = (SCREEN_WIDTH (s)
3253 * FONT_WIDTH (s->display.x->font)
3254 + 2 * s->display.x->internal_border_width
3255 + s->display.x->v_scrollbar_width) / 2;
3256 else
3257 pix_x = x * FONT_WIDTH (s->display.x->font) + 2; /* add 2 pixels to each
3258 dimension to move the
3259 mouse into the char
3260 cell */
3261
3262 if (y < 0)
3263 pix_y = (SCREEN_HEIGHT (s)
3264 * FONT_HEIGHT (s->display.x->font)
3265 + 2 * s->display.x->internal_border_width
3266 + s->display.x->h_scrollbar_height) / 2;
3267 else
3268 pix_y = y * FONT_HEIGHT (s->display.x->font) + 2;
3269
3270 BLOCK_INPUT;
3271 x_mouse_x = x;
3272 x_mouse_y = y;
3273
3274 XWarpMousePointer (s->display.x->window_desc, pix_x, pix_y);
3275 UNBLOCK_INPUT;
3276}
3277
3278#ifdef HAVE_X11
3279x_focus_on_screen (s)
3280 struct screen *s;
3281{
3282 x_raise_screen (s);
3283 XSetInputFocus (x_current_display, s->display.x->window_desc,
3284 RevertToPointerRoot, CurrentTime);
3285}
3286
3287x_unfocus_screen (s)
3288 struct screen *s;
3289{
3290 if (x_focus_screen == s)
3291 XSetInputFocus (x_current_display, PointerRoot,
3292 RevertToPointerRoot, CurrentTime);
3293}
3294
3295#endif
3296
3297/* Raise screen S. */
3298
3299x_raise_screen (s)
3300 struct screen *s;
3301{
3302 if (s->visible)
3303 {
3304 BLOCK_INPUT;
3305 XRaiseWindow (XDISPLAY s->display.x->window_desc);
3306 XFlushQueue ();
3307 UNBLOCK_INPUT;
3308 }
3309}
3310
3311/* Lower screen S. */
3312
3313x_lower_screen (s)
3314 struct screen *s;
3315{
3316 if (s->visible)
3317 {
3318 BLOCK_INPUT;
3319 XLowerWindow (XDISPLAY s->display.x->window_desc);
3320 XFlushQueue ();
3321 UNBLOCK_INPUT;
3322 }
3323}
3324
3325/* Change from withdrawn state to mapped state. */
3326
3327x_make_screen_visible (s)
3328 struct screen *s;
3329{
3330 int mask;
3331
3332 if (s->visible)
3333 {
3334 BLOCK_INPUT;
3335 XRaiseWindow (XDISPLAY s->display.x->window_desc);
3336 XFlushQueue ();
3337 UNBLOCK_INPUT;
3338 return;
3339 }
3340
3341 BLOCK_INPUT;
3342#ifdef HAVE_X11
3343
3344 if (! EQ (Vx_no_window_manager, Qt))
3345 x_wm_set_window_state (s, NormalState);
3346
3347 XMapWindow (XDISPLAY s->display.x->window_desc);
3348 if (s->display.x->v_scrollbar != 0 || s->display.x->h_scrollbar != 0)
3349 XMapSubwindows (x_current_display, s->display.x->window_desc);
3350
3351#else
3352 XMapWindow (XDISPLAY s->display.x->window_desc);
3353 if (s->display.x->icon_desc != 0)
3354 XUnmapWindow (s->display.x->icon_desc);
3355
3356 /* Handled by the MapNotify event for X11 */
3357 s->visible = 1;
3358 s->iconified = 0;
3359
3360 /* NOTE: this may cause problems for the first screen. */
3361 XTcursor_to (0, 0);
3362#endif /* not HAVE_X11 */
3363
3364 XRaiseWindow (XDISPLAY s->display.x->window_desc);
3365 XFlushQueue ();
3366 UNBLOCK_INPUT;
3367}
3368
3369/* Change from mapped state to withdrawn state. */
3370
3371x_make_screen_invisible (s)
3372 struct screen *s;
3373{
3374 int mask;
3375
3376 if (! s->visible)
3377 return;
3378
3379 BLOCK_INPUT;
3380#ifdef HAVE_X11
3381#if 0
3382 if (! EQ (Vx_no_window_manager, Qt))
3383 {
3384 XUnmapEvent unmap;
3385
3386 unmap.type = UnmapNotify;
3387 unmap.window = s->display.x->window_desc;
3388 unmap.event = DefaultRootWindow (x_current_display);
3389 unmap.from_configure = False;
3390 XSendEvent (x_current_display, DefaultRootWindow (x_current_display),
3391 False, SubstructureRedirectMask|SubstructureNotifyMask,
3392 &unmap);
3393 }
3394
3395 /* The new function below does the same as the above code, plus unmapping
3396 the window. Sending the event without actually unmapping can make
3397 the window manager start ignoring the window (i.e., no more title bar,
3398 icon manager stuff.) */
3399#endif
3400
3401 /* New function available with R4 */
3402 if (! XWithdrawWindow (x_current_display, s->display.x->window_desc,
3403 DefaultScreen (x_current_display)))
3404 {
3405 UNBLOCK_INPUT_RESIGNAL;
3406 error ("Can't notify window manager of iconification.");
3407 }
3408
3409#else
3410 XUnmapWindow (XDISPLAY s->display.x->window_desc);
3411
3412 s->visible = 0; /* Handled by the UnMap event for X11 */
3413 if (s->display.x->icon_desc != 0)
3414 XUnmapWindow (XDISPLAY s->display.x->icon_desc);
3415#endif /* not HAVE_X11 */
3416
3417 XFlushQueue ();
3418 UNBLOCK_INPUT;
3419}
3420
3421 /* Window manager communication. Created in Fx_open_connection. */
3422extern Atom Xatom_wm_change_state;
3423
3424/* Change window state from mapped to iconified. */
3425
3426x_iconify_screen (s)
3427 struct screen *s;
3428{
3429 int mask;
3430
3431 if (s->iconified)
3432 return;
3433
3434 BLOCK_INPUT;
3435
3436#ifdef HAVE_X11
3437 if (! EQ (Vx_no_window_manager, Qt))
3438 if (! XIconifyWindow (x_current_display, s->display.x->window_desc,
3439 DefaultScreen (x_current_display)))
3440 {
3441 UNBLOCK_INPUT_RESIGNAL;
3442 error ("Can't notify window manager of iconification.");
3443 }
3444
3445 s->iconified = 1;
3446
3447#if 0
3448 {
3449 XClientMessageEvent message;
3450
3451 message.window = s->display.x->window_desc;
3452 message.type = ClientMessage;
3453 message.message_type = Xatom_wm_change_state;
3454 message.format = 32;
3455 message.data.l[0] = IconicState;
3456
3457 if (! XSendEvent (x_current_display,
3458 DefaultRootWindow (x_current_display),
3459 False,
3460 SubstructureRedirectMask | SubstructureNotifyMask,
3461 &message))
3462 {
3463 UNBLOCK_INPUT_RESIGNAL;
3464 error ("Can't notify window manager of iconification.");
3465 }
3466 }
3467#endif
3468#else /* X10 */
3469 XUnmapWindow (XDISPLAY s->display.x->window_desc);
3470
3471 s->visible = 0; /* Handled in the UnMap event for X11. */
3472 if (s->display.x->icon_desc != 0)
3473 {
3474 XMapWindow (XDISPLAY s->display.x->icon_desc);
3475 refreshicon (s);
3476 }
3477#endif /* X10 */
3478
3479 XFlushQueue ();
3480 UNBLOCK_INPUT;
3481}
3482
3483/* Destroy the X window of screen S.
3484 DISPL is the former s->display (since s->display
3485 has already been nulled out). */
3486
3487x_destroy_window (s, displ)
3488 struct screen *s;
3489 union display displ;
3490{
3491 int mask;
3492
3493 BLOCK_INPUT;
3494 if (displ.x->icon_desc != 0)
3495 XDestroyWindow (XDISPLAY displ.x->icon_desc);
3496 XDestroyWindow (XDISPLAY displ.x->window_desc);
3497 XFlushQueue ();
3498 UNBLOCK_INPUT;
3499
3500 free (displ.x);
3501 if (s == x_focus_screen)
3502 x_focus_screen = 0;
3503}
3504
3505#ifndef HAVE_X11
3506
3507/* Manage event queues.
3508
3509 This code is only used by the X10 support.
3510
3511 We cannot leave events in the X queue and get them when we are ready
3512 because X does not provide a subroutine to get only a certain kind
3513 of event but not block if there are no queued events of that kind.
3514
3515 Therefore, we must examine events as they come in and copy events
3516 of certain kinds into our private queues.
3517
3518 All ExposeRegion events are put in x_expose_queue.
3519 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
3520
3521
3522/* Write the event *P_XREP into the event queue *QUEUE.
3523 If the queue is full, do nothing, but return nonzero. */
3524
3525int
3526enqueue_event (p_xrep, queue)
3527 register XEvent *p_xrep;
3528 register struct event_queue *queue;
3529{
3530 int newindex = queue->windex + 1;
3531 if (newindex == EVENT_BUFFER_SIZE)
3532 newindex = 0;
3533 if (newindex == queue->rindex)
3534 return -1;
3535 queue->xrep[queue->windex] = *p_xrep;
3536 queue->windex = newindex;
3537 return 0;
3538}
3539
3540/* Fetch the next event from queue *QUEUE and store it in *P_XREP.
3541 If *QUEUE is empty, do nothing and return 0. */
3542
3543int
3544dequeue_event (p_xrep, queue)
3545 register XEvent *p_xrep;
3546 register struct event_queue *queue;
3547{
3548 if (queue->windex == queue->rindex)
3549 return 0;
3550 *p_xrep = queue->xrep[queue->rindex++];
3551 if (queue->rindex == EVENT_BUFFER_SIZE)
3552 queue->rindex = 0;
3553 return 1;
3554}
3555
3556/* Return the number of events buffered in *QUEUE. */
3557
3558int
3559queue_event_count (queue)
3560 register struct event_queue *queue;
3561{
3562 int tem = queue->windex - queue->rindex;
3563 if (tem >= 0)
3564 return tem;
3565 return EVENT_BUFFER_SIZE + tem;
3566}
3567
3568/* Return nonzero if mouse input is pending. */
3569
3570int
3571mouse_event_pending_p ()
3572{
3573 return queue_event_count (&x_mouse_queue);
3574}
3575#endif
3576
3577#ifdef HAVE_X11
3578
3579x_wm_set_size_hint (s, prompting)
3580 struct screen *s;
3581 long prompting;
3582{
3583 XSizeHints size_hints;
3584 Window window = s->display.x->window_desc;
3585
3586 size_hints.flags = PResizeInc | PMinSize | PMaxSize;
3587
3588 flexlines = s->height;
3589
3590 size_hints.x = s->display.x->left_pos;
3591 size_hints.y = s->display.x->top_pos;
3592 size_hints.height = PIXEL_HEIGHT (s);
3593 size_hints.width = PIXEL_WIDTH (s);
3594 size_hints.width_inc = FONT_WIDTH (s->display.x->font);
3595 size_hints.height_inc = FONT_HEIGHT (s->display.x->font);
3596 size_hints.base_width = (2 * s->display.x->internal_border_width)
3597 + s->display.x->v_scrollbar_width;
3598 size_hints.base_height = (2 * s->display.x->internal_border_width)
3599 + s->display.x->h_scrollbar_height;
3600 size_hints.min_width = size_hints.base_width + size_hints.width_inc;
3601 size_hints.min_height = size_hints.base_height + size_hints.height_inc;
3602 size_hints.max_width = x_screen_width
3603 - ((2 * s->display.x->internal_border_width)
3604 + s->display.x->v_scrollbar_width);
3605 size_hints.max_height = x_screen_height
3606 - ((2 * s->display.x->internal_border_width)
3607 + s->display.x->h_scrollbar_height);
3608
3609 if (prompting)
3610 size_hints.flags |= prompting;
3611 else
3612 {
3613 XSizeHints hints; /* Sometimes I hate X Windows... */
3614
3615 XGetNormalHints (x_current_display, window, &hints);
3616 if (hints.flags & PSize)
3617 size_hints.flags |= PSize;
3618 if (hints.flags & PPosition)
3619 size_hints.flags |= PPosition;
3620 if (hints.flags & USPosition)
3621 size_hints.flags |= USPosition;
3622 if (hints.flags & USSize)
3623 size_hints.flags |= USSize;
3624 }
3625
3626#if 0 /* R3 */
3627 XSetNormalHints (x_current_display, window, &size_hints);
3628#endif
3629 XSetWMNormalHints (x_current_display, window, &size_hints);
3630}
3631
3632/* Used for IconicState or NormalState */
3633x_wm_set_window_state (s, state)
3634 struct screen *s;
3635 int state;
3636{
3637 XWMHints wm_hints;
3638 Window window = s->display.x->window_desc;
3639
3640 wm_hints.flags = StateHint;
3641 wm_hints.initial_state = state;
3642 XSetWMHints (x_current_display, window, &wm_hints);
3643}
3644
3645x_wm_set_icon_pixmap (s, icon_pixmap)
3646 struct screen *s;
3647 Pixmap icon_pixmap;
3648{
3649 XWMHints wm_hints;
3650 Window window = s->display.x->window_desc;
3651
3652 wm_hints.flags = IconPixmapHint;
3653 wm_hints.icon_pixmap = icon_pixmap;
3654 XSetWMHints (x_current_display, window, &wm_hints);
3655}
3656
3657x_wm_set_icon_position (s, icon_x, icon_y)
3658 struct screen *s;
3659 int icon_x, icon_y;
3660{
3661 XWMHints wm_hints;
3662 Window window = s->display.x->window_desc;
3663
3664 wm_hints.flags = IconPositionHint;
3665 wm_hints.icon_x = icon_x;
3666 wm_hints.icon_y = icon_y;
3667 XSetWMHints (x_current_display, window, &wm_hints);
3668}
3669
3670
3671static void
3672init_input_symbols ()
3673{
3674 Qmapped_screen = intern ("mapped-screen");
3675 Qunmapped_screen = intern ("unmapped-screen");
3676 Qexited_scrollbar = intern ("exited-scrollbar");
3677 Qexited_window = intern ("exited-window");
3678 Qredraw_screen = intern ("redraw-screen");
3679 Qmouse_moved = intern ("mouse-moved");
3680 Qmouse_click = intern ("mouse-click");
3681 Qscrollbar_click = intern ("scrollbar-click");
3682}
3683
3684void
3685x_term_init (display_name)
3686 char *display_name;
3687{
3688 Lisp_Object screen;
3689 char *defaultvalue;
3690#ifdef F_SETOWN
3691 extern int old_fcntl_owner;
3692#endif
3693
3694 x_current_display = XOpenDisplay (display_name);
3695 if (x_current_display == 0)
3696 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
3697 display_name);
3698
3699#ifdef HAVE_X11
3700 {
3701 int hostname_size = MAXHOSTNAMELEN + 1;
3702
3703 hostname = (char *) xmalloc (hostname_size);
3704
3705#if 0
3706 XSetAfterFunction (x_current_display, x_trace_wire);
3707#endif
3708
3709 invocation_name = (char *)
3710 XSTRING (Ffile_name_nondirectory (Fcar (Vcommand_line_args)))->data;
3711
3712 /* Try to get the host name; if the buffer is too short, try
3713 again. Apparently, the only indication gethostname gives of
3714 whether the buffer was large enough is the presence or absence
3715 of a '\0' in the string. Eech. */
3716 for (;;)
3717 {
3718 gethostname (hostname, hostname_size - 1);
3719 hostname[hostname_size - 1] = '\0';
3720
3721 /* Was the buffer large enough for gethostname to store the '\0'? */
3722 if (strlen (hostname) < hostname_size - 1)
3723 break;
3724
3725 hostname_size <<= 1;
3726 hostname = (char *) xrealloc (hostname, hostname_size);
3727 }
3728 id_name = (char *) xmalloc (strlen (invocation_name)
3729 + strlen (hostname)
3730 + 2);
3731 sprintf (id_name, "%s@%s", invocation_name, hostname);
3732 }
3733
3734 dup2 (ConnectionNumber (x_current_display), 0);
3735 close (ConnectionNumber (x_current_display));
3736 ConnectionNumber (x_current_display) = 0;
3737#endif /* HAVE_X11 */
3738
3739#ifdef F_SETOWN
3740 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
3741#ifdef F_SETOWN_SOCK_NEG
3742 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
3743#else
3744 fcntl (0, F_SETOWN, getpid ());
3745#endif /* F_SETOWN_SOCK_NEG */
3746#endif /* F_SETOWN */
3747
3748#ifdef SIGIO
3749 init_sigio ();
3750#endif
3751
3752 /* Must use interrupt input because we cannot otherwise
3753 arrange for C-g to be noticed immediately.
3754 We cannot connect it to SIGINT. */
3755 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3756
3757 expose_all_windows = 0;
3758
3759 clear_screen_hook = XTclear_screen;
3760 clear_end_of_line_hook = XTclear_end_of_line;
3761 ins_del_lines_hook = XTins_del_lines;
3762 change_line_highlight_hook = XTchange_line_highlight;
3763 insert_glyphs_hook = XTinsert_glyphs;
3764 write_glyphs_hook = XTwrite_glyphs;
3765 delete_glyphs_hook = XTdelete_glyphs;
3766 ring_bell_hook = XTring_bell;
3767 reset_terminal_modes_hook = XTreset_terminal_modes;
3768 set_terminal_modes_hook = XTset_terminal_modes;
3769 update_begin_hook = XTupdate_begin;
3770 update_end_hook = XTupdate_end;
3771 set_terminal_window_hook = XTset_terminal_window;
3772 read_socket_hook = XTread_socket;
3773 cursor_to_hook = XTcursor_to;
3774 reassert_line_highlight_hook = XTreassert_line_highlight;
3775 mouse_tracking_enable_hook = XTmouse_tracking_enable;
3776
3777 scroll_region_ok = 1; /* we'll scroll partial screens */
3778 char_ins_del_ok = 0; /* just as fast to write the line */
3779 line_ins_del_ok = 1; /* we'll just blt 'em */
3780 fast_clear_end_of_line = 1; /* X does this well */
3781 memory_below_screen = 0; /* we don't remember what scrolls
3782 off the bottom */
3783 baud_rate = 19200;
3784
3785 init_input_symbols ();
3786
3787 XHandleError (x_error_handler);
3788 XHandleIOError (x_error_handler);
3789
3790 /* Disable Window Change signals; they are handled by X events. */
3791#ifdef SIGWINCH
3792 signal (SIGWINCH, SIG_DFL);
3793#endif /* SIGWINCH */
3794
3795 signal (SIGPIPE, x_error_handler);
3796}
3797#endif /* HAVE_X11 */
3798#endif /* HAVE_X_WINDOWS */