1 /* Functions for the X window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996 Free Software Foundation.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Completely rewritten by Richard Stallman. */
23 /* Rewritten for X11 by Joseph Arceneaux */
28 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
36 #include "dispextern.h"
38 #include "blockinput.h"
44 /* On some systems, the character-composition stuff is broken in X11R5. */
45 #if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
46 #ifdef X11R5_INHIBIT_I18N
47 #define X_I18N_INHIBITED
52 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
53 #include "bitmaps/gray.xbm"
55 #include <X11/bitmaps/gray>
58 #include "[.bitmaps]gray.xbm"
62 #include <X11/Shell.h>
65 #include <X11/Xaw/Paned.h>
66 #include <X11/Xaw/Label.h>
67 #endif /* USE_MOTIF */
70 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
79 #include "../lwlib/lwlib.h"
81 /* Do the EDITRES protocol if running X11R5
82 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
83 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
85 extern void _XEditResCheckMessages ();
86 #endif /* R5 + Athena */
88 /* Unique id counter for widgets created by the Lucid Widget
90 extern LWLIB_ID widget_id_tick
;
93 /* This is part of a kludge--see lwlib/xlwmenu.c. */
94 extern XFontStruct
*xlwmenu_default_font
;
97 extern void free_frame_menubar ();
98 #endif /* USE_X_TOOLKIT */
100 #define min(a,b) ((a) < (b) ? (a) : (b))
101 #define max(a,b) ((a) > (b) ? (a) : (b))
104 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
106 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
109 /* The name we're using in resource queries. */
110 Lisp_Object Vx_resource_name
;
112 /* The background and shape of the mouse pointer, and shape when not
113 over text or in the modeline. */
114 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
115 /* The shape when over mouse-sensitive text. */
116 Lisp_Object Vx_sensitive_text_pointer_shape
;
118 /* Color of chars displayed in cursor box. */
119 Lisp_Object Vx_cursor_fore_pixel
;
121 /* Nonzero if using X. */
124 /* Non nil if no window manager is in use. */
125 Lisp_Object Vx_no_window_manager
;
127 /* Search path for bitmap files. */
128 Lisp_Object Vx_bitmap_file_path
;
130 /* Evaluate this expression to rebuild the section of syms_of_xfns
131 that initializes and staticpros the symbols declared below. Note
132 that Emacs 18 has a bug that keeps C-x C-e from being able to
133 evaluate this expression.
136 ;; Accumulate a list of the symbols we want to initialize from the
137 ;; declarations at the top of the file.
138 (goto-char (point-min))
139 (search-forward "/\*&&& symbols declared here &&&*\/\n")
141 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
143 (cons (buffer-substring (match-beginning 1) (match-end 1))
146 (setq symbol-list (nreverse symbol-list))
147 ;; Delete the section of syms_of_... where we initialize the symbols.
148 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
149 (let ((start (point)))
150 (while (looking-at "^ Q")
152 (kill-region start (point)))
153 ;; Write a new symbol initialization section.
155 (insert (format " %s = intern (\"" (car symbol-list)))
156 (let ((start (point)))
157 (insert (substring (car symbol-list) 1))
158 (subst-char-in-region start (point) ?_ ?-))
159 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
160 (setq symbol-list (cdr symbol-list)))))
164 /*&&& symbols declared here &&&*/
165 Lisp_Object Qauto_raise
;
166 Lisp_Object Qauto_lower
;
167 Lisp_Object Qbackground_color
;
169 Lisp_Object Qborder_color
;
170 Lisp_Object Qborder_width
;
172 Lisp_Object Qcursor_color
;
173 Lisp_Object Qcursor_type
;
174 Lisp_Object Qforeground_color
;
175 Lisp_Object Qgeometry
;
176 Lisp_Object Qicon_left
;
177 Lisp_Object Qicon_top
;
178 Lisp_Object Qicon_type
;
179 Lisp_Object Qicon_name
;
180 Lisp_Object Qinternal_border_width
;
182 Lisp_Object Qmouse_color
;
184 Lisp_Object Qparent_id
;
185 Lisp_Object Qscroll_bar_width
;
186 Lisp_Object Qsuppress_icon
;
188 Lisp_Object Qundefined_color
;
189 Lisp_Object Qvertical_scroll_bars
;
190 Lisp_Object Qvisibility
;
191 Lisp_Object Qwindow_id
;
192 Lisp_Object Qx_frame_parameter
;
193 Lisp_Object Qx_resource_name
;
194 Lisp_Object Quser_position
;
195 Lisp_Object Quser_size
;
196 Lisp_Object Qdisplay
;
198 /* The below are defined in frame.c. */
199 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
200 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
202 extern Lisp_Object Vwindow_system_version
;
205 /* Error if we are not connected to X. */
210 error ("X windows are not in use or not initialized");
213 /* Nonzero if we can use mouse menus.
214 You should not call this unless HAVE_MENUS is defined. */
222 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
223 and checking validity for X. */
226 check_x_frame (frame
)
235 CHECK_LIVE_FRAME (frame
, 0);
239 error ("Non-X frame used");
243 /* Let the user specify an X display with a frame.
244 nil stands for the selected frame--or, if that is not an X frame,
245 the first X display on the list. */
247 static struct x_display_info
*
248 check_x_display_info (frame
)
253 if (FRAME_X_P (selected_frame
))
254 return FRAME_X_DISPLAY_INFO (selected_frame
);
255 else if (x_display_list
!= 0)
256 return x_display_list
;
258 error ("X windows are not in use or not initialized");
260 else if (STRINGP (frame
))
261 return x_display_info_for_name (frame
);
266 CHECK_LIVE_FRAME (frame
, 0);
269 error ("Non-X frame used");
270 return FRAME_X_DISPLAY_INFO (f
);
274 /* Return the Emacs frame-object corresponding to an X window.
275 It could be the frame's main window or an icon window. */
277 /* This function can be called during GC, so use GC_xxx type test macros. */
280 x_window_to_frame (dpyinfo
, wdesc
)
281 struct x_display_info
*dpyinfo
;
284 Lisp_Object tail
, frame
;
287 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
289 frame
= XCONS (tail
)->car
;
290 if (!GC_FRAMEP (frame
))
293 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
296 if ((f
->output_data
.x
->edit_widget
297 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
298 || f
->output_data
.x
->icon_desc
== wdesc
)
300 #else /* not USE_X_TOOLKIT */
301 if (FRAME_X_WINDOW (f
) == wdesc
302 || f
->output_data
.x
->icon_desc
== wdesc
)
304 #endif /* not USE_X_TOOLKIT */
310 /* Like x_window_to_frame but also compares the window with the widget's
314 x_any_window_to_frame (dpyinfo
, wdesc
)
315 struct x_display_info
*dpyinfo
;
318 Lisp_Object tail
, frame
;
322 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
324 frame
= XCONS (tail
)->car
;
325 if (!GC_FRAMEP (frame
))
328 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
330 x
= f
->output_data
.x
;
331 /* This frame matches if the window is any of its widgets. */
332 if (wdesc
== XtWindow (x
->widget
)
333 || wdesc
== XtWindow (x
->column_widget
)
334 || wdesc
== XtWindow (x
->edit_widget
))
336 /* Match if the window is this frame's menubar. */
337 if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
343 /* Likewise, but exclude the menu bar widget. */
346 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
347 struct x_display_info
*dpyinfo
;
350 Lisp_Object tail
, frame
;
354 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
356 frame
= XCONS (tail
)->car
;
357 if (!GC_FRAMEP (frame
))
360 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
362 x
= f
->output_data
.x
;
363 /* This frame matches if the window is any of its widgets. */
364 if (wdesc
== XtWindow (x
->widget
)
365 || wdesc
== XtWindow (x
->column_widget
)
366 || wdesc
== XtWindow (x
->edit_widget
))
372 /* Likewise, but consider only the menu bar widget. */
375 x_menubar_window_to_frame (dpyinfo
, wdesc
)
376 struct x_display_info
*dpyinfo
;
379 Lisp_Object tail
, frame
;
383 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
385 frame
= XCONS (tail
)->car
;
386 if (!GC_FRAMEP (frame
))
389 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
391 x
= f
->output_data
.x
;
392 /* Match if the window is this frame's menubar. */
393 if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
399 /* Return the frame whose principal (outermost) window is WDESC.
400 If WDESC is some other (smaller) window, we return 0. */
403 x_top_window_to_frame (dpyinfo
, wdesc
)
404 struct x_display_info
*dpyinfo
;
407 Lisp_Object tail
, frame
;
411 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
413 frame
= XCONS (tail
)->car
;
414 if (!GC_FRAMEP (frame
))
417 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
419 x
= f
->output_data
.x
;
420 /* This frame matches if the window is its topmost widget. */
421 if (wdesc
== XtWindow (x
->widget
))
423 #if 0 /* I don't know why it did this,
424 but it seems logically wrong,
425 and it causes trouble for MapNotify events. */
426 /* Match if the window is this frame's menubar. */
427 if (x
->menubar_widget
428 && wdesc
== XtWindow (x
->menubar_widget
))
434 #endif /* USE_X_TOOLKIT */
438 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
439 id, which is just an int that this section returns. Bitmaps are
440 reference counted so they can be shared among frames.
442 Bitmap indices are guaranteed to be > 0, so a negative number can
443 be used to indicate no bitmap.
445 If you use x_create_bitmap_from_data, then you must keep track of
446 the bitmaps yourself. That is, creating a bitmap from the same
447 data more than once will not be caught. */
450 /* Functions to access the contents of a bitmap, given an id. */
453 x_bitmap_height (f
, id
)
457 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
461 x_bitmap_width (f
, id
)
465 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
469 x_bitmap_pixmap (f
, id
)
473 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
477 /* Allocate a new bitmap record. Returns index of new record. */
480 x_allocate_bitmap_record (f
)
483 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
486 if (dpyinfo
->bitmaps
== NULL
)
488 dpyinfo
->bitmaps_size
= 10;
490 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
491 dpyinfo
->bitmaps_last
= 1;
495 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
496 return ++dpyinfo
->bitmaps_last
;
498 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
499 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
502 dpyinfo
->bitmaps_size
*= 2;
504 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
505 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
506 return ++dpyinfo
->bitmaps_last
;
509 /* Add one reference to the reference count of the bitmap with id ID. */
512 x_reference_bitmap (f
, id
)
516 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
519 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
522 x_create_bitmap_from_data (f
, bits
, width
, height
)
525 unsigned int width
, height
;
527 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
531 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
532 bits
, width
, height
);
537 id
= x_allocate_bitmap_record (f
);
538 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
539 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
540 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
541 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
542 dpyinfo
->bitmaps
[id
- 1].height
= height
;
543 dpyinfo
->bitmaps
[id
- 1].width
= width
;
548 /* Create bitmap from file FILE for frame F. */
551 x_create_bitmap_from_file (f
, file
)
555 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
556 unsigned int width
, height
;
558 int xhot
, yhot
, result
, id
;
563 /* Look for an existing bitmap with the same name. */
564 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
566 if (dpyinfo
->bitmaps
[id
].refcount
567 && dpyinfo
->bitmaps
[id
].file
568 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
570 ++dpyinfo
->bitmaps
[id
].refcount
;
575 /* Search bitmap-file-path for the file, if appropriate. */
576 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
581 filename
= (char *) XSTRING (found
)->data
;
583 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
584 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
585 if (result
!= BitmapSuccess
)
588 id
= x_allocate_bitmap_record (f
);
589 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
590 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
591 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (XSTRING (file
)->size
+ 1);
592 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
593 dpyinfo
->bitmaps
[id
- 1].height
= height
;
594 dpyinfo
->bitmaps
[id
- 1].width
= width
;
595 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
600 /* Remove reference to bitmap with id number ID. */
603 x_destroy_bitmap (f
, id
)
607 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
611 --dpyinfo
->bitmaps
[id
- 1].refcount
;
612 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
615 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
616 if (dpyinfo
->bitmaps
[id
- 1].file
)
618 free (dpyinfo
->bitmaps
[id
- 1].file
);
619 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
626 /* Free all the bitmaps for the display specified by DPYINFO. */
629 x_destroy_all_bitmaps (dpyinfo
)
630 struct x_display_info
*dpyinfo
;
633 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
634 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
636 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
637 if (dpyinfo
->bitmaps
[i
].file
)
638 free (dpyinfo
->bitmaps
[i
].file
);
640 dpyinfo
->bitmaps_last
= 0;
643 /* Connect the frame-parameter names for X frames
644 to the ways of passing the parameter values to the window system.
646 The name of a parameter, as a Lisp symbol,
647 has an `x-frame-parameter' property which is an integer in Lisp
648 that is an index in this table. */
650 struct x_frame_parm_table
653 void (*setter
)( /* struct frame *frame, Lisp_Object val, oldval */ );
656 void x_set_foreground_color ();
657 void x_set_background_color ();
658 void x_set_mouse_color ();
659 void x_set_cursor_color ();
660 void x_set_border_color ();
661 void x_set_cursor_type ();
662 void x_set_icon_type ();
663 void x_set_icon_name ();
665 void x_set_border_width ();
666 void x_set_internal_border_width ();
667 void x_explicitly_set_name ();
668 void x_set_autoraise ();
669 void x_set_autolower ();
670 void x_set_vertical_scroll_bars ();
671 void x_set_visibility ();
672 void x_set_menu_bar_lines ();
673 void x_set_scroll_bar_width ();
675 void x_set_unsplittable ();
677 static struct x_frame_parm_table x_frame_parms
[] =
679 "auto-raise", x_set_autoraise
,
680 "auto-lower", x_set_autolower
,
681 "background-color", x_set_background_color
,
682 "border-color", x_set_border_color
,
683 "border-width", x_set_border_width
,
684 "cursor-color", x_set_cursor_color
,
685 "cursor-type", x_set_cursor_type
,
687 "foreground-color", x_set_foreground_color
,
688 "icon-name", x_set_icon_name
,
689 "icon-type", x_set_icon_type
,
690 "internal-border-width", x_set_internal_border_width
,
691 "menu-bar-lines", x_set_menu_bar_lines
,
692 "mouse-color", x_set_mouse_color
,
693 "name", x_explicitly_set_name
,
694 "scroll-bar-width", x_set_scroll_bar_width
,
695 "title", x_set_title
,
696 "unsplittable", x_set_unsplittable
,
697 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
698 "visibility", x_set_visibility
,
701 /* Attach the `x-frame-parameter' properties to
702 the Lisp symbol names of parameters relevant to X. */
704 init_x_parm_symbols ()
708 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
709 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
713 /* Change the parameters of FRAME as specified by ALIST.
714 If a parameter is not specially recognized, do nothing;
715 otherwise call the `x_set_...' function for that parameter. */
718 x_set_frame_parameters (f
, alist
)
724 /* If both of these parameters are present, it's more efficient to
725 set them both at once. So we wait until we've looked at the
726 entire list before we set them. */
730 Lisp_Object left
, top
;
732 /* Same with these. */
733 Lisp_Object icon_left
, icon_top
;
735 /* Record in these vectors all the parms specified. */
739 int left_no_change
= 0, top_no_change
= 0;
740 int icon_left_no_change
= 0, icon_top_no_change
= 0;
743 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
746 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
747 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
749 /* Extract parm names and values into those vectors. */
752 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
754 Lisp_Object elt
, prop
, val
;
757 parms
[i
] = Fcar (elt
);
758 values
[i
] = Fcdr (elt
);
762 top
= left
= Qunbound
;
763 icon_left
= icon_top
= Qunbound
;
765 /* Provide default values for HEIGHT and WIDTH. */
766 if (FRAME_NEW_WIDTH (f
))
767 width
= FRAME_NEW_WIDTH (f
);
769 width
= FRAME_WIDTH (f
);
771 if (FRAME_NEW_HEIGHT (f
))
772 height
= FRAME_NEW_HEIGHT (f
);
774 height
= FRAME_HEIGHT (f
);
776 /* Now process them in reverse of specified order. */
777 for (i
--; i
>= 0; i
--)
779 Lisp_Object prop
, val
;
784 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
785 width
= XFASTINT (val
);
786 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
787 height
= XFASTINT (val
);
788 else if (EQ (prop
, Qtop
))
790 else if (EQ (prop
, Qleft
))
792 else if (EQ (prop
, Qicon_top
))
794 else if (EQ (prop
, Qicon_left
))
798 register Lisp_Object param_index
, old_value
;
800 param_index
= Fget (prop
, Qx_frame_parameter
);
801 old_value
= get_frame_param (f
, prop
);
802 store_frame_param (f
, prop
, val
);
803 if (NATNUMP (param_index
)
804 && (XFASTINT (param_index
)
805 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
806 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
810 /* Don't die if just one of these was set. */
811 if (EQ (left
, Qunbound
))
814 if (f
->output_data
.x
->left_pos
< 0)
815 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
817 XSETINT (left
, f
->output_data
.x
->left_pos
);
819 if (EQ (top
, Qunbound
))
822 if (f
->output_data
.x
->top_pos
< 0)
823 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
825 XSETINT (top
, f
->output_data
.x
->top_pos
);
828 /* If one of the icon positions was not set, preserve or default it. */
829 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
831 icon_left_no_change
= 1;
832 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
833 if (NILP (icon_left
))
834 XSETINT (icon_left
, 0);
836 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
838 icon_top_no_change
= 1;
839 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
841 XSETINT (icon_top
, 0);
844 /* Don't set these parameters unless they've been explicitly
845 specified. The window might be mapped or resized while we're in
846 this function, and we don't want to override that unless the lisp
847 code has asked for it.
849 Don't set these parameters unless they actually differ from the
850 window's current parameters; the window may not actually exist
855 check_frame_size (f
, &height
, &width
);
857 XSETFRAME (frame
, f
);
859 if (width
!= FRAME_WIDTH (f
)
860 || height
!= FRAME_HEIGHT (f
)
861 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
862 Fset_frame_size (frame
, make_number (width
), make_number (height
));
864 if ((!NILP (left
) || !NILP (top
))
865 && ! (left_no_change
&& top_no_change
)
866 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
867 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
872 /* Record the signs. */
873 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
874 if (EQ (left
, Qminus
))
875 f
->output_data
.x
->size_hint_flags
|= XNegative
;
876 else if (INTEGERP (left
))
878 leftpos
= XINT (left
);
880 f
->output_data
.x
->size_hint_flags
|= XNegative
;
882 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qminus
)
883 && CONSP (XCONS (left
)->cdr
)
884 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
886 leftpos
= - XINT (XCONS (XCONS (left
)->cdr
)->car
);
887 f
->output_data
.x
->size_hint_flags
|= XNegative
;
889 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qplus
)
890 && CONSP (XCONS (left
)->cdr
)
891 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
893 leftpos
= XINT (XCONS (XCONS (left
)->cdr
)->car
);
896 if (EQ (top
, Qminus
))
897 f
->output_data
.x
->size_hint_flags
|= YNegative
;
898 else if (INTEGERP (top
))
902 f
->output_data
.x
->size_hint_flags
|= YNegative
;
904 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qminus
)
905 && CONSP (XCONS (top
)->cdr
)
906 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
908 toppos
= - XINT (XCONS (XCONS (top
)->cdr
)->car
);
909 f
->output_data
.x
->size_hint_flags
|= YNegative
;
911 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qplus
)
912 && CONSP (XCONS (top
)->cdr
)
913 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
915 toppos
= XINT (XCONS (XCONS (top
)->cdr
)->car
);
919 /* Store the numeric value of the position. */
920 f
->output_data
.x
->top_pos
= toppos
;
921 f
->output_data
.x
->left_pos
= leftpos
;
923 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
925 /* Actually set that position, and convert to absolute. */
926 x_set_offset (f
, leftpos
, toppos
, -1);
929 if ((!NILP (icon_left
) || !NILP (icon_top
))
930 && ! (icon_left_no_change
&& icon_top_no_change
))
931 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
935 /* Store the screen positions of frame F into XPTR and YPTR.
936 These are the positions of the containing window manager window,
937 not Emacs's own window. */
940 x_real_positions (f
, xptr
, yptr
)
947 /* This is pretty gross, but seems to be the easiest way out of
948 the problem that arises when restarting window-managers. */
951 Window outer
= XtWindow (f
->output_data
.x
->widget
);
953 Window outer
= f
->output_data
.x
->window_desc
;
955 Window tmp_root_window
;
956 Window
*tmp_children
;
961 x_catch_errors (FRAME_X_DISPLAY (f
));
963 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
964 &f
->output_data
.x
->parent_desc
,
965 &tmp_children
, &tmp_nchildren
);
966 XFree ((char *) tmp_children
);
970 /* Find the position of the outside upper-left corner of
971 the inner window, with respect to the outer window. */
972 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
974 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
976 /* From-window, to-window. */
978 XtWindow (f
->output_data
.x
->widget
),
980 f
->output_data
.x
->window_desc
,
982 f
->output_data
.x
->parent_desc
,
984 /* From-position, to-position. */
985 0, 0, &win_x
, &win_y
,
990 #if 0 /* The values seem to be right without this and wrong with. */
991 win_x
+= f
->output_data
.x
->border_width
;
992 win_y
+= f
->output_data
.x
->border_width
;
996 /* It is possible for the window returned by the XQueryNotify
997 to become invalid by the time we call XTranslateCoordinates.
998 That can happen when you restart some window managers.
999 If so, we get an error in XTranslateCoordinates.
1000 Detect that and try the whole thing over. */
1001 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1003 x_uncatch_errors (FRAME_X_DISPLAY (f
));
1007 x_uncatch_errors (FRAME_X_DISPLAY (f
));
1010 *xptr
= f
->output_data
.x
->left_pos
- win_x
;
1011 *yptr
= f
->output_data
.x
->top_pos
- win_y
;
1014 /* Insert a description of internally-recorded parameters of frame X
1015 into the parameter alist *ALISTPTR that is to be given to the user.
1016 Only parameters that are specific to the X window system
1017 and whose values are not correctly recorded in the frame's
1018 param_alist need to be considered here. */
1020 x_report_frame_params (f
, alistptr
)
1022 Lisp_Object
*alistptr
;
1027 /* Represent negative positions (off the top or left screen edge)
1028 in a way that Fmodify_frame_parameters will understand correctly. */
1029 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1030 if (f
->output_data
.x
->left_pos
>= 0)
1031 store_in_alist (alistptr
, Qleft
, tem
);
1033 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1035 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1036 if (f
->output_data
.x
->top_pos
>= 0)
1037 store_in_alist (alistptr
, Qtop
, tem
);
1039 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1041 store_in_alist (alistptr
, Qborder_width
,
1042 make_number (f
->output_data
.x
->border_width
));
1043 store_in_alist (alistptr
, Qinternal_border_width
,
1044 make_number (f
->output_data
.x
->internal_border_width
));
1045 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1046 store_in_alist (alistptr
, Qwindow_id
,
1047 build_string (buf
));
1048 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1049 FRAME_SAMPLE_VISIBILITY (f
);
1050 store_in_alist (alistptr
, Qvisibility
,
1051 (FRAME_VISIBLE_P (f
) ? Qt
1052 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1053 store_in_alist (alistptr
, Qdisplay
,
1054 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->car
);
1056 store_in_alist (alistptr
, Qparent_id
,
1057 (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
1058 ? Qnil
: f
->output_data
.x
->parent_desc
));
1062 /* Decide if color named COLOR is valid for the display associated with
1063 the selected frame; if so, return the rgb values in COLOR_DEF.
1064 If ALLOC is nonzero, allocate a new colormap cell. */
1067 defined_color (f
, color
, color_def
, alloc
)
1073 register int status
;
1074 Colormap screen_colormap
;
1075 Display
*display
= FRAME_X_DISPLAY (f
);
1078 screen_colormap
= DefaultColormap (display
, XDefaultScreen (display
));
1080 status
= XParseColor (display
, screen_colormap
, color
, color_def
);
1081 if (status
&& alloc
)
1083 status
= XAllocColor (display
, screen_colormap
, color_def
);
1086 /* If we got to this point, the colormap is full, so we're
1087 going to try and get the next closest color.
1088 The algorithm used is a least-squares matching, which is
1089 what X uses for closest color matching with StaticColor visuals. */
1094 long nearest_delta
, trial_delta
;
1097 no_cells
= XDisplayCells (display
, XDefaultScreen (display
));
1098 cells
= (XColor
*) alloca (sizeof (XColor
) * no_cells
);
1100 for (x
= 0; x
< no_cells
; x
++)
1103 XQueryColors (display
, screen_colormap
, cells
, no_cells
);
1105 /* I'm assuming CSE so I'm not going to condense this. */
1106 nearest_delta
= ((((color_def
->red
>> 8) - (cells
[0].red
>> 8))
1107 * ((color_def
->red
>> 8) - (cells
[0].red
>> 8)))
1109 (((color_def
->green
>> 8) - (cells
[0].green
>> 8))
1110 * ((color_def
->green
>> 8) - (cells
[0].green
>> 8)))
1112 (((color_def
->blue
>> 8) - (cells
[0].blue
>> 8))
1113 * ((color_def
->blue
>> 8) - (cells
[0].blue
>> 8))));
1114 for (x
= 1; x
< no_cells
; x
++)
1116 trial_delta
= ((((color_def
->red
>> 8) - (cells
[x
].red
>> 8))
1117 * ((color_def
->red
>> 8) - (cells
[x
].red
>> 8)))
1119 (((color_def
->green
>> 8) - (cells
[x
].green
>> 8))
1120 * ((color_def
->green
>> 8) - (cells
[x
].green
>> 8)))
1122 (((color_def
->blue
>> 8) - (cells
[x
].blue
>> 8))
1123 * ((color_def
->blue
>> 8) - (cells
[x
].blue
>> 8))));
1124 if (trial_delta
< nearest_delta
)
1127 temp
.red
= cells
[x
].red
;
1128 temp
.green
= cells
[x
].green
;
1129 temp
.blue
= cells
[x
].blue
;
1130 status
= XAllocColor (display
, screen_colormap
, &temp
);
1134 nearest_delta
= trial_delta
;
1138 color_def
->red
= cells
[nearest
].red
;
1139 color_def
->green
= cells
[nearest
].green
;
1140 color_def
->blue
= cells
[nearest
].blue
;
1141 status
= XAllocColor (display
, screen_colormap
, color_def
);
1152 /* Given a string ARG naming a color, compute a pixel value from it
1153 suitable for screen F.
1154 If F is not a color screen, return DEF (default) regardless of what
1158 x_decode_color (f
, arg
, def
)
1165 CHECK_STRING (arg
, 0);
1167 if (strcmp (XSTRING (arg
)->data
, "black") == 0)
1168 return BLACK_PIX_DEFAULT (f
);
1169 else if (strcmp (XSTRING (arg
)->data
, "white") == 0)
1170 return WHITE_PIX_DEFAULT (f
);
1172 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1175 /* defined_color is responsible for coping with failures
1176 by looking for a near-miss. */
1177 if (defined_color (f
, XSTRING (arg
)->data
, &cdef
, 1))
1180 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
1181 Fcons (arg
, Qnil
)));
1184 /* Functions called only from `x_set_frame_param'
1185 to set individual parameters.
1187 If FRAME_X_WINDOW (f) is 0,
1188 the frame is being created and its X-window does not exist yet.
1189 In that case, just record the parameter's new value
1190 in the standard place; do not attempt to change the window. */
1193 x_set_foreground_color (f
, arg
, oldval
)
1195 Lisp_Object arg
, oldval
;
1197 f
->output_data
.x
->foreground_pixel
1198 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1199 if (FRAME_X_WINDOW (f
) != 0)
1202 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1203 f
->output_data
.x
->foreground_pixel
);
1204 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1205 f
->output_data
.x
->foreground_pixel
);
1207 recompute_basic_faces (f
);
1208 if (FRAME_VISIBLE_P (f
))
1214 x_set_background_color (f
, arg
, oldval
)
1216 Lisp_Object arg
, oldval
;
1221 f
->output_data
.x
->background_pixel
1222 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1224 if (FRAME_X_WINDOW (f
) != 0)
1227 /* The main frame area. */
1228 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1229 f
->output_data
.x
->background_pixel
);
1230 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1231 f
->output_data
.x
->background_pixel
);
1232 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1233 f
->output_data
.x
->background_pixel
);
1234 XSetWindowBackground (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1235 f
->output_data
.x
->background_pixel
);
1238 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
);
1239 bar
= XSCROLL_BAR (bar
)->next
)
1240 XSetWindowBackground (FRAME_X_DISPLAY (f
),
1241 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
1242 f
->output_data
.x
->background_pixel
);
1246 recompute_basic_faces (f
);
1248 if (FRAME_VISIBLE_P (f
))
1254 x_set_mouse_color (f
, arg
, oldval
)
1256 Lisp_Object arg
, oldval
;
1258 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1261 if (!EQ (Qnil
, arg
))
1262 f
->output_data
.x
->mouse_pixel
1263 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1264 mask_color
= f
->output_data
.x
->background_pixel
;
1265 /* No invisible pointers. */
1266 if (mask_color
== f
->output_data
.x
->mouse_pixel
1267 && mask_color
== f
->output_data
.x
->background_pixel
)
1268 f
->output_data
.x
->mouse_pixel
= f
->output_data
.x
->foreground_pixel
;
1272 /* It's not okay to crash if the user selects a screwy cursor. */
1273 x_catch_errors (FRAME_X_DISPLAY (f
));
1275 if (!EQ (Qnil
, Vx_pointer_shape
))
1277 CHECK_NUMBER (Vx_pointer_shape
, 0);
1278 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XINT (Vx_pointer_shape
));
1281 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1282 x_check_errors (FRAME_X_DISPLAY (f
), "bad text pointer cursor: %s");
1284 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1286 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1287 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1288 XINT (Vx_nontext_pointer_shape
));
1291 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_left_ptr
);
1292 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1294 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1296 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1297 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1298 XINT (Vx_mode_pointer_shape
));
1301 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1302 x_check_errors (FRAME_X_DISPLAY (f
), "bad modeline pointer cursor: %s");
1304 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1306 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1308 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1309 XINT (Vx_sensitive_text_pointer_shape
));
1312 cross_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_crosshair
);
1314 /* Check and report errors with the above calls. */
1315 x_check_errors (FRAME_X_DISPLAY (f
), "can't set cursor shape: %s");
1316 x_uncatch_errors (FRAME_X_DISPLAY (f
));
1319 XColor fore_color
, back_color
;
1321 fore_color
.pixel
= f
->output_data
.x
->mouse_pixel
;
1322 back_color
.pixel
= mask_color
;
1323 XQueryColor (FRAME_X_DISPLAY (f
),
1324 DefaultColormap (FRAME_X_DISPLAY (f
),
1325 DefaultScreen (FRAME_X_DISPLAY (f
))),
1327 XQueryColor (FRAME_X_DISPLAY (f
),
1328 DefaultColormap (FRAME_X_DISPLAY (f
),
1329 DefaultScreen (FRAME_X_DISPLAY (f
))),
1331 XRecolorCursor (FRAME_X_DISPLAY (f
), cursor
,
1332 &fore_color
, &back_color
);
1333 XRecolorCursor (FRAME_X_DISPLAY (f
), nontext_cursor
,
1334 &fore_color
, &back_color
);
1335 XRecolorCursor (FRAME_X_DISPLAY (f
), mode_cursor
,
1336 &fore_color
, &back_color
);
1337 XRecolorCursor (FRAME_X_DISPLAY (f
), cross_cursor
,
1338 &fore_color
, &back_color
);
1341 if (FRAME_X_WINDOW (f
) != 0)
1343 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
1346 if (cursor
!= f
->output_data
.x
->text_cursor
&& f
->output_data
.x
->text_cursor
!= 0)
1347 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
1348 f
->output_data
.x
->text_cursor
= cursor
;
1350 if (nontext_cursor
!= f
->output_data
.x
->nontext_cursor
1351 && f
->output_data
.x
->nontext_cursor
!= 0)
1352 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
1353 f
->output_data
.x
->nontext_cursor
= nontext_cursor
;
1355 if (mode_cursor
!= f
->output_data
.x
->modeline_cursor
1356 && f
->output_data
.x
->modeline_cursor
!= 0)
1357 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
1358 f
->output_data
.x
->modeline_cursor
= mode_cursor
;
1359 if (cross_cursor
!= f
->output_data
.x
->cross_cursor
1360 && f
->output_data
.x
->cross_cursor
!= 0)
1361 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cross_cursor
);
1362 f
->output_data
.x
->cross_cursor
= cross_cursor
;
1364 XFlush (FRAME_X_DISPLAY (f
));
1369 x_set_cursor_color (f
, arg
, oldval
)
1371 Lisp_Object arg
, oldval
;
1373 unsigned long fore_pixel
;
1375 if (!EQ (Vx_cursor_fore_pixel
, Qnil
))
1376 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1377 WHITE_PIX_DEFAULT (f
));
1379 fore_pixel
= f
->output_data
.x
->background_pixel
;
1380 f
->output_data
.x
->cursor_pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1382 /* Make sure that the cursor color differs from the background color. */
1383 if (f
->output_data
.x
->cursor_pixel
== f
->output_data
.x
->background_pixel
)
1385 f
->output_data
.x
->cursor_pixel
= f
->output_data
.x
->mouse_pixel
;
1386 if (f
->output_data
.x
->cursor_pixel
== fore_pixel
)
1387 fore_pixel
= f
->output_data
.x
->background_pixel
;
1389 f
->output_data
.x
->cursor_foreground_pixel
= fore_pixel
;
1391 if (FRAME_X_WINDOW (f
) != 0)
1394 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1395 f
->output_data
.x
->cursor_pixel
);
1396 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1400 if (FRAME_VISIBLE_P (f
))
1402 x_update_cursor (f
, 0);
1403 x_update_cursor (f
, 1);
1408 /* Set the border-color of frame F to value described by ARG.
1409 ARG can be a string naming a color.
1410 The border-color is used for the border that is drawn by the X server.
1411 Note that this does not fully take effect if done before
1412 F has an x-window; it must be redone when the window is created.
1414 Note: this is done in two routines because of the way X10 works.
1416 Note: under X11, this is normally the province of the window manager,
1417 and so emacs' border colors may be overridden. */
1420 x_set_border_color (f
, arg
, oldval
)
1422 Lisp_Object arg
, oldval
;
1427 CHECK_STRING (arg
, 0);
1428 str
= XSTRING (arg
)->data
;
1430 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1432 x_set_border_pixel (f
, pix
);
1435 /* Set the border-color of frame F to pixel value PIX.
1436 Note that this does not fully take effect if done before
1437 F has an x-window. */
1439 x_set_border_pixel (f
, pix
)
1443 f
->output_data
.x
->border_pixel
= pix
;
1445 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1451 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1452 (unsigned long)pix
);
1455 if (FRAME_VISIBLE_P (f
))
1461 x_set_cursor_type (f
, arg
, oldval
)
1463 Lisp_Object arg
, oldval
;
1467 FRAME_DESIRED_CURSOR (f
) = bar_cursor
;
1468 f
->output_data
.x
->cursor_width
= 2;
1470 else if (CONSP (arg
) && EQ (XCONS (arg
)->car
, Qbar
)
1471 && INTEGERP (XCONS (arg
)->cdr
))
1473 FRAME_DESIRED_CURSOR (f
) = bar_cursor
;
1474 f
->output_data
.x
->cursor_width
= XINT (XCONS (arg
)->cdr
);
1477 /* Treat anything unknown as "box cursor".
1478 It was bad to signal an error; people have trouble fixing
1479 .Xdefaults with Emacs, when it has something bad in it. */
1480 FRAME_DESIRED_CURSOR (f
) = filled_box_cursor
;
1482 /* Make sure the cursor gets redrawn. This is overkill, but how
1483 often do people change cursor types? */
1484 update_mode_lines
++;
1488 x_set_icon_type (f
, arg
, oldval
)
1490 Lisp_Object arg
, oldval
;
1497 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1500 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1505 result
= x_text_icon (f
,
1506 (char *) XSTRING ((!NILP (f
->icon_name
)
1510 result
= x_bitmap_icon (f
, arg
);
1515 error ("No icon window available");
1518 XFlush (FRAME_X_DISPLAY (f
));
1522 /* Return non-nil if frame F wants a bitmap icon. */
1530 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1532 return XCONS (tem
)->cdr
;
1538 x_set_icon_name (f
, arg
, oldval
)
1540 Lisp_Object arg
, oldval
;
1547 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1550 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1555 if (f
->output_data
.x
->icon_bitmap
!= 0)
1560 result
= x_text_icon (f
,
1561 (char *) XSTRING ((!NILP (f
->icon_name
)
1570 error ("No icon window available");
1573 XFlush (FRAME_X_DISPLAY (f
));
1577 extern Lisp_Object
x_new_font ();
1580 x_set_font (f
, arg
, oldval
)
1582 Lisp_Object arg
, oldval
;
1586 CHECK_STRING (arg
, 1);
1589 result
= x_new_font (f
, XSTRING (arg
)->data
);
1592 if (EQ (result
, Qnil
))
1593 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1594 else if (EQ (result
, Qt
))
1595 error ("the characters of the given font have varying widths");
1596 else if (STRINGP (result
))
1598 recompute_basic_faces (f
);
1599 store_frame_param (f
, Qfont
, result
);
1606 x_set_border_width (f
, arg
, oldval
)
1608 Lisp_Object arg
, oldval
;
1610 CHECK_NUMBER (arg
, 0);
1612 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1615 if (FRAME_X_WINDOW (f
) != 0)
1616 error ("Cannot change the border width of a window");
1618 f
->output_data
.x
->border_width
= XINT (arg
);
1622 x_set_internal_border_width (f
, arg
, oldval
)
1624 Lisp_Object arg
, oldval
;
1627 int old
= f
->output_data
.x
->internal_border_width
;
1629 CHECK_NUMBER (arg
, 0);
1630 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1631 if (f
->output_data
.x
->internal_border_width
< 0)
1632 f
->output_data
.x
->internal_border_width
= 0;
1634 if (f
->output_data
.x
->internal_border_width
== old
)
1637 if (FRAME_X_WINDOW (f
) != 0)
1640 x_set_window_size (f
, 0, f
->width
, f
->height
);
1642 x_set_resize_hint (f
);
1644 XFlush (FRAME_X_DISPLAY (f
));
1646 SET_FRAME_GARBAGED (f
);
1651 x_set_visibility (f
, value
, oldval
)
1653 Lisp_Object value
, oldval
;
1656 XSETFRAME (frame
, f
);
1659 Fmake_frame_invisible (frame
, Qt
);
1660 else if (EQ (value
, Qicon
))
1661 Ficonify_frame (frame
);
1663 Fmake_frame_visible (frame
);
1667 x_set_menu_bar_lines_1 (window
, n
)
1671 struct window
*w
= XWINDOW (window
);
1673 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1674 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1676 /* Handle just the top child in a vertical split. */
1677 if (!NILP (w
->vchild
))
1678 x_set_menu_bar_lines_1 (w
->vchild
, n
);
1680 /* Adjust all children in a horizontal split. */
1681 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1683 w
= XWINDOW (window
);
1684 x_set_menu_bar_lines_1 (window
, n
);
1689 x_set_menu_bar_lines (f
, value
, oldval
)
1691 Lisp_Object value
, oldval
;
1694 int olines
= FRAME_MENU_BAR_LINES (f
);
1696 /* Right now, menu bars don't work properly in minibuf-only frames;
1697 most of the commands try to apply themselves to the minibuffer
1698 frame itslef, and get an error because you can't switch buffers
1699 in or split the minibuffer window. */
1700 if (FRAME_MINIBUF_ONLY_P (f
))
1703 if (INTEGERP (value
))
1704 nlines
= XINT (value
);
1708 #ifdef USE_X_TOOLKIT
1709 FRAME_MENU_BAR_LINES (f
) = 0;
1712 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1713 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
1714 /* Make sure next redisplay shows the menu bar. */
1715 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
1719 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1720 free_frame_menubar (f
);
1721 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1723 f
->output_data
.x
->menubar_widget
= 0;
1725 #else /* not USE_X_TOOLKIT */
1726 FRAME_MENU_BAR_LINES (f
) = nlines
;
1727 x_set_menu_bar_lines_1 (f
->root_window
, nlines
- olines
);
1728 #endif /* not USE_X_TOOLKIT */
1731 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1734 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1735 name; if NAME is a string, set F's name to NAME and set
1736 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1738 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1739 suggesting a new name, which lisp code should override; if
1740 F->explicit_name is set, ignore the new name; otherwise, set it. */
1743 x_set_name (f
, name
, explicit)
1748 /* Make sure that requests from lisp code override requests from
1749 Emacs redisplay code. */
1752 /* If we're switching from explicit to implicit, we had better
1753 update the mode lines and thereby update the title. */
1754 if (f
->explicit_name
&& NILP (name
))
1755 update_mode_lines
= 1;
1757 f
->explicit_name
= ! NILP (name
);
1759 else if (f
->explicit_name
)
1762 /* If NAME is nil, set the name to the x_id_name. */
1765 /* Check for no change needed in this very common case
1766 before we do any consing. */
1767 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
1768 XSTRING (f
->name
)->data
))
1770 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
1773 CHECK_STRING (name
, 0);
1775 /* Don't change the name if it's already NAME. */
1776 if (! NILP (Fstring_equal (name
, f
->name
)))
1781 /* For setting the frame title, the title parameter should override
1782 the name parameter. */
1783 if (! NILP (f
->title
))
1786 if (FRAME_X_WINDOW (f
))
1791 XTextProperty text
, icon
;
1792 Lisp_Object icon_name
;
1794 text
.value
= XSTRING (name
)->data
;
1795 text
.encoding
= XA_STRING
;
1797 text
.nitems
= XSTRING (name
)->size
;
1799 icon_name
= (!NILP (f
->icon_name
) ? f
->icon_name
: name
);
1801 icon
.value
= XSTRING (icon_name
)->data
;
1802 icon
.encoding
= XA_STRING
;
1804 icon
.nitems
= XSTRING (icon_name
)->size
;
1805 #ifdef USE_X_TOOLKIT
1806 XSetWMName (FRAME_X_DISPLAY (f
),
1807 XtWindow (f
->output_data
.x
->widget
), &text
);
1808 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
1810 #else /* not USE_X_TOOLKIT */
1811 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
1812 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
1813 #endif /* not USE_X_TOOLKIT */
1815 #else /* not HAVE_X11R4 */
1816 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1817 XSTRING (name
)->data
);
1818 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1819 XSTRING (name
)->data
);
1820 #endif /* not HAVE_X11R4 */
1825 /* This function should be called when the user's lisp code has
1826 specified a name for the frame; the name will override any set by the
1829 x_explicitly_set_name (f
, arg
, oldval
)
1831 Lisp_Object arg
, oldval
;
1833 x_set_name (f
, arg
, 1);
1836 /* This function should be called by Emacs redisplay code to set the
1837 name; names set this way will never override names set by the user's
1840 x_implicitly_set_name (f
, arg
, oldval
)
1842 Lisp_Object arg
, oldval
;
1844 x_set_name (f
, arg
, 0);
1847 /* Change the title of frame F to NAME.
1848 If NAME is nil, use the frame name as the title.
1850 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1851 name; if NAME is a string, set F's name to NAME and set
1852 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1854 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1855 suggesting a new name, which lisp code should override; if
1856 F->explicit_name is set, ignore the new name; otherwise, set it. */
1859 x_set_title (f
, name
)
1863 /* Don't change the title if it's already NAME. */
1864 if (EQ (name
, f
->title
))
1867 update_mode_lines
= 1;
1874 if (FRAME_X_WINDOW (f
))
1879 XTextProperty text
, icon
;
1880 Lisp_Object icon_name
;
1882 text
.value
= XSTRING (name
)->data
;
1883 text
.encoding
= XA_STRING
;
1885 text
.nitems
= XSTRING (name
)->size
;
1887 icon_name
= (!NILP (f
->icon_name
) ? f
->icon_name
: name
);
1889 icon
.value
= XSTRING (icon_name
)->data
;
1890 icon
.encoding
= XA_STRING
;
1892 icon
.nitems
= XSTRING (icon_name
)->size
;
1893 #ifdef USE_X_TOOLKIT
1894 XSetWMName (FRAME_X_DISPLAY (f
),
1895 XtWindow (f
->output_data
.x
->widget
), &text
);
1896 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
1898 #else /* not USE_X_TOOLKIT */
1899 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
1900 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
1901 #endif /* not USE_X_TOOLKIT */
1903 #else /* not HAVE_X11R4 */
1904 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1905 XSTRING (name
)->data
);
1906 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1907 XSTRING (name
)->data
);
1908 #endif /* not HAVE_X11R4 */
1914 x_set_autoraise (f
, arg
, oldval
)
1916 Lisp_Object arg
, oldval
;
1918 f
->auto_raise
= !EQ (Qnil
, arg
);
1922 x_set_autolower (f
, arg
, oldval
)
1924 Lisp_Object arg
, oldval
;
1926 f
->auto_lower
= !EQ (Qnil
, arg
);
1930 x_set_unsplittable (f
, arg
, oldval
)
1932 Lisp_Object arg
, oldval
;
1934 f
->no_split
= !NILP (arg
);
1938 x_set_vertical_scroll_bars (f
, arg
, oldval
)
1940 Lisp_Object arg
, oldval
;
1942 if (NILP (arg
) != ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1944 FRAME_HAS_VERTICAL_SCROLL_BARS (f
) = ! NILP (arg
);
1946 /* We set this parameter before creating the X window for the
1947 frame, so we can get the geometry right from the start.
1948 However, if the window hasn't been created yet, we shouldn't
1949 call x_set_window_size. */
1950 if (FRAME_X_WINDOW (f
))
1951 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
1956 x_set_scroll_bar_width (f
, arg
, oldval
)
1958 Lisp_Object arg
, oldval
;
1962 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
1963 FRAME_SCROLL_BAR_COLS (f
) = 2;
1964 if (FRAME_X_WINDOW (f
))
1965 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
1967 else if (INTEGERP (arg
) && XINT (arg
) > 0
1968 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
1970 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
1971 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
1972 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
1973 if (FRAME_X_WINDOW (f
))
1974 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
1978 /* Subroutines of creating an X frame. */
1980 /* Make sure that Vx_resource_name is set to a reasonable value.
1981 Fix it up, or set it to `emacs' if it is too hopeless. */
1984 validate_x_resource_name ()
1987 /* Number of valid characters in the resource name. */
1989 /* Number of invalid characters in the resource name. */
1994 if (STRINGP (Vx_resource_name
))
1996 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
1999 len
= XSTRING (Vx_resource_name
)->size
;
2001 /* Only letters, digits, - and _ are valid in resource names.
2002 Count the valid characters and count the invalid ones. */
2003 for (i
= 0; i
< len
; i
++)
2006 if (! ((c
>= 'a' && c
<= 'z')
2007 || (c
>= 'A' && c
<= 'Z')
2008 || (c
>= '0' && c
<= '9')
2009 || c
== '-' || c
== '_'))
2016 /* Not a string => completely invalid. */
2017 bad_count
= 5, good_count
= 0;
2019 /* If name is valid already, return. */
2023 /* If name is entirely invalid, or nearly so, use `emacs'. */
2025 || (good_count
== 1 && bad_count
> 0))
2027 Vx_resource_name
= build_string ("emacs");
2031 /* Name is partly valid. Copy it and replace the invalid characters
2032 with underscores. */
2034 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2036 for (i
= 0; i
< len
; i
++)
2038 int c
= XSTRING (new)->data
[i
];
2039 if (! ((c
>= 'a' && c
<= 'z')
2040 || (c
>= 'A' && c
<= 'Z')
2041 || (c
>= '0' && c
<= '9')
2042 || c
== '-' || c
== '_'))
2043 XSTRING (new)->data
[i
] = '_';
2048 extern char *x_get_string_resource ();
2050 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2051 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2052 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2053 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2054 the name specified by the `-name' or `-rn' command-line arguments.\n\
2056 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2057 class, respectively. You must specify both of them or neither.\n\
2058 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2059 and the class is `Emacs.CLASS.SUBCLASS'.")
2060 (attribute
, class, component
, subclass
)
2061 Lisp_Object attribute
, class, component
, subclass
;
2063 register char *value
;
2069 CHECK_STRING (attribute
, 0);
2070 CHECK_STRING (class, 0);
2072 if (!NILP (component
))
2073 CHECK_STRING (component
, 1);
2074 if (!NILP (subclass
))
2075 CHECK_STRING (subclass
, 2);
2076 if (NILP (component
) != NILP (subclass
))
2077 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2079 validate_x_resource_name ();
2081 /* Allocate space for the components, the dots which separate them,
2082 and the final '\0'. Make them big enough for the worst case. */
2083 name_key
= (char *) alloca (XSTRING (Vx_resource_name
)->size
2084 + (STRINGP (component
)
2085 ? XSTRING (component
)->size
: 0)
2086 + XSTRING (attribute
)->size
2089 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2090 + XSTRING (class)->size
2091 + (STRINGP (subclass
)
2092 ? XSTRING (subclass
)->size
: 0)
2095 /* Start with emacs.FRAMENAME for the name (the specific one)
2096 and with `Emacs' for the class key (the general one). */
2097 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2098 strcpy (class_key
, EMACS_CLASS
);
2100 strcat (class_key
, ".");
2101 strcat (class_key
, XSTRING (class)->data
);
2103 if (!NILP (component
))
2105 strcat (class_key
, ".");
2106 strcat (class_key
, XSTRING (subclass
)->data
);
2108 strcat (name_key
, ".");
2109 strcat (name_key
, XSTRING (component
)->data
);
2112 strcat (name_key
, ".");
2113 strcat (name_key
, XSTRING (attribute
)->data
);
2115 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2116 name_key
, class_key
);
2118 if (value
!= (char *) 0)
2119 return build_string (value
);
2124 /* Used when C code wants a resource value. */
2127 x_get_resource_string (attribute
, class)
2128 char *attribute
, *class;
2130 register char *value
;
2134 /* Allocate space for the components, the dots which separate them,
2135 and the final '\0'. */
2136 name_key
= (char *) alloca (XSTRING (Vinvocation_name
)->size
2137 + strlen (attribute
) + 2);
2138 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2139 + strlen (class) + 2);
2141 sprintf (name_key
, "%s.%s",
2142 XSTRING (Vinvocation_name
)->data
,
2144 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2146 return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame
)->xrdb
,
2147 name_key
, class_key
);
2150 /* Types we might convert a resource string into. */
2153 number
, boolean
, string
, symbol
2156 /* Return the value of parameter PARAM.
2158 First search ALIST, then Vdefault_frame_alist, then the X defaults
2159 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2161 Convert the resource to the type specified by desired_type.
2163 If no default is specified, return Qunbound. If you call
2164 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2165 and don't let it get stored in any Lisp-visible variables! */
2168 x_get_arg (alist
, param
, attribute
, class, type
)
2169 Lisp_Object alist
, param
;
2172 enum resource_types type
;
2174 register Lisp_Object tem
;
2176 tem
= Fassq (param
, alist
);
2178 tem
= Fassq (param
, Vdefault_frame_alist
);
2184 tem
= Fx_get_resource (build_string (attribute
),
2185 build_string (class),
2194 return make_number (atoi (XSTRING (tem
)->data
));
2197 tem
= Fdowncase (tem
);
2198 if (!strcmp (XSTRING (tem
)->data
, "on")
2199 || !strcmp (XSTRING (tem
)->data
, "true"))
2208 /* As a special case, we map the values `true' and `on'
2209 to Qt, and `false' and `off' to Qnil. */
2212 lower
= Fdowncase (tem
);
2213 if (!strcmp (XSTRING (lower
)->data
, "on")
2214 || !strcmp (XSTRING (lower
)->data
, "true"))
2216 else if (!strcmp (XSTRING (lower
)->data
, "off")
2217 || !strcmp (XSTRING (lower
)->data
, "false"))
2220 return Fintern (tem
, Qnil
);
2233 /* Like x_get_arg, but also record the value in f->param_alist. */
2236 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2238 Lisp_Object alist
, param
;
2241 enum resource_types type
;
2245 value
= x_get_arg (alist
, param
, attribute
, class, type
);
2247 store_frame_param (f
, param
, value
);
2252 /* Record in frame F the specified or default value according to ALIST
2253 of the parameter named PARAM (a Lisp symbol).
2254 If no value is specified for PARAM, look for an X default for XPROP
2255 on the frame named NAME.
2256 If that is not found either, use the value DEFLT. */
2259 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2266 enum resource_types type
;
2270 tem
= x_get_arg (alist
, prop
, xprop
, xclass
, type
);
2271 if (EQ (tem
, Qunbound
))
2273 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2277 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2278 "Parse an X-style geometry string STRING.\n\
2279 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2280 The properties returned may include `top', `left', `height', and `width'.\n\
2281 The value of `left' or `top' may be an integer,\n\
2282 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2283 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2288 unsigned int width
, height
;
2291 CHECK_STRING (string
, 0);
2293 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2294 &x
, &y
, &width
, &height
);
2297 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
2298 error ("Must specify both x and y position, or neither");
2302 if (geometry
& XValue
)
2304 Lisp_Object element
;
2306 if (x
>= 0 && (geometry
& XNegative
))
2307 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2308 else if (x
< 0 && ! (geometry
& XNegative
))
2309 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2311 element
= Fcons (Qleft
, make_number (x
));
2312 result
= Fcons (element
, result
);
2315 if (geometry
& YValue
)
2317 Lisp_Object element
;
2319 if (y
>= 0 && (geometry
& YNegative
))
2320 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2321 else if (y
< 0 && ! (geometry
& YNegative
))
2322 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2324 element
= Fcons (Qtop
, make_number (y
));
2325 result
= Fcons (element
, result
);
2328 if (geometry
& WidthValue
)
2329 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2330 if (geometry
& HeightValue
)
2331 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2336 /* Calculate the desired size and position of this window,
2337 and return the flags saying which aspects were specified.
2339 This function does not make the coordinates positive. */
2341 #define DEFAULT_ROWS 40
2342 #define DEFAULT_COLS 80
2345 x_figure_window_size (f
, parms
)
2349 register Lisp_Object tem0
, tem1
, tem2
;
2350 int height
, width
, left
, top
;
2351 register int geometry
;
2352 long window_prompting
= 0;
2354 /* Default values if we fall through.
2355 Actually, if that happens we should get
2356 window manager prompting. */
2357 f
->width
= DEFAULT_COLS
;
2358 f
->height
= DEFAULT_ROWS
;
2359 /* Window managers expect that if program-specified
2360 positions are not (0,0), they're intentional, not defaults. */
2361 f
->output_data
.x
->top_pos
= 0;
2362 f
->output_data
.x
->left_pos
= 0;
2364 tem0
= x_get_arg (parms
, Qheight
, 0, 0, number
);
2365 tem1
= x_get_arg (parms
, Qwidth
, 0, 0, number
);
2366 tem2
= x_get_arg (parms
, Quser_size
, 0, 0, number
);
2367 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2369 if (!EQ (tem0
, Qunbound
))
2371 CHECK_NUMBER (tem0
, 0);
2372 f
->height
= XINT (tem0
);
2374 if (!EQ (tem1
, Qunbound
))
2376 CHECK_NUMBER (tem1
, 0);
2377 f
->width
= XINT (tem1
);
2379 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
2380 window_prompting
|= USSize
;
2382 window_prompting
|= PSize
;
2385 f
->output_data
.x
->vertical_scroll_bar_extra
2386 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2388 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2389 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2390 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2391 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
2392 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
2394 tem0
= x_get_arg (parms
, Qtop
, 0, 0, number
);
2395 tem1
= x_get_arg (parms
, Qleft
, 0, 0, number
);
2396 tem2
= x_get_arg (parms
, Quser_position
, 0, 0, number
);
2397 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2399 if (EQ (tem0
, Qminus
))
2401 f
->output_data
.x
->top_pos
= 0;
2402 window_prompting
|= YNegative
;
2404 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qminus
)
2405 && CONSP (XCONS (tem0
)->cdr
)
2406 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2408 f
->output_data
.x
->top_pos
= - XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2409 window_prompting
|= YNegative
;
2411 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qplus
)
2412 && CONSP (XCONS (tem0
)->cdr
)
2413 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2415 f
->output_data
.x
->top_pos
= XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2417 else if (EQ (tem0
, Qunbound
))
2418 f
->output_data
.x
->top_pos
= 0;
2421 CHECK_NUMBER (tem0
, 0);
2422 f
->output_data
.x
->top_pos
= XINT (tem0
);
2423 if (f
->output_data
.x
->top_pos
< 0)
2424 window_prompting
|= YNegative
;
2427 if (EQ (tem1
, Qminus
))
2429 f
->output_data
.x
->left_pos
= 0;
2430 window_prompting
|= XNegative
;
2432 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qminus
)
2433 && CONSP (XCONS (tem1
)->cdr
)
2434 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2436 f
->output_data
.x
->left_pos
= - XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2437 window_prompting
|= XNegative
;
2439 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qplus
)
2440 && CONSP (XCONS (tem1
)->cdr
)
2441 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2443 f
->output_data
.x
->left_pos
= XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2445 else if (EQ (tem1
, Qunbound
))
2446 f
->output_data
.x
->left_pos
= 0;
2449 CHECK_NUMBER (tem1
, 0);
2450 f
->output_data
.x
->left_pos
= XINT (tem1
);
2451 if (f
->output_data
.x
->left_pos
< 0)
2452 window_prompting
|= XNegative
;
2455 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
2456 window_prompting
|= USPosition
;
2458 window_prompting
|= PPosition
;
2461 return window_prompting
;
2464 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2467 XSetWMProtocols (dpy
, w
, protocols
, count
)
2474 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
2475 if (prop
== None
) return False
;
2476 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
2477 (unsigned char *) protocols
, count
);
2480 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2482 #ifdef USE_X_TOOLKIT
2484 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2485 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2486 already be present because of the toolkit (Motif adds some of them,
2487 for example, but Xt doesn't). */
2490 hack_wm_protocols (f
, widget
)
2494 Display
*dpy
= XtDisplay (widget
);
2495 Window w
= XtWindow (widget
);
2496 int need_delete
= 1;
2502 Atom type
, *atoms
= 0;
2504 unsigned long nitems
= 0;
2505 unsigned long bytes_after
;
2507 if ((XGetWindowProperty (dpy
, w
,
2508 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
2509 (long)0, (long)100, False
, XA_ATOM
,
2510 &type
, &format
, &nitems
, &bytes_after
,
2511 (unsigned char **) &atoms
)
2513 && format
== 32 && type
== XA_ATOM
)
2517 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
2519 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
2521 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
2524 if (atoms
) XFree ((char *) atoms
);
2530 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
2532 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
2534 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
2536 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
2537 XA_ATOM
, 32, PropModeAppend
,
2538 (unsigned char *) props
, count
);
2544 #ifdef USE_X_TOOLKIT
2546 /* Create and set up the X widget for frame F. */
2549 x_window (f
, window_prompting
, minibuffer_only
)
2551 long window_prompting
;
2552 int minibuffer_only
;
2554 XClassHint class_hints
;
2555 XSetWindowAttributes attributes
;
2556 unsigned long attribute_mask
;
2558 Widget shell_widget
;
2560 Widget frame_widget
;
2566 /* Use the resource name as the top-level widget name
2567 for looking up resources. Make a non-Lisp copy
2568 for the window manager, so GC relocation won't bother it.
2570 Elsewhere we specify the window name for the window manager. */
2573 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
2574 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
2575 strcpy (f
->namebuf
, str
);
2579 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
2580 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
2581 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
2582 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
2583 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
2584 applicationShellWidgetClass
,
2585 FRAME_X_DISPLAY (f
), al
, ac
);
2587 f
->output_data
.x
->widget
= shell_widget
;
2588 /* maybe_set_screen_title_format (shell_widget); */
2590 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
2591 (widget_value
*) NULL
,
2592 shell_widget
, False
,
2595 (lw_callback
) NULL
);
2597 f
->output_data
.x
->column_widget
= pane_widget
;
2599 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2600 the emacs screen when changing menubar. This reduces flickering. */
2603 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
2604 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
2605 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
2606 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
2607 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
2608 frame_widget
= XtCreateWidget (f
->namebuf
,
2610 pane_widget
, al
, ac
);
2612 f
->output_data
.x
->edit_widget
= frame_widget
;
2614 XtManageChild (frame_widget
);
2616 /* Do some needed geometry management. */
2619 char *tem
, shell_position
[32];
2622 int extra_borders
= 0;
2624 = (f
->output_data
.x
->menubar_widget
2625 ? (f
->output_data
.x
->menubar_widget
->core
.height
2626 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
2628 extern char *lwlib_toolkit_type
;
2630 #if 0 /* Experimentally, we now get the right results
2631 for -geometry -0-0 without this. 24 Aug 96, rms. */
2632 if (FRAME_EXTERNAL_MENU_BAR (f
))
2635 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
2636 menubar_size
+= ibw
;
2640 f
->output_data
.x
->menubar_height
= menubar_size
;
2642 /* Motif seems to need this amount added to the sizes
2643 specified for the shell widget. The Athena/Lucid widgets don't.
2644 Both conclusions reached experimentally. -- rms. */
2645 if (!strcmp (lwlib_toolkit_type
, "motif"))
2646 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
2647 &extra_borders
, NULL
);
2649 /* Convert our geometry parameters into a geometry string
2651 Note that we do not specify here whether the position
2652 is a user-specified or program-specified one.
2653 We pass that information later, in x_wm_set_size_hints. */
2655 int left
= f
->output_data
.x
->left_pos
;
2656 int xneg
= window_prompting
& XNegative
;
2657 int top
= f
->output_data
.x
->top_pos
;
2658 int yneg
= window_prompting
& YNegative
;
2664 if (window_prompting
& USPosition
)
2665 sprintf (shell_position
, "=%dx%d%c%d%c%d",
2666 PIXEL_WIDTH (f
) + extra_borders
,
2667 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
2668 (xneg
? '-' : '+'), left
,
2669 (yneg
? '-' : '+'), top
);
2671 sprintf (shell_position
, "=%dx%d",
2672 PIXEL_WIDTH (f
) + extra_borders
,
2673 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
2676 len
= strlen (shell_position
) + 1;
2677 tem
= (char *) xmalloc (len
);
2678 strncpy (tem
, shell_position
, len
);
2679 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
2680 XtSetValues (shell_widget
, al
, ac
);
2683 XtManageChild (pane_widget
);
2684 XtRealizeWidget (shell_widget
);
2686 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
2688 validate_x_resource_name ();
2690 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
2691 class_hints
.res_class
= EMACS_CLASS
;
2692 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
2695 #ifndef X_I18N_INHIBITED
2700 xim
= XOpenIM (FRAME_X_DISPLAY (f
), NULL
, NULL
, NULL
);
2704 xic
= XCreateIC (xim
,
2705 XNInputStyle
, XIMPreeditNothing
| XIMStatusNothing
,
2706 XNClientWindow
, FRAME_X_WINDOW(f
),
2707 XNFocusWindow
, FRAME_X_WINDOW(f
),
2716 FRAME_XIM (f
) = xim
;
2717 FRAME_XIC (f
) = xic
;
2719 #else /* X_I18N_INHIBITED */
2722 #endif /* X_I18N_INHIBITED */
2723 #endif /* HAVE_X_I18N */
2725 f
->output_data
.x
->wm_hints
.input
= True
;
2726 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
2727 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2728 &f
->output_data
.x
->wm_hints
);
2730 hack_wm_protocols (f
, shell_widget
);
2733 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
2736 /* Do a stupid property change to force the server to generate a
2737 propertyNotify event so that the event_stream server timestamp will
2738 be initialized to something relevant to the time we created the window.
2740 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
2741 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
2742 XA_ATOM
, 32, PropModeAppend
,
2743 (unsigned char*) NULL
, 0);
2745 /* Make all the standard events reach the Emacs frame. */
2746 attributes
.event_mask
= STANDARD_EVENT_SET
;
2747 attribute_mask
= CWEventMask
;
2748 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
2749 attribute_mask
, &attributes
);
2751 XtMapWidget (frame_widget
);
2753 /* x_set_name normally ignores requests to set the name if the
2754 requested name is the same as the current name. This is the one
2755 place where that assumption isn't correct; f->name is set, but
2756 the X server hasn't been told. */
2759 int explicit = f
->explicit_name
;
2761 f
->explicit_name
= 0;
2764 x_set_name (f
, name
, explicit);
2767 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2768 f
->output_data
.x
->text_cursor
);
2772 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
2773 initialize_frame_menubar (f
);
2774 lw_set_main_areas (pane_widget
, f
->output_data
.x
->menubar_widget
, frame_widget
);
2776 if (FRAME_X_WINDOW (f
) == 0)
2777 error ("Unable to create window");
2780 #else /* not USE_X_TOOLKIT */
2782 /* Create and set up the X window for frame F. */
2788 XClassHint class_hints
;
2789 XSetWindowAttributes attributes
;
2790 unsigned long attribute_mask
;
2792 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
2793 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
2794 attributes
.bit_gravity
= StaticGravity
;
2795 attributes
.backing_store
= NotUseful
;
2796 attributes
.save_under
= True
;
2797 attributes
.event_mask
= STANDARD_EVENT_SET
;
2798 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
2800 | CWBackingStore
| CWSaveUnder
2806 = XCreateWindow (FRAME_X_DISPLAY (f
),
2807 f
->output_data
.x
->parent_desc
,
2808 f
->output_data
.x
->left_pos
,
2809 f
->output_data
.x
->top_pos
,
2810 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
2811 f
->output_data
.x
->border_width
,
2812 CopyFromParent
, /* depth */
2813 InputOutput
, /* class */
2814 FRAME_X_DISPLAY_INFO (f
)->visual
,
2815 attribute_mask
, &attributes
);
2817 #ifndef X_I18N_INHIBITED
2822 xim
= XOpenIM (FRAME_X_DISPLAY(f
), NULL
, NULL
, NULL
);
2826 xic
= XCreateIC (xim
,
2827 XNInputStyle
, XIMPreeditNothing
| XIMStatusNothing
,
2828 XNClientWindow
, FRAME_X_WINDOW(f
),
2829 XNFocusWindow
, FRAME_X_WINDOW(f
),
2839 FRAME_XIM (f
) = xim
;
2840 FRAME_XIC (f
) = xic
;
2842 #else /* X_I18N_INHIBITED */
2845 #endif /* X_I18N_INHIBITED */
2846 #endif /* HAVE_X_I18N */
2848 validate_x_resource_name ();
2850 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
2851 class_hints
.res_class
= EMACS_CLASS
;
2852 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
2854 /* The menubar is part of the ordinary display;
2855 it does not count in addition to the height of the window. */
2856 f
->output_data
.x
->menubar_height
= 0;
2858 /* This indicates that we use the "Passive Input" input model.
2859 Unless we do this, we don't get the Focus{In,Out} events that we
2860 need to draw the cursor correctly. Accursed bureaucrats.
2861 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
2863 f
->output_data
.x
->wm_hints
.input
= True
;
2864 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
2865 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2866 &f
->output_data
.x
->wm_hints
);
2867 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
2869 /* Request "save yourself" and "delete window" commands from wm. */
2872 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
2873 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
2874 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
2877 /* x_set_name normally ignores requests to set the name if the
2878 requested name is the same as the current name. This is the one
2879 place where that assumption isn't correct; f->name is set, but
2880 the X server hasn't been told. */
2883 int explicit = f
->explicit_name
;
2885 f
->explicit_name
= 0;
2888 x_set_name (f
, name
, explicit);
2891 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2892 f
->output_data
.x
->text_cursor
);
2896 if (FRAME_X_WINDOW (f
) == 0)
2897 error ("Unable to create window");
2900 #endif /* not USE_X_TOOLKIT */
2902 /* Handle the icon stuff for this window. Perhaps later we might
2903 want an x_set_icon_position which can be called interactively as
2911 Lisp_Object icon_x
, icon_y
;
2913 /* Set the position of the icon. Note that twm groups all
2914 icons in an icon window. */
2915 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, number
);
2916 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, number
);
2917 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
2919 CHECK_NUMBER (icon_x
, 0);
2920 CHECK_NUMBER (icon_y
, 0);
2922 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
2923 error ("Both left and top icon corners of icon must be specified");
2927 if (! EQ (icon_x
, Qunbound
))
2928 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
2930 /* Start up iconic or window? */
2931 x_wm_set_window_state
2932 (f
, (EQ (x_get_arg (parms
, Qvisibility
, 0, 0, symbol
), Qicon
)
2936 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
2943 /* Make the GC's needed for this window, setting the
2944 background, border and mouse colors; also create the
2945 mouse cursor and the gray border tile. */
2947 static char cursor_bits
[] =
2949 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2950 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2951 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2952 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2959 XGCValues gc_values
;
2965 /* Create the GC's of this frame.
2966 Note that many default values are used. */
2969 gc_values
.font
= f
->output_data
.x
->font
->fid
;
2970 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
2971 gc_values
.background
= f
->output_data
.x
->background_pixel
;
2972 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
2973 f
->output_data
.x
->normal_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
2975 GCLineWidth
| GCFont
2976 | GCForeground
| GCBackground
,
2979 /* Reverse video style. */
2980 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
2981 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
2982 f
->output_data
.x
->reverse_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
2984 GCFont
| GCForeground
| GCBackground
2988 /* Cursor has cursor-color background, background-color foreground. */
2989 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
2990 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
2991 gc_values
.fill_style
= FillOpaqueStippled
;
2993 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
2994 FRAME_X_DISPLAY_INFO (f
)->root_window
,
2995 cursor_bits
, 16, 16);
2996 f
->output_data
.x
->cursor_gc
2997 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2998 (GCFont
| GCForeground
| GCBackground
2999 | GCFillStyle
| GCStipple
| GCLineWidth
),
3002 /* Create the gray border tile used when the pointer is not in
3003 the frame. Since this depends on the frame's pixel values,
3004 this must be done on a per-frame basis. */
3005 f
->output_data
.x
->border_tile
3006 = (XCreatePixmapFromBitmapData
3007 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
3008 gray_bits
, gray_width
, gray_height
,
3009 f
->output_data
.x
->foreground_pixel
,
3010 f
->output_data
.x
->background_pixel
,
3011 DefaultDepth (FRAME_X_DISPLAY (f
),
3012 XScreenNumberOfScreen (FRAME_X_SCREEN (f
)))));
3017 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
3019 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3020 Returns an Emacs frame object.\n\
3021 ALIST is an alist of frame parameters.\n\
3022 If the parameters specify that the frame should not have a minibuffer,\n\
3023 and do not specify a specific minibuffer window to use,\n\
3024 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3025 be shared by the new frame.\n\
3027 This function is an internal primitive--use `make-frame' instead.")
3032 Lisp_Object frame
, tem
;
3034 int minibuffer_only
= 0;
3035 long window_prompting
= 0;
3037 int count
= specpdl_ptr
- specpdl
;
3038 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3039 Lisp_Object display
;
3040 struct x_display_info
*dpyinfo
;
3046 /* Use this general default value to start with
3047 until we know if this frame has a specified name. */
3048 Vx_resource_name
= Vinvocation_name
;
3050 display
= x_get_arg (parms
, Qdisplay
, 0, 0, string
);
3051 if (EQ (display
, Qunbound
))
3053 dpyinfo
= check_x_display_info (display
);
3055 kb
= dpyinfo
->kboard
;
3057 kb
= &the_only_kboard
;
3060 name
= x_get_arg (parms
, Qname
, "name", "Name", string
);
3062 && ! EQ (name
, Qunbound
)
3064 error ("Invalid frame name--not a string or nil");
3067 Vx_resource_name
= name
;
3069 /* See if parent window is specified. */
3070 parent
= x_get_arg (parms
, Qparent_id
, NULL
, NULL
, number
);
3071 if (EQ (parent
, Qunbound
))
3073 if (! NILP (parent
))
3074 CHECK_NUMBER (parent
, 0);
3076 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3077 /* No need to protect DISPLAY because that's not used after passing
3078 it to make_frame_without_minibuffer. */
3080 GCPRO4 (parms
, parent
, name
, frame
);
3081 tem
= x_get_arg (parms
, Qminibuffer
, 0, 0, symbol
);
3082 if (EQ (tem
, Qnone
) || NILP (tem
))
3083 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
3084 else if (EQ (tem
, Qonly
))
3086 f
= make_minibuffer_frame ();
3087 minibuffer_only
= 1;
3089 else if (WINDOWP (tem
))
3090 f
= make_frame_without_minibuffer (tem
, kb
, display
);
3094 XSETFRAME (frame
, f
);
3096 /* Note that X Windows does support scroll bars. */
3097 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
3099 f
->output_method
= output_x_window
;
3100 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
3101 bzero (f
->output_data
.x
, sizeof (struct x_output
));
3102 f
->output_data
.x
->icon_bitmap
= -1;
3105 = x_get_arg (parms
, Qicon_name
, "iconName", "Title", string
);
3106 if (! STRINGP (f
->icon_name
))
3107 f
->icon_name
= Qnil
;
3109 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
3111 FRAME_KBOARD (f
) = kb
;
3114 /* Specify the parent under which to make this X window. */
3118 f
->output_data
.x
->parent_desc
= parent
;
3119 f
->output_data
.x
->explicit_parent
= 1;
3123 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
3124 f
->output_data
.x
->explicit_parent
= 0;
3127 /* Note that the frame has no physical cursor right now. */
3128 f
->phys_cursor_x
= -1;
3130 /* Set the name; the functions to which we pass f expect the name to
3132 if (EQ (name
, Qunbound
) || NILP (name
))
3134 f
->name
= build_string (dpyinfo
->x_id_name
);
3135 f
->explicit_name
= 0;
3140 f
->explicit_name
= 1;
3141 /* use the frame's title when getting resources for this frame. */
3142 specbind (Qx_resource_name
, name
);
3145 /* Extract the window parameters from the supplied values
3146 that are needed to determine window geometry. */
3150 font
= x_get_arg (parms
, Qfont
, "font", "Font", string
);
3152 /* First, try whatever font the caller has specified. */
3154 font
= x_new_font (f
, XSTRING (font
)->data
);
3155 /* Try out a font which we hope has bold and italic variations. */
3156 if (!STRINGP (font
))
3157 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3158 if (! STRINGP (font
))
3159 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3160 if (! STRINGP (font
))
3161 /* This was formerly the first thing tried, but it finds too many fonts
3162 and takes too long. */
3163 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3164 /* If those didn't work, look for something which will at least work. */
3165 if (! STRINGP (font
))
3166 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3168 if (! STRINGP (font
))
3169 font
= build_string ("fixed");
3171 x_default_parameter (f
, parms
, Qfont
, font
,
3172 "font", "Font", string
);
3176 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3177 whereby it fails to get any font. */
3178 xlwmenu_default_font
= f
->output_data
.x
->font
;
3181 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
3182 "borderwidth", "BorderWidth", number
);
3183 /* This defaults to 2 in order to match xterm. We recognize either
3184 internalBorderWidth or internalBorder (which is what xterm calls
3186 if (NILP (Fassq (Qinternal_border_width
, parms
)))
3190 value
= x_get_arg (parms
, Qinternal_border_width
,
3191 "internalBorder", "BorderWidth", number
);
3192 if (! EQ (value
, Qunbound
))
3193 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
3196 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (2),
3197 "internalBorderWidth", "BorderWidth", number
);
3198 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qt
,
3199 "verticalScrollBars", "ScrollBars", boolean
);
3201 /* Also do the stuff which must be set before the window exists. */
3202 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
3203 "foreground", "Foreground", string
);
3204 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
3205 "background", "Background", string
);
3206 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
3207 "pointerColor", "Foreground", string
);
3208 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
3209 "cursorColor", "Foreground", string
);
3210 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
3211 "borderColor", "BorderColor", string
);
3213 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
3214 "menuBar", "MenuBar", number
);
3215 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
3216 "scrollBarWidth", "ScrollBarWidth", number
);
3217 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
3218 "bufferPredicate", "BufferPredicate", symbol
);
3219 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
3220 "title", "Title", string
);
3222 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
3223 window_prompting
= x_figure_window_size (f
, parms
);
3225 if (window_prompting
& XNegative
)
3227 if (window_prompting
& YNegative
)
3228 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
3230 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
3234 if (window_prompting
& YNegative
)
3235 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
3237 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3240 f
->output_data
.x
->size_hint_flags
= window_prompting
;
3242 #ifdef USE_X_TOOLKIT
3243 x_window (f
, window_prompting
, minibuffer_only
);
3249 init_frame_faces (f
);
3251 /* We need to do this after creating the X window, so that the
3252 icon-creation functions can say whose icon they're describing. */
3253 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
3254 "bitmapIcon", "BitmapIcon", symbol
);
3256 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
3257 "autoRaise", "AutoRaiseLower", boolean
);
3258 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
3259 "autoLower", "AutoRaiseLower", boolean
);
3260 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
3261 "cursorType", "CursorType", symbol
);
3263 /* Dimensions, especially f->height, must be done via change_frame_size.
3264 Change will not be effected unless different from the current
3268 f
->height
= f
->width
= 0;
3269 change_frame_size (f
, height
, width
, 1, 0);
3271 /* Tell the server what size and position, etc, we want,
3272 and how badly we want them. */
3274 x_wm_set_size_hint (f
, window_prompting
, 0);
3277 tem
= x_get_arg (parms
, Qunsplittable
, 0, 0, boolean
);
3278 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
3282 /* It is now ok to make the frame official
3283 even if we get an error below.
3284 And the frame needs to be on Vframe_list
3285 or making it visible won't work. */
3286 Vframe_list
= Fcons (frame
, Vframe_list
);
3288 /* Now that the frame is official, it counts as a reference to
3290 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
3292 /* Make the window appear on the frame and enable display,
3293 unless the caller says not to. However, with explicit parent,
3294 Emacs cannot control visibility, so don't try. */
3295 if (! f
->output_data
.x
->explicit_parent
)
3297 Lisp_Object visibility
;
3299 visibility
= x_get_arg (parms
, Qvisibility
, 0, 0, symbol
);
3300 if (EQ (visibility
, Qunbound
))
3303 if (EQ (visibility
, Qicon
))
3304 x_iconify_frame (f
);
3305 else if (! NILP (visibility
))
3306 x_make_frame_visible (f
);
3308 /* Must have been Qnil. */
3312 return unbind_to (count
, frame
);
3315 /* FRAME is used only to get a handle on the X display. We don't pass the
3316 display info directly because we're called from frame.c, which doesn't
3317 know about that structure. */
3320 x_get_focus_frame (frame
)
3321 struct frame
*frame
;
3323 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
3325 if (! dpyinfo
->x_focus_frame
)
3328 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
3332 DEFUN ("x-list-fonts", Fx_list_fonts
, Sx_list_fonts
, 1, 4, 0,
3333 "Return a list of the names of available fonts matching PATTERN.\n\
3334 If optional arguments FACE and FRAME are specified, return only fonts\n\
3335 the same size as FACE on FRAME.\n\
3337 PATTERN is a string, perhaps with wildcard characters;\n\
3338 the * character matches any substring, and\n\
3339 the ? character matches any single character.\n\
3340 PATTERN is case-insensitive.\n\
3341 FACE is a face name--a symbol.\n\
3343 The return value is a list of strings, suitable as arguments to\n\
3346 Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
3347 even if they match PATTERN and FACE.\n\
3349 The optional fourth argument MAXIMUM sets a limit on how many\n\
3350 fonts to match. The first MAXIMUM fonts are reported.")
3351 (pattern
, face
, frame
, maximum
)
3352 Lisp_Object pattern
, face
, frame
, maximum
;
3356 #ifndef BROKEN_XLISTFONTSWITHINFO
3359 XFontStruct
*size_ref
;
3366 CHECK_STRING (pattern
, 0);
3368 CHECK_SYMBOL (face
, 1);
3374 CHECK_NATNUM (maximum
, 0);
3375 maxnames
= XINT (maximum
);
3378 f
= check_x_frame (frame
);
3380 /* Determine the width standard for comparison with the fonts we find. */
3388 /* Don't die if we get called with a terminal frame. */
3389 if (! FRAME_X_P (f
))
3390 error ("Non-X frame used in `x-list-fonts'");
3392 face_id
= face_name_id_number (f
, face
);
3394 if (face_id
< 0 || face_id
>= FRAME_N_PARAM_FACES (f
)
3395 || FRAME_PARAM_FACES (f
) [face_id
] == 0)
3396 size_ref
= f
->output_data
.x
->font
;
3399 size_ref
= FRAME_PARAM_FACES (f
) [face_id
]->font
;
3400 if (size_ref
== (XFontStruct
*) (~0))
3401 size_ref
= f
->output_data
.x
->font
;
3405 /* See if we cached the result for this particular query. */
3406 key
= Fcons (pattern
, maximum
);
3408 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
3410 /* We have info in the cache for this PATTERN. */
3413 Lisp_Object tem
, newlist
;
3415 /* We have info about this pattern. */
3416 list
= XCONS (list
)->cdr
;
3423 /* Filter the cached info and return just the fonts that match FACE. */
3425 for (tem
= list
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
3427 XFontStruct
*thisinfo
;
3429 x_catch_errors (FRAME_X_DISPLAY (f
));
3431 thisinfo
= XLoadQueryFont (FRAME_X_DISPLAY (f
),
3432 XSTRING (XCONS (tem
)->car
)->data
);
3434 x_check_errors (FRAME_X_DISPLAY (f
), "XLoadQueryFont failure: %s");
3435 x_uncatch_errors (FRAME_X_DISPLAY (f
));
3437 if (thisinfo
&& same_size_fonts (thisinfo
, size_ref
))
3438 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
3441 XFreeFont (FRAME_X_DISPLAY (f
), thisinfo
);
3451 x_catch_errors (FRAME_X_DISPLAY (f
));
3453 /* Solaris 2.3 has a bug in XListFontsWithInfo. */
3454 #ifndef BROKEN_XLISTFONTSWITHINFO
3456 names
= XListFontsWithInfo (FRAME_X_DISPLAY (f
),
3457 XSTRING (pattern
)->data
,
3459 &num_fonts
, /* count_return */
3460 &info
); /* info_return */
3463 names
= XListFonts (FRAME_X_DISPLAY (f
),
3464 XSTRING (pattern
)->data
,
3466 &num_fonts
); /* count_return */
3468 x_check_errors (FRAME_X_DISPLAY (f
), "XListFonts failure: %s");
3469 x_uncatch_errors (FRAME_X_DISPLAY (f
));
3478 Lisp_Object full_list
;
3480 /* Make a list of all the fonts we got back.
3481 Store that in the font cache for the display. */
3483 for (i
= 0; i
< num_fonts
; i
++)
3484 full_list
= Fcons (build_string (names
[i
]), full_list
);
3485 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
3486 = Fcons (Fcons (key
, full_list
),
3487 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
3489 /* Make a list of the fonts that have the right width. */
3491 for (i
= 0; i
< num_fonts
; i
++)
3499 #ifdef BROKEN_XLISTFONTSWITHINFO
3500 XFontStruct
*thisinfo
;
3504 x_catch_errors (FRAME_X_DISPLAY (f
));
3505 thisinfo
= XLoadQueryFont (FRAME_X_DISPLAY (f
), names
[i
]);
3506 x_check_errors (FRAME_X_DISPLAY (f
),
3507 "XLoadQueryFont failure: %s");
3508 x_uncatch_errors (FRAME_X_DISPLAY (f
));
3512 keeper
= thisinfo
&& same_size_fonts (thisinfo
, size_ref
);
3514 if (thisinfo
&& ! keeper
)
3515 XFreeFont (FRAME_X_DISPLAY (f
), thisinfo
);
3517 XFreeFontInfo (NULL
, thisinfo
, 1);
3520 keeper
= same_size_fonts (&info
[i
], size_ref
);
3524 list
= Fcons (build_string (names
[i
]), list
);
3526 list
= Fnreverse (list
);
3529 #ifndef BROKEN_XLISTFONTSWITHINFO
3531 XFreeFontInfo (names
, info
, num_fonts
);
3534 XFreeFontNames (names
);
3542 DEFUN ("x-color-defined-p", Fx_color_defined_p
, Sx_color_defined_p
, 1, 2, 0,
3543 "Return non-nil if color COLOR is supported on frame FRAME.\n\
3544 If FRAME is omitted or nil, use the selected frame.")
3546 Lisp_Object color
, frame
;
3549 FRAME_PTR f
= check_x_frame (frame
);
3551 CHECK_STRING (color
, 1);
3553 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
3559 DEFUN ("x-color-values", Fx_color_values
, Sx_color_values
, 1, 2, 0,
3560 "Return a description of the color named COLOR on frame FRAME.\n\
3561 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
3562 These values appear to range from 0 to 65280 or 65535, depending\n\
3563 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
3564 If FRAME is omitted or nil, use the selected frame.")
3566 Lisp_Object color
, frame
;
3569 FRAME_PTR f
= check_x_frame (frame
);
3571 CHECK_STRING (color
, 1);
3573 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
3577 rgb
[0] = make_number (foo
.red
);
3578 rgb
[1] = make_number (foo
.green
);
3579 rgb
[2] = make_number (foo
.blue
);
3580 return Flist (3, rgb
);
3586 DEFUN ("x-display-color-p", Fx_display_color_p
, Sx_display_color_p
, 0, 1, 0,
3587 "Return t if the X display supports color.\n\
3588 The optional argument DISPLAY specifies which display to ask about.\n\
3589 DISPLAY should be either a frame or a display name (a string).\n\
3590 If omitted or nil, that stands for the selected frame's display.")
3592 Lisp_Object display
;
3594 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3596 if (dpyinfo
->n_planes
<= 2)
3599 switch (dpyinfo
->visual
->class)
3612 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
3614 "Return t if the X display supports shades of gray.\n\
3615 Note that color displays do support shades of gray.\n\
3616 The optional argument DISPLAY specifies which display to ask about.\n\
3617 DISPLAY should be either a frame or a display name (a string).\n\
3618 If omitted or nil, that stands for the selected frame's display.")
3620 Lisp_Object display
;
3622 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3624 if (dpyinfo
->n_planes
<= 1)
3627 switch (dpyinfo
->visual
->class)
3642 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
3644 "Returns the width in pixels of the X display DISPLAY.\n\
3645 The optional argument DISPLAY specifies which display to ask about.\n\
3646 DISPLAY should be either a frame or a display name (a string).\n\
3647 If omitted or nil, that stands for the selected frame's display.")
3649 Lisp_Object display
;
3651 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3653 return make_number (dpyinfo
->width
);
3656 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
3657 Sx_display_pixel_height
, 0, 1, 0,
3658 "Returns the height in pixels of the X display DISPLAY.\n\
3659 The optional argument DISPLAY specifies which display to ask about.\n\
3660 DISPLAY should be either a frame or a display name (a string).\n\
3661 If omitted or nil, that stands for the selected frame's display.")
3663 Lisp_Object display
;
3665 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3667 return make_number (dpyinfo
->height
);
3670 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
3672 "Returns the number of bitplanes of the X display DISPLAY.\n\
3673 The optional argument DISPLAY specifies which display to ask about.\n\
3674 DISPLAY should be either a frame or a display name (a string).\n\
3675 If omitted or nil, that stands for the selected frame's display.")
3677 Lisp_Object display
;
3679 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3681 return make_number (dpyinfo
->n_planes
);
3684 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
3686 "Returns the number of color cells of the X display DISPLAY.\n\
3687 The optional argument DISPLAY specifies which display to ask about.\n\
3688 DISPLAY should be either a frame or a display name (a string).\n\
3689 If omitted or nil, that stands for the selected frame's display.")
3691 Lisp_Object display
;
3693 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3695 return make_number (DisplayCells (dpyinfo
->display
,
3696 XScreenNumberOfScreen (dpyinfo
->screen
)));
3699 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
3700 Sx_server_max_request_size
,
3702 "Returns the maximum request size of the X server of display DISPLAY.\n\
3703 The optional argument DISPLAY specifies which display to ask about.\n\
3704 DISPLAY should be either a frame or a display name (a string).\n\
3705 If omitted or nil, that stands for the selected frame's display.")
3707 Lisp_Object display
;
3709 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3711 return make_number (MAXREQUEST (dpyinfo
->display
));
3714 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
3715 "Returns the vendor ID string of the X server of display DISPLAY.\n\
3716 The optional argument DISPLAY specifies which display to ask about.\n\
3717 DISPLAY should be either a frame or a display name (a string).\n\
3718 If omitted or nil, that stands for the selected frame's display.")
3720 Lisp_Object display
;
3722 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3723 char *vendor
= ServerVendor (dpyinfo
->display
);
3725 if (! vendor
) vendor
= "";
3726 return build_string (vendor
);
3729 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
3730 "Returns the version numbers of the X server of display DISPLAY.\n\
3731 The value is a list of three integers: the major and minor\n\
3732 version numbers of the X Protocol in use, and the vendor-specific release\n\
3733 number. See also the function `x-server-vendor'.\n\n\
3734 The optional argument DISPLAY specifies which display to ask about.\n\
3735 DISPLAY should be either a frame or a display name (a string).\n\
3736 If omitted or nil, that stands for the selected frame's display.")
3738 Lisp_Object display
;
3740 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3741 Display
*dpy
= dpyinfo
->display
;
3743 return Fcons (make_number (ProtocolVersion (dpy
)),
3744 Fcons (make_number (ProtocolRevision (dpy
)),
3745 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
3748 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
3749 "Returns the number of screens on the X server of display DISPLAY.\n\
3750 The optional argument DISPLAY specifies which display to ask about.\n\
3751 DISPLAY should be either a frame or a display name (a string).\n\
3752 If omitted or nil, that stands for the selected frame's display.")
3754 Lisp_Object display
;
3756 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3758 return make_number (ScreenCount (dpyinfo
->display
));
3761 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
3762 "Returns the height in millimeters of the X display DISPLAY.\n\
3763 The optional argument DISPLAY specifies which display to ask about.\n\
3764 DISPLAY should be either a frame or a display name (a string).\n\
3765 If omitted or nil, that stands for the selected frame's display.")
3767 Lisp_Object display
;
3769 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3771 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
3774 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
3775 "Returns the width in millimeters of the X display DISPLAY.\n\
3776 The optional argument DISPLAY specifies which display to ask about.\n\
3777 DISPLAY should be either a frame or a display name (a string).\n\
3778 If omitted or nil, that stands for the selected frame's display.")
3780 Lisp_Object display
;
3782 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3784 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
3787 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
3788 Sx_display_backing_store
, 0, 1, 0,
3789 "Returns an indication of whether X display DISPLAY does backing store.\n\
3790 The value may be `always', `when-mapped', or `not-useful'.\n\
3791 The optional argument DISPLAY specifies which display to ask about.\n\
3792 DISPLAY should be either a frame or a display name (a string).\n\
3793 If omitted or nil, that stands for the selected frame's display.")
3795 Lisp_Object display
;
3797 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3799 switch (DoesBackingStore (dpyinfo
->screen
))
3802 return intern ("always");
3805 return intern ("when-mapped");
3808 return intern ("not-useful");
3811 error ("Strange value for BackingStore parameter of screen");
3815 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
3816 Sx_display_visual_class
, 0, 1, 0,
3817 "Returns the visual class of the X display DISPLAY.\n\
3818 The value is one of the symbols `static-gray', `gray-scale',\n\
3819 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
3820 The optional argument DISPLAY specifies which display to ask about.\n\
3821 DISPLAY should be either a frame or a display name (a string).\n\
3822 If omitted or nil, that stands for the selected frame's display.")
3824 Lisp_Object display
;
3826 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3828 switch (dpyinfo
->visual
->class)
3830 case StaticGray
: return (intern ("static-gray"));
3831 case GrayScale
: return (intern ("gray-scale"));
3832 case StaticColor
: return (intern ("static-color"));
3833 case PseudoColor
: return (intern ("pseudo-color"));
3834 case TrueColor
: return (intern ("true-color"));
3835 case DirectColor
: return (intern ("direct-color"));
3837 error ("Display has an unknown visual class");
3841 DEFUN ("x-display-save-under", Fx_display_save_under
,
3842 Sx_display_save_under
, 0, 1, 0,
3843 "Returns t if the X display DISPLAY supports the save-under feature.\n\
3844 The optional argument DISPLAY specifies which display to ask about.\n\
3845 DISPLAY should be either a frame or a display name (a string).\n\
3846 If omitted or nil, that stands for the selected frame's display.")
3848 Lisp_Object display
;
3850 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3852 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
3860 register struct frame
*f
;
3862 return PIXEL_WIDTH (f
);
3867 register struct frame
*f
;
3869 return PIXEL_HEIGHT (f
);
3874 register struct frame
*f
;
3876 return FONT_WIDTH (f
->output_data
.x
->font
);
3881 register struct frame
*f
;
3883 return f
->output_data
.x
->line_height
;
3887 x_screen_planes (frame
)
3890 return FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
;
3893 #if 0 /* These no longer seem like the right way to do things. */
3895 /* Draw a rectangle on the frame with left top corner including
3896 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
3897 CHARS by LINES wide and long and is the color of the cursor. */
3900 x_rectangle (f
, gc
, left_char
, top_char
, chars
, lines
)
3901 register struct frame
*f
;
3903 register int top_char
, left_char
, chars
, lines
;
3907 int left
= (left_char
* FONT_WIDTH (f
->output_data
.x
->font
)
3908 + f
->output_data
.x
->internal_border_width
);
3909 int top
= (top_char
* f
->output_data
.x
->line_height
3910 + f
->output_data
.x
->internal_border_width
);
3913 width
= FONT_WIDTH (f
->output_data
.x
->font
) / 2;
3915 width
= FONT_WIDTH (f
->output_data
.x
->font
) * chars
;
3917 height
= f
->output_data
.x
->line_height
/ 2;
3919 height
= f
->output_data
.x
->line_height
* lines
;
3921 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3922 gc
, left
, top
, width
, height
);
3925 DEFUN ("x-draw-rectangle", Fx_draw_rectangle
, Sx_draw_rectangle
, 5, 5, 0,
3926 "Draw a rectangle on FRAME between coordinates specified by\n\
3927 numbers X0, Y0, X1, Y1 in the cursor pixel.")
3928 (frame
, X0
, Y0
, X1
, Y1
)
3929 register Lisp_Object frame
, X0
, X1
, Y0
, Y1
;
3931 register int x0
, y0
, x1
, y1
, top
, left
, n_chars
, n_lines
;
3933 CHECK_LIVE_FRAME (frame
, 0);
3934 CHECK_NUMBER (X0
, 0);
3935 CHECK_NUMBER (Y0
, 1);
3936 CHECK_NUMBER (X1
, 2);
3937 CHECK_NUMBER (Y1
, 3);
3947 n_lines
= y1
- y0
+ 1;
3952 n_lines
= y0
- y1
+ 1;
3958 n_chars
= x1
- x0
+ 1;
3963 n_chars
= x0
- x1
+ 1;
3967 x_rectangle (XFRAME (frame
), XFRAME (frame
)->output_data
.x
->cursor_gc
,
3968 left
, top
, n_chars
, n_lines
);
3974 DEFUN ("x-erase-rectangle", Fx_erase_rectangle
, Sx_erase_rectangle
, 5, 5, 0,
3975 "Draw a rectangle drawn on FRAME between coordinates\n\
3976 X0, Y0, X1, Y1 in the regular background-pixel.")
3977 (frame
, X0
, Y0
, X1
, Y1
)
3978 register Lisp_Object frame
, X0
, Y0
, X1
, Y1
;
3980 register int x0
, y0
, x1
, y1
, top
, left
, n_chars
, n_lines
;
3982 CHECK_LIVE_FRAME (frame
, 0);
3983 CHECK_NUMBER (X0
, 0);
3984 CHECK_NUMBER (Y0
, 1);
3985 CHECK_NUMBER (X1
, 2);
3986 CHECK_NUMBER (Y1
, 3);
3996 n_lines
= y1
- y0
+ 1;
4001 n_lines
= y0
- y1
+ 1;
4007 n_chars
= x1
- x0
+ 1;
4012 n_chars
= x0
- x1
+ 1;
4016 x_rectangle (XFRAME (frame
), XFRAME (frame
)->output_data
.x
->reverse_gc
,
4017 left
, top
, n_chars
, n_lines
);
4023 /* Draw lines around the text region beginning at the character position
4024 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
4025 pixel and line characteristics. */
4027 #define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
4030 outline_region (f
, gc
, top_x
, top_y
, bottom_x
, bottom_y
)
4031 register struct frame
*f
;
4033 int top_x
, top_y
, bottom_x
, bottom_y
;
4035 register int ibw
= f
->output_data
.x
->internal_border_width
;
4036 register int font_w
= FONT_WIDTH (f
->output_data
.x
->font
);
4037 register int font_h
= f
->output_data
.x
->line_height
;
4039 int x
= line_len (y
);
4040 XPoint
*pixel_points
4041 = (XPoint
*) alloca (((bottom_y
- top_y
+ 2) * 4) * sizeof (XPoint
));
4042 register XPoint
*this_point
= pixel_points
;
4044 /* Do the horizontal top line/lines */
4047 this_point
->x
= ibw
;
4048 this_point
->y
= ibw
+ (font_h
* top_y
);
4051 this_point
->x
= ibw
+ (font_w
/ 2); /* Half-size for newline chars. */
4053 this_point
->x
= ibw
+ (font_w
* x
);
4054 this_point
->y
= (this_point
- 1)->y
;
4058 this_point
->x
= ibw
;
4059 this_point
->y
= ibw
+ (font_h
* (top_y
+ 1));
4061 this_point
->x
= ibw
+ (font_w
* top_x
);
4062 this_point
->y
= (this_point
- 1)->y
;
4064 this_point
->x
= (this_point
- 1)->x
;
4065 this_point
->y
= ibw
+ (font_h
* top_y
);
4067 this_point
->x
= ibw
+ (font_w
* x
);
4068 this_point
->y
= (this_point
- 1)->y
;
4071 /* Now do the right side. */
4072 while (y
< bottom_y
)
4073 { /* Right vertical edge */
4075 this_point
->x
= (this_point
- 1)->x
;
4076 this_point
->y
= ibw
+ (font_h
* (y
+ 1));
4079 y
++; /* Horizontal connection to next line */
4082 this_point
->x
= ibw
+ (font_w
/ 2);
4084 this_point
->x
= ibw
+ (font_w
* x
);
4086 this_point
->y
= (this_point
- 1)->y
;
4089 /* Now do the bottom and connect to the top left point. */
4090 this_point
->x
= ibw
+ (font_w
* (bottom_x
+ 1));
4093 this_point
->x
= (this_point
- 1)->x
;
4094 this_point
->y
= ibw
+ (font_h
* (bottom_y
+ 1));
4096 this_point
->x
= ibw
;
4097 this_point
->y
= (this_point
- 1)->y
;
4099 this_point
->x
= pixel_points
->x
;
4100 this_point
->y
= pixel_points
->y
;
4102 XDrawLines (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4104 (this_point
- pixel_points
+ 1), CoordModeOrigin
);
4107 DEFUN ("x-contour-region", Fx_contour_region
, Sx_contour_region
, 1, 1, 0,
4108 "Highlight the region between point and the character under the mouse\n\
4111 register Lisp_Object event
;
4113 register int x0
, y0
, x1
, y1
;
4114 register struct frame
*f
= selected_frame
;
4115 register int p1
, p2
;
4117 CHECK_CONS (event
, 0);
4120 x0
= XINT (Fcar (Fcar (event
)));
4121 y0
= XINT (Fcar (Fcdr (Fcar (event
))));
4123 /* If the mouse is past the end of the line, don't that area. */
4124 /* ReWrite this... */
4129 if (y1
> y0
) /* point below mouse */
4130 outline_region (f
, f
->output_data
.x
->cursor_gc
,
4132 else if (y1
< y0
) /* point above mouse */
4133 outline_region (f
, f
->output_data
.x
->cursor_gc
,
4135 else /* same line: draw horizontal rectangle */
4138 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4139 x0
, y0
, (x1
- x0
+ 1), 1);
4141 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4142 x1
, y1
, (x0
- x1
+ 1), 1);
4145 XFlush (FRAME_X_DISPLAY (f
));
4151 DEFUN ("x-uncontour-region", Fx_uncontour_region
, Sx_uncontour_region
, 1, 1, 0,
4152 "Erase any highlighting of the region between point and the character\n\
4153 at X, Y on the selected frame.")
4155 register Lisp_Object event
;
4157 register int x0
, y0
, x1
, y1
;
4158 register struct frame
*f
= selected_frame
;
4161 x0
= XINT (Fcar (Fcar (event
)));
4162 y0
= XINT (Fcar (Fcdr (Fcar (event
))));
4166 if (y1
> y0
) /* point below mouse */
4167 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4169 else if (y1
< y0
) /* point above mouse */
4170 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4172 else /* same line: draw horizontal rectangle */
4175 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4176 x0
, y0
, (x1
- x0
+ 1), 1);
4178 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4179 x1
, y1
, (x0
- x1
+ 1), 1);
4187 int contour_begin_x
, contour_begin_y
;
4188 int contour_end_x
, contour_end_y
;
4189 int contour_npoints
;
4191 /* Clip the top part of the contour lines down (and including) line Y_POS.
4192 If X_POS is in the middle (rather than at the end) of the line, drop
4193 down a line at that character. */
4196 clip_contour_top (y_pos
, x_pos
)
4198 register XPoint
*begin
= contour_lines
[y_pos
].top_left
;
4199 register XPoint
*end
;
4200 register int npoints
;
4201 register struct display_line
*line
= selected_frame
->phys_lines
[y_pos
+ 1];
4203 if (x_pos
>= line
->len
- 1) /* Draw one, straight horizontal line. */
4205 end
= contour_lines
[y_pos
].top_right
;
4206 npoints
= (end
- begin
+ 1);
4207 XDrawLines (x_current_display
, contour_window
,
4208 contour_erase_gc
, begin_erase
, npoints
, CoordModeOrigin
);
4210 bcopy (end
, begin
+ 1, contour_last_point
- end
+ 1);
4211 contour_last_point
-= (npoints
- 2);
4212 XDrawLines (x_current_display
, contour_window
,
4213 contour_erase_gc
, begin
, 2, CoordModeOrigin
);
4214 XFlush (x_current_display
);
4216 /* Now, update contour_lines structure. */
4221 register XPoint
*p
= begin
+ 1;
4222 end
= contour_lines
[y_pos
].bottom_right
;
4223 npoints
= (end
- begin
+ 1);
4224 XDrawLines (x_current_display
, contour_window
,
4225 contour_erase_gc
, begin_erase
, npoints
, CoordModeOrigin
);
4228 p
->x
= ibw
+ (font_w
* (x_pos
+ 1));
4230 p
->y
= begin
->y
+ font_h
;
4232 bcopy (end
, begin
+ 3, contour_last_point
- end
+ 1);
4233 contour_last_point
-= (npoints
- 5);
4234 XDrawLines (x_current_display
, contour_window
,
4235 contour_erase_gc
, begin
, 4, CoordModeOrigin
);
4236 XFlush (x_current_display
);
4238 /* Now, update contour_lines structure. */
4242 /* Erase the top horizontal lines of the contour, and then extend
4243 the contour upwards. */
4246 extend_contour_top (line
)
4251 clip_contour_bottom (x_pos
, y_pos
)
4257 extend_contour_bottom (x_pos
, y_pos
)
4261 DEFUN ("x-select-region", Fx_select_region
, Sx_select_region
, 1, 1, "e",
4266 register struct frame
*f
= selected_frame
;
4267 register int point_x
= f
->cursor_x
;
4268 register int point_y
= f
->cursor_y
;
4269 register int mouse_below_point
;
4270 register Lisp_Object obj
;
4271 register int x_contour_x
, x_contour_y
;
4273 x_contour_x
= x_mouse_x
;
4274 x_contour_y
= x_mouse_y
;
4275 if (x_contour_y
> point_y
|| (x_contour_y
== point_y
4276 && x_contour_x
> point_x
))
4278 mouse_below_point
= 1;
4279 outline_region (f
, f
->output_data
.x
->cursor_gc
, point_x
, point_y
,
4280 x_contour_x
, x_contour_y
);
4284 mouse_below_point
= 0;
4285 outline_region (f
, f
->output_data
.x
->cursor_gc
, x_contour_x
, x_contour_y
,
4291 obj
= read_char (-1, 0, 0, Qnil
, 0);
4295 if (mouse_below_point
)
4297 if (x_mouse_y
<= point_y
) /* Flipped. */
4299 mouse_below_point
= 0;
4301 outline_region (f
, f
->output_data
.x
->reverse_gc
, point_x
, point_y
,
4302 x_contour_x
, x_contour_y
);
4303 outline_region (f
, f
->output_data
.x
->cursor_gc
, x_mouse_x
, x_mouse_y
,
4306 else if (x_mouse_y
< x_contour_y
) /* Bottom clipped. */
4308 clip_contour_bottom (x_mouse_y
);
4310 else if (x_mouse_y
> x_contour_y
) /* Bottom extended. */
4312 extend_bottom_contour (x_mouse_y
);
4315 x_contour_x
= x_mouse_x
;
4316 x_contour_y
= x_mouse_y
;
4318 else /* mouse above or same line as point */
4320 if (x_mouse_y
>= point_y
) /* Flipped. */
4322 mouse_below_point
= 1;
4324 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4325 x_contour_x
, x_contour_y
, point_x
, point_y
);
4326 outline_region (f
, f
->output_data
.x
->cursor_gc
, point_x
, point_y
,
4327 x_mouse_x
, x_mouse_y
);
4329 else if (x_mouse_y
> x_contour_y
) /* Top clipped. */
4331 clip_contour_top (x_mouse_y
);
4333 else if (x_mouse_y
< x_contour_y
) /* Top extended. */
4335 extend_contour_top (x_mouse_y
);
4340 unread_command_event
= obj
;
4341 if (mouse_below_point
)
4343 contour_begin_x
= point_x
;
4344 contour_begin_y
= point_y
;
4345 contour_end_x
= x_contour_x
;
4346 contour_end_y
= x_contour_y
;
4350 contour_begin_x
= x_contour_x
;
4351 contour_begin_y
= x_contour_y
;
4352 contour_end_x
= point_x
;
4353 contour_end_y
= point_y
;
4358 DEFUN ("x-horizontal-line", Fx_horizontal_line
, Sx_horizontal_line
, 1, 1, "e",
4363 register Lisp_Object obj
;
4364 struct frame
*f
= selected_frame
;
4365 register struct window
*w
= XWINDOW (selected_window
);
4366 register GC line_gc
= f
->output_data
.x
->cursor_gc
;
4367 register GC erase_gc
= f
->output_data
.x
->reverse_gc
;
4369 char dash_list
[] = {6, 4, 6, 4};
4371 XGCValues gc_values
;
4373 register int previous_y
;
4374 register int line
= (x_mouse_y
+ 1) * f
->output_data
.x
->line_height
4375 + f
->output_data
.x
->internal_border_width
;
4376 register int left
= f
->output_data
.x
->internal_border_width
4378 * FONT_WIDTH (f
->output_data
.x
->font
));
4379 register int right
= left
+ (w
->width
4380 * FONT_WIDTH (f
->output_data
.x
->font
))
4381 - f
->output_data
.x
->internal_border_width
;
4385 gc_values
.foreground
= f
->output_data
.x
->cursor_pixel
;
4386 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4387 gc_values
.line_width
= 1;
4388 gc_values
.line_style
= LineOnOffDash
;
4389 gc_values
.cap_style
= CapRound
;
4390 gc_values
.join_style
= JoinRound
;
4392 line_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4393 GCLineStyle
| GCJoinStyle
| GCCapStyle
4394 | GCLineWidth
| GCForeground
| GCBackground
,
4396 XSetDashes (FRAME_X_DISPLAY (f
), line_gc
, 0, dash_list
, dashes
);
4397 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4398 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4399 erase_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4400 GCLineStyle
| GCJoinStyle
| GCCapStyle
4401 | GCLineWidth
| GCForeground
| GCBackground
,
4403 XSetDashes (FRAME_X_DISPLAY (f
), erase_gc
, 0, dash_list
, dashes
);
4410 if (x_mouse_y
>= XINT (w
->top
)
4411 && x_mouse_y
< XINT (w
->top
) + XINT (w
->height
) - 1)
4413 previous_y
= x_mouse_y
;
4414 line
= (x_mouse_y
+ 1) * f
->output_data
.x
->line_height
4415 + f
->output_data
.x
->internal_border_width
;
4416 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4417 line_gc
, left
, line
, right
, line
);
4419 XFlush (FRAME_X_DISPLAY (f
));
4424 obj
= read_char (-1, 0, 0, Qnil
, 0);
4426 || (! EQ (Fcar (Fcdr (Fcdr (obj
))),
4427 Qvertical_scroll_bar
))
4431 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4432 erase_gc
, left
, line
, right
, line
);
4433 unread_command_event
= obj
;
4435 XFreeGC (FRAME_X_DISPLAY (f
), line_gc
);
4436 XFreeGC (FRAME_X_DISPLAY (f
), erase_gc
);
4442 while (x_mouse_y
== previous_y
);
4445 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4446 erase_gc
, left
, line
, right
, line
);
4453 /* These keep track of the rectangle following the pointer. */
4454 int mouse_track_top
, mouse_track_left
, mouse_track_width
;
4456 /* Offset in buffer of character under the pointer, or 0. */
4457 int mouse_buffer_offset
;
4459 DEFUN ("x-track-pointer", Fx_track_pointer
, Sx_track_pointer
, 0, 0, 0,
4460 "Track the pointer.")
4463 static Cursor current_pointer_shape
;
4464 FRAME_PTR f
= x_mouse_frame
;
4467 if (EQ (Vmouse_frame_part
, Qtext_part
)
4468 && (current_pointer_shape
!= f
->output_data
.x
->nontext_cursor
))
4473 current_pointer_shape
= f
->output_data
.x
->nontext_cursor
;
4474 XDefineCursor (FRAME_X_DISPLAY (f
),
4476 current_pointer_shape
);
4478 buf
= XBUFFER (XWINDOW (Vmouse_window
)->buffer
);
4479 c
= *(BUF_CHAR_ADDRESS (buf
, mouse_buffer_offset
));
4481 else if (EQ (Vmouse_frame_part
, Qmodeline_part
)
4482 && (current_pointer_shape
!= f
->output_data
.x
->modeline_cursor
))
4484 current_pointer_shape
= f
->output_data
.x
->modeline_cursor
;
4485 XDefineCursor (FRAME_X_DISPLAY (f
),
4487 current_pointer_shape
);
4490 XFlush (FRAME_X_DISPLAY (f
));
4496 DEFUN ("x-track-pointer", Fx_track_pointer
, Sx_track_pointer
, 1, 1, "e",
4497 "Draw rectangle around character under mouse pointer, if there is one.")
4501 struct window
*w
= XWINDOW (Vmouse_window
);
4502 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4503 struct buffer
*b
= XBUFFER (w
->buffer
);
4506 if (! EQ (Vmouse_window
, selected_window
))
4509 if (EQ (event
, Qnil
))
4513 x_read_mouse_position (selected_frame
, &x
, &y
);
4517 mouse_track_width
= 0;
4518 mouse_track_left
= mouse_track_top
= -1;
4522 if ((x_mouse_x
!= mouse_track_left
4523 && (x_mouse_x
< mouse_track_left
4524 || x_mouse_x
> (mouse_track_left
+ mouse_track_width
)))
4525 || x_mouse_y
!= mouse_track_top
)
4527 int hp
= 0; /* Horizontal position */
4528 int len
= FRAME_CURRENT_GLYPHS (f
)->used
[x_mouse_y
];
4529 int p
= FRAME_CURRENT_GLYPHS (f
)->bufp
[x_mouse_y
];
4530 int tab_width
= XINT (b
->tab_width
);
4531 int ctl_arrow_p
= !NILP (b
->ctl_arrow
);
4533 int mode_line_vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
4534 int in_mode_line
= 0;
4536 if (! FRAME_CURRENT_GLYPHS (f
)->enable
[x_mouse_y
])
4539 /* Erase previous rectangle. */
4540 if (mouse_track_width
)
4542 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4543 mouse_track_left
, mouse_track_top
,
4544 mouse_track_width
, 1);
4546 if ((mouse_track_left
== f
->phys_cursor_x
4547 || mouse_track_left
== f
->phys_cursor_x
- 1)
4548 && mouse_track_top
== f
->phys_cursor_y
)
4550 x_display_cursor (f
, 1);
4554 mouse_track_left
= x_mouse_x
;
4555 mouse_track_top
= x_mouse_y
;
4556 mouse_track_width
= 0;
4558 if (mouse_track_left
> len
) /* Past the end of line. */
4561 if (mouse_track_top
== mode_line_vpos
)
4567 if (tab_width
<= 0 || tab_width
> 20) tab_width
= 8;
4571 if (len
== f
->width
&& hp
== len
- 1 && c
!= '\n')
4577 mouse_track_width
= tab_width
- (hp
% tab_width
);
4579 hp
+= mouse_track_width
;
4582 mouse_track_left
= hp
- mouse_track_width
;
4588 mouse_track_width
= -1;
4592 if (ctl_arrow_p
&& (c
< 040 || c
== 0177))
4597 mouse_track_width
= 2;
4602 mouse_track_left
= hp
- mouse_track_width
;
4608 mouse_track_width
= 1;
4615 while (hp
<= x_mouse_x
);
4618 if (mouse_track_width
) /* Over text; use text pointer shape. */
4620 XDefineCursor (FRAME_X_DISPLAY (f
),
4622 f
->output_data
.x
->text_cursor
);
4623 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4624 mouse_track_left
, mouse_track_top
,
4625 mouse_track_width
, 1);
4627 else if (in_mode_line
)
4628 XDefineCursor (FRAME_X_DISPLAY (f
),
4630 f
->output_data
.x
->modeline_cursor
);
4632 XDefineCursor (FRAME_X_DISPLAY (f
),
4634 f
->output_data
.x
->nontext_cursor
);
4637 XFlush (FRAME_X_DISPLAY (f
));
4640 obj
= read_char (-1, 0, 0, Qnil
, 0);
4643 while (CONSP (obj
) /* Mouse event */
4644 && EQ (Fcar (Fcdr (Fcdr (obj
))), Qnil
) /* Not scroll bar */
4645 && EQ (Vmouse_depressed
, Qnil
) /* Only motion events */
4646 && EQ (Vmouse_window
, selected_window
) /* In this window */
4649 unread_command_event
= obj
;
4651 if (mouse_track_width
)
4653 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4654 mouse_track_left
, mouse_track_top
,
4655 mouse_track_width
, 1);
4656 mouse_track_width
= 0;
4657 if ((mouse_track_left
== f
->phys_cursor_x
4658 || mouse_track_left
- 1 == f
->phys_cursor_x
)
4659 && mouse_track_top
== f
->phys_cursor_y
)
4661 x_display_cursor (f
, 1);
4664 XDefineCursor (FRAME_X_DISPLAY (f
),
4666 f
->output_data
.x
->nontext_cursor
);
4667 XFlush (FRAME_X_DISPLAY (f
));
4677 /* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
4678 on the frame F at position X, Y. */
4680 x_draw_pixmap (f
, x
, y
, image_data
, width
, height
)
4682 int x
, y
, width
, height
;
4687 image
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4688 FRAME_X_WINDOW (f
), image_data
,
4690 XCopyPlane (FRAME_X_DISPLAY (f
), image
, FRAME_X_WINDOW (f
),
4691 f
->output_data
.x
->normal_gc
, 0, 0, width
, height
, x
, y
);
4695 #if 0 /* I'm told these functions are superfluous
4696 given the ability to bind function keys. */
4699 DEFUN ("x-rebind-key", Fx_rebind_key
, Sx_rebind_key
, 3, 3, 0,
4700 "Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
4701 KEYSYM is a string which conforms to the X keysym definitions found\n\
4702 in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
4703 list of strings specifying modifier keys such as Control_L, which must\n\
4704 also be depressed for NEWSTRING to appear.")
4705 (x_keysym
, modifiers
, newstring
)
4706 register Lisp_Object x_keysym
;
4707 register Lisp_Object modifiers
;
4708 register Lisp_Object newstring
;
4711 register KeySym keysym
;
4712 KeySym modifier_list
[16];
4715 CHECK_STRING (x_keysym
, 1);
4716 CHECK_STRING (newstring
, 3);
4718 keysym
= XStringToKeysym ((char *) XSTRING (x_keysym
)->data
);
4719 if (keysym
== NoSymbol
)
4720 error ("Keysym does not exist");
4722 if (NILP (modifiers
))
4723 XRebindKeysym (x_current_display
, keysym
, modifier_list
, 0,
4724 XSTRING (newstring
)->data
, XSTRING (newstring
)->size
);
4727 register Lisp_Object rest
, mod
;
4730 for (rest
= modifiers
; !NILP (rest
); rest
= Fcdr (rest
))
4733 error ("Can't have more than 16 modifiers");
4736 CHECK_STRING (mod
, 3);
4737 modifier_list
[i
] = XStringToKeysym ((char *) XSTRING (mod
)->data
);
4739 if (modifier_list
[i
] == NoSymbol
4740 || !(IsModifierKey (modifier_list
[i
])
4741 || ((unsigned)(modifier_list
[i
]) == XK_Mode_switch
)
4742 || ((unsigned)(modifier_list
[i
]) == XK_Num_Lock
)))
4744 if (modifier_list
[i
] == NoSymbol
4745 || !IsModifierKey (modifier_list
[i
]))
4747 error ("Element is not a modifier keysym");
4751 XRebindKeysym (x_current_display
, keysym
, modifier_list
, i
,
4752 XSTRING (newstring
)->data
, XSTRING (newstring
)->size
);
4758 DEFUN ("x-rebind-keys", Fx_rebind_keys
, Sx_rebind_keys
, 2, 2, 0,
4759 "Rebind KEYCODE to list of strings STRINGS.\n\
4760 STRINGS should be a list of 16 elements, one for each shift combination.\n\
4761 nil as element means don't change.\n\
4762 See the documentation of `x-rebind-key' for more information.")
4764 register Lisp_Object keycode
;
4765 register Lisp_Object strings
;
4767 register Lisp_Object item
;
4768 register unsigned char *rawstring
;
4769 KeySym rawkey
, modifier
[1];
4771 register unsigned i
;
4774 CHECK_NUMBER (keycode
, 1);
4775 CHECK_CONS (strings
, 2);
4776 rawkey
= (KeySym
) ((unsigned) (XINT (keycode
))) & 255;
4777 for (i
= 0; i
<= 15; strings
= Fcdr (strings
), i
++)
4779 item
= Fcar (strings
);
4782 CHECK_STRING (item
, 2);
4783 strsize
= XSTRING (item
)->size
;
4784 rawstring
= (unsigned char *) xmalloc (strsize
);
4785 bcopy (XSTRING (item
)->data
, rawstring
, strsize
);
4786 modifier
[1] = 1 << i
;
4787 XRebindKeysym (x_current_display
, rawkey
, modifier
, 1,
4788 rawstring
, strsize
);
4793 #endif /* HAVE_X11 */
4796 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4798 XScreenNumberOfScreen (scr
)
4799 register Screen
*scr
;
4801 register Display
*dpy
;
4802 register Screen
*dpyscr
;
4806 dpyscr
= dpy
->screens
;
4808 for (i
= 0; i
< dpy
->nscreens
; i
++, dpyscr
++)
4814 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4817 select_visual (dpy
, screen
, depth
)
4820 unsigned int *depth
;
4823 XVisualInfo
*vinfo
, vinfo_template
;
4826 v
= DefaultVisualOfScreen (screen
);
4829 vinfo_template
.visualid
= XVisualIDFromVisual (v
);
4831 vinfo_template
.visualid
= v
->visualid
;
4834 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
4836 vinfo
= XGetVisualInfo (dpy
,
4837 VisualIDMask
| VisualScreenMask
, &vinfo_template
,
4840 fatal ("Can't get proper X visual info");
4842 if ((1 << vinfo
->depth
) == vinfo
->colormap_size
)
4843 *depth
= vinfo
->depth
;
4847 int n
= vinfo
->colormap_size
- 1;
4856 XFree ((char *) vinfo
);
4860 /* Return the X display structure for the display named NAME.
4861 Open a new connection if necessary. */
4863 struct x_display_info
*
4864 x_display_info_for_name (name
)
4868 struct x_display_info
*dpyinfo
;
4870 CHECK_STRING (name
, 0);
4872 if (! EQ (Vwindow_system
, intern ("x")))
4873 error ("Not using X Windows");
4875 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
4877 dpyinfo
= dpyinfo
->next
, names
= XCONS (names
)->cdr
)
4880 tem
= Fstring_equal (XCONS (XCONS (names
)->car
)->car
, name
);
4885 /* Use this general default value to start with. */
4886 Vx_resource_name
= Vinvocation_name
;
4888 validate_x_resource_name ();
4890 dpyinfo
= x_term_init (name
, (unsigned char *)0,
4891 (char *) XSTRING (Vx_resource_name
)->data
);
4894 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
4897 XSETFASTINT (Vwindow_system_version
, 11);
4902 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
4903 1, 3, 0, "Open a connection to an X server.\n\
4904 DISPLAY is the name of the display to connect to.\n\
4905 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4906 If the optional third arg MUST-SUCCEED is non-nil,\n\
4907 terminate Emacs if we can't open the connection.")
4908 (display
, xrm_string
, must_succeed
)
4909 Lisp_Object display
, xrm_string
, must_succeed
;
4911 unsigned int n_planes
;
4912 unsigned char *xrm_option
;
4913 struct x_display_info
*dpyinfo
;
4915 CHECK_STRING (display
, 0);
4916 if (! NILP (xrm_string
))
4917 CHECK_STRING (xrm_string
, 1);
4919 if (! EQ (Vwindow_system
, intern ("x")))
4920 error ("Not using X Windows");
4922 if (! NILP (xrm_string
))
4923 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
4925 xrm_option
= (unsigned char *) 0;
4927 validate_x_resource_name ();
4929 /* This is what opens the connection and sets x_current_display.
4930 This also initializes many symbols, such as those used for input. */
4931 dpyinfo
= x_term_init (display
, xrm_option
,
4932 (char *) XSTRING (Vx_resource_name
)->data
);
4936 if (!NILP (must_succeed
))
4937 fatal ("Cannot connect to X server %s.\n\
4938 Check the DISPLAY environment variable or use `-d'.\n\
4939 Also use the `xhost' program to verify that it is set to permit\n\
4940 connections from your machine.\n",
4941 XSTRING (display
)->data
);
4943 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
4948 XSETFASTINT (Vwindow_system_version
, 11);
4952 DEFUN ("x-close-connection", Fx_close_connection
,
4953 Sx_close_connection
, 1, 1, 0,
4954 "Close the connection to DISPLAY's X server.\n\
4955 For DISPLAY, specify either a frame or a display name (a string).\n\
4956 If DISPLAY is nil, that stands for the selected frame's display.")
4958 Lisp_Object display
;
4960 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4961 struct x_display_info
*tail
;
4964 if (dpyinfo
->reference_count
> 0)
4965 error ("Display still has frames on it");
4968 /* Free the fonts in the font table. */
4969 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4971 if (dpyinfo
->font_table
[i
].name
)
4972 free (dpyinfo
->font_table
[i
].name
);
4973 /* Don't free the full_name string;
4974 it is always shared with something else. */
4975 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
4977 x_destroy_all_bitmaps (dpyinfo
);
4978 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
4980 #ifdef USE_X_TOOLKIT
4981 XtCloseDisplay (dpyinfo
->display
);
4983 XCloseDisplay (dpyinfo
->display
);
4986 x_delete_display (dpyinfo
);
4992 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
4993 "Return the list of display names that Emacs has connections to.")
4996 Lisp_Object tail
, result
;
4999 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCONS (tail
)->cdr
)
5000 result
= Fcons (XCONS (XCONS (tail
)->car
)->car
, result
);
5005 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5006 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5007 If ON is nil, allow buffering of requests.\n\
5008 Turning on synchronization prohibits the Xlib routines from buffering\n\
5009 requests and seriously degrades performance, but makes debugging much\n\
5011 The optional second argument DISPLAY specifies which display to act on.\n\
5012 DISPLAY should be either a frame or a display name (a string).\n\
5013 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5015 Lisp_Object display
, on
;
5017 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5019 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5024 /* Wait for responses to all X commands issued so far for frame F. */
5031 XSync (FRAME_X_DISPLAY (f
), False
);
5037 /* This is zero if not using X windows. */
5040 /* The section below is built by the lisp expression at the top of the file,
5041 just above where these variables are declared. */
5042 /*&&& init symbols here &&&*/
5043 Qauto_raise
= intern ("auto-raise");
5044 staticpro (&Qauto_raise
);
5045 Qauto_lower
= intern ("auto-lower");
5046 staticpro (&Qauto_lower
);
5047 Qbackground_color
= intern ("background-color");
5048 staticpro (&Qbackground_color
);
5049 Qbar
= intern ("bar");
5051 Qborder_color
= intern ("border-color");
5052 staticpro (&Qborder_color
);
5053 Qborder_width
= intern ("border-width");
5054 staticpro (&Qborder_width
);
5055 Qbox
= intern ("box");
5057 Qcursor_color
= intern ("cursor-color");
5058 staticpro (&Qcursor_color
);
5059 Qcursor_type
= intern ("cursor-type");
5060 staticpro (&Qcursor_type
);
5061 Qforeground_color
= intern ("foreground-color");
5062 staticpro (&Qforeground_color
);
5063 Qgeometry
= intern ("geometry");
5064 staticpro (&Qgeometry
);
5065 Qicon_left
= intern ("icon-left");
5066 staticpro (&Qicon_left
);
5067 Qicon_top
= intern ("icon-top");
5068 staticpro (&Qicon_top
);
5069 Qicon_type
= intern ("icon-type");
5070 staticpro (&Qicon_type
);
5071 Qicon_name
= intern ("icon-name");
5072 staticpro (&Qicon_name
);
5073 Qinternal_border_width
= intern ("internal-border-width");
5074 staticpro (&Qinternal_border_width
);
5075 Qleft
= intern ("left");
5077 Qmouse_color
= intern ("mouse-color");
5078 staticpro (&Qmouse_color
);
5079 Qnone
= intern ("none");
5081 Qparent_id
= intern ("parent-id");
5082 staticpro (&Qparent_id
);
5083 Qscroll_bar_width
= intern ("scroll-bar-width");
5084 staticpro (&Qscroll_bar_width
);
5085 Qsuppress_icon
= intern ("suppress-icon");
5086 staticpro (&Qsuppress_icon
);
5087 Qtop
= intern ("top");
5089 Qundefined_color
= intern ("undefined-color");
5090 staticpro (&Qundefined_color
);
5091 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
5092 staticpro (&Qvertical_scroll_bars
);
5093 Qvisibility
= intern ("visibility");
5094 staticpro (&Qvisibility
);
5095 Qwindow_id
= intern ("window-id");
5096 staticpro (&Qwindow_id
);
5097 Qx_frame_parameter
= intern ("x-frame-parameter");
5098 staticpro (&Qx_frame_parameter
);
5099 Qx_resource_name
= intern ("x-resource-name");
5100 staticpro (&Qx_resource_name
);
5101 Quser_position
= intern ("user-position");
5102 staticpro (&Quser_position
);
5103 Quser_size
= intern ("user-size");
5104 staticpro (&Quser_size
);
5105 Qdisplay
= intern ("display");
5106 staticpro (&Qdisplay
);
5107 /* This is the end of symbol initialization. */
5109 Fput (Qundefined_color
, Qerror_conditions
,
5110 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
5111 Fput (Qundefined_color
, Qerror_message
,
5112 build_string ("Undefined color"));
5114 init_x_parm_symbols ();
5116 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
5117 "List of directories to search for bitmap files for X.");
5118 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
5120 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
5121 "The shape of the pointer when over text.\n\
5122 Changing the value does not affect existing frames\n\
5123 unless you set the mouse color.");
5124 Vx_pointer_shape
= Qnil
;
5126 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
5127 "The name Emacs uses to look up X resources; for internal use only.\n\
5128 `x-get-resource' uses this as the first component of the instance name\n\
5129 when requesting resource values.\n\
5130 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
5131 was invoked, or to the value specified with the `-name' or `-rn'\n\
5132 switches, if present.");
5133 Vx_resource_name
= Qnil
;
5135 #if 0 /* This doesn't really do anything. */
5136 DEFVAR_INT ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
5137 "The shape of the pointer when not over text.\n\
5138 This variable takes effect when you create a new frame\n\
5139 or when you set the mouse color.");
5141 Vx_nontext_pointer_shape
= Qnil
;
5143 #if 0 /* This doesn't really do anything. */
5144 DEFVAR_INT ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
5145 "The shape of the pointer when over the mode line.\n\
5146 This variable takes effect when you create a new frame\n\
5147 or when you set the mouse color.");
5149 Vx_mode_pointer_shape
= Qnil
;
5151 DEFVAR_INT ("x-sensitive-text-pointer-shape",
5152 &Vx_sensitive_text_pointer_shape
,
5153 "The shape of the pointer when over mouse-sensitive text.\n\
5154 This variable takes effect when you create a new frame\n\
5155 or when you set the mouse color.");
5156 Vx_sensitive_text_pointer_shape
= Qnil
;
5158 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
5159 "A string indicating the foreground color of the cursor box.");
5160 Vx_cursor_fore_pixel
= Qnil
;
5162 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
5163 "Non-nil if no X window manager is in use.\n\
5164 Emacs doesn't try to figure this out; this is always nil\n\
5165 unless you set it to something else.");
5166 /* We don't have any way to find this out, so set it to nil
5167 and maybe the user would like to set it to t. */
5168 Vx_no_window_manager
= Qnil
;
5170 #ifdef USE_X_TOOLKIT
5171 Fprovide (intern ("x-toolkit"));
5174 Fprovide (intern ("motif"));
5177 defsubr (&Sx_get_resource
);
5179 defsubr (&Sx_draw_rectangle
);
5180 defsubr (&Sx_erase_rectangle
);
5181 defsubr (&Sx_contour_region
);
5182 defsubr (&Sx_uncontour_region
);
5184 defsubr (&Sx_list_fonts
);
5185 defsubr (&Sx_display_color_p
);
5186 defsubr (&Sx_display_grayscale_p
);
5187 defsubr (&Sx_color_defined_p
);
5188 defsubr (&Sx_color_values
);
5189 defsubr (&Sx_server_max_request_size
);
5190 defsubr (&Sx_server_vendor
);
5191 defsubr (&Sx_server_version
);
5192 defsubr (&Sx_display_pixel_width
);
5193 defsubr (&Sx_display_pixel_height
);
5194 defsubr (&Sx_display_mm_width
);
5195 defsubr (&Sx_display_mm_height
);
5196 defsubr (&Sx_display_screens
);
5197 defsubr (&Sx_display_planes
);
5198 defsubr (&Sx_display_color_cells
);
5199 defsubr (&Sx_display_visual_class
);
5200 defsubr (&Sx_display_backing_store
);
5201 defsubr (&Sx_display_save_under
);
5203 defsubr (&Sx_rebind_key
);
5204 defsubr (&Sx_rebind_keys
);
5205 defsubr (&Sx_track_pointer
);
5206 defsubr (&Sx_grab_pointer
);
5207 defsubr (&Sx_ungrab_pointer
);
5209 defsubr (&Sx_parse_geometry
);
5210 defsubr (&Sx_create_frame
);
5212 defsubr (&Sx_horizontal_line
);
5214 defsubr (&Sx_open_connection
);
5215 defsubr (&Sx_close_connection
);
5216 defsubr (&Sx_display_list
);
5217 defsubr (&Sx_synchronize
);
5220 #endif /* HAVE_X_WINDOWS */