1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
27 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
36 #include "intervals.h"
37 #include "dispextern.h"
39 #include "blockinput.h"
45 #include "termhooks.h"
51 #include <sys/types.h>
55 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
56 #include "bitmaps/gray.xbm"
58 #include <X11/bitmaps/gray>
61 #include "[.bitmaps]gray.xbm"
65 #include <X11/Shell.h>
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* USE_MOTIF */
73 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
82 #include "../lwlib/lwlib.h"
86 #include <Xm/DialogS.h>
87 #include <Xm/FileSB.h>
90 /* Do the EDITRES protocol if running X11R5
91 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
93 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
95 extern void _XEditResCheckMessages ();
96 #endif /* R5 + Athena */
98 /* Unique id counter for widgets created by the Lucid Widget Library. */
100 extern LWLIB_ID widget_id_tick
;
103 /* This is part of a kludge--see lwlib/xlwmenu.c. */
104 extern XFontStruct
*xlwmenu_default_font
;
107 extern void free_frame_menubar ();
108 extern double atof ();
112 /* LessTif/Motif version info. */
114 static Lisp_Object Vmotif_version_string
;
116 #endif /* USE_MOTIF */
118 #endif /* USE_X_TOOLKIT */
120 #define min(a,b) ((a) < (b) ? (a) : (b))
121 #define max(a,b) ((a) > (b) ? (a) : (b))
124 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
126 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
129 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
130 it, and including `bitmaps/gray' more than once is a problem when
131 config.h defines `static' as an empty replacement string. */
133 int gray_bitmap_width
= gray_width
;
134 int gray_bitmap_height
= gray_height
;
135 char *gray_bitmap_bits
= gray_bits
;
137 /* The name we're using in resource queries. Most often "emacs". */
139 Lisp_Object Vx_resource_name
;
141 /* The application class we're using in resource queries.
144 Lisp_Object Vx_resource_class
;
146 /* Non-zero means we're allowed to display an hourglass cursor. */
148 int display_hourglass_p
;
150 /* The background and shape of the mouse pointer, and shape when not
151 over text or in the modeline. */
153 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
154 Lisp_Object Vx_hourglass_pointer_shape
;
156 /* The shape when over mouse-sensitive text. */
158 Lisp_Object Vx_sensitive_text_pointer_shape
;
160 /* If non-nil, the pointer shape to indicate that windows can be
161 dragged horizontally. */
163 Lisp_Object Vx_window_horizontal_drag_shape
;
165 /* Color of chars displayed in cursor box. */
167 Lisp_Object Vx_cursor_fore_pixel
;
169 /* Nonzero if using X. */
173 /* Non nil if no window manager is in use. */
175 Lisp_Object Vx_no_window_manager
;
177 /* Search path for bitmap files. */
179 Lisp_Object Vx_bitmap_file_path
;
181 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
183 Lisp_Object Vx_pixel_size_width_font_regexp
;
185 Lisp_Object Qauto_raise
;
186 Lisp_Object Qauto_lower
;
188 Lisp_Object Qborder_color
;
189 Lisp_Object Qborder_width
;
191 Lisp_Object Qcursor_color
;
192 Lisp_Object Qcursor_type
;
193 Lisp_Object Qgeometry
;
194 Lisp_Object Qicon_left
;
195 Lisp_Object Qicon_top
;
196 Lisp_Object Qicon_type
;
197 Lisp_Object Qicon_name
;
198 Lisp_Object Qinternal_border_width
;
201 Lisp_Object Qmouse_color
;
203 Lisp_Object Qouter_window_id
;
204 Lisp_Object Qparent_id
;
205 Lisp_Object Qscroll_bar_width
;
206 Lisp_Object Qsuppress_icon
;
207 extern Lisp_Object Qtop
;
208 Lisp_Object Qundefined_color
;
209 Lisp_Object Qvertical_scroll_bars
;
210 Lisp_Object Qvisibility
;
211 Lisp_Object Qwindow_id
;
212 Lisp_Object Qx_frame_parameter
;
213 Lisp_Object Qx_resource_name
;
214 Lisp_Object Quser_position
;
215 Lisp_Object Quser_size
;
216 extern Lisp_Object Qdisplay
;
217 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
218 Lisp_Object Qscreen_gamma
, Qline_spacing
, Qcenter
;
219 Lisp_Object Qcompound_text
, Qcancel_timer
;
220 Lisp_Object Qwait_for_wm
;
222 /* The below are defined in frame.c. */
224 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
225 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
226 extern Lisp_Object Qtool_bar_lines
;
228 extern Lisp_Object Vwindow_system_version
;
230 Lisp_Object Qface_set_after_frame_default
;
233 int image_cache_refcount
, dpyinfo_refcount
;
238 /* Error if we are not connected to X. */
244 error ("X windows are not in use or not initialized");
247 /* Nonzero if we can use mouse menus.
248 You should not call this unless HAVE_MENUS is defined. */
256 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
257 and checking validity for X. */
260 check_x_frame (frame
)
266 frame
= selected_frame
;
267 CHECK_LIVE_FRAME (frame
, 0);
270 error ("Non-X frame used");
274 /* Let the user specify an X display with a frame.
275 nil stands for the selected frame--or, if that is not an X frame,
276 the first X display on the list. */
278 static struct x_display_info
*
279 check_x_display_info (frame
)
282 struct x_display_info
*dpyinfo
= NULL
;
286 struct frame
*sf
= XFRAME (selected_frame
);
288 if (FRAME_X_P (sf
) && FRAME_LIVE_P (sf
))
289 dpyinfo
= FRAME_X_DISPLAY_INFO (sf
);
290 else if (x_display_list
!= 0)
291 dpyinfo
= x_display_list
;
293 error ("X windows are not in use or not initialized");
295 else if (STRINGP (frame
))
296 dpyinfo
= x_display_info_for_name (frame
);
301 CHECK_LIVE_FRAME (frame
, 0);
304 error ("Non-X frame used");
305 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
312 /* Return the Emacs frame-object corresponding to an X window.
313 It could be the frame's main window or an icon window. */
315 /* This function can be called during GC, so use GC_xxx type test macros. */
318 x_window_to_frame (dpyinfo
, wdesc
)
319 struct x_display_info
*dpyinfo
;
322 Lisp_Object tail
, frame
;
325 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
328 if (!GC_FRAMEP (frame
))
331 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
333 if (f
->output_data
.x
->hourglass_window
== wdesc
)
336 if ((f
->output_data
.x
->edit_widget
337 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
338 /* A tooltip frame? */
339 || (!f
->output_data
.x
->edit_widget
340 && FRAME_X_WINDOW (f
) == wdesc
)
341 || f
->output_data
.x
->icon_desc
== wdesc
)
343 #else /* not USE_X_TOOLKIT */
344 if (FRAME_X_WINDOW (f
) == wdesc
345 || f
->output_data
.x
->icon_desc
== wdesc
)
347 #endif /* not USE_X_TOOLKIT */
353 /* Like x_window_to_frame but also compares the window with the widget's
357 x_any_window_to_frame (dpyinfo
, wdesc
)
358 struct x_display_info
*dpyinfo
;
361 Lisp_Object tail
, frame
;
362 struct frame
*f
, *found
;
366 for (tail
= Vframe_list
; GC_CONSP (tail
) && !found
; tail
= XCDR (tail
))
369 if (!GC_FRAMEP (frame
))
373 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
375 /* This frame matches if the window is any of its widgets. */
376 x
= f
->output_data
.x
;
377 if (x
->hourglass_window
== wdesc
)
381 if (wdesc
== XtWindow (x
->widget
)
382 || wdesc
== XtWindow (x
->column_widget
)
383 || wdesc
== XtWindow (x
->edit_widget
))
385 /* Match if the window is this frame's menubar. */
386 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
389 else if (FRAME_X_WINDOW (f
) == wdesc
)
390 /* A tooltip frame. */
398 /* Likewise, but exclude the menu bar widget. */
401 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
402 struct x_display_info
*dpyinfo
;
405 Lisp_Object tail
, frame
;
409 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
412 if (!GC_FRAMEP (frame
))
415 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
417 x
= f
->output_data
.x
;
418 /* This frame matches if the window is any of its widgets. */
419 if (x
->hourglass_window
== wdesc
)
423 if (wdesc
== XtWindow (x
->widget
)
424 || wdesc
== XtWindow (x
->column_widget
)
425 || wdesc
== XtWindow (x
->edit_widget
))
428 else if (FRAME_X_WINDOW (f
) == wdesc
)
429 /* A tooltip frame. */
435 /* Likewise, but consider only the menu bar widget. */
438 x_menubar_window_to_frame (dpyinfo
, wdesc
)
439 struct x_display_info
*dpyinfo
;
442 Lisp_Object tail
, frame
;
446 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
449 if (!GC_FRAMEP (frame
))
452 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
454 x
= f
->output_data
.x
;
455 /* Match if the window is this frame's menubar. */
456 if (x
->menubar_widget
457 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
463 /* Return the frame whose principal (outermost) window is WDESC.
464 If WDESC is some other (smaller) window, we return 0. */
467 x_top_window_to_frame (dpyinfo
, wdesc
)
468 struct x_display_info
*dpyinfo
;
471 Lisp_Object tail
, frame
;
475 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
478 if (!GC_FRAMEP (frame
))
481 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
483 x
= f
->output_data
.x
;
487 /* This frame matches if the window is its topmost widget. */
488 if (wdesc
== XtWindow (x
->widget
))
490 #if 0 /* I don't know why it did this,
491 but it seems logically wrong,
492 and it causes trouble for MapNotify events. */
493 /* Match if the window is this frame's menubar. */
494 if (x
->menubar_widget
495 && wdesc
== XtWindow (x
->menubar_widget
))
499 else if (FRAME_X_WINDOW (f
) == wdesc
)
505 #endif /* USE_X_TOOLKIT */
509 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
510 id, which is just an int that this section returns. Bitmaps are
511 reference counted so they can be shared among frames.
513 Bitmap indices are guaranteed to be > 0, so a negative number can
514 be used to indicate no bitmap.
516 If you use x_create_bitmap_from_data, then you must keep track of
517 the bitmaps yourself. That is, creating a bitmap from the same
518 data more than once will not be caught. */
521 /* Functions to access the contents of a bitmap, given an id. */
524 x_bitmap_height (f
, id
)
528 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
532 x_bitmap_width (f
, id
)
536 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
540 x_bitmap_pixmap (f
, id
)
544 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
548 /* Allocate a new bitmap record. Returns index of new record. */
551 x_allocate_bitmap_record (f
)
554 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
557 if (dpyinfo
->bitmaps
== NULL
)
559 dpyinfo
->bitmaps_size
= 10;
561 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
562 dpyinfo
->bitmaps_last
= 1;
566 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
567 return ++dpyinfo
->bitmaps_last
;
569 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
570 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
573 dpyinfo
->bitmaps_size
*= 2;
575 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
576 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
577 return ++dpyinfo
->bitmaps_last
;
580 /* Add one reference to the reference count of the bitmap with id ID. */
583 x_reference_bitmap (f
, id
)
587 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
590 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
593 x_create_bitmap_from_data (f
, bits
, width
, height
)
596 unsigned int width
, height
;
598 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
602 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
603 bits
, width
, height
);
608 id
= x_allocate_bitmap_record (f
);
609 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
610 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
611 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
612 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
613 dpyinfo
->bitmaps
[id
- 1].height
= height
;
614 dpyinfo
->bitmaps
[id
- 1].width
= width
;
619 /* Create bitmap from file FILE for frame F. */
622 x_create_bitmap_from_file (f
, file
)
626 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
627 unsigned int width
, height
;
629 int xhot
, yhot
, result
, id
;
634 /* Look for an existing bitmap with the same name. */
635 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
637 if (dpyinfo
->bitmaps
[id
].refcount
638 && dpyinfo
->bitmaps
[id
].file
639 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
641 ++dpyinfo
->bitmaps
[id
].refcount
;
646 /* Search bitmap-file-path for the file, if appropriate. */
647 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
652 filename
= (char *) XSTRING (found
)->data
;
654 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
655 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
656 if (result
!= BitmapSuccess
)
659 id
= x_allocate_bitmap_record (f
);
660 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
661 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
662 dpyinfo
->bitmaps
[id
- 1].file
663 = (char *) xmalloc (STRING_BYTES (XSTRING (file
)) + 1);
664 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
665 dpyinfo
->bitmaps
[id
- 1].height
= height
;
666 dpyinfo
->bitmaps
[id
- 1].width
= width
;
667 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
672 /* Remove reference to bitmap with id number ID. */
675 x_destroy_bitmap (f
, id
)
679 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
683 --dpyinfo
->bitmaps
[id
- 1].refcount
;
684 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
687 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
688 if (dpyinfo
->bitmaps
[id
- 1].file
)
690 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
691 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
698 /* Free all the bitmaps for the display specified by DPYINFO. */
701 x_destroy_all_bitmaps (dpyinfo
)
702 struct x_display_info
*dpyinfo
;
705 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
706 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
708 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
709 if (dpyinfo
->bitmaps
[i
].file
)
710 xfree (dpyinfo
->bitmaps
[i
].file
);
712 dpyinfo
->bitmaps_last
= 0;
715 /* Connect the frame-parameter names for X frames
716 to the ways of passing the parameter values to the window system.
718 The name of a parameter, as a Lisp symbol,
719 has an `x-frame-parameter' property which is an integer in Lisp
720 that is an index in this table. */
722 struct x_frame_parm_table
725 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
728 static Lisp_Object unwind_create_frame
P_ ((Lisp_Object
));
729 static Lisp_Object unwind_create_tip_frame
P_ ((Lisp_Object
));
730 static void x_change_window_heights
P_ ((Lisp_Object
, int));
731 static void x_disable_image
P_ ((struct frame
*, struct image
*));
732 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
733 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
734 static void x_set_wait_for_wm
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
735 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
736 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
737 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
738 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
739 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
740 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
741 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
742 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
743 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
744 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
746 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
747 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
748 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
749 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
751 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
752 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
753 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
754 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
755 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
756 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
757 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
759 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
761 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
766 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
767 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
769 static void init_color_table
P_ ((void));
770 static void free_color_table
P_ ((void));
771 static unsigned long *colors_in_color_table
P_ ((int *n
));
772 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
773 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
777 static struct x_frame_parm_table x_frame_parms
[] =
779 "auto-raise", x_set_autoraise
,
780 "auto-lower", x_set_autolower
,
781 "background-color", x_set_background_color
,
782 "border-color", x_set_border_color
,
783 "border-width", x_set_border_width
,
784 "cursor-color", x_set_cursor_color
,
785 "cursor-type", x_set_cursor_type
,
787 "foreground-color", x_set_foreground_color
,
788 "icon-name", x_set_icon_name
,
789 "icon-type", x_set_icon_type
,
790 "internal-border-width", x_set_internal_border_width
,
791 "menu-bar-lines", x_set_menu_bar_lines
,
792 "mouse-color", x_set_mouse_color
,
793 "name", x_explicitly_set_name
,
794 "scroll-bar-width", x_set_scroll_bar_width
,
795 "title", x_set_title
,
796 "unsplittable", x_set_unsplittable
,
797 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
798 "visibility", x_set_visibility
,
799 "tool-bar-lines", x_set_tool_bar_lines
,
800 "scroll-bar-foreground", x_set_scroll_bar_foreground
,
801 "scroll-bar-background", x_set_scroll_bar_background
,
802 "screen-gamma", x_set_screen_gamma
,
803 "line-spacing", x_set_line_spacing
,
804 "wait-for-wm", x_set_wait_for_wm
807 /* Attach the `x-frame-parameter' properties to
808 the Lisp symbol names of parameters relevant to X. */
811 init_x_parm_symbols ()
815 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
816 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
820 /* Change the parameters of frame F as specified by ALIST.
821 If a parameter is not specially recognized, do nothing special;
822 otherwise call the `x_set_...' function for that parameter.
823 Except for certain geometry properties, always call store_frame_param
824 to store the new value in the parameter alist. */
827 x_set_frame_parameters (f
, alist
)
833 /* If both of these parameters are present, it's more efficient to
834 set them both at once. So we wait until we've looked at the
835 entire list before we set them. */
839 Lisp_Object left
, top
;
841 /* Same with these. */
842 Lisp_Object icon_left
, icon_top
;
844 /* Record in these vectors all the parms specified. */
848 int left_no_change
= 0, top_no_change
= 0;
849 int icon_left_no_change
= 0, icon_top_no_change
= 0;
851 struct gcpro gcpro1
, gcpro2
;
854 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
857 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
858 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
860 /* Extract parm names and values into those vectors. */
863 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
868 parms
[i
] = Fcar (elt
);
869 values
[i
] = Fcdr (elt
);
872 /* TAIL and ALIST are not used again below here. */
875 GCPRO2 (*parms
, *values
);
879 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
880 because their values appear in VALUES and strings are not valid. */
881 top
= left
= Qunbound
;
882 icon_left
= icon_top
= Qunbound
;
884 /* Provide default values for HEIGHT and WIDTH. */
885 if (FRAME_NEW_WIDTH (f
))
886 width
= FRAME_NEW_WIDTH (f
);
888 width
= FRAME_WIDTH (f
);
890 if (FRAME_NEW_HEIGHT (f
))
891 height
= FRAME_NEW_HEIGHT (f
);
893 height
= FRAME_HEIGHT (f
);
895 /* Process foreground_color and background_color before anything else.
896 They are independent of other properties, but other properties (e.g.,
897 cursor_color) are dependent upon them. */
898 for (p
= 0; p
< i
; p
++)
900 Lisp_Object prop
, val
;
904 if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
906 register Lisp_Object param_index
, old_value
;
908 param_index
= Fget (prop
, Qx_frame_parameter
);
909 old_value
= get_frame_param (f
, prop
);
910 store_frame_param (f
, prop
, val
);
911 if (NATNUMP (param_index
)
912 && (XFASTINT (param_index
)
913 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
914 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
918 /* Now process them in reverse of specified order. */
919 for (i
--; i
>= 0; i
--)
921 Lisp_Object prop
, val
;
926 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
927 width
= XFASTINT (val
);
928 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
929 height
= XFASTINT (val
);
930 else if (EQ (prop
, Qtop
))
932 else if (EQ (prop
, Qleft
))
934 else if (EQ (prop
, Qicon_top
))
936 else if (EQ (prop
, Qicon_left
))
938 else if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
939 /* Processed above. */
943 register Lisp_Object param_index
, old_value
;
945 param_index
= Fget (prop
, Qx_frame_parameter
);
946 old_value
= get_frame_param (f
, prop
);
947 store_frame_param (f
, prop
, val
);
948 if (NATNUMP (param_index
)
949 && (XFASTINT (param_index
)
950 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
951 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
955 /* Don't die if just one of these was set. */
956 if (EQ (left
, Qunbound
))
959 if (f
->output_data
.x
->left_pos
< 0)
960 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
962 XSETINT (left
, f
->output_data
.x
->left_pos
);
964 if (EQ (top
, Qunbound
))
967 if (f
->output_data
.x
->top_pos
< 0)
968 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
970 XSETINT (top
, f
->output_data
.x
->top_pos
);
973 /* If one of the icon positions was not set, preserve or default it. */
974 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
976 icon_left_no_change
= 1;
977 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
978 if (NILP (icon_left
))
979 XSETINT (icon_left
, 0);
981 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
983 icon_top_no_change
= 1;
984 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
986 XSETINT (icon_top
, 0);
989 /* Don't set these parameters unless they've been explicitly
990 specified. The window might be mapped or resized while we're in
991 this function, and we don't want to override that unless the lisp
992 code has asked for it.
994 Don't set these parameters unless they actually differ from the
995 window's current parameters; the window may not actually exist
1000 check_frame_size (f
, &height
, &width
);
1002 XSETFRAME (frame
, f
);
1004 if (width
!= FRAME_WIDTH (f
)
1005 || height
!= FRAME_HEIGHT (f
)
1006 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
1007 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1009 if ((!NILP (left
) || !NILP (top
))
1010 && ! (left_no_change
&& top_no_change
)
1011 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1012 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1017 /* Record the signs. */
1018 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1019 if (EQ (left
, Qminus
))
1020 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1021 else if (INTEGERP (left
))
1023 leftpos
= XINT (left
);
1025 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1027 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1028 && CONSP (XCDR (left
))
1029 && INTEGERP (XCAR (XCDR (left
))))
1031 leftpos
= - XINT (XCAR (XCDR (left
)));
1032 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1034 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1035 && CONSP (XCDR (left
))
1036 && INTEGERP (XCAR (XCDR (left
))))
1038 leftpos
= XINT (XCAR (XCDR (left
)));
1041 if (EQ (top
, Qminus
))
1042 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1043 else if (INTEGERP (top
))
1045 toppos
= XINT (top
);
1047 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1049 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1050 && CONSP (XCDR (top
))
1051 && INTEGERP (XCAR (XCDR (top
))))
1053 toppos
= - XINT (XCAR (XCDR (top
)));
1054 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1056 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1057 && CONSP (XCDR (top
))
1058 && INTEGERP (XCAR (XCDR (top
))))
1060 toppos
= XINT (XCAR (XCDR (top
)));
1064 /* Store the numeric value of the position. */
1065 f
->output_data
.x
->top_pos
= toppos
;
1066 f
->output_data
.x
->left_pos
= leftpos
;
1068 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1070 /* Actually set that position, and convert to absolute. */
1071 x_set_offset (f
, leftpos
, toppos
, -1);
1074 if ((!NILP (icon_left
) || !NILP (icon_top
))
1075 && ! (icon_left_no_change
&& icon_top_no_change
))
1076 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1082 /* Store the screen positions of frame F into XPTR and YPTR.
1083 These are the positions of the containing window manager window,
1084 not Emacs's own window. */
1087 x_real_positions (f
, xptr
, yptr
)
1094 /* This is pretty gross, but seems to be the easiest way out of
1095 the problem that arises when restarting window-managers. */
1097 #ifdef USE_X_TOOLKIT
1098 Window outer
= (f
->output_data
.x
->widget
1099 ? XtWindow (f
->output_data
.x
->widget
)
1100 : FRAME_X_WINDOW (f
));
1102 Window outer
= f
->output_data
.x
->window_desc
;
1104 Window tmp_root_window
;
1105 Window
*tmp_children
;
1106 unsigned int tmp_nchildren
;
1110 int count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1111 Window outer_window
;
1113 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
1114 &f
->output_data
.x
->parent_desc
,
1115 &tmp_children
, &tmp_nchildren
);
1116 XFree ((char *) tmp_children
);
1120 /* Find the position of the outside upper-left corner of
1121 the inner window, with respect to the outer window. */
1122 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
1123 outer_window
= f
->output_data
.x
->parent_desc
;
1125 outer_window
= outer
;
1127 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1129 /* From-window, to-window. */
1131 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1133 /* From-position, to-position. */
1134 0, 0, &win_x
, &win_y
,
1139 /* It is possible for the window returned by the XQueryNotify
1140 to become invalid by the time we call XTranslateCoordinates.
1141 That can happen when you restart some window managers.
1142 If so, we get an error in XTranslateCoordinates.
1143 Detect that and try the whole thing over. */
1144 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1146 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1150 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1157 /* Insert a description of internally-recorded parameters of frame X
1158 into the parameter alist *ALISTPTR that is to be given to the user.
1159 Only parameters that are specific to the X window system
1160 and whose values are not correctly recorded in the frame's
1161 param_alist need to be considered here. */
1164 x_report_frame_params (f
, alistptr
)
1166 Lisp_Object
*alistptr
;
1171 /* Represent negative positions (off the top or left screen edge)
1172 in a way that Fmodify_frame_parameters will understand correctly. */
1173 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1174 if (f
->output_data
.x
->left_pos
>= 0)
1175 store_in_alist (alistptr
, Qleft
, tem
);
1177 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1179 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1180 if (f
->output_data
.x
->top_pos
>= 0)
1181 store_in_alist (alistptr
, Qtop
, tem
);
1183 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1185 store_in_alist (alistptr
, Qborder_width
,
1186 make_number (f
->output_data
.x
->border_width
));
1187 store_in_alist (alistptr
, Qinternal_border_width
,
1188 make_number (f
->output_data
.x
->internal_border_width
));
1189 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1190 store_in_alist (alistptr
, Qwindow_id
,
1191 build_string (buf
));
1192 #ifdef USE_X_TOOLKIT
1193 /* Tooltip frame may not have this widget. */
1194 if (f
->output_data
.x
->widget
)
1196 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1197 store_in_alist (alistptr
, Qouter_window_id
,
1198 build_string (buf
));
1199 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1200 FRAME_SAMPLE_VISIBILITY (f
);
1201 store_in_alist (alistptr
, Qvisibility
,
1202 (FRAME_VISIBLE_P (f
) ? Qt
1203 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1204 store_in_alist (alistptr
, Qdisplay
,
1205 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1207 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1210 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1211 store_in_alist (alistptr
, Qparent_id
, tem
);
1216 /* Gamma-correct COLOR on frame F. */
1219 gamma_correct (f
, color
)
1225 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1226 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1227 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1232 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1233 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1234 allocate the color. Value is zero if COLOR_NAME is invalid, or
1235 no color could be allocated. */
1238 x_defined_color (f
, color_name
, color
, alloc_p
)
1245 Display
*dpy
= FRAME_X_DISPLAY (f
);
1246 Colormap cmap
= FRAME_X_COLORMAP (f
);
1249 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1250 if (success_p
&& alloc_p
)
1251 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1258 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1259 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1260 Signal an error if color can't be allocated. */
1263 x_decode_color (f
, color_name
, mono_color
)
1265 Lisp_Object color_name
;
1270 CHECK_STRING (color_name
, 0);
1272 #if 0 /* Don't do this. It's wrong when we're not using the default
1273 colormap, it makes freeing difficult, and it's probably not
1274 an important optimization. */
1275 if (strcmp (XSTRING (color_name
)->data
, "black") == 0)
1276 return BLACK_PIX_DEFAULT (f
);
1277 else if (strcmp (XSTRING (color_name
)->data
, "white") == 0)
1278 return WHITE_PIX_DEFAULT (f
);
1281 /* Return MONO_COLOR for monochrome frames. */
1282 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1285 /* x_defined_color is responsible for coping with failures
1286 by looking for a near-miss. */
1287 if (x_defined_color (f
, XSTRING (color_name
)->data
, &cdef
, 1))
1290 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1291 Fcons (color_name
, Qnil
)));
1297 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1298 the previous value of that parameter, NEW_VALUE is the new value. */
1301 x_set_line_spacing (f
, new_value
, old_value
)
1303 Lisp_Object new_value
, old_value
;
1305 if (NILP (new_value
))
1306 f
->extra_line_spacing
= 0;
1307 else if (NATNUMP (new_value
))
1308 f
->extra_line_spacing
= XFASTINT (new_value
);
1310 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1311 Fcons (new_value
, Qnil
)));
1312 if (FRAME_VISIBLE_P (f
))
1317 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1318 the previous value of that parameter, NEW_VALUE is the new value.
1319 See also the comment of wait_for_wm in struct x_output. */
1322 x_set_wait_for_wm (f
, new_value
, old_value
)
1324 Lisp_Object new_value
, old_value
;
1326 f
->output_data
.x
->wait_for_wm
= !NILP (new_value
);
1330 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1331 the previous value of that parameter, NEW_VALUE is the new
1335 x_set_screen_gamma (f
, new_value
, old_value
)
1337 Lisp_Object new_value
, old_value
;
1339 if (NILP (new_value
))
1341 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1342 /* The value 0.4545 is the normal viewing gamma. */
1343 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1345 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1346 Fcons (new_value
, Qnil
)));
1348 clear_face_cache (0);
1352 /* Functions called only from `x_set_frame_param'
1353 to set individual parameters.
1355 If FRAME_X_WINDOW (f) is 0,
1356 the frame is being created and its X-window does not exist yet.
1357 In that case, just record the parameter's new value
1358 in the standard place; do not attempt to change the window. */
1361 x_set_foreground_color (f
, arg
, oldval
)
1363 Lisp_Object arg
, oldval
;
1365 struct x_output
*x
= f
->output_data
.x
;
1366 unsigned long fg
, old_fg
;
1368 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1369 old_fg
= x
->foreground_pixel
;
1370 x
->foreground_pixel
= fg
;
1372 if (FRAME_X_WINDOW (f
) != 0)
1374 Display
*dpy
= FRAME_X_DISPLAY (f
);
1377 XSetForeground (dpy
, x
->normal_gc
, fg
);
1378 XSetBackground (dpy
, x
->reverse_gc
, fg
);
1380 if (x
->cursor_pixel
== old_fg
)
1382 unload_color (f
, x
->cursor_pixel
);
1383 x
->cursor_pixel
= x_copy_color (f
, fg
);
1384 XSetBackground (dpy
, x
->cursor_gc
, x
->cursor_pixel
);
1389 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1391 if (FRAME_VISIBLE_P (f
))
1395 unload_color (f
, old_fg
);
1399 x_set_background_color (f
, arg
, oldval
)
1401 Lisp_Object arg
, oldval
;
1403 struct x_output
*x
= f
->output_data
.x
;
1406 bg
= x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1407 unload_color (f
, x
->background_pixel
);
1408 x
->background_pixel
= bg
;
1410 if (FRAME_X_WINDOW (f
) != 0)
1412 Display
*dpy
= FRAME_X_DISPLAY (f
);
1416 XSetBackground (dpy
, x
->normal_gc
, bg
);
1417 XSetForeground (dpy
, x
->reverse_gc
, bg
);
1418 XSetWindowBackground (dpy
, FRAME_X_WINDOW (f
), bg
);
1419 XSetForeground (dpy
, x
->cursor_gc
, bg
);
1421 for (bar
= FRAME_SCROLL_BARS (f
);
1423 bar
= XSCROLL_BAR (bar
)->next
)
1425 Window window
= SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
));
1426 XSetWindowBackground (dpy
, window
, bg
);
1430 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1432 if (FRAME_VISIBLE_P (f
))
1438 x_set_mouse_color (f
, arg
, oldval
)
1440 Lisp_Object arg
, oldval
;
1442 struct x_output
*x
= f
->output_data
.x
;
1443 Display
*dpy
= FRAME_X_DISPLAY (f
);
1444 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1445 Cursor hourglass_cursor
, horizontal_drag_cursor
;
1447 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1448 unsigned long mask_color
= x
->background_pixel
;
1450 /* Don't let pointers be invisible. */
1451 if (mask_color
== pixel
)
1453 x_free_colors (f
, &pixel
, 1);
1454 pixel
= x_copy_color (f
, x
->foreground_pixel
);
1457 unload_color (f
, x
->mouse_pixel
);
1458 x
->mouse_pixel
= pixel
;
1462 /* It's not okay to crash if the user selects a screwy cursor. */
1463 count
= x_catch_errors (dpy
);
1465 if (!NILP (Vx_pointer_shape
))
1467 CHECK_NUMBER (Vx_pointer_shape
, 0);
1468 cursor
= XCreateFontCursor (dpy
, XINT (Vx_pointer_shape
));
1471 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1472 x_check_errors (dpy
, "bad text pointer cursor: %s");
1474 if (!NILP (Vx_nontext_pointer_shape
))
1476 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1478 = XCreateFontCursor (dpy
, XINT (Vx_nontext_pointer_shape
));
1481 nontext_cursor
= XCreateFontCursor (dpy
, XC_left_ptr
);
1482 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1484 if (!NILP (Vx_hourglass_pointer_shape
))
1486 CHECK_NUMBER (Vx_hourglass_pointer_shape
, 0);
1488 = XCreateFontCursor (dpy
, XINT (Vx_hourglass_pointer_shape
));
1491 hourglass_cursor
= XCreateFontCursor (dpy
, XC_watch
);
1492 x_check_errors (dpy
, "bad hourglass pointer cursor: %s");
1494 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1495 if (!NILP (Vx_mode_pointer_shape
))
1497 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1498 mode_cursor
= XCreateFontCursor (dpy
, XINT (Vx_mode_pointer_shape
));
1501 mode_cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1502 x_check_errors (dpy
, "bad modeline pointer cursor: %s");
1504 if (!NILP (Vx_sensitive_text_pointer_shape
))
1506 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1508 = XCreateFontCursor (dpy
, XINT (Vx_sensitive_text_pointer_shape
));
1511 cross_cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
1513 if (!NILP (Vx_window_horizontal_drag_shape
))
1515 CHECK_NUMBER (Vx_window_horizontal_drag_shape
, 0);
1516 horizontal_drag_cursor
1517 = XCreateFontCursor (dpy
, XINT (Vx_window_horizontal_drag_shape
));
1520 horizontal_drag_cursor
1521 = XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
1523 /* Check and report errors with the above calls. */
1524 x_check_errors (dpy
, "can't set cursor shape: %s");
1525 x_uncatch_errors (dpy
, count
);
1528 XColor fore_color
, back_color
;
1530 fore_color
.pixel
= x
->mouse_pixel
;
1531 x_query_color (f
, &fore_color
);
1532 back_color
.pixel
= mask_color
;
1533 x_query_color (f
, &back_color
);
1535 XRecolorCursor (dpy
, cursor
, &fore_color
, &back_color
);
1536 XRecolorCursor (dpy
, nontext_cursor
, &fore_color
, &back_color
);
1537 XRecolorCursor (dpy
, mode_cursor
, &fore_color
, &back_color
);
1538 XRecolorCursor (dpy
, cross_cursor
, &fore_color
, &back_color
);
1539 XRecolorCursor (dpy
, hourglass_cursor
, &fore_color
, &back_color
);
1540 XRecolorCursor (dpy
, horizontal_drag_cursor
, &fore_color
, &back_color
);
1543 if (FRAME_X_WINDOW (f
) != 0)
1544 XDefineCursor (dpy
, FRAME_X_WINDOW (f
), cursor
);
1546 if (cursor
!= x
->text_cursor
1547 && x
->text_cursor
!= 0)
1548 XFreeCursor (dpy
, x
->text_cursor
);
1549 x
->text_cursor
= cursor
;
1551 if (nontext_cursor
!= x
->nontext_cursor
1552 && x
->nontext_cursor
!= 0)
1553 XFreeCursor (dpy
, x
->nontext_cursor
);
1554 x
->nontext_cursor
= nontext_cursor
;
1556 if (hourglass_cursor
!= x
->hourglass_cursor
1557 && x
->hourglass_cursor
!= 0)
1558 XFreeCursor (dpy
, x
->hourglass_cursor
);
1559 x
->hourglass_cursor
= hourglass_cursor
;
1561 if (mode_cursor
!= x
->modeline_cursor
1562 && x
->modeline_cursor
!= 0)
1563 XFreeCursor (dpy
, f
->output_data
.x
->modeline_cursor
);
1564 x
->modeline_cursor
= mode_cursor
;
1566 if (cross_cursor
!= x
->cross_cursor
1567 && x
->cross_cursor
!= 0)
1568 XFreeCursor (dpy
, x
->cross_cursor
);
1569 x
->cross_cursor
= cross_cursor
;
1571 if (horizontal_drag_cursor
!= x
->horizontal_drag_cursor
1572 && x
->horizontal_drag_cursor
!= 0)
1573 XFreeCursor (dpy
, x
->horizontal_drag_cursor
);
1574 x
->horizontal_drag_cursor
= horizontal_drag_cursor
;
1579 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1583 x_set_cursor_color (f
, arg
, oldval
)
1585 Lisp_Object arg
, oldval
;
1587 unsigned long fore_pixel
, pixel
;
1588 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1589 struct x_output
*x
= f
->output_data
.x
;
1591 if (!NILP (Vx_cursor_fore_pixel
))
1593 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1594 WHITE_PIX_DEFAULT (f
));
1595 fore_pixel_allocated_p
= 1;
1598 fore_pixel
= x
->background_pixel
;
1600 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1601 pixel_allocated_p
= 1;
1603 /* Make sure that the cursor color differs from the background color. */
1604 if (pixel
== x
->background_pixel
)
1606 if (pixel_allocated_p
)
1608 x_free_colors (f
, &pixel
, 1);
1609 pixel_allocated_p
= 0;
1612 pixel
= x
->mouse_pixel
;
1613 if (pixel
== fore_pixel
)
1615 if (fore_pixel_allocated_p
)
1617 x_free_colors (f
, &fore_pixel
, 1);
1618 fore_pixel_allocated_p
= 0;
1620 fore_pixel
= x
->background_pixel
;
1624 unload_color (f
, x
->cursor_foreground_pixel
);
1625 if (!fore_pixel_allocated_p
)
1626 fore_pixel
= x_copy_color (f
, fore_pixel
);
1627 x
->cursor_foreground_pixel
= fore_pixel
;
1629 unload_color (f
, x
->cursor_pixel
);
1630 if (!pixel_allocated_p
)
1631 pixel
= x_copy_color (f
, pixel
);
1632 x
->cursor_pixel
= pixel
;
1634 if (FRAME_X_WINDOW (f
) != 0)
1637 XSetBackground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, x
->cursor_pixel
);
1638 XSetForeground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, fore_pixel
);
1641 if (FRAME_VISIBLE_P (f
))
1643 x_update_cursor (f
, 0);
1644 x_update_cursor (f
, 1);
1648 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1651 /* Set the border-color of frame F to value described by ARG.
1652 ARG can be a string naming a color.
1653 The border-color is used for the border that is drawn by the X server.
1654 Note that this does not fully take effect if done before
1655 F has an x-window; it must be redone when the window is created.
1657 Note: this is done in two routines because of the way X10 works.
1659 Note: under X11, this is normally the province of the window manager,
1660 and so emacs' border colors may be overridden. */
1663 x_set_border_color (f
, arg
, oldval
)
1665 Lisp_Object arg
, oldval
;
1669 CHECK_STRING (arg
, 0);
1670 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1671 x_set_border_pixel (f
, pix
);
1672 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1675 /* Set the border-color of frame F to pixel value PIX.
1676 Note that this does not fully take effect if done before
1677 F has an x-window. */
1680 x_set_border_pixel (f
, pix
)
1684 unload_color (f
, f
->output_data
.x
->border_pixel
);
1685 f
->output_data
.x
->border_pixel
= pix
;
1687 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1690 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1691 (unsigned long)pix
);
1694 if (FRAME_VISIBLE_P (f
))
1700 /* Value is the internal representation of the specified cursor type
1701 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1702 of the bar cursor. */
1704 enum text_cursor_kinds
1705 x_specified_cursor_type (arg
, width
)
1709 enum text_cursor_kinds type
;
1716 else if (CONSP (arg
)
1717 && EQ (XCAR (arg
), Qbar
)
1718 && INTEGERP (XCDR (arg
))
1719 && XINT (XCDR (arg
)) >= 0)
1722 *width
= XINT (XCDR (arg
));
1724 else if (NILP (arg
))
1727 /* Treat anything unknown as "box cursor".
1728 It was bad to signal an error; people have trouble fixing
1729 .Xdefaults with Emacs, when it has something bad in it. */
1730 type
= FILLED_BOX_CURSOR
;
1736 x_set_cursor_type (f
, arg
, oldval
)
1738 Lisp_Object arg
, oldval
;
1742 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1743 f
->output_data
.x
->cursor_width
= width
;
1745 /* Make sure the cursor gets redrawn. This is overkill, but how
1746 often do people change cursor types? */
1747 update_mode_lines
++;
1751 x_set_icon_type (f
, arg
, oldval
)
1753 Lisp_Object arg
, oldval
;
1759 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1762 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1767 result
= x_text_icon (f
,
1768 (char *) XSTRING ((!NILP (f
->icon_name
)
1772 result
= x_bitmap_icon (f
, arg
);
1777 error ("No icon window available");
1780 XFlush (FRAME_X_DISPLAY (f
));
1784 /* Return non-nil if frame F wants a bitmap icon. */
1792 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1800 x_set_icon_name (f
, arg
, oldval
)
1802 Lisp_Object arg
, oldval
;
1808 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1811 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1816 if (f
->output_data
.x
->icon_bitmap
!= 0)
1821 result
= x_text_icon (f
,
1822 (char *) XSTRING ((!NILP (f
->icon_name
)
1831 error ("No icon window available");
1834 XFlush (FRAME_X_DISPLAY (f
));
1839 x_set_font (f
, arg
, oldval
)
1841 Lisp_Object arg
, oldval
;
1844 Lisp_Object fontset_name
;
1846 int old_fontset
= f
->output_data
.x
->fontset
;
1848 CHECK_STRING (arg
, 1);
1850 fontset_name
= Fquery_fontset (arg
, Qnil
);
1853 result
= (STRINGP (fontset_name
)
1854 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1855 : x_new_font (f
, XSTRING (arg
)->data
));
1858 if (EQ (result
, Qnil
))
1859 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1860 else if (EQ (result
, Qt
))
1861 error ("The characters of the given font have varying widths");
1862 else if (STRINGP (result
))
1864 if (STRINGP (fontset_name
))
1866 /* Fontset names are built from ASCII font names, so the
1867 names may be equal despite there was a change. */
1868 if (old_fontset
== f
->output_data
.x
->fontset
)
1871 else if (!NILP (Fequal (result
, oldval
)))
1874 store_frame_param (f
, Qfont
, result
);
1875 recompute_basic_faces (f
);
1880 do_pending_window_change (0);
1882 /* Don't call `face-set-after-frame-default' when faces haven't been
1883 initialized yet. This is the case when called from
1884 Fx_create_frame. In that case, the X widget or window doesn't
1885 exist either, and we can end up in x_report_frame_params with a
1886 null widget which gives a segfault. */
1887 if (FRAME_FACE_CACHE (f
))
1889 XSETFRAME (frame
, f
);
1890 call1 (Qface_set_after_frame_default
, frame
);
1895 x_set_border_width (f
, arg
, oldval
)
1897 Lisp_Object arg
, oldval
;
1899 CHECK_NUMBER (arg
, 0);
1901 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1904 if (FRAME_X_WINDOW (f
) != 0)
1905 error ("Cannot change the border width of a window");
1907 f
->output_data
.x
->border_width
= XINT (arg
);
1911 x_set_internal_border_width (f
, arg
, oldval
)
1913 Lisp_Object arg
, oldval
;
1915 int old
= f
->output_data
.x
->internal_border_width
;
1917 CHECK_NUMBER (arg
, 0);
1918 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1919 if (f
->output_data
.x
->internal_border_width
< 0)
1920 f
->output_data
.x
->internal_border_width
= 0;
1922 #ifdef USE_X_TOOLKIT
1923 if (f
->output_data
.x
->edit_widget
)
1924 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1927 if (f
->output_data
.x
->internal_border_width
== old
)
1930 if (FRAME_X_WINDOW (f
) != 0)
1932 x_set_window_size (f
, 0, f
->width
, f
->height
);
1933 SET_FRAME_GARBAGED (f
);
1934 do_pending_window_change (0);
1939 x_set_visibility (f
, value
, oldval
)
1941 Lisp_Object value
, oldval
;
1944 XSETFRAME (frame
, f
);
1947 Fmake_frame_invisible (frame
, Qt
);
1948 else if (EQ (value
, Qicon
))
1949 Ficonify_frame (frame
);
1951 Fmake_frame_visible (frame
);
1955 /* Change window heights in windows rooted in WINDOW by N lines. */
1958 x_change_window_heights (window
, n
)
1962 struct window
*w
= XWINDOW (window
);
1964 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1965 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1967 if (INTEGERP (w
->orig_top
))
1968 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
1969 if (INTEGERP (w
->orig_height
))
1970 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
1972 /* Handle just the top child in a vertical split. */
1973 if (!NILP (w
->vchild
))
1974 x_change_window_heights (w
->vchild
, n
);
1976 /* Adjust all children in a horizontal split. */
1977 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1979 w
= XWINDOW (window
);
1980 x_change_window_heights (window
, n
);
1985 x_set_menu_bar_lines (f
, value
, oldval
)
1987 Lisp_Object value
, oldval
;
1990 #ifndef USE_X_TOOLKIT
1991 int olines
= FRAME_MENU_BAR_LINES (f
);
1994 /* Right now, menu bars don't work properly in minibuf-only frames;
1995 most of the commands try to apply themselves to the minibuffer
1996 frame itself, and get an error because you can't switch buffers
1997 in or split the minibuffer window. */
1998 if (FRAME_MINIBUF_ONLY_P (f
))
2001 if (INTEGERP (value
))
2002 nlines
= XINT (value
);
2006 /* Make sure we redisplay all windows in this frame. */
2007 windows_or_buffers_changed
++;
2009 #ifdef USE_X_TOOLKIT
2010 FRAME_MENU_BAR_LINES (f
) = 0;
2013 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2014 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2015 /* Make sure next redisplay shows the menu bar. */
2016 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2020 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2021 free_frame_menubar (f
);
2022 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2024 f
->output_data
.x
->menubar_widget
= 0;
2026 #else /* not USE_X_TOOLKIT */
2027 FRAME_MENU_BAR_LINES (f
) = nlines
;
2028 x_change_window_heights (f
->root_window
, nlines
- olines
);
2029 #endif /* not USE_X_TOOLKIT */
2034 /* Set the number of lines used for the tool bar of frame F to VALUE.
2035 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2036 is the old number of tool bar lines. This function changes the
2037 height of all windows on frame F to match the new tool bar height.
2038 The frame's height doesn't change. */
2041 x_set_tool_bar_lines (f
, value
, oldval
)
2043 Lisp_Object value
, oldval
;
2045 int delta
, nlines
, root_height
;
2046 Lisp_Object root_window
;
2048 /* Treat tool bars like menu bars. */
2049 if (FRAME_MINIBUF_ONLY_P (f
))
2052 /* Use VALUE only if an integer >= 0. */
2053 if (INTEGERP (value
) && XINT (value
) >= 0)
2054 nlines
= XFASTINT (value
);
2058 /* Make sure we redisplay all windows in this frame. */
2059 ++windows_or_buffers_changed
;
2061 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2063 /* Don't resize the tool-bar to more than we have room for. */
2064 root_window
= FRAME_ROOT_WINDOW (f
);
2065 root_height
= XINT (XWINDOW (root_window
)->height
);
2066 if (root_height
- delta
< 1)
2068 delta
= root_height
- 1;
2069 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2072 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2073 x_change_window_heights (root_window
, delta
);
2076 /* We also have to make sure that the internal border at the top of
2077 the frame, below the menu bar or tool bar, is redrawn when the
2078 tool bar disappears. This is so because the internal border is
2079 below the tool bar if one is displayed, but is below the menu bar
2080 if there isn't a tool bar. The tool bar draws into the area
2081 below the menu bar. */
2082 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2086 clear_current_matrices (f
);
2087 updating_frame
= NULL
;
2090 /* If the tool bar gets smaller, the internal border below it
2091 has to be cleared. It was formerly part of the display
2092 of the larger tool bar, and updating windows won't clear it. */
2095 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2096 int width
= PIXEL_WIDTH (f
);
2097 int y
= nlines
* CANON_Y_UNIT (f
);
2100 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2101 0, y
, width
, height
, False
);
2104 if (WINDOWP (f
->tool_bar_window
))
2105 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2110 /* Set the foreground color for scroll bars on frame F to VALUE.
2111 VALUE should be a string, a color name. If it isn't a string or
2112 isn't a valid color name, do nothing. OLDVAL is the old value of
2113 the frame parameter. */
2116 x_set_scroll_bar_foreground (f
, value
, oldval
)
2118 Lisp_Object value
, oldval
;
2120 unsigned long pixel
;
2122 if (STRINGP (value
))
2123 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2127 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2128 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2130 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2131 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2133 /* Remove all scroll bars because they have wrong colors. */
2134 if (condemn_scroll_bars_hook
)
2135 (*condemn_scroll_bars_hook
) (f
);
2136 if (judge_scroll_bars_hook
)
2137 (*judge_scroll_bars_hook
) (f
);
2139 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2145 /* Set the background color for scroll bars on frame F to VALUE VALUE
2146 should be a string, a color name. If it isn't a string or isn't a
2147 valid color name, do nothing. OLDVAL is the old value of the frame
2151 x_set_scroll_bar_background (f
, value
, oldval
)
2153 Lisp_Object value
, oldval
;
2155 unsigned long pixel
;
2157 if (STRINGP (value
))
2158 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2162 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2163 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2165 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2166 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2168 /* Remove all scroll bars because they have wrong colors. */
2169 if (condemn_scroll_bars_hook
)
2170 (*condemn_scroll_bars_hook
) (f
);
2171 if (judge_scroll_bars_hook
)
2172 (*judge_scroll_bars_hook
) (f
);
2174 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2180 /* Encode Lisp string STRING as a text in a format appropriate for
2181 XICCC (X Inter Client Communication Conventions).
2183 If STRING contains only ASCII characters, do no conversion and
2184 return the string data of STRING. Otherwise, encode the text by
2185 CODING_SYSTEM, and return a newly allocated memory area which
2186 should be freed by `xfree' by a caller.
2188 Store the byte length of resulting text in *TEXT_BYTES.
2190 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2191 which means that the `encoding' of the result can be `STRING'.
2192 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2193 the result should be `COMPOUND_TEXT'. */
2196 x_encode_text (string
, coding_system
, text_bytes
, stringp
)
2197 Lisp_Object string
, coding_system
;
2198 int *text_bytes
, *stringp
;
2200 unsigned char *str
= XSTRING (string
)->data
;
2201 int chars
= XSTRING (string
)->size
;
2202 int bytes
= STRING_BYTES (XSTRING (string
));
2206 struct coding_system coding
;
2208 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2209 if (charset_info
== 0)
2211 /* No multibyte character in OBJ. We need not encode it. */
2212 *text_bytes
= bytes
;
2217 setup_coding_system (coding_system
, &coding
);
2218 coding
.src_multibyte
= 1;
2219 coding
.dst_multibyte
= 0;
2220 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2221 if (coding
.type
== coding_type_iso2022
)
2222 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2223 /* We suppress producing escape sequences for composition. */
2224 coding
.composing
= COMPOSITION_DISABLED
;
2225 bufsize
= encoding_buffer_size (&coding
, bytes
);
2226 buf
= (unsigned char *) xmalloc (bufsize
);
2227 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2228 *text_bytes
= coding
.produced
;
2229 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2234 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2237 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2238 name; if NAME is a string, set F's name to NAME and set
2239 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2241 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2242 suggesting a new name, which lisp code should override; if
2243 F->explicit_name is set, ignore the new name; otherwise, set it. */
2246 x_set_name (f
, name
, explicit)
2251 /* Make sure that requests from lisp code override requests from
2252 Emacs redisplay code. */
2255 /* If we're switching from explicit to implicit, we had better
2256 update the mode lines and thereby update the title. */
2257 if (f
->explicit_name
&& NILP (name
))
2258 update_mode_lines
= 1;
2260 f
->explicit_name
= ! NILP (name
);
2262 else if (f
->explicit_name
)
2265 /* If NAME is nil, set the name to the x_id_name. */
2268 /* Check for no change needed in this very common case
2269 before we do any consing. */
2270 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2271 XSTRING (f
->name
)->data
))
2273 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2276 CHECK_STRING (name
, 0);
2278 /* Don't change the name if it's already NAME. */
2279 if (! NILP (Fstring_equal (name
, f
->name
)))
2284 /* For setting the frame title, the title parameter should override
2285 the name parameter. */
2286 if (! NILP (f
->title
))
2289 if (FRAME_X_WINDOW (f
))
2294 XTextProperty text
, icon
;
2296 Lisp_Object coding_system
;
2298 coding_system
= Vlocale_coding_system
;
2299 if (NILP (coding_system
))
2300 coding_system
= Qcompound_text
;
2301 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2302 text
.encoding
= (stringp
? XA_STRING
2303 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2305 text
.nitems
= bytes
;
2307 if (NILP (f
->icon_name
))
2313 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2315 icon
.encoding
= (stringp
? XA_STRING
2316 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2318 icon
.nitems
= bytes
;
2320 #ifdef USE_X_TOOLKIT
2321 XSetWMName (FRAME_X_DISPLAY (f
),
2322 XtWindow (f
->output_data
.x
->widget
), &text
);
2323 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2325 #else /* not USE_X_TOOLKIT */
2326 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2327 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2328 #endif /* not USE_X_TOOLKIT */
2329 if (!NILP (f
->icon_name
)
2330 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2332 if (text
.value
!= XSTRING (name
)->data
)
2335 #else /* not HAVE_X11R4 */
2336 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2337 XSTRING (name
)->data
);
2338 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2339 XSTRING (name
)->data
);
2340 #endif /* not HAVE_X11R4 */
2345 /* This function should be called when the user's lisp code has
2346 specified a name for the frame; the name will override any set by the
2349 x_explicitly_set_name (f
, arg
, oldval
)
2351 Lisp_Object arg
, oldval
;
2353 x_set_name (f
, arg
, 1);
2356 /* This function should be called by Emacs redisplay code to set the
2357 name; names set this way will never override names set by the user's
2360 x_implicitly_set_name (f
, arg
, oldval
)
2362 Lisp_Object arg
, oldval
;
2364 x_set_name (f
, arg
, 0);
2367 /* Change the title of frame F to NAME.
2368 If NAME is nil, use the frame name as the title.
2370 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2371 name; if NAME is a string, set F's name to NAME and set
2372 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2374 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2375 suggesting a new name, which lisp code should override; if
2376 F->explicit_name is set, ignore the new name; otherwise, set it. */
2379 x_set_title (f
, name
, old_name
)
2381 Lisp_Object name
, old_name
;
2383 /* Don't change the title if it's already NAME. */
2384 if (EQ (name
, f
->title
))
2387 update_mode_lines
= 1;
2394 CHECK_STRING (name
, 0);
2396 if (FRAME_X_WINDOW (f
))
2401 XTextProperty text
, icon
;
2403 Lisp_Object coding_system
;
2405 coding_system
= Vlocale_coding_system
;
2406 if (NILP (coding_system
))
2407 coding_system
= Qcompound_text
;
2408 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2409 text
.encoding
= (stringp
? XA_STRING
2410 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2412 text
.nitems
= bytes
;
2414 if (NILP (f
->icon_name
))
2420 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2422 icon
.encoding
= (stringp
? XA_STRING
2423 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2425 icon
.nitems
= bytes
;
2427 #ifdef USE_X_TOOLKIT
2428 XSetWMName (FRAME_X_DISPLAY (f
),
2429 XtWindow (f
->output_data
.x
->widget
), &text
);
2430 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2432 #else /* not USE_X_TOOLKIT */
2433 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2434 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2435 #endif /* not USE_X_TOOLKIT */
2436 if (!NILP (f
->icon_name
)
2437 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2439 if (text
.value
!= XSTRING (name
)->data
)
2442 #else /* not HAVE_X11R4 */
2443 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2444 XSTRING (name
)->data
);
2445 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2446 XSTRING (name
)->data
);
2447 #endif /* not HAVE_X11R4 */
2453 x_set_autoraise (f
, arg
, oldval
)
2455 Lisp_Object arg
, oldval
;
2457 f
->auto_raise
= !EQ (Qnil
, arg
);
2461 x_set_autolower (f
, arg
, oldval
)
2463 Lisp_Object arg
, oldval
;
2465 f
->auto_lower
= !EQ (Qnil
, arg
);
2469 x_set_unsplittable (f
, arg
, oldval
)
2471 Lisp_Object arg
, oldval
;
2473 f
->no_split
= !NILP (arg
);
2477 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2479 Lisp_Object arg
, oldval
;
2481 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2482 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2483 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2484 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2486 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2488 ? vertical_scroll_bar_none
2490 ? vertical_scroll_bar_right
2491 : vertical_scroll_bar_left
);
2493 /* We set this parameter before creating the X window for the
2494 frame, so we can get the geometry right from the start.
2495 However, if the window hasn't been created yet, we shouldn't
2496 call x_set_window_size. */
2497 if (FRAME_X_WINDOW (f
))
2498 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2499 do_pending_window_change (0);
2504 x_set_scroll_bar_width (f
, arg
, oldval
)
2506 Lisp_Object arg
, oldval
;
2508 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2512 #ifdef USE_TOOLKIT_SCROLL_BARS
2513 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2514 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2515 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2516 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2518 /* Make the actual width at least 14 pixels and a multiple of a
2520 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2522 /* Use all of that space (aside from required margins) for the
2524 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2527 if (FRAME_X_WINDOW (f
))
2528 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2529 do_pending_window_change (0);
2531 else if (INTEGERP (arg
) && XINT (arg
) > 0
2532 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2534 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2535 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2537 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2538 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2539 if (FRAME_X_WINDOW (f
))
2540 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2543 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2544 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2545 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2550 /* Subroutines of creating an X frame. */
2552 /* Make sure that Vx_resource_name is set to a reasonable value.
2553 Fix it up, or set it to `emacs' if it is too hopeless. */
2556 validate_x_resource_name ()
2559 /* Number of valid characters in the resource name. */
2561 /* Number of invalid characters in the resource name. */
2566 if (!STRINGP (Vx_resource_class
))
2567 Vx_resource_class
= build_string (EMACS_CLASS
);
2569 if (STRINGP (Vx_resource_name
))
2571 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2574 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2576 /* Only letters, digits, - and _ are valid in resource names.
2577 Count the valid characters and count the invalid ones. */
2578 for (i
= 0; i
< len
; i
++)
2581 if (! ((c
>= 'a' && c
<= 'z')
2582 || (c
>= 'A' && c
<= 'Z')
2583 || (c
>= '0' && c
<= '9')
2584 || c
== '-' || c
== '_'))
2591 /* Not a string => completely invalid. */
2592 bad_count
= 5, good_count
= 0;
2594 /* If name is valid already, return. */
2598 /* If name is entirely invalid, or nearly so, use `emacs'. */
2600 || (good_count
== 1 && bad_count
> 0))
2602 Vx_resource_name
= build_string ("emacs");
2606 /* Name is partly valid. Copy it and replace the invalid characters
2607 with underscores. */
2609 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2611 for (i
= 0; i
< len
; i
++)
2613 int c
= XSTRING (new)->data
[i
];
2614 if (! ((c
>= 'a' && c
<= 'z')
2615 || (c
>= 'A' && c
<= 'Z')
2616 || (c
>= '0' && c
<= '9')
2617 || c
== '-' || c
== '_'))
2618 XSTRING (new)->data
[i
] = '_';
2623 extern char *x_get_string_resource ();
2625 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2626 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2627 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2628 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2629 the name specified by the `-name' or `-rn' command-line arguments.\n\
2631 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2632 class, respectively. You must specify both of them or neither.\n\
2633 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2634 and the class is `Emacs.CLASS.SUBCLASS'.")
2635 (attribute
, class, component
, subclass
)
2636 Lisp_Object attribute
, class, component
, subclass
;
2638 register char *value
;
2644 CHECK_STRING (attribute
, 0);
2645 CHECK_STRING (class, 0);
2647 if (!NILP (component
))
2648 CHECK_STRING (component
, 1);
2649 if (!NILP (subclass
))
2650 CHECK_STRING (subclass
, 2);
2651 if (NILP (component
) != NILP (subclass
))
2652 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2654 validate_x_resource_name ();
2656 /* Allocate space for the components, the dots which separate them,
2657 and the final '\0'. Make them big enough for the worst case. */
2658 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2659 + (STRINGP (component
)
2660 ? STRING_BYTES (XSTRING (component
)) : 0)
2661 + STRING_BYTES (XSTRING (attribute
))
2664 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2665 + STRING_BYTES (XSTRING (class))
2666 + (STRINGP (subclass
)
2667 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2670 /* Start with emacs.FRAMENAME for the name (the specific one)
2671 and with `Emacs' for the class key (the general one). */
2672 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2673 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2675 strcat (class_key
, ".");
2676 strcat (class_key
, XSTRING (class)->data
);
2678 if (!NILP (component
))
2680 strcat (class_key
, ".");
2681 strcat (class_key
, XSTRING (subclass
)->data
);
2683 strcat (name_key
, ".");
2684 strcat (name_key
, XSTRING (component
)->data
);
2687 strcat (name_key
, ".");
2688 strcat (name_key
, XSTRING (attribute
)->data
);
2690 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2691 name_key
, class_key
);
2693 if (value
!= (char *) 0)
2694 return build_string (value
);
2699 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2702 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2703 struct x_display_info
*dpyinfo
;
2704 Lisp_Object attribute
, class, component
, subclass
;
2706 register char *value
;
2710 CHECK_STRING (attribute
, 0);
2711 CHECK_STRING (class, 0);
2713 if (!NILP (component
))
2714 CHECK_STRING (component
, 1);
2715 if (!NILP (subclass
))
2716 CHECK_STRING (subclass
, 2);
2717 if (NILP (component
) != NILP (subclass
))
2718 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2720 validate_x_resource_name ();
2722 /* Allocate space for the components, the dots which separate them,
2723 and the final '\0'. Make them big enough for the worst case. */
2724 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2725 + (STRINGP (component
)
2726 ? STRING_BYTES (XSTRING (component
)) : 0)
2727 + STRING_BYTES (XSTRING (attribute
))
2730 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2731 + STRING_BYTES (XSTRING (class))
2732 + (STRINGP (subclass
)
2733 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2736 /* Start with emacs.FRAMENAME for the name (the specific one)
2737 and with `Emacs' for the class key (the general one). */
2738 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2739 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2741 strcat (class_key
, ".");
2742 strcat (class_key
, XSTRING (class)->data
);
2744 if (!NILP (component
))
2746 strcat (class_key
, ".");
2747 strcat (class_key
, XSTRING (subclass
)->data
);
2749 strcat (name_key
, ".");
2750 strcat (name_key
, XSTRING (component
)->data
);
2753 strcat (name_key
, ".");
2754 strcat (name_key
, XSTRING (attribute
)->data
);
2756 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2758 if (value
!= (char *) 0)
2759 return build_string (value
);
2764 /* Used when C code wants a resource value. */
2767 x_get_resource_string (attribute
, class)
2768 char *attribute
, *class;
2772 struct frame
*sf
= SELECTED_FRAME ();
2774 /* Allocate space for the components, the dots which separate them,
2775 and the final '\0'. */
2776 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2777 + strlen (attribute
) + 2);
2778 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2779 + strlen (class) + 2);
2781 sprintf (name_key
, "%s.%s",
2782 XSTRING (Vinvocation_name
)->data
,
2784 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2786 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2787 name_key
, class_key
);
2790 /* Types we might convert a resource string into. */
2800 /* Return the value of parameter PARAM.
2802 First search ALIST, then Vdefault_frame_alist, then the X defaults
2803 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2805 Convert the resource to the type specified by desired_type.
2807 If no default is specified, return Qunbound. If you call
2808 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2809 and don't let it get stored in any Lisp-visible variables! */
2812 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2813 struct x_display_info
*dpyinfo
;
2814 Lisp_Object alist
, param
;
2817 enum resource_types type
;
2819 register Lisp_Object tem
;
2821 tem
= Fassq (param
, alist
);
2823 tem
= Fassq (param
, Vdefault_frame_alist
);
2829 tem
= display_x_get_resource (dpyinfo
,
2830 build_string (attribute
),
2831 build_string (class),
2839 case RES_TYPE_NUMBER
:
2840 return make_number (atoi (XSTRING (tem
)->data
));
2842 case RES_TYPE_FLOAT
:
2843 return make_float (atof (XSTRING (tem
)->data
));
2845 case RES_TYPE_BOOLEAN
:
2846 tem
= Fdowncase (tem
);
2847 if (!strcmp (XSTRING (tem
)->data
, "on")
2848 || !strcmp (XSTRING (tem
)->data
, "true"))
2853 case RES_TYPE_STRING
:
2856 case RES_TYPE_SYMBOL
:
2857 /* As a special case, we map the values `true' and `on'
2858 to Qt, and `false' and `off' to Qnil. */
2861 lower
= Fdowncase (tem
);
2862 if (!strcmp (XSTRING (lower
)->data
, "on")
2863 || !strcmp (XSTRING (lower
)->data
, "true"))
2865 else if (!strcmp (XSTRING (lower
)->data
, "off")
2866 || !strcmp (XSTRING (lower
)->data
, "false"))
2869 return Fintern (tem
, Qnil
);
2882 /* Like x_get_arg, but also record the value in f->param_alist. */
2885 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2887 Lisp_Object alist
, param
;
2890 enum resource_types type
;
2894 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2895 attribute
, class, type
);
2897 store_frame_param (f
, param
, value
);
2902 /* Record in frame F the specified or default value according to ALIST
2903 of the parameter named PROP (a Lisp symbol).
2904 If no value is specified for PROP, look for an X default for XPROP
2905 on the frame named NAME.
2906 If that is not found either, use the value DEFLT. */
2909 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2916 enum resource_types type
;
2920 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2921 if (EQ (tem
, Qunbound
))
2923 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2928 /* Record in frame F the specified or default value according to ALIST
2929 of the parameter named PROP (a Lisp symbol). If no value is
2930 specified for PROP, look for an X default for XPROP on the frame
2931 named NAME. If that is not found either, use the value DEFLT. */
2934 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2943 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2946 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
2947 if (EQ (tem
, Qunbound
))
2949 #ifdef USE_TOOLKIT_SCROLL_BARS
2951 /* See if an X resource for the scroll bar color has been
2953 tem
= display_x_get_resource (dpyinfo
,
2954 build_string (foreground_p
2958 build_string ("verticalScrollBar"),
2962 /* If nothing has been specified, scroll bars will use a
2963 toolkit-dependent default. Because these defaults are
2964 difficult to get at without actually creating a scroll
2965 bar, use nil to indicate that no color has been
2970 #else /* not USE_TOOLKIT_SCROLL_BARS */
2974 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2977 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2983 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2984 "Parse an X-style geometry string STRING.\n\
2985 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2986 The properties returned may include `top', `left', `height', and `width'.\n\
2987 The value of `left' or `top' may be an integer,\n\
2988 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2989 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2994 unsigned int width
, height
;
2997 CHECK_STRING (string
, 0);
2999 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
3000 &x
, &y
, &width
, &height
);
3003 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3004 error ("Must specify both x and y position, or neither");
3008 if (geometry
& XValue
)
3010 Lisp_Object element
;
3012 if (x
>= 0 && (geometry
& XNegative
))
3013 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3014 else if (x
< 0 && ! (geometry
& XNegative
))
3015 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3017 element
= Fcons (Qleft
, make_number (x
));
3018 result
= Fcons (element
, result
);
3021 if (geometry
& YValue
)
3023 Lisp_Object element
;
3025 if (y
>= 0 && (geometry
& YNegative
))
3026 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3027 else if (y
< 0 && ! (geometry
& YNegative
))
3028 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3030 element
= Fcons (Qtop
, make_number (y
));
3031 result
= Fcons (element
, result
);
3034 if (geometry
& WidthValue
)
3035 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3036 if (geometry
& HeightValue
)
3037 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3042 /* Calculate the desired size and position of this window,
3043 and return the flags saying which aspects were specified.
3045 This function does not make the coordinates positive. */
3047 #define DEFAULT_ROWS 40
3048 #define DEFAULT_COLS 80
3051 x_figure_window_size (f
, parms
)
3055 register Lisp_Object tem0
, tem1
, tem2
;
3056 long window_prompting
= 0;
3057 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3059 /* Default values if we fall through.
3060 Actually, if that happens we should get
3061 window manager prompting. */
3062 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3063 f
->height
= DEFAULT_ROWS
;
3064 /* Window managers expect that if program-specified
3065 positions are not (0,0), they're intentional, not defaults. */
3066 f
->output_data
.x
->top_pos
= 0;
3067 f
->output_data
.x
->left_pos
= 0;
3069 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3070 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3071 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3072 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3074 if (!EQ (tem0
, Qunbound
))
3076 CHECK_NUMBER (tem0
, 0);
3077 f
->height
= XINT (tem0
);
3079 if (!EQ (tem1
, Qunbound
))
3081 CHECK_NUMBER (tem1
, 0);
3082 SET_FRAME_WIDTH (f
, XINT (tem1
));
3084 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3085 window_prompting
|= USSize
;
3087 window_prompting
|= PSize
;
3090 f
->output_data
.x
->vertical_scroll_bar_extra
3091 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3093 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3094 f
->output_data
.x
->flags_areas_extra
3095 = FRAME_FLAGS_AREA_WIDTH (f
);
3096 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3097 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3099 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3100 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3101 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3102 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3104 if (EQ (tem0
, Qminus
))
3106 f
->output_data
.x
->top_pos
= 0;
3107 window_prompting
|= YNegative
;
3109 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3110 && CONSP (XCDR (tem0
))
3111 && INTEGERP (XCAR (XCDR (tem0
))))
3113 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3114 window_prompting
|= YNegative
;
3116 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3117 && CONSP (XCDR (tem0
))
3118 && INTEGERP (XCAR (XCDR (tem0
))))
3120 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3122 else if (EQ (tem0
, Qunbound
))
3123 f
->output_data
.x
->top_pos
= 0;
3126 CHECK_NUMBER (tem0
, 0);
3127 f
->output_data
.x
->top_pos
= XINT (tem0
);
3128 if (f
->output_data
.x
->top_pos
< 0)
3129 window_prompting
|= YNegative
;
3132 if (EQ (tem1
, Qminus
))
3134 f
->output_data
.x
->left_pos
= 0;
3135 window_prompting
|= XNegative
;
3137 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3138 && CONSP (XCDR (tem1
))
3139 && INTEGERP (XCAR (XCDR (tem1
))))
3141 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3142 window_prompting
|= XNegative
;
3144 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3145 && CONSP (XCDR (tem1
))
3146 && INTEGERP (XCAR (XCDR (tem1
))))
3148 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3150 else if (EQ (tem1
, Qunbound
))
3151 f
->output_data
.x
->left_pos
= 0;
3154 CHECK_NUMBER (tem1
, 0);
3155 f
->output_data
.x
->left_pos
= XINT (tem1
);
3156 if (f
->output_data
.x
->left_pos
< 0)
3157 window_prompting
|= XNegative
;
3160 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3161 window_prompting
|= USPosition
;
3163 window_prompting
|= PPosition
;
3166 return window_prompting
;
3169 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3172 XSetWMProtocols (dpy
, w
, protocols
, count
)
3179 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3180 if (prop
== None
) return False
;
3181 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3182 (unsigned char *) protocols
, count
);
3185 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3187 #ifdef USE_X_TOOLKIT
3189 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3190 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3191 already be present because of the toolkit (Motif adds some of them,
3192 for example, but Xt doesn't). */
3195 hack_wm_protocols (f
, widget
)
3199 Display
*dpy
= XtDisplay (widget
);
3200 Window w
= XtWindow (widget
);
3201 int need_delete
= 1;
3207 Atom type
, *atoms
= 0;
3209 unsigned long nitems
= 0;
3210 unsigned long bytes_after
;
3212 if ((XGetWindowProperty (dpy
, w
,
3213 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3214 (long)0, (long)100, False
, XA_ATOM
,
3215 &type
, &format
, &nitems
, &bytes_after
,
3216 (unsigned char **) &atoms
)
3218 && format
== 32 && type
== XA_ATOM
)
3222 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3224 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3226 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3229 if (atoms
) XFree ((char *) atoms
);
3235 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3237 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3239 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3241 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3242 XA_ATOM
, 32, PropModeAppend
,
3243 (unsigned char *) props
, count
);
3251 /* Support routines for XIC (X Input Context). */
3255 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3256 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3259 /* Supported XIM styles, ordered by preferenc. */
3261 static XIMStyle supported_xim_styles
[] =
3263 XIMPreeditPosition
| XIMStatusArea
,
3264 XIMPreeditPosition
| XIMStatusNothing
,
3265 XIMPreeditPosition
| XIMStatusNone
,
3266 XIMPreeditNothing
| XIMStatusArea
,
3267 XIMPreeditNothing
| XIMStatusNothing
,
3268 XIMPreeditNothing
| XIMStatusNone
,
3269 XIMPreeditNone
| XIMStatusArea
,
3270 XIMPreeditNone
| XIMStatusNothing
,
3271 XIMPreeditNone
| XIMStatusNone
,
3276 /* Create an X fontset on frame F with base font name
3280 xic_create_xfontset (f
, base_fontname
)
3282 char *base_fontname
;
3285 char **missing_list
;
3289 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3290 base_fontname
, &missing_list
,
3291 &missing_count
, &def_string
);
3293 XFreeStringList (missing_list
);
3295 /* No need to free def_string. */
3300 /* Value is the best input style, given user preferences USER (already
3301 checked to be supported by Emacs), and styles supported by the
3302 input method XIM. */
3305 best_xim_style (user
, xim
)
3311 for (i
= 0; i
< user
->count_styles
; ++i
)
3312 for (j
= 0; j
< xim
->count_styles
; ++j
)
3313 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3314 return user
->supported_styles
[i
];
3316 /* Return the default style. */
3317 return XIMPreeditNothing
| XIMStatusNothing
;
3320 /* Create XIC for frame F. */
3322 static XIMStyle xic_style
;
3325 create_frame_xic (f
)
3330 XFontSet xfs
= NULL
;
3335 xim
= FRAME_X_XIM (f
);
3340 XVaNestedList preedit_attr
;
3341 XVaNestedList status_attr
;
3342 char *base_fontname
;
3345 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3346 spot
.x
= 0; spot
.y
= 1;
3347 /* Create X fontset. */
3348 fontset
= FRAME_FONTSET (f
);
3350 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3353 /* Determine the base fontname from the ASCII font name of
3355 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3356 char *p
= ascii_font
;
3359 for (i
= 0; *p
; p
++)
3362 /* As the font name doesn't conform to XLFD, we can't
3363 modify it to get a suitable base fontname for the
3365 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3368 int len
= strlen (ascii_font
) + 1;
3371 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3380 base_fontname
= (char *) alloca (len
);
3381 bzero (base_fontname
, len
);
3382 strcpy (base_fontname
, "-*-*-");
3383 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3384 strcat (base_fontname
, "*-*-*-*-*-*-*");
3387 xfs
= xic_create_xfontset (f
, base_fontname
);
3389 /* Determine XIC style. */
3392 XIMStyles supported_list
;
3393 supported_list
.count_styles
= (sizeof supported_xim_styles
3394 / sizeof supported_xim_styles
[0]);
3395 supported_list
.supported_styles
= supported_xim_styles
;
3396 xic_style
= best_xim_style (&supported_list
,
3397 FRAME_X_XIM_STYLES (f
));
3400 preedit_attr
= XVaCreateNestedList (0,
3403 FRAME_FOREGROUND_PIXEL (f
),
3405 FRAME_BACKGROUND_PIXEL (f
),
3406 (xic_style
& XIMPreeditPosition
3411 status_attr
= XVaCreateNestedList (0,
3417 FRAME_FOREGROUND_PIXEL (f
),
3419 FRAME_BACKGROUND_PIXEL (f
),
3422 xic
= XCreateIC (xim
,
3423 XNInputStyle
, xic_style
,
3424 XNClientWindow
, FRAME_X_WINDOW(f
),
3425 XNFocusWindow
, FRAME_X_WINDOW(f
),
3426 XNStatusAttributes
, status_attr
,
3427 XNPreeditAttributes
, preedit_attr
,
3429 XFree (preedit_attr
);
3430 XFree (status_attr
);
3433 FRAME_XIC (f
) = xic
;
3434 FRAME_XIC_STYLE (f
) = xic_style
;
3435 FRAME_XIC_FONTSET (f
) = xfs
;
3439 /* Destroy XIC and free XIC fontset of frame F, if any. */
3445 if (FRAME_XIC (f
) == NULL
)
3448 XDestroyIC (FRAME_XIC (f
));
3449 if (FRAME_XIC_FONTSET (f
))
3450 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3452 FRAME_XIC (f
) = NULL
;
3453 FRAME_XIC_FONTSET (f
) = NULL
;
3457 /* Place preedit area for XIC of window W's frame to specified
3458 pixel position X/Y. X and Y are relative to window W. */
3461 xic_set_preeditarea (w
, x
, y
)
3465 struct frame
*f
= XFRAME (w
->frame
);
3469 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3470 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3471 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3472 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3477 /* Place status area for XIC in bottom right corner of frame F.. */
3480 xic_set_statusarea (f
)
3483 XIC xic
= FRAME_XIC (f
);
3488 /* Negotiate geometry of status area. If input method has existing
3489 status area, use its current size. */
3490 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3491 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3492 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3495 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3496 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3499 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3501 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3502 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3506 area
.width
= needed
->width
;
3507 area
.height
= needed
->height
;
3508 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3509 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3510 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3513 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3514 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3519 /* Set X fontset for XIC of frame F, using base font name
3520 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3523 xic_set_xfontset (f
, base_fontname
)
3525 char *base_fontname
;
3530 xfs
= xic_create_xfontset (f
, base_fontname
);
3532 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3533 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3534 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3535 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3536 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3539 if (FRAME_XIC_FONTSET (f
))
3540 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3541 FRAME_XIC_FONTSET (f
) = xfs
;
3544 #endif /* HAVE_X_I18N */
3548 #ifdef USE_X_TOOLKIT
3550 /* Create and set up the X widget for frame F. */
3553 x_window (f
, window_prompting
, minibuffer_only
)
3555 long window_prompting
;
3556 int minibuffer_only
;
3558 XClassHint class_hints
;
3559 XSetWindowAttributes attributes
;
3560 unsigned long attribute_mask
;
3561 Widget shell_widget
;
3563 Widget frame_widget
;
3569 /* Use the resource name as the top-level widget name
3570 for looking up resources. Make a non-Lisp copy
3571 for the window manager, so GC relocation won't bother it.
3573 Elsewhere we specify the window name for the window manager. */
3576 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3577 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3578 strcpy (f
->namebuf
, str
);
3582 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3583 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3584 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3585 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3586 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3587 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3588 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3589 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3590 applicationShellWidgetClass
,
3591 FRAME_X_DISPLAY (f
), al
, ac
);
3593 f
->output_data
.x
->widget
= shell_widget
;
3594 /* maybe_set_screen_title_format (shell_widget); */
3596 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3597 (widget_value
*) NULL
,
3598 shell_widget
, False
,
3602 (lw_callback
) NULL
);
3605 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3606 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3607 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3608 XtSetValues (pane_widget
, al
, ac
);
3609 f
->output_data
.x
->column_widget
= pane_widget
;
3611 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3612 the emacs screen when changing menubar. This reduces flickering. */
3615 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3616 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3617 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3618 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3619 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3620 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3621 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3622 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3623 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3626 f
->output_data
.x
->edit_widget
= frame_widget
;
3628 XtManageChild (frame_widget
);
3630 /* Do some needed geometry management. */
3633 char *tem
, shell_position
[32];
3636 int extra_borders
= 0;
3638 = (f
->output_data
.x
->menubar_widget
3639 ? (f
->output_data
.x
->menubar_widget
->core
.height
3640 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3643 #if 0 /* Experimentally, we now get the right results
3644 for -geometry -0-0 without this. 24 Aug 96, rms. */
3645 if (FRAME_EXTERNAL_MENU_BAR (f
))
3648 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3649 menubar_size
+= ibw
;
3653 f
->output_data
.x
->menubar_height
= menubar_size
;
3656 /* Motif seems to need this amount added to the sizes
3657 specified for the shell widget. The Athena/Lucid widgets don't.
3658 Both conclusions reached experimentally. -- rms. */
3659 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3660 &extra_borders
, NULL
);
3664 /* Convert our geometry parameters into a geometry string
3666 Note that we do not specify here whether the position
3667 is a user-specified or program-specified one.
3668 We pass that information later, in x_wm_set_size_hints. */
3670 int left
= f
->output_data
.x
->left_pos
;
3671 int xneg
= window_prompting
& XNegative
;
3672 int top
= f
->output_data
.x
->top_pos
;
3673 int yneg
= window_prompting
& YNegative
;
3679 if (window_prompting
& USPosition
)
3680 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3681 PIXEL_WIDTH (f
) + extra_borders
,
3682 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3683 (xneg
? '-' : '+'), left
,
3684 (yneg
? '-' : '+'), top
);
3686 sprintf (shell_position
, "=%dx%d",
3687 PIXEL_WIDTH (f
) + extra_borders
,
3688 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3691 len
= strlen (shell_position
) + 1;
3692 /* We don't free this because we don't know whether
3693 it is safe to free it while the frame exists.
3694 It isn't worth the trouble of arranging to free it
3695 when the frame is deleted. */
3696 tem
= (char *) xmalloc (len
);
3697 strncpy (tem
, shell_position
, len
);
3698 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3699 XtSetValues (shell_widget
, al
, ac
);
3702 XtManageChild (pane_widget
);
3703 XtRealizeWidget (shell_widget
);
3705 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3707 validate_x_resource_name ();
3709 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3710 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3711 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3714 FRAME_XIC (f
) = NULL
;
3716 create_frame_xic (f
);
3720 f
->output_data
.x
->wm_hints
.input
= True
;
3721 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3722 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3723 &f
->output_data
.x
->wm_hints
);
3725 hack_wm_protocols (f
, shell_widget
);
3728 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3731 /* Do a stupid property change to force the server to generate a
3732 PropertyNotify event so that the event_stream server timestamp will
3733 be initialized to something relevant to the time we created the window.
3735 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3736 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3737 XA_ATOM
, 32, PropModeAppend
,
3738 (unsigned char*) NULL
, 0);
3740 /* Make all the standard events reach the Emacs frame. */
3741 attributes
.event_mask
= STANDARD_EVENT_SET
;
3746 /* XIM server might require some X events. */
3747 unsigned long fevent
= NoEventMask
;
3748 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3749 attributes
.event_mask
|= fevent
;
3751 #endif /* HAVE_X_I18N */
3753 attribute_mask
= CWEventMask
;
3754 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3755 attribute_mask
, &attributes
);
3757 XtMapWidget (frame_widget
);
3759 /* x_set_name normally ignores requests to set the name if the
3760 requested name is the same as the current name. This is the one
3761 place where that assumption isn't correct; f->name is set, but
3762 the X server hasn't been told. */
3765 int explicit = f
->explicit_name
;
3767 f
->explicit_name
= 0;
3770 x_set_name (f
, name
, explicit);
3773 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3774 f
->output_data
.x
->text_cursor
);
3778 /* This is a no-op, except under Motif. Make sure main areas are
3779 set to something reasonable, in case we get an error later. */
3780 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3783 #else /* not USE_X_TOOLKIT */
3785 /* Create and set up the X window for frame F. */
3792 XClassHint class_hints
;
3793 XSetWindowAttributes attributes
;
3794 unsigned long attribute_mask
;
3796 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3797 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3798 attributes
.bit_gravity
= StaticGravity
;
3799 attributes
.backing_store
= NotUseful
;
3800 attributes
.save_under
= True
;
3801 attributes
.event_mask
= STANDARD_EVENT_SET
;
3802 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3803 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3808 = XCreateWindow (FRAME_X_DISPLAY (f
),
3809 f
->output_data
.x
->parent_desc
,
3810 f
->output_data
.x
->left_pos
,
3811 f
->output_data
.x
->top_pos
,
3812 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3813 f
->output_data
.x
->border_width
,
3814 CopyFromParent
, /* depth */
3815 InputOutput
, /* class */
3817 attribute_mask
, &attributes
);
3821 create_frame_xic (f
);
3824 /* XIM server might require some X events. */
3825 unsigned long fevent
= NoEventMask
;
3826 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3827 attributes
.event_mask
|= fevent
;
3828 attribute_mask
= CWEventMask
;
3829 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3830 attribute_mask
, &attributes
);
3833 #endif /* HAVE_X_I18N */
3835 validate_x_resource_name ();
3837 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3838 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3839 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3841 /* The menubar is part of the ordinary display;
3842 it does not count in addition to the height of the window. */
3843 f
->output_data
.x
->menubar_height
= 0;
3845 /* This indicates that we use the "Passive Input" input model.
3846 Unless we do this, we don't get the Focus{In,Out} events that we
3847 need to draw the cursor correctly. Accursed bureaucrats.
3848 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3850 f
->output_data
.x
->wm_hints
.input
= True
;
3851 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3852 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3853 &f
->output_data
.x
->wm_hints
);
3854 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3856 /* Request "save yourself" and "delete window" commands from wm. */
3859 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3860 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3861 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3864 /* x_set_name normally ignores requests to set the name if the
3865 requested name is the same as the current name. This is the one
3866 place where that assumption isn't correct; f->name is set, but
3867 the X server hasn't been told. */
3870 int explicit = f
->explicit_name
;
3872 f
->explicit_name
= 0;
3875 x_set_name (f
, name
, explicit);
3878 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3879 f
->output_data
.x
->text_cursor
);
3883 if (FRAME_X_WINDOW (f
) == 0)
3884 error ("Unable to create window");
3887 #endif /* not USE_X_TOOLKIT */
3889 /* Handle the icon stuff for this window. Perhaps later we might
3890 want an x_set_icon_position which can be called interactively as
3898 Lisp_Object icon_x
, icon_y
;
3899 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3901 /* Set the position of the icon. Note that twm groups all
3902 icons in an icon window. */
3903 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3904 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3905 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3907 CHECK_NUMBER (icon_x
, 0);
3908 CHECK_NUMBER (icon_y
, 0);
3910 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3911 error ("Both left and top icon corners of icon must be specified");
3915 if (! EQ (icon_x
, Qunbound
))
3916 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3918 /* Start up iconic or window? */
3919 x_wm_set_window_state
3920 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3925 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3932 /* Make the GCs needed for this window, setting the
3933 background, border and mouse colors; also create the
3934 mouse cursor and the gray border tile. */
3936 static char cursor_bits
[] =
3938 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3939 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3940 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3948 XGCValues gc_values
;
3952 /* Create the GCs of this frame.
3953 Note that many default values are used. */
3956 gc_values
.font
= f
->output_data
.x
->font
->fid
;
3957 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
3958 gc_values
.background
= f
->output_data
.x
->background_pixel
;
3959 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
3960 f
->output_data
.x
->normal_gc
3961 = XCreateGC (FRAME_X_DISPLAY (f
),
3963 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
3966 /* Reverse video style. */
3967 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3968 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
3969 f
->output_data
.x
->reverse_gc
3970 = XCreateGC (FRAME_X_DISPLAY (f
),
3972 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
3975 /* Cursor has cursor-color background, background-color foreground. */
3976 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3977 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
3978 gc_values
.fill_style
= FillOpaqueStippled
;
3980 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
3981 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3982 cursor_bits
, 16, 16);
3983 f
->output_data
.x
->cursor_gc
3984 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3985 (GCFont
| GCForeground
| GCBackground
3986 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
3990 f
->output_data
.x
->white_relief
.gc
= 0;
3991 f
->output_data
.x
->black_relief
.gc
= 0;
3993 /* Create the gray border tile used when the pointer is not in
3994 the frame. Since this depends on the frame's pixel values,
3995 this must be done on a per-frame basis. */
3996 f
->output_data
.x
->border_tile
3997 = (XCreatePixmapFromBitmapData
3998 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
3999 gray_bits
, gray_width
, gray_height
,
4000 f
->output_data
.x
->foreground_pixel
,
4001 f
->output_data
.x
->background_pixel
,
4002 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4008 /* Free what was was allocated in x_make_gc. */
4014 Display
*dpy
= FRAME_X_DISPLAY (f
);
4018 if (f
->output_data
.x
->normal_gc
)
4020 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4021 f
->output_data
.x
->normal_gc
= 0;
4024 if (f
->output_data
.x
->reverse_gc
)
4026 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4027 f
->output_data
.x
->reverse_gc
= 0;
4030 if (f
->output_data
.x
->cursor_gc
)
4032 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4033 f
->output_data
.x
->cursor_gc
= 0;
4036 if (f
->output_data
.x
->border_tile
)
4038 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4039 f
->output_data
.x
->border_tile
= 0;
4046 /* Handler for signals raised during x_create_frame and
4047 x_create_top_frame. FRAME is the frame which is partially
4051 unwind_create_frame (frame
)
4054 struct frame
*f
= XFRAME (frame
);
4056 /* If frame is ``official'', nothing to do. */
4057 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4060 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4063 x_free_frame_resources (f
);
4065 /* Check that reference counts are indeed correct. */
4066 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4067 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4075 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4077 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
4078 Returns an Emacs frame object.\n\
4079 ALIST is an alist of frame parameters.\n\
4080 If the parameters specify that the frame should not have a minibuffer,\n\
4081 and do not specify a specific minibuffer window to use,\n\
4082 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
4083 be shared by the new frame.\n\
4085 This function is an internal primitive--use `make-frame' instead.")
4090 Lisp_Object frame
, tem
;
4092 int minibuffer_only
= 0;
4093 long window_prompting
= 0;
4095 int count
= BINDING_STACK_SIZE ();
4096 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4097 Lisp_Object display
;
4098 struct x_display_info
*dpyinfo
= NULL
;
4104 /* Use this general default value to start with
4105 until we know if this frame has a specified name. */
4106 Vx_resource_name
= Vinvocation_name
;
4108 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4109 if (EQ (display
, Qunbound
))
4111 dpyinfo
= check_x_display_info (display
);
4113 kb
= dpyinfo
->kboard
;
4115 kb
= &the_only_kboard
;
4118 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4120 && ! EQ (name
, Qunbound
)
4122 error ("Invalid frame name--not a string or nil");
4125 Vx_resource_name
= name
;
4127 /* See if parent window is specified. */
4128 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4129 if (EQ (parent
, Qunbound
))
4131 if (! NILP (parent
))
4132 CHECK_NUMBER (parent
, 0);
4134 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4135 /* No need to protect DISPLAY because that's not used after passing
4136 it to make_frame_without_minibuffer. */
4138 GCPRO4 (parms
, parent
, name
, frame
);
4139 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4141 if (EQ (tem
, Qnone
) || NILP (tem
))
4142 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4143 else if (EQ (tem
, Qonly
))
4145 f
= make_minibuffer_frame ();
4146 minibuffer_only
= 1;
4148 else if (WINDOWP (tem
))
4149 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4153 XSETFRAME (frame
, f
);
4155 /* Note that X Windows does support scroll bars. */
4156 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4158 f
->output_method
= output_x_window
;
4159 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4160 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4161 f
->output_data
.x
->icon_bitmap
= -1;
4162 f
->output_data
.x
->fontset
= -1;
4163 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4164 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4165 record_unwind_protect (unwind_create_frame
, frame
);
4168 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4170 if (! STRINGP (f
->icon_name
))
4171 f
->icon_name
= Qnil
;
4173 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4175 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4176 dpyinfo_refcount
= dpyinfo
->reference_count
;
4177 #endif /* GLYPH_DEBUG */
4179 FRAME_KBOARD (f
) = kb
;
4182 /* These colors will be set anyway later, but it's important
4183 to get the color reference counts right, so initialize them! */
4186 struct gcpro gcpro1
;
4188 /* Function x_decode_color can signal an error. Make
4189 sure to initialize color slots so that we won't try
4190 to free colors we haven't allocated. */
4191 f
->output_data
.x
->foreground_pixel
= -1;
4192 f
->output_data
.x
->background_pixel
= -1;
4193 f
->output_data
.x
->cursor_pixel
= -1;
4194 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4195 f
->output_data
.x
->border_pixel
= -1;
4196 f
->output_data
.x
->mouse_pixel
= -1;
4198 black
= build_string ("black");
4200 f
->output_data
.x
->foreground_pixel
4201 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4202 f
->output_data
.x
->background_pixel
4203 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4204 f
->output_data
.x
->cursor_pixel
4205 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4206 f
->output_data
.x
->cursor_foreground_pixel
4207 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4208 f
->output_data
.x
->border_pixel
4209 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4210 f
->output_data
.x
->mouse_pixel
4211 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4215 /* Specify the parent under which to make this X window. */
4219 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4220 f
->output_data
.x
->explicit_parent
= 1;
4224 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4225 f
->output_data
.x
->explicit_parent
= 0;
4228 /* Set the name; the functions to which we pass f expect the name to
4230 if (EQ (name
, Qunbound
) || NILP (name
))
4232 f
->name
= build_string (dpyinfo
->x_id_name
);
4233 f
->explicit_name
= 0;
4238 f
->explicit_name
= 1;
4239 /* use the frame's title when getting resources for this frame. */
4240 specbind (Qx_resource_name
, name
);
4243 /* Extract the window parameters from the supplied values
4244 that are needed to determine window geometry. */
4248 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4251 /* First, try whatever font the caller has specified. */
4254 tem
= Fquery_fontset (font
, Qnil
);
4256 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4258 font
= x_new_font (f
, XSTRING (font
)->data
);
4261 /* Try out a font which we hope has bold and italic variations. */
4262 if (!STRINGP (font
))
4263 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4264 if (!STRINGP (font
))
4265 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4266 if (! STRINGP (font
))
4267 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4268 if (! STRINGP (font
))
4269 /* This was formerly the first thing tried, but it finds too many fonts
4270 and takes too long. */
4271 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4272 /* If those didn't work, look for something which will at least work. */
4273 if (! STRINGP (font
))
4274 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4276 if (! STRINGP (font
))
4277 font
= build_string ("fixed");
4279 x_default_parameter (f
, parms
, Qfont
, font
,
4280 "font", "Font", RES_TYPE_STRING
);
4284 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4285 whereby it fails to get any font. */
4286 xlwmenu_default_font
= f
->output_data
.x
->font
;
4289 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4290 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4292 /* This defaults to 2 in order to match xterm. We recognize either
4293 internalBorderWidth or internalBorder (which is what xterm calls
4295 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4299 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4300 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4301 if (! EQ (value
, Qunbound
))
4302 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4305 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4306 "internalBorderWidth", "internalBorderWidth",
4308 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4309 "verticalScrollBars", "ScrollBars",
4312 /* Also do the stuff which must be set before the window exists. */
4313 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4314 "foreground", "Foreground", RES_TYPE_STRING
);
4315 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4316 "background", "Background", RES_TYPE_STRING
);
4317 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4318 "pointerColor", "Foreground", RES_TYPE_STRING
);
4319 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4320 "cursorColor", "Foreground", RES_TYPE_STRING
);
4321 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4322 "borderColor", "BorderColor", RES_TYPE_STRING
);
4323 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4324 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4325 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4326 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4328 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4329 "scrollBarForeground",
4330 "ScrollBarForeground", 1);
4331 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4332 "scrollBarBackground",
4333 "ScrollBarBackground", 0);
4335 /* Init faces before x_default_parameter is called for scroll-bar
4336 parameters because that function calls x_set_scroll_bar_width,
4337 which calls change_frame_size, which calls Fset_window_buffer,
4338 which runs hooks, which call Fvertical_motion. At the end, we
4339 end up in init_iterator with a null face cache, which should not
4341 init_frame_faces (f
);
4343 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4344 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4345 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4346 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4347 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4348 "bufferPredicate", "BufferPredicate",
4350 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4351 "title", "Title", RES_TYPE_STRING
);
4352 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4353 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4355 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4357 /* Add the tool-bar height to the initial frame height so that the
4358 user gets a text display area of the size he specified with -g or
4359 via .Xdefaults. Later changes of the tool-bar height don't
4360 change the frame size. This is done so that users can create
4361 tall Emacs frames without having to guess how tall the tool-bar
4363 if (FRAME_TOOL_BAR_LINES (f
))
4365 int margin
, relief
, bar_height
;
4367 relief
= (tool_bar_button_relief
> 0
4368 ? tool_bar_button_relief
4369 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4371 if (INTEGERP (Vtool_bar_button_margin
)
4372 && XINT (Vtool_bar_button_margin
) > 0)
4373 margin
= XFASTINT (Vtool_bar_button_margin
);
4374 else if (CONSP (Vtool_bar_button_margin
)
4375 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4376 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4377 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4381 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4382 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4385 /* Compute the size of the X window. */
4386 window_prompting
= x_figure_window_size (f
, parms
);
4388 if (window_prompting
& XNegative
)
4390 if (window_prompting
& YNegative
)
4391 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4393 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4397 if (window_prompting
& YNegative
)
4398 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4400 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4403 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4405 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4406 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4408 /* Create the X widget or window. */
4409 #ifdef USE_X_TOOLKIT
4410 x_window (f
, window_prompting
, minibuffer_only
);
4418 /* Now consider the frame official. */
4419 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4420 Vframe_list
= Fcons (frame
, Vframe_list
);
4422 /* We need to do this after creating the X window, so that the
4423 icon-creation functions can say whose icon they're describing. */
4424 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4425 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4427 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4428 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4429 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4430 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4431 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4432 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4433 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4434 "scrollBarWidth", "ScrollBarWidth",
4437 /* Dimensions, especially f->height, must be done via change_frame_size.
4438 Change will not be effected unless different from the current
4444 SET_FRAME_WIDTH (f
, 0);
4445 change_frame_size (f
, height
, width
, 1, 0, 0);
4447 /* Set up faces after all frame parameters are known. This call
4448 also merges in face attributes specified for new frames. If we
4449 don't do this, the `menu' face for instance won't have the right
4450 colors, and the menu bar won't appear in the specified colors for
4452 call1 (Qface_set_after_frame_default
, frame
);
4454 #ifdef USE_X_TOOLKIT
4455 /* Create the menu bar. */
4456 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4458 /* If this signals an error, we haven't set size hints for the
4459 frame and we didn't make it visible. */
4460 initialize_frame_menubar (f
);
4462 /* This is a no-op, except under Motif where it arranges the
4463 main window for the widgets on it. */
4464 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4465 f
->output_data
.x
->menubar_widget
,
4466 f
->output_data
.x
->edit_widget
);
4468 #endif /* USE_X_TOOLKIT */
4470 /* Tell the server what size and position, etc, we want, and how
4471 badly we want them. This should be done after we have the menu
4472 bar so that its size can be taken into account. */
4474 x_wm_set_size_hint (f
, window_prompting
, 0);
4477 /* Make the window appear on the frame and enable display, unless
4478 the caller says not to. However, with explicit parent, Emacs
4479 cannot control visibility, so don't try. */
4480 if (! f
->output_data
.x
->explicit_parent
)
4482 Lisp_Object visibility
;
4484 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4486 if (EQ (visibility
, Qunbound
))
4489 if (EQ (visibility
, Qicon
))
4490 x_iconify_frame (f
);
4491 else if (! NILP (visibility
))
4492 x_make_frame_visible (f
);
4494 /* Must have been Qnil. */
4500 /* Make sure windows on this frame appear in calls to next-window
4501 and similar functions. */
4502 Vwindow_list
= Qnil
;
4504 return unbind_to (count
, frame
);
4508 /* FRAME is used only to get a handle on the X display. We don't pass the
4509 display info directly because we're called from frame.c, which doesn't
4510 know about that structure. */
4513 x_get_focus_frame (frame
)
4514 struct frame
*frame
;
4516 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4518 if (! dpyinfo
->x_focus_frame
)
4521 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4526 /* In certain situations, when the window manager follows a
4527 click-to-focus policy, there seems to be no way around calling
4528 XSetInputFocus to give another frame the input focus .
4530 In an ideal world, XSetInputFocus should generally be avoided so
4531 that applications don't interfere with the window manager's focus
4532 policy. But I think it's okay to use when it's clearly done
4533 following a user-command. */
4535 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4536 "Set the input focus to FRAME.\n\
4537 FRAME nil means use the selected frame.")
4541 struct frame
*f
= check_x_frame (frame
);
4542 Display
*dpy
= FRAME_X_DISPLAY (f
);
4546 count
= x_catch_errors (dpy
);
4547 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4548 RevertToParent
, CurrentTime
);
4549 x_uncatch_errors (dpy
, count
);
4556 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4557 "Internal function called by `color-defined-p', which see.")
4559 Lisp_Object color
, frame
;
4562 FRAME_PTR f
= check_x_frame (frame
);
4564 CHECK_STRING (color
, 1);
4566 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4572 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4573 "Internal function called by `color-values', which see.")
4575 Lisp_Object color
, frame
;
4578 FRAME_PTR f
= check_x_frame (frame
);
4580 CHECK_STRING (color
, 1);
4582 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4586 rgb
[0] = make_number (foo
.red
);
4587 rgb
[1] = make_number (foo
.green
);
4588 rgb
[2] = make_number (foo
.blue
);
4589 return Flist (3, rgb
);
4595 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4596 "Internal function called by `display-color-p', which see.")
4598 Lisp_Object display
;
4600 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4602 if (dpyinfo
->n_planes
<= 2)
4605 switch (dpyinfo
->visual
->class)
4618 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4620 "Return t if the X display supports shades of gray.\n\
4621 Note that color displays do support shades of gray.\n\
4622 The optional argument DISPLAY specifies which display to ask about.\n\
4623 DISPLAY should be either a frame or a display name (a string).\n\
4624 If omitted or nil, that stands for the selected frame's display.")
4626 Lisp_Object display
;
4628 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4630 if (dpyinfo
->n_planes
<= 1)
4633 switch (dpyinfo
->visual
->class)
4648 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4650 "Returns the width in pixels of the X display DISPLAY.\n\
4651 The optional argument DISPLAY specifies which display to ask about.\n\
4652 DISPLAY should be either a frame or a display name (a string).\n\
4653 If omitted or nil, that stands for the selected frame's display.")
4655 Lisp_Object display
;
4657 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4659 return make_number (dpyinfo
->width
);
4662 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4663 Sx_display_pixel_height
, 0, 1, 0,
4664 "Returns the height in pixels of the X display DISPLAY.\n\
4665 The optional argument DISPLAY specifies which display to ask about.\n\
4666 DISPLAY should be either a frame or a display name (a string).\n\
4667 If omitted or nil, that stands for the selected frame's display.")
4669 Lisp_Object display
;
4671 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4673 return make_number (dpyinfo
->height
);
4676 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4678 "Returns the number of bitplanes of the X display DISPLAY.\n\
4679 The optional argument DISPLAY specifies which display to ask about.\n\
4680 DISPLAY should be either a frame or a display name (a string).\n\
4681 If omitted or nil, that stands for the selected frame's display.")
4683 Lisp_Object display
;
4685 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4687 return make_number (dpyinfo
->n_planes
);
4690 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4692 "Returns the number of color cells of the X display DISPLAY.\n\
4693 The optional argument DISPLAY specifies which display to ask about.\n\
4694 DISPLAY should be either a frame or a display name (a string).\n\
4695 If omitted or nil, that stands for the selected frame's display.")
4697 Lisp_Object display
;
4699 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4701 return make_number (DisplayCells (dpyinfo
->display
,
4702 XScreenNumberOfScreen (dpyinfo
->screen
)));
4705 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4706 Sx_server_max_request_size
,
4708 "Returns the maximum request size of the X server of display DISPLAY.\n\
4709 The optional argument DISPLAY specifies which display to ask about.\n\
4710 DISPLAY should be either a frame or a display name (a string).\n\
4711 If omitted or nil, that stands for the selected frame's display.")
4713 Lisp_Object display
;
4715 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4717 return make_number (MAXREQUEST (dpyinfo
->display
));
4720 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4721 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4722 The optional argument DISPLAY specifies which display to ask about.\n\
4723 DISPLAY should be either a frame or a display name (a string).\n\
4724 If omitted or nil, that stands for the selected frame's display.")
4726 Lisp_Object display
;
4728 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4729 char *vendor
= ServerVendor (dpyinfo
->display
);
4731 if (! vendor
) vendor
= "";
4732 return build_string (vendor
);
4735 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4736 "Returns the version numbers of the X server of display DISPLAY.\n\
4737 The value is a list of three integers: the major and minor\n\
4738 version numbers of the X Protocol in use, and the vendor-specific release\n\
4739 number. See also the function `x-server-vendor'.\n\n\
4740 The optional argument DISPLAY specifies which display to ask about.\n\
4741 DISPLAY should be either a frame or a display name (a string).\n\
4742 If omitted or nil, that stands for the selected frame's display.")
4744 Lisp_Object display
;
4746 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4747 Display
*dpy
= dpyinfo
->display
;
4749 return Fcons (make_number (ProtocolVersion (dpy
)),
4750 Fcons (make_number (ProtocolRevision (dpy
)),
4751 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4754 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4755 "Returns the number of screens on the X server of display DISPLAY.\n\
4756 The optional argument DISPLAY specifies which display to ask about.\n\
4757 DISPLAY should be either a frame or a display name (a string).\n\
4758 If omitted or nil, that stands for the selected frame's display.")
4760 Lisp_Object display
;
4762 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4764 return make_number (ScreenCount (dpyinfo
->display
));
4767 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4768 "Returns the height in millimeters of the X display DISPLAY.\n\
4769 The optional argument DISPLAY specifies which display to ask about.\n\
4770 DISPLAY should be either a frame or a display name (a string).\n\
4771 If omitted or nil, that stands for the selected frame's display.")
4773 Lisp_Object display
;
4775 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4777 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4780 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4781 "Returns the width in millimeters of the X display DISPLAY.\n\
4782 The optional argument DISPLAY specifies which display to ask about.\n\
4783 DISPLAY should be either a frame or a display name (a string).\n\
4784 If omitted or nil, that stands for the selected frame's display.")
4786 Lisp_Object display
;
4788 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4790 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4793 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4794 Sx_display_backing_store
, 0, 1, 0,
4795 "Returns an indication of whether X display DISPLAY does backing store.\n\
4796 The value may be `always', `when-mapped', or `not-useful'.\n\
4797 The optional argument DISPLAY specifies which display to ask about.\n\
4798 DISPLAY should be either a frame or a display name (a string).\n\
4799 If omitted or nil, that stands for the selected frame's display.")
4801 Lisp_Object display
;
4803 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4806 switch (DoesBackingStore (dpyinfo
->screen
))
4809 result
= intern ("always");
4813 result
= intern ("when-mapped");
4817 result
= intern ("not-useful");
4821 error ("Strange value for BackingStore parameter of screen");
4828 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4829 Sx_display_visual_class
, 0, 1, 0,
4830 "Returns the visual class of the X display DISPLAY.\n\
4831 The value is one of the symbols `static-gray', `gray-scale',\n\
4832 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4833 The optional argument DISPLAY specifies which display to ask about.\n\
4834 DISPLAY should be either a frame or a display name (a string).\n\
4835 If omitted or nil, that stands for the selected frame's display.")
4837 Lisp_Object display
;
4839 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4842 switch (dpyinfo
->visual
->class)
4845 result
= intern ("static-gray");
4848 result
= intern ("gray-scale");
4851 result
= intern ("static-color");
4854 result
= intern ("pseudo-color");
4857 result
= intern ("true-color");
4860 result
= intern ("direct-color");
4863 error ("Display has an unknown visual class");
4870 DEFUN ("x-display-save-under", Fx_display_save_under
,
4871 Sx_display_save_under
, 0, 1, 0,
4872 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4873 The optional argument DISPLAY specifies which display to ask about.\n\
4874 DISPLAY should be either a frame or a display name (a string).\n\
4875 If omitted or nil, that stands for the selected frame's display.")
4877 Lisp_Object display
;
4879 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4881 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4889 register struct frame
*f
;
4891 return PIXEL_WIDTH (f
);
4896 register struct frame
*f
;
4898 return PIXEL_HEIGHT (f
);
4903 register struct frame
*f
;
4905 return FONT_WIDTH (f
->output_data
.x
->font
);
4910 register struct frame
*f
;
4912 return f
->output_data
.x
->line_height
;
4917 register struct frame
*f
;
4919 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4924 /************************************************************************
4926 ************************************************************************/
4929 /* Mapping visual names to visuals. */
4931 static struct visual_class
4938 {"StaticGray", StaticGray
},
4939 {"GrayScale", GrayScale
},
4940 {"StaticColor", StaticColor
},
4941 {"PseudoColor", PseudoColor
},
4942 {"TrueColor", TrueColor
},
4943 {"DirectColor", DirectColor
},
4948 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4950 /* Value is the screen number of screen SCR. This is a substitute for
4951 the X function with the same name when that doesn't exist. */
4954 XScreenNumberOfScreen (scr
)
4955 register Screen
*scr
;
4957 Display
*dpy
= scr
->display
;
4960 for (i
= 0; i
< dpy
->nscreens
; ++i
)
4961 if (scr
== dpy
->screens
[i
])
4967 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4970 /* Select the visual that should be used on display DPYINFO. Set
4971 members of DPYINFO appropriately. Called from x_term_init. */
4974 select_visual (dpyinfo
)
4975 struct x_display_info
*dpyinfo
;
4977 Display
*dpy
= dpyinfo
->display
;
4978 Screen
*screen
= dpyinfo
->screen
;
4981 /* See if a visual is specified. */
4982 value
= display_x_get_resource (dpyinfo
,
4983 build_string ("visualClass"),
4984 build_string ("VisualClass"),
4986 if (STRINGP (value
))
4988 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4989 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4990 depth, a decimal number. NAME is compared with case ignored. */
4991 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
4996 strcpy (s
, XSTRING (value
)->data
);
4997 dash
= index (s
, '-');
5000 dpyinfo
->n_planes
= atoi (dash
+ 1);
5004 /* We won't find a matching visual with depth 0, so that
5005 an error will be printed below. */
5006 dpyinfo
->n_planes
= 0;
5008 /* Determine the visual class. */
5009 for (i
= 0; visual_classes
[i
].name
; ++i
)
5010 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5012 class = visual_classes
[i
].class;
5016 /* Look up a matching visual for the specified class. */
5018 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5019 dpyinfo
->n_planes
, class, &vinfo
))
5020 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
5022 dpyinfo
->visual
= vinfo
.visual
;
5027 XVisualInfo
*vinfo
, vinfo_template
;
5029 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5032 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5034 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5036 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5037 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5038 &vinfo_template
, &n_visuals
);
5040 fatal ("Can't get proper X visual info");
5042 dpyinfo
->n_planes
= vinfo
->depth
;
5043 XFree ((char *) vinfo
);
5048 /* Return the X display structure for the display named NAME.
5049 Open a new connection if necessary. */
5051 struct x_display_info
*
5052 x_display_info_for_name (name
)
5056 struct x_display_info
*dpyinfo
;
5058 CHECK_STRING (name
, 0);
5060 if (! EQ (Vwindow_system
, intern ("x")))
5061 error ("Not using X Windows");
5063 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5065 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5068 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5073 /* Use this general default value to start with. */
5074 Vx_resource_name
= Vinvocation_name
;
5076 validate_x_resource_name ();
5078 dpyinfo
= x_term_init (name
, (char *)0,
5079 (char *) XSTRING (Vx_resource_name
)->data
);
5082 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5085 XSETFASTINT (Vwindow_system_version
, 11);
5091 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5092 1, 3, 0, "Open a connection to an X server.\n\
5093 DISPLAY is the name of the display to connect to.\n\
5094 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5095 If the optional third arg MUST-SUCCEED is non-nil,\n\
5096 terminate Emacs if we can't open the connection.")
5097 (display
, xrm_string
, must_succeed
)
5098 Lisp_Object display
, xrm_string
, must_succeed
;
5100 unsigned char *xrm_option
;
5101 struct x_display_info
*dpyinfo
;
5103 CHECK_STRING (display
, 0);
5104 if (! NILP (xrm_string
))
5105 CHECK_STRING (xrm_string
, 1);
5107 if (! EQ (Vwindow_system
, intern ("x")))
5108 error ("Not using X Windows");
5110 if (! NILP (xrm_string
))
5111 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5113 xrm_option
= (unsigned char *) 0;
5115 validate_x_resource_name ();
5117 /* This is what opens the connection and sets x_current_display.
5118 This also initializes many symbols, such as those used for input. */
5119 dpyinfo
= x_term_init (display
, xrm_option
,
5120 (char *) XSTRING (Vx_resource_name
)->data
);
5124 if (!NILP (must_succeed
))
5125 fatal ("Cannot connect to X server %s.\n\
5126 Check the DISPLAY environment variable or use `-d'.\n\
5127 Also use the `xhost' program to verify that it is set to permit\n\
5128 connections from your machine.\n",
5129 XSTRING (display
)->data
);
5131 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5136 XSETFASTINT (Vwindow_system_version
, 11);
5140 DEFUN ("x-close-connection", Fx_close_connection
,
5141 Sx_close_connection
, 1, 1, 0,
5142 "Close the connection to DISPLAY's X server.\n\
5143 For DISPLAY, specify either a frame or a display name (a string).\n\
5144 If DISPLAY is nil, that stands for the selected frame's display.")
5146 Lisp_Object display
;
5148 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5151 if (dpyinfo
->reference_count
> 0)
5152 error ("Display still has frames on it");
5155 /* Free the fonts in the font table. */
5156 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5157 if (dpyinfo
->font_table
[i
].name
)
5159 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5160 xfree (dpyinfo
->font_table
[i
].full_name
);
5161 xfree (dpyinfo
->font_table
[i
].name
);
5162 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5165 x_destroy_all_bitmaps (dpyinfo
);
5166 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5168 #ifdef USE_X_TOOLKIT
5169 XtCloseDisplay (dpyinfo
->display
);
5171 XCloseDisplay (dpyinfo
->display
);
5174 x_delete_display (dpyinfo
);
5180 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5181 "Return the list of display names that Emacs has connections to.")
5184 Lisp_Object tail
, result
;
5187 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5188 result
= Fcons (XCAR (XCAR (tail
)), result
);
5193 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5194 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5195 If ON is nil, allow buffering of requests.\n\
5196 Turning on synchronization prohibits the Xlib routines from buffering\n\
5197 requests and seriously degrades performance, but makes debugging much\n\
5199 The optional second argument DISPLAY specifies which display to act on.\n\
5200 DISPLAY should be either a frame or a display name (a string).\n\
5201 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5203 Lisp_Object display
, on
;
5205 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5207 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5212 /* Wait for responses to all X commands issued so far for frame F. */
5219 XSync (FRAME_X_DISPLAY (f
), False
);
5224 /***********************************************************************
5226 ***********************************************************************/
5228 /* Value is the number of elements of vector VECTOR. */
5230 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5232 /* List of supported image types. Use define_image_type to add new
5233 types. Use lookup_image_type to find a type for a given symbol. */
5235 static struct image_type
*image_types
;
5237 /* The symbol `image' which is the car of the lists used to represent
5240 extern Lisp_Object Qimage
;
5242 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5248 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5249 extern Lisp_Object QCdata
;
5250 Lisp_Object QCtype
, QCascent
, QCmargin
, QCrelief
;
5251 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5252 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5254 /* Other symbols. */
5256 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5258 /* Time in seconds after which images should be removed from the cache
5259 if not displayed. */
5261 Lisp_Object Vimage_cache_eviction_delay
;
5263 /* Function prototypes. */
5265 static void define_image_type
P_ ((struct image_type
*type
));
5266 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5267 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5268 static void x_laplace
P_ ((struct frame
*, struct image
*));
5269 static void x_emboss
P_ ((struct frame
*, struct image
*));
5270 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5274 /* Define a new image type from TYPE. This adds a copy of TYPE to
5275 image_types and adds the symbol *TYPE->type to Vimage_types. */
5278 define_image_type (type
)
5279 struct image_type
*type
;
5281 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5282 The initialized data segment is read-only. */
5283 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5284 bcopy (type
, p
, sizeof *p
);
5285 p
->next
= image_types
;
5287 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5291 /* Look up image type SYMBOL, and return a pointer to its image_type
5292 structure. Value is null if SYMBOL is not a known image type. */
5294 static INLINE
struct image_type
*
5295 lookup_image_type (symbol
)
5298 struct image_type
*type
;
5300 for (type
= image_types
; type
; type
= type
->next
)
5301 if (EQ (symbol
, *type
->type
))
5308 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5309 valid image specification is a list whose car is the symbol
5310 `image', and whose rest is a property list. The property list must
5311 contain a value for key `:type'. That value must be the name of a
5312 supported image type. The rest of the property list depends on the
5316 valid_image_p (object
)
5321 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5325 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5326 if (EQ (XCAR (tem
), QCtype
))
5329 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5331 struct image_type
*type
;
5332 type
= lookup_image_type (XCAR (tem
));
5334 valid_p
= type
->valid_p (object
);
5345 /* Log error message with format string FORMAT and argument ARG.
5346 Signaling an error, e.g. when an image cannot be loaded, is not a
5347 good idea because this would interrupt redisplay, and the error
5348 message display would lead to another redisplay. This function
5349 therefore simply displays a message. */
5352 image_error (format
, arg1
, arg2
)
5354 Lisp_Object arg1
, arg2
;
5356 add_to_log (format
, arg1
, arg2
);
5361 /***********************************************************************
5362 Image specifications
5363 ***********************************************************************/
5365 enum image_value_type
5367 IMAGE_DONT_CHECK_VALUE_TYPE
,
5369 IMAGE_STRING_OR_NIL_VALUE
,
5371 IMAGE_POSITIVE_INTEGER_VALUE
,
5372 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5373 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5375 IMAGE_INTEGER_VALUE
,
5376 IMAGE_FUNCTION_VALUE
,
5381 /* Structure used when parsing image specifications. */
5383 struct image_keyword
5385 /* Name of keyword. */
5388 /* The type of value allowed. */
5389 enum image_value_type type
;
5391 /* Non-zero means key must be present. */
5394 /* Used to recognize duplicate keywords in a property list. */
5397 /* The value that was found. */
5402 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5404 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5407 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5408 has the format (image KEYWORD VALUE ...). One of the keyword/
5409 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5410 image_keywords structures of size NKEYWORDS describing other
5411 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5414 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5416 struct image_keyword
*keywords
;
5423 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5426 plist
= XCDR (spec
);
5427 while (CONSP (plist
))
5429 Lisp_Object key
, value
;
5431 /* First element of a pair must be a symbol. */
5433 plist
= XCDR (plist
);
5437 /* There must follow a value. */
5440 value
= XCAR (plist
);
5441 plist
= XCDR (plist
);
5443 /* Find key in KEYWORDS. Error if not found. */
5444 for (i
= 0; i
< nkeywords
; ++i
)
5445 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5451 /* Record that we recognized the keyword. If a keywords
5452 was found more than once, it's an error. */
5453 keywords
[i
].value
= value
;
5454 ++keywords
[i
].count
;
5456 if (keywords
[i
].count
> 1)
5459 /* Check type of value against allowed type. */
5460 switch (keywords
[i
].type
)
5462 case IMAGE_STRING_VALUE
:
5463 if (!STRINGP (value
))
5467 case IMAGE_STRING_OR_NIL_VALUE
:
5468 if (!STRINGP (value
) && !NILP (value
))
5472 case IMAGE_SYMBOL_VALUE
:
5473 if (!SYMBOLP (value
))
5477 case IMAGE_POSITIVE_INTEGER_VALUE
:
5478 if (!INTEGERP (value
) || XINT (value
) <= 0)
5482 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5483 if (INTEGERP (value
) && XINT (value
) >= 0)
5486 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5487 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5491 case IMAGE_ASCENT_VALUE
:
5492 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5494 else if (INTEGERP (value
)
5495 && XINT (value
) >= 0
5496 && XINT (value
) <= 100)
5500 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5501 if (!INTEGERP (value
) || XINT (value
) < 0)
5505 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5508 case IMAGE_FUNCTION_VALUE
:
5509 value
= indirect_function (value
);
5511 || COMPILEDP (value
)
5512 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5516 case IMAGE_NUMBER_VALUE
:
5517 if (!INTEGERP (value
) && !FLOATP (value
))
5521 case IMAGE_INTEGER_VALUE
:
5522 if (!INTEGERP (value
))
5526 case IMAGE_BOOL_VALUE
:
5527 if (!NILP (value
) && !EQ (value
, Qt
))
5536 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5540 /* Check that all mandatory fields are present. */
5541 for (i
= 0; i
< nkeywords
; ++i
)
5542 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5545 return NILP (plist
);
5549 /* Return the value of KEY in image specification SPEC. Value is nil
5550 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5551 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5554 image_spec_value (spec
, key
, found
)
5555 Lisp_Object spec
, key
;
5560 xassert (valid_image_p (spec
));
5562 for (tail
= XCDR (spec
);
5563 CONSP (tail
) && CONSP (XCDR (tail
));
5564 tail
= XCDR (XCDR (tail
)))
5566 if (EQ (XCAR (tail
), key
))
5570 return XCAR (XCDR (tail
));
5580 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5581 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5582 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5583 size in canonical character units.\n\
5584 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5585 or omitted means use the selected frame.")
5586 (spec
, pixels
, frame
)
5587 Lisp_Object spec
, pixels
, frame
;
5592 if (valid_image_p (spec
))
5594 struct frame
*f
= check_x_frame (frame
);
5595 int id
= lookup_image (f
, spec
);
5596 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5597 int width
= img
->width
+ 2 * img
->hmargin
;
5598 int height
= img
->height
+ 2 * img
->vmargin
;
5601 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5602 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5604 size
= Fcons (make_number (width
), make_number (height
));
5607 error ("Invalid image specification");
5613 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5614 "Return t if image SPEC has a mask bitmap.\n\
5615 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5616 or omitted means use the selected frame.")
5618 Lisp_Object spec
, frame
;
5623 if (valid_image_p (spec
))
5625 struct frame
*f
= check_x_frame (frame
);
5626 int id
= lookup_image (f
, spec
);
5627 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5632 error ("Invalid image specification");
5639 /***********************************************************************
5640 Image type independent image structures
5641 ***********************************************************************/
5643 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5644 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5647 /* Allocate and return a new image structure for image specification
5648 SPEC. SPEC has a hash value of HASH. */
5650 static struct image
*
5651 make_image (spec
, hash
)
5655 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5657 xassert (valid_image_p (spec
));
5658 bzero (img
, sizeof *img
);
5659 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5660 xassert (img
->type
!= NULL
);
5662 img
->data
.lisp_val
= Qnil
;
5663 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5669 /* Free image IMG which was used on frame F, including its resources. */
5678 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5680 /* Remove IMG from the hash table of its cache. */
5682 img
->prev
->next
= img
->next
;
5684 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5687 img
->next
->prev
= img
->prev
;
5689 c
->images
[img
->id
] = NULL
;
5691 /* Free resources, then free IMG. */
5692 img
->type
->free (f
, img
);
5698 /* Prepare image IMG for display on frame F. Must be called before
5699 drawing an image. */
5702 prepare_image_for_display (f
, img
)
5708 /* We're about to display IMG, so set its timestamp to `now'. */
5710 img
->timestamp
= EMACS_SECS (t
);
5712 /* If IMG doesn't have a pixmap yet, load it now, using the image
5713 type dependent loader function. */
5714 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5715 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5719 /* Value is the number of pixels for the ascent of image IMG when
5720 drawn in face FACE. */
5723 image_ascent (img
, face
)
5727 int height
= img
->height
+ img
->vmargin
;
5730 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5733 /* This expression is arranged so that if the image can't be
5734 exactly centered, it will be moved slightly up. This is
5735 because a typical font is `top-heavy' (due to the presence
5736 uppercase letters), so the image placement should err towards
5737 being top-heavy too. It also just generally looks better. */
5738 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5740 ascent
= height
/ 2;
5743 ascent
= height
* img
->ascent
/ 100.0;
5750 /***********************************************************************
5751 Helper functions for X image types
5752 ***********************************************************************/
5754 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
5756 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5757 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5759 Lisp_Object color_name
,
5760 unsigned long dflt
));
5763 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5764 free the pixmap if any. MASK_P non-zero means clear the mask
5765 pixmap if any. COLORS_P non-zero means free colors allocated for
5766 the image, if any. */
5769 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
5772 int pixmap_p
, mask_p
, colors_p
;
5774 if (pixmap_p
&& img
->pixmap
)
5776 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5780 if (mask_p
&& img
->mask
)
5782 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5786 if (colors_p
&& img
->ncolors
)
5788 x_free_colors (f
, img
->colors
, img
->ncolors
);
5789 xfree (img
->colors
);
5795 /* Free X resources of image IMG which is used on frame F. */
5798 x_clear_image (f
, img
)
5803 x_clear_image_1 (f
, img
, 1, 1, 1);
5808 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5809 cannot be allocated, use DFLT. Add a newly allocated color to
5810 IMG->colors, so that it can be freed again. Value is the pixel
5813 static unsigned long
5814 x_alloc_image_color (f
, img
, color_name
, dflt
)
5817 Lisp_Object color_name
;
5821 unsigned long result
;
5823 xassert (STRINGP (color_name
));
5825 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
5827 /* This isn't called frequently so we get away with simply
5828 reallocating the color vector to the needed size, here. */
5831 (unsigned long *) xrealloc (img
->colors
,
5832 img
->ncolors
* sizeof *img
->colors
);
5833 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5834 result
= color
.pixel
;
5844 /***********************************************************************
5846 ***********************************************************************/
5848 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
5849 static void postprocess_image
P_ ((struct frame
*, struct image
*));
5852 /* Return a new, initialized image cache that is allocated from the
5853 heap. Call free_image_cache to free an image cache. */
5855 struct image_cache
*
5858 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
5861 bzero (c
, sizeof *c
);
5863 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
5864 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
5865 c
->buckets
= (struct image
**) xmalloc (size
);
5866 bzero (c
->buckets
, size
);
5871 /* Free image cache of frame F. Be aware that X frames share images
5875 free_image_cache (f
)
5878 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5883 /* Cache should not be referenced by any frame when freed. */
5884 xassert (c
->refcount
== 0);
5886 for (i
= 0; i
< c
->used
; ++i
)
5887 free_image (f
, c
->images
[i
]);
5891 FRAME_X_IMAGE_CACHE (f
) = NULL
;
5896 /* Clear image cache of frame F. FORCE_P non-zero means free all
5897 images. FORCE_P zero means clear only images that haven't been
5898 displayed for some time. Should be called from time to time to
5899 reduce the number of loaded images. If image-eviction-seconds is
5900 non-nil, this frees images in the cache which weren't displayed for
5901 at least that many seconds. */
5904 clear_image_cache (f
, force_p
)
5908 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5910 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
5917 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
5919 /* Block input so that we won't be interrupted by a SIGIO
5920 while being in an inconsistent state. */
5923 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
5925 struct image
*img
= c
->images
[i
];
5927 && (force_p
|| img
->timestamp
< old
))
5929 free_image (f
, img
);
5934 /* We may be clearing the image cache because, for example,
5935 Emacs was iconified for a longer period of time. In that
5936 case, current matrices may still contain references to
5937 images freed above. So, clear these matrices. */
5940 Lisp_Object tail
, frame
;
5942 FOR_EACH_FRAME (tail
, frame
)
5944 struct frame
*f
= XFRAME (frame
);
5946 && FRAME_X_IMAGE_CACHE (f
) == c
)
5947 clear_current_matrices (f
);
5950 ++windows_or_buffers_changed
;
5958 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
5960 "Clear the image cache of FRAME.\n\
5961 FRAME nil or omitted means use the selected frame.\n\
5962 FRAME t means clear the image caches of all frames.")
5970 FOR_EACH_FRAME (tail
, frame
)
5971 if (FRAME_X_P (XFRAME (frame
)))
5972 clear_image_cache (XFRAME (frame
), 1);
5975 clear_image_cache (check_x_frame (frame
), 1);
5981 /* Compute masks and transform image IMG on frame F, as specified
5982 by the image's specification, */
5985 postprocess_image (f
, img
)
5989 /* Manipulation of the image's mask. */
5992 Lisp_Object conversion
, spec
;
5997 /* `:heuristic-mask t'
5999 means build a mask heuristically.
6000 `:heuristic-mask (R G B)'
6001 `:mask (heuristic (R G B))'
6002 means build a mask from color (R G B) in the
6005 means remove a mask, if any. */
6007 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6009 x_build_heuristic_mask (f
, img
, mask
);
6014 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6016 if (EQ (mask
, Qheuristic
))
6017 x_build_heuristic_mask (f
, img
, Qt
);
6018 else if (CONSP (mask
)
6019 && EQ (XCAR (mask
), Qheuristic
))
6021 if (CONSP (XCDR (mask
)))
6022 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6024 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6026 else if (NILP (mask
) && found_p
&& img
->mask
)
6028 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6034 /* Should we apply an image transformation algorithm? */
6035 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6036 if (EQ (conversion
, Qdisabled
))
6037 x_disable_image (f
, img
);
6038 else if (EQ (conversion
, Qlaplace
))
6040 else if (EQ (conversion
, Qemboss
))
6042 else if (CONSP (conversion
)
6043 && EQ (XCAR (conversion
), Qedge_detection
))
6046 tem
= XCDR (conversion
);
6048 x_edge_detection (f
, img
,
6049 Fplist_get (tem
, QCmatrix
),
6050 Fplist_get (tem
, QCcolor_adjustment
));
6056 /* Return the id of image with Lisp specification SPEC on frame F.
6057 SPEC must be a valid Lisp image specification (see valid_image_p). */
6060 lookup_image (f
, spec
)
6064 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6068 struct gcpro gcpro1
;
6071 /* F must be a window-system frame, and SPEC must be a valid image
6073 xassert (FRAME_WINDOW_P (f
));
6074 xassert (valid_image_p (spec
));
6078 /* Look up SPEC in the hash table of the image cache. */
6079 hash
= sxhash (spec
, 0);
6080 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6082 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6083 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6086 /* If not found, create a new image and cache it. */
6089 extern Lisp_Object Qpostscript
;
6092 img
= make_image (spec
, hash
);
6093 cache_image (f
, img
);
6094 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6096 /* If we can't load the image, and we don't have a width and
6097 height, use some arbitrary width and height so that we can
6098 draw a rectangle for it. */
6099 if (img
->load_failed_p
)
6103 value
= image_spec_value (spec
, QCwidth
, NULL
);
6104 img
->width
= (INTEGERP (value
)
6105 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6106 value
= image_spec_value (spec
, QCheight
, NULL
);
6107 img
->height
= (INTEGERP (value
)
6108 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6112 /* Handle image type independent image attributes
6113 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
6114 Lisp_Object ascent
, margin
, relief
;
6116 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6117 if (INTEGERP (ascent
))
6118 img
->ascent
= XFASTINT (ascent
);
6119 else if (EQ (ascent
, Qcenter
))
6120 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6122 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6123 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6124 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6125 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6126 && INTEGERP (XCDR (margin
)))
6128 if (XINT (XCAR (margin
)) > 0)
6129 img
->hmargin
= XFASTINT (XCAR (margin
));
6130 if (XINT (XCDR (margin
)) > 0)
6131 img
->vmargin
= XFASTINT (XCDR (margin
));
6134 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6135 if (INTEGERP (relief
))
6137 img
->relief
= XINT (relief
);
6138 img
->hmargin
+= abs (img
->relief
);
6139 img
->vmargin
+= abs (img
->relief
);
6142 /* Do image transformations and compute masks, unless we
6143 don't have the image yet. */
6144 if (!EQ (*img
->type
->type
, Qpostscript
))
6145 postprocess_image (f
, img
);
6149 xassert (!interrupt_input_blocked
);
6152 /* We're using IMG, so set its timestamp to `now'. */
6153 EMACS_GET_TIME (now
);
6154 img
->timestamp
= EMACS_SECS (now
);
6158 /* Value is the image id. */
6163 /* Cache image IMG in the image cache of frame F. */
6166 cache_image (f
, img
)
6170 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6173 /* Find a free slot in c->images. */
6174 for (i
= 0; i
< c
->used
; ++i
)
6175 if (c
->images
[i
] == NULL
)
6178 /* If no free slot found, maybe enlarge c->images. */
6179 if (i
== c
->used
&& c
->used
== c
->size
)
6182 c
->images
= (struct image
**) xrealloc (c
->images
,
6183 c
->size
* sizeof *c
->images
);
6186 /* Add IMG to c->images, and assign IMG an id. */
6192 /* Add IMG to the cache's hash table. */
6193 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6194 img
->next
= c
->buckets
[i
];
6196 img
->next
->prev
= img
;
6198 c
->buckets
[i
] = img
;
6202 /* Call FN on every image in the image cache of frame F. Used to mark
6203 Lisp Objects in the image cache. */
6206 forall_images_in_image_cache (f
, fn
)
6208 void (*fn
) P_ ((struct image
*img
));
6210 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6212 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6216 for (i
= 0; i
< c
->used
; ++i
)
6225 /***********************************************************************
6227 ***********************************************************************/
6229 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6230 XImage
**, Pixmap
*));
6231 static void x_destroy_x_image
P_ ((XImage
*));
6232 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6235 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6236 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6237 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6238 via xmalloc. Print error messages via image_error if an error
6239 occurs. Value is non-zero if successful. */
6242 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6244 int width
, height
, depth
;
6248 Display
*display
= FRAME_X_DISPLAY (f
);
6249 Screen
*screen
= FRAME_X_SCREEN (f
);
6250 Window window
= FRAME_X_WINDOW (f
);
6252 xassert (interrupt_input_blocked
);
6255 depth
= DefaultDepthOfScreen (screen
);
6256 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6257 depth
, ZPixmap
, 0, NULL
, width
, height
,
6258 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6261 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6265 /* Allocate image raster. */
6266 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6268 /* Allocate a pixmap of the same size. */
6269 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6270 if (*pixmap
== None
)
6272 x_destroy_x_image (*ximg
);
6274 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6282 /* Destroy XImage XIMG. Free XIMG->data. */
6285 x_destroy_x_image (ximg
)
6288 xassert (interrupt_input_blocked
);
6293 XDestroyImage (ximg
);
6298 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6299 are width and height of both the image and pixmap. */
6302 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6309 xassert (interrupt_input_blocked
);
6310 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6311 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6312 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6317 /***********************************************************************
6319 ***********************************************************************/
6321 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6322 static char *slurp_file
P_ ((char *, int *));
6325 /* Find image file FILE. Look in data-directory, then
6326 x-bitmap-file-path. Value is the full name of the file found, or
6327 nil if not found. */
6330 x_find_image_file (file
)
6333 Lisp_Object file_found
, search_path
;
6334 struct gcpro gcpro1
, gcpro2
;
6338 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6339 GCPRO2 (file_found
, search_path
);
6341 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6342 fd
= openp (search_path
, file
, "", &file_found
, 0);
6354 /* Read FILE into memory. Value is a pointer to a buffer allocated
6355 with xmalloc holding FILE's contents. Value is null if an error
6356 occurred. *SIZE is set to the size of the file. */
6359 slurp_file (file
, size
)
6367 if (stat (file
, &st
) == 0
6368 && (fp
= fopen (file
, "r")) != NULL
6369 && (buf
= (char *) xmalloc (st
.st_size
),
6370 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6391 /***********************************************************************
6393 ***********************************************************************/
6395 static int xbm_scan
P_ ((char **, char *, char *, int *));
6396 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6397 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6399 static int xbm_image_p
P_ ((Lisp_Object object
));
6400 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6402 static int xbm_file_p
P_ ((Lisp_Object
));
6405 /* Indices of image specification fields in xbm_format, below. */
6407 enum xbm_keyword_index
6425 /* Vector of image_keyword structures describing the format
6426 of valid XBM image specifications. */
6428 static struct image_keyword xbm_format
[XBM_LAST
] =
6430 {":type", IMAGE_SYMBOL_VALUE
, 1},
6431 {":file", IMAGE_STRING_VALUE
, 0},
6432 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6433 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6434 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6435 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6436 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6437 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6438 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6439 {":relief", IMAGE_INTEGER_VALUE
, 0},
6440 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6441 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6442 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6445 /* Structure describing the image type XBM. */
6447 static struct image_type xbm_type
=
6456 /* Tokens returned from xbm_scan. */
6465 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6466 A valid specification is a list starting with the symbol `image'
6467 The rest of the list is a property list which must contain an
6470 If the specification specifies a file to load, it must contain
6471 an entry `:file FILENAME' where FILENAME is a string.
6473 If the specification is for a bitmap loaded from memory it must
6474 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6475 WIDTH and HEIGHT are integers > 0. DATA may be:
6477 1. a string large enough to hold the bitmap data, i.e. it must
6478 have a size >= (WIDTH + 7) / 8 * HEIGHT
6480 2. a bool-vector of size >= WIDTH * HEIGHT
6482 3. a vector of strings or bool-vectors, one for each line of the
6485 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6486 may not be specified in this case because they are defined in the
6489 Both the file and data forms may contain the additional entries
6490 `:background COLOR' and `:foreground COLOR'. If not present,
6491 foreground and background of the frame on which the image is
6492 displayed is used. */
6495 xbm_image_p (object
)
6498 struct image_keyword kw
[XBM_LAST
];
6500 bcopy (xbm_format
, kw
, sizeof kw
);
6501 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6504 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6506 if (kw
[XBM_FILE
].count
)
6508 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6511 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6513 /* In-memory XBM file. */
6514 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6522 /* Entries for `:width', `:height' and `:data' must be present. */
6523 if (!kw
[XBM_WIDTH
].count
6524 || !kw
[XBM_HEIGHT
].count
6525 || !kw
[XBM_DATA
].count
)
6528 data
= kw
[XBM_DATA
].value
;
6529 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6530 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6532 /* Check type of data, and width and height against contents of
6538 /* Number of elements of the vector must be >= height. */
6539 if (XVECTOR (data
)->size
< height
)
6542 /* Each string or bool-vector in data must be large enough
6543 for one line of the image. */
6544 for (i
= 0; i
< height
; ++i
)
6546 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6550 if (XSTRING (elt
)->size
6551 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6554 else if (BOOL_VECTOR_P (elt
))
6556 if (XBOOL_VECTOR (elt
)->size
< width
)
6563 else if (STRINGP (data
))
6565 if (XSTRING (data
)->size
6566 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6569 else if (BOOL_VECTOR_P (data
))
6571 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6582 /* Scan a bitmap file. FP is the stream to read from. Value is
6583 either an enumerator from enum xbm_token, or a character for a
6584 single-character token, or 0 at end of file. If scanning an
6585 identifier, store the lexeme of the identifier in SVAL. If
6586 scanning a number, store its value in *IVAL. */
6589 xbm_scan (s
, end
, sval
, ival
)
6598 /* Skip white space. */
6599 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6604 else if (isdigit (c
))
6606 int value
= 0, digit
;
6608 if (c
== '0' && *s
< end
)
6611 if (c
== 'x' || c
== 'X')
6618 else if (c
>= 'a' && c
<= 'f')
6619 digit
= c
- 'a' + 10;
6620 else if (c
>= 'A' && c
<= 'F')
6621 digit
= c
- 'A' + 10;
6624 value
= 16 * value
+ digit
;
6627 else if (isdigit (c
))
6631 && (c
= *(*s
)++, isdigit (c
)))
6632 value
= 8 * value
+ c
- '0';
6639 && (c
= *(*s
)++, isdigit (c
)))
6640 value
= 10 * value
+ c
- '0';
6648 else if (isalpha (c
) || c
== '_')
6652 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6659 else if (c
== '/' && **s
== '*')
6661 /* C-style comment. */
6663 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6676 /* Replacement for XReadBitmapFileData which isn't available under old
6677 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6678 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6679 the image. Return in *DATA the bitmap data allocated with xmalloc.
6680 Value is non-zero if successful. DATA null means just test if
6681 CONTENTS looks like an in-memory XBM file. */
6684 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
6685 char *contents
, *end
;
6686 int *width
, *height
;
6687 unsigned char **data
;
6690 char buffer
[BUFSIZ
];
6693 int bytes_per_line
, i
, nbytes
;
6699 LA1 = xbm_scan (&s, end, buffer, &value)
6701 #define expect(TOKEN) \
6702 if (LA1 != (TOKEN)) \
6707 #define expect_ident(IDENT) \
6708 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6713 *width
= *height
= -1;
6716 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
6718 /* Parse defines for width, height and hot-spots. */
6722 expect_ident ("define");
6723 expect (XBM_TK_IDENT
);
6725 if (LA1
== XBM_TK_NUMBER
);
6727 char *p
= strrchr (buffer
, '_');
6728 p
= p
? p
+ 1 : buffer
;
6729 if (strcmp (p
, "width") == 0)
6731 else if (strcmp (p
, "height") == 0)
6734 expect (XBM_TK_NUMBER
);
6737 if (*width
< 0 || *height
< 0)
6739 else if (data
== NULL
)
6742 /* Parse bits. Must start with `static'. */
6743 expect_ident ("static");
6744 if (LA1
== XBM_TK_IDENT
)
6746 if (strcmp (buffer
, "unsigned") == 0)
6749 expect_ident ("char");
6751 else if (strcmp (buffer
, "short") == 0)
6755 if (*width
% 16 && *width
% 16 < 9)
6758 else if (strcmp (buffer
, "char") == 0)
6766 expect (XBM_TK_IDENT
);
6772 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6773 nbytes
= bytes_per_line
* *height
;
6774 p
= *data
= (char *) xmalloc (nbytes
);
6778 for (i
= 0; i
< nbytes
; i
+= 2)
6781 expect (XBM_TK_NUMBER
);
6784 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6787 if (LA1
== ',' || LA1
== '}')
6795 for (i
= 0; i
< nbytes
; ++i
)
6798 expect (XBM_TK_NUMBER
);
6802 if (LA1
== ',' || LA1
== '}')
6827 /* Load XBM image IMG which will be displayed on frame F from buffer
6828 CONTENTS. END is the end of the buffer. Value is non-zero if
6832 xbm_load_image (f
, img
, contents
, end
)
6835 char *contents
, *end
;
6838 unsigned char *data
;
6841 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
6844 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6845 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6846 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6849 xassert (img
->width
> 0 && img
->height
> 0);
6851 /* Get foreground and background colors, maybe allocate colors. */
6852 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
6854 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
6856 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6858 background
= x_alloc_image_color (f
, img
, value
, background
);
6861 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6864 img
->width
, img
->height
,
6865 foreground
, background
,
6869 if (img
->pixmap
== None
)
6871 x_clear_image (f
, img
);
6872 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
6878 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6884 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6891 return (STRINGP (data
)
6892 && xbm_read_bitmap_data (XSTRING (data
)->data
,
6893 (XSTRING (data
)->data
6894 + STRING_BYTES (XSTRING (data
))),
6899 /* Fill image IMG which is used on frame F with pixmap data. Value is
6900 non-zero if successful. */
6908 Lisp_Object file_name
;
6910 xassert (xbm_image_p (img
->spec
));
6912 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6913 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
6914 if (STRINGP (file_name
))
6919 struct gcpro gcpro1
;
6921 file
= x_find_image_file (file_name
);
6923 if (!STRINGP (file
))
6925 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
6930 contents
= slurp_file (XSTRING (file
)->data
, &size
);
6931 if (contents
== NULL
)
6933 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6938 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
6943 struct image_keyword fmt
[XBM_LAST
];
6946 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6947 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6950 int in_memory_file_p
= 0;
6952 /* See if data looks like an in-memory XBM file. */
6953 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6954 in_memory_file_p
= xbm_file_p (data
);
6956 /* Parse the image specification. */
6957 bcopy (xbm_format
, fmt
, sizeof fmt
);
6958 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
6961 /* Get specified width, and height. */
6962 if (!in_memory_file_p
)
6964 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
6965 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
6966 xassert (img
->width
> 0 && img
->height
> 0);
6969 /* Get foreground and background colors, maybe allocate colors. */
6970 if (fmt
[XBM_FOREGROUND
].count
6971 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
6972 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
6974 if (fmt
[XBM_BACKGROUND
].count
6975 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
6976 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
6979 if (in_memory_file_p
)
6980 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
6981 (XSTRING (data
)->data
6982 + STRING_BYTES (XSTRING (data
))));
6989 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
6991 p
= bits
= (char *) alloca (nbytes
* img
->height
);
6992 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
6994 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
6996 bcopy (XSTRING (line
)->data
, p
, nbytes
);
6998 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7001 else if (STRINGP (data
))
7002 bits
= XSTRING (data
)->data
;
7004 bits
= XBOOL_VECTOR (data
)->data
;
7006 /* Create the pixmap. */
7007 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7009 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7012 img
->width
, img
->height
,
7013 foreground
, background
,
7019 image_error ("Unable to create pixmap for XBM image `%s'",
7021 x_clear_image (f
, img
);
7031 /***********************************************************************
7033 ***********************************************************************/
7037 static int xpm_image_p
P_ ((Lisp_Object object
));
7038 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7039 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7041 #include "X11/xpm.h"
7043 /* The symbol `xpm' identifying XPM-format images. */
7047 /* Indices of image specification fields in xpm_format, below. */
7049 enum xpm_keyword_index
7064 /* Vector of image_keyword structures describing the format
7065 of valid XPM image specifications. */
7067 static struct image_keyword xpm_format
[XPM_LAST
] =
7069 {":type", IMAGE_SYMBOL_VALUE
, 1},
7070 {":file", IMAGE_STRING_VALUE
, 0},
7071 {":data", IMAGE_STRING_VALUE
, 0},
7072 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7073 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7074 {":relief", IMAGE_INTEGER_VALUE
, 0},
7075 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7076 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7077 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7078 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7081 /* Structure describing the image type XBM. */
7083 static struct image_type xpm_type
=
7093 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7094 functions for allocating image colors. Our own functions handle
7095 color allocation failures more gracefully than the ones on the XPM
7098 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7099 #define ALLOC_XPM_COLORS
7102 #ifdef ALLOC_XPM_COLORS
7104 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7105 static void xpm_free_color_cache
P_ ((void));
7106 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7107 static int xpm_color_bucket
P_ ((char *));
7108 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7111 /* An entry in a hash table used to cache color definitions of named
7112 colors. This cache is necessary to speed up XPM image loading in
7113 case we do color allocations ourselves. Without it, we would need
7114 a call to XParseColor per pixel in the image. */
7116 struct xpm_cached_color
7118 /* Next in collision chain. */
7119 struct xpm_cached_color
*next
;
7121 /* Color definition (RGB and pixel color). */
7128 /* The hash table used for the color cache, and its bucket vector
7131 #define XPM_COLOR_CACHE_BUCKETS 1001
7132 struct xpm_cached_color
**xpm_color_cache
;
7134 /* Initialize the color cache. */
7137 xpm_init_color_cache (f
, attrs
)
7139 XpmAttributes
*attrs
;
7141 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7142 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7143 memset (xpm_color_cache
, 0, nbytes
);
7144 init_color_table ();
7146 if (attrs
->valuemask
& XpmColorSymbols
)
7151 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7152 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7153 attrs
->colorsymbols
[i
].value
, &color
))
7155 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7157 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7163 /* Free the color cache. */
7166 xpm_free_color_cache ()
7168 struct xpm_cached_color
*p
, *next
;
7171 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7172 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7178 xfree (xpm_color_cache
);
7179 xpm_color_cache
= NULL
;
7180 free_color_table ();
7184 /* Return the bucket index for color named COLOR_NAME in the color
7188 xpm_color_bucket (color_name
)
7194 for (s
= color_name
; *s
; ++s
)
7196 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7200 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7201 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7204 static struct xpm_cached_color
*
7205 xpm_cache_color (f
, color_name
, color
, bucket
)
7212 struct xpm_cached_color
*p
;
7215 bucket
= xpm_color_bucket (color_name
);
7217 nbytes
= sizeof *p
+ strlen (color_name
);
7218 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7219 strcpy (p
->name
, color_name
);
7221 p
->next
= xpm_color_cache
[bucket
];
7222 xpm_color_cache
[bucket
] = p
;
7227 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7228 return the cached definition in *COLOR. Otherwise, make a new
7229 entry in the cache and allocate the color. Value is zero if color
7230 allocation failed. */
7233 xpm_lookup_color (f
, color_name
, color
)
7238 struct xpm_cached_color
*p
;
7239 int h
= xpm_color_bucket (color_name
);
7241 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7242 if (strcmp (p
->name
, color_name
) == 0)
7247 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7250 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7252 p
= xpm_cache_color (f
, color_name
, color
, h
);
7259 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7260 CLOSURE is a pointer to the frame on which we allocate the
7261 color. Return in *COLOR the allocated color. Value is non-zero
7265 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7272 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7276 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7277 is a pointer to the frame on which we allocate the color. Value is
7278 non-zero if successful. */
7281 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7291 #endif /* ALLOC_XPM_COLORS */
7294 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7295 for XPM images. Such a list must consist of conses whose car and
7299 xpm_valid_color_symbols_p (color_symbols
)
7300 Lisp_Object color_symbols
;
7302 while (CONSP (color_symbols
))
7304 Lisp_Object sym
= XCAR (color_symbols
);
7306 || !STRINGP (XCAR (sym
))
7307 || !STRINGP (XCDR (sym
)))
7309 color_symbols
= XCDR (color_symbols
);
7312 return NILP (color_symbols
);
7316 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7319 xpm_image_p (object
)
7322 struct image_keyword fmt
[XPM_LAST
];
7323 bcopy (xpm_format
, fmt
, sizeof fmt
);
7324 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7325 /* Either `:file' or `:data' must be present. */
7326 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7327 /* Either no `:color-symbols' or it's a list of conses
7328 whose car and cdr are strings. */
7329 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7330 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7334 /* Load image IMG which will be displayed on frame F. Value is
7335 non-zero if successful. */
7343 XpmAttributes attrs
;
7344 Lisp_Object specified_file
, color_symbols
;
7346 /* Configure the XPM lib. Use the visual of frame F. Allocate
7347 close colors. Return colors allocated. */
7348 bzero (&attrs
, sizeof attrs
);
7349 attrs
.visual
= FRAME_X_VISUAL (f
);
7350 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7351 attrs
.valuemask
|= XpmVisual
;
7352 attrs
.valuemask
|= XpmColormap
;
7354 #ifdef ALLOC_XPM_COLORS
7355 /* Allocate colors with our own functions which handle
7356 failing color allocation more gracefully. */
7357 attrs
.color_closure
= f
;
7358 attrs
.alloc_color
= xpm_alloc_color
;
7359 attrs
.free_colors
= xpm_free_colors
;
7360 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7361 #else /* not ALLOC_XPM_COLORS */
7362 /* Let the XPM lib allocate colors. */
7363 attrs
.valuemask
|= XpmReturnAllocPixels
;
7364 #ifdef XpmAllocCloseColors
7365 attrs
.alloc_close_colors
= 1;
7366 attrs
.valuemask
|= XpmAllocCloseColors
;
7367 #else /* not XpmAllocCloseColors */
7368 attrs
.closeness
= 600;
7369 attrs
.valuemask
|= XpmCloseness
;
7370 #endif /* not XpmAllocCloseColors */
7371 #endif /* ALLOC_XPM_COLORS */
7373 /* If image specification contains symbolic color definitions, add
7374 these to `attrs'. */
7375 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7376 if (CONSP (color_symbols
))
7379 XpmColorSymbol
*xpm_syms
;
7382 attrs
.valuemask
|= XpmColorSymbols
;
7384 /* Count number of symbols. */
7385 attrs
.numsymbols
= 0;
7386 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7389 /* Allocate an XpmColorSymbol array. */
7390 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7391 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7392 bzero (xpm_syms
, size
);
7393 attrs
.colorsymbols
= xpm_syms
;
7395 /* Fill the color symbol array. */
7396 for (tail
= color_symbols
, i
= 0;
7398 ++i
, tail
= XCDR (tail
))
7400 Lisp_Object name
= XCAR (XCAR (tail
));
7401 Lisp_Object color
= XCDR (XCAR (tail
));
7402 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7403 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7404 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7405 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7409 /* Create a pixmap for the image, either from a file, or from a
7410 string buffer containing data in the same format as an XPM file. */
7411 #ifdef ALLOC_XPM_COLORS
7412 xpm_init_color_cache (f
, &attrs
);
7415 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7416 if (STRINGP (specified_file
))
7418 Lisp_Object file
= x_find_image_file (specified_file
);
7419 if (!STRINGP (file
))
7421 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7425 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7426 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7431 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7432 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7433 XSTRING (buffer
)->data
,
7434 &img
->pixmap
, &img
->mask
,
7438 if (rc
== XpmSuccess
)
7440 #ifdef ALLOC_XPM_COLORS
7441 img
->colors
= colors_in_color_table (&img
->ncolors
);
7442 #else /* not ALLOC_XPM_COLORS */
7445 img
->ncolors
= attrs
.nalloc_pixels
;
7446 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7447 * sizeof *img
->colors
);
7448 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7450 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7451 #ifdef DEBUG_X_COLORS
7452 register_color (img
->colors
[i
]);
7455 #endif /* not ALLOC_XPM_COLORS */
7457 img
->width
= attrs
.width
;
7458 img
->height
= attrs
.height
;
7459 xassert (img
->width
> 0 && img
->height
> 0);
7461 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7462 XpmFreeAttributes (&attrs
);
7469 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7472 case XpmFileInvalid
:
7473 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7477 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7480 case XpmColorFailed
:
7481 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7485 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7490 #ifdef ALLOC_XPM_COLORS
7491 xpm_free_color_cache ();
7493 return rc
== XpmSuccess
;
7496 #endif /* HAVE_XPM != 0 */
7499 /***********************************************************************
7501 ***********************************************************************/
7503 /* An entry in the color table mapping an RGB color to a pixel color. */
7508 unsigned long pixel
;
7510 /* Next in color table collision list. */
7511 struct ct_color
*next
;
7514 /* The bucket vector size to use. Must be prime. */
7518 /* Value is a hash of the RGB color given by R, G, and B. */
7520 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7522 /* The color hash table. */
7524 struct ct_color
**ct_table
;
7526 /* Number of entries in the color table. */
7528 int ct_colors_allocated
;
7530 /* Initialize the color table. */
7535 int size
= CT_SIZE
* sizeof (*ct_table
);
7536 ct_table
= (struct ct_color
**) xmalloc (size
);
7537 bzero (ct_table
, size
);
7538 ct_colors_allocated
= 0;
7542 /* Free memory associated with the color table. */
7548 struct ct_color
*p
, *next
;
7550 for (i
= 0; i
< CT_SIZE
; ++i
)
7551 for (p
= ct_table
[i
]; p
; p
= next
)
7562 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7563 entry for that color already is in the color table, return the
7564 pixel color of that entry. Otherwise, allocate a new color for R,
7565 G, B, and make an entry in the color table. */
7567 static unsigned long
7568 lookup_rgb_color (f
, r
, g
, b
)
7572 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7573 int i
= hash
% CT_SIZE
;
7576 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7577 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7590 cmap
= FRAME_X_COLORMAP (f
);
7591 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7595 ++ct_colors_allocated
;
7597 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7601 p
->pixel
= color
.pixel
;
7602 p
->next
= ct_table
[i
];
7606 return FRAME_FOREGROUND_PIXEL (f
);
7613 /* Look up pixel color PIXEL which is used on frame F in the color
7614 table. If not already present, allocate it. Value is PIXEL. */
7616 static unsigned long
7617 lookup_pixel_color (f
, pixel
)
7619 unsigned long pixel
;
7621 int i
= pixel
% CT_SIZE
;
7624 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7625 if (p
->pixel
== pixel
)
7634 cmap
= FRAME_X_COLORMAP (f
);
7635 color
.pixel
= pixel
;
7636 x_query_color (f
, &color
);
7637 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7641 ++ct_colors_allocated
;
7643 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7648 p
->next
= ct_table
[i
];
7652 return FRAME_FOREGROUND_PIXEL (f
);
7659 /* Value is a vector of all pixel colors contained in the color table,
7660 allocated via xmalloc. Set *N to the number of colors. */
7662 static unsigned long *
7663 colors_in_color_table (n
)
7668 unsigned long *colors
;
7670 if (ct_colors_allocated
== 0)
7677 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7679 *n
= ct_colors_allocated
;
7681 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7682 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7683 colors
[j
++] = p
->pixel
;
7691 /***********************************************************************
7693 ***********************************************************************/
7695 static void x_laplace_write_row
P_ ((struct frame
*, long *,
7696 int, XImage
*, int));
7697 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
7698 XColor
*, int, XImage
*, int));
7699 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
7700 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
7701 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
7703 /* Non-zero means draw a cross on images having `:conversion
7706 int cross_disabled_images
;
7708 /* Edge detection matrices for different edge-detection
7711 static int emboss_matrix
[9] = {
7713 2, -1, 0, /* y - 1 */
7715 0, 1, -2 /* y + 1 */
7718 static int laplace_matrix
[9] = {
7720 1, 0, 0, /* y - 1 */
7722 0, 0, -1 /* y + 1 */
7725 /* Value is the intensity of the color whose red/green/blue values
7728 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7731 /* On frame F, return an array of XColor structures describing image
7732 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7733 non-zero means also fill the red/green/blue members of the XColor
7734 structures. Value is a pointer to the array of XColors structures,
7735 allocated with xmalloc; it must be freed by the caller. */
7738 x_to_xcolors (f
, img
, rgb_p
)
7747 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
7749 /* Get the X image IMG->pixmap. */
7750 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7751 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7753 /* Fill the `pixel' members of the XColor array. I wished there
7754 were an easy and portable way to circumvent XGetPixel. */
7756 for (y
= 0; y
< img
->height
; ++y
)
7760 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7761 p
->pixel
= XGetPixel (ximg
, x
, y
);
7764 x_query_colors (f
, row
, img
->width
);
7767 XDestroyImage (ximg
);
7772 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7773 RGB members are set. F is the frame on which this all happens.
7774 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7777 x_from_xcolors (f
, img
, colors
)
7787 init_color_table ();
7789 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
7792 for (y
= 0; y
< img
->height
; ++y
)
7793 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7795 unsigned long pixel
;
7796 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
7797 XPutPixel (oimg
, x
, y
, pixel
);
7801 x_clear_image_1 (f
, img
, 1, 0, 1);
7803 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7804 x_destroy_x_image (oimg
);
7805 img
->pixmap
= pixmap
;
7806 img
->colors
= colors_in_color_table (&img
->ncolors
);
7807 free_color_table ();
7811 /* On frame F, perform edge-detection on image IMG.
7813 MATRIX is a nine-element array specifying the transformation
7814 matrix. See emboss_matrix for an example.
7816 COLOR_ADJUST is a color adjustment added to each pixel of the
7820 x_detect_edges (f
, img
, matrix
, color_adjust
)
7823 int matrix
[9], color_adjust
;
7825 XColor
*colors
= x_to_xcolors (f
, img
, 1);
7829 for (i
= sum
= 0; i
< 9; ++i
)
7830 sum
+= abs (matrix
[i
]);
7832 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7834 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
7836 for (y
= 0; y
< img
->height
; ++y
)
7838 p
= COLOR (new, 0, y
);
7839 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7840 p
= COLOR (new, img
->width
- 1, y
);
7841 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7844 for (x
= 1; x
< img
->width
- 1; ++x
)
7846 p
= COLOR (new, x
, 0);
7847 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7848 p
= COLOR (new, x
, img
->height
- 1);
7849 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7852 for (y
= 1; y
< img
->height
- 1; ++y
)
7854 p
= COLOR (new, 1, y
);
7856 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
7858 int r
, g
, b
, y1
, x1
;
7861 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
7862 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
7865 XColor
*t
= COLOR (colors
, x1
, y1
);
7866 r
+= matrix
[i
] * t
->red
;
7867 g
+= matrix
[i
] * t
->green
;
7868 b
+= matrix
[i
] * t
->blue
;
7871 r
= (r
/ sum
+ color_adjust
) & 0xffff;
7872 g
= (g
/ sum
+ color_adjust
) & 0xffff;
7873 b
= (b
/ sum
+ color_adjust
) & 0xffff;
7874 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
7879 x_from_xcolors (f
, img
, new);
7885 /* Perform the pre-defined `emboss' edge-detection on image IMG
7893 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
7897 /* Perform the pre-defined `laplace' edge-detection on image IMG
7905 x_detect_edges (f
, img
, laplace_matrix
, 45000);
7909 /* Perform edge-detection on image IMG on frame F, with specified
7910 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7912 MATRIX must be either
7914 - a list of at least 9 numbers in row-major form
7915 - a vector of at least 9 numbers
7917 COLOR_ADJUST nil means use a default; otherwise it must be a
7921 x_edge_detection (f
, img
, matrix
, color_adjust
)
7924 Lisp_Object matrix
, color_adjust
;
7932 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
7933 ++i
, matrix
= XCDR (matrix
))
7934 trans
[i
] = XFLOATINT (XCAR (matrix
));
7936 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
7938 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
7939 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
7942 if (NILP (color_adjust
))
7943 color_adjust
= make_number (0xffff / 2);
7945 if (i
== 9 && NUMBERP (color_adjust
))
7946 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
7950 /* Transform image IMG on frame F so that it looks disabled. */
7953 x_disable_image (f
, img
)
7957 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7959 if (dpyinfo
->n_planes
>= 2)
7961 /* Color (or grayscale). Convert to gray, and equalize. Just
7962 drawing such images with a stipple can look very odd, so
7963 we're using this method instead. */
7964 XColor
*colors
= x_to_xcolors (f
, img
, 1);
7966 const int h
= 15000;
7967 const int l
= 30000;
7969 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
7973 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
7974 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
7975 p
->red
= p
->green
= p
->blue
= i2
;
7978 x_from_xcolors (f
, img
, colors
);
7981 /* Draw a cross over the disabled image, if we must or if we
7983 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
7985 Display
*dpy
= FRAME_X_DISPLAY (f
);
7988 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
7989 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
7990 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
7991 img
->width
- 1, img
->height
- 1);
7992 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
7998 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
7999 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8000 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8001 img
->width
- 1, img
->height
- 1);
8002 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8010 /* Build a mask for image IMG which is used on frame F. FILE is the
8011 name of an image file, for error messages. HOW determines how to
8012 determine the background color of IMG. If it is a list '(R G B)',
8013 with R, G, and B being integers >= 0, take that as the color of the
8014 background. Otherwise, determine the background color of IMG
8015 heuristically. Value is non-zero if successful. */
8018 x_build_heuristic_mask (f
, img
, how
)
8023 Display
*dpy
= FRAME_X_DISPLAY (f
);
8024 XImage
*ximg
, *mask_img
;
8025 int x
, y
, rc
, look_at_corners_p
;
8026 unsigned long bg
= 0;
8030 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8034 /* Create an image and pixmap serving as mask. */
8035 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8036 &mask_img
, &img
->mask
);
8040 /* Get the X image of IMG->pixmap. */
8041 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8044 /* Determine the background color of ximg. If HOW is `(R G B)'
8045 take that as color. Otherwise, try to determine the color
8047 look_at_corners_p
= 1;
8055 && NATNUMP (XCAR (how
)))
8057 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8061 if (i
== 3 && NILP (how
))
8063 char color_name
[30];
8064 XColor exact
, color
;
8067 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8069 cmap
= FRAME_X_COLORMAP (f
);
8070 if (XLookupColor (dpy
, cmap
, color_name
, &exact
, &color
))
8073 look_at_corners_p
= 0;
8078 if (look_at_corners_p
)
8080 unsigned long corners
[4];
8083 /* Get the colors at the corners of ximg. */
8084 corners
[0] = XGetPixel (ximg
, 0, 0);
8085 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
8086 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
8087 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
8089 /* Choose the most frequently found color as background. */
8090 for (i
= best_count
= 0; i
< 4; ++i
)
8094 for (j
= n
= 0; j
< 4; ++j
)
8095 if (corners
[i
] == corners
[j
])
8099 bg
= corners
[i
], best_count
= n
;
8103 /* Set all bits in mask_img to 1 whose color in ximg is different
8104 from the background color bg. */
8105 for (y
= 0; y
< img
->height
; ++y
)
8106 for (x
= 0; x
< img
->width
; ++x
)
8107 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8109 /* Put mask_img into img->mask. */
8110 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8111 x_destroy_x_image (mask_img
);
8112 XDestroyImage (ximg
);
8119 /***********************************************************************
8120 PBM (mono, gray, color)
8121 ***********************************************************************/
8123 static int pbm_image_p
P_ ((Lisp_Object object
));
8124 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8125 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8127 /* The symbol `pbm' identifying images of this type. */
8131 /* Indices of image specification fields in gs_format, below. */
8133 enum pbm_keyword_index
8149 /* Vector of image_keyword structures describing the format
8150 of valid user-defined image specifications. */
8152 static struct image_keyword pbm_format
[PBM_LAST
] =
8154 {":type", IMAGE_SYMBOL_VALUE
, 1},
8155 {":file", IMAGE_STRING_VALUE
, 0},
8156 {":data", IMAGE_STRING_VALUE
, 0},
8157 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8158 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8159 {":relief", IMAGE_INTEGER_VALUE
, 0},
8160 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8161 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8162 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8163 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8164 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8167 /* Structure describing the image type `pbm'. */
8169 static struct image_type pbm_type
=
8179 /* Return non-zero if OBJECT is a valid PBM image specification. */
8182 pbm_image_p (object
)
8185 struct image_keyword fmt
[PBM_LAST
];
8187 bcopy (pbm_format
, fmt
, sizeof fmt
);
8189 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8192 /* Must specify either :data or :file. */
8193 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8197 /* Scan a decimal number from *S and return it. Advance *S while
8198 reading the number. END is the end of the string. Value is -1 at
8202 pbm_scan_number (s
, end
)
8203 unsigned char **s
, *end
;
8205 int c
= 0, val
= -1;
8209 /* Skip white-space. */
8210 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8215 /* Skip comment to end of line. */
8216 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8219 else if (isdigit (c
))
8221 /* Read decimal number. */
8223 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8224 val
= 10 * val
+ c
- '0';
8235 /* Load PBM image IMG for use on frame F. */
8243 int width
, height
, max_color_idx
= 0;
8245 Lisp_Object file
, specified_file
;
8246 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8247 struct gcpro gcpro1
;
8248 unsigned char *contents
= NULL
;
8249 unsigned char *end
, *p
;
8252 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8256 if (STRINGP (specified_file
))
8258 file
= x_find_image_file (specified_file
);
8259 if (!STRINGP (file
))
8261 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8266 contents
= slurp_file (XSTRING (file
)->data
, &size
);
8267 if (contents
== NULL
)
8269 image_error ("Error reading `%s'", file
, Qnil
);
8275 end
= contents
+ size
;
8280 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8281 p
= XSTRING (data
)->data
;
8282 end
= p
+ STRING_BYTES (XSTRING (data
));
8285 /* Check magic number. */
8286 if (end
- p
< 2 || *p
++ != 'P')
8288 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8298 raw_p
= 0, type
= PBM_MONO
;
8302 raw_p
= 0, type
= PBM_GRAY
;
8306 raw_p
= 0, type
= PBM_COLOR
;
8310 raw_p
= 1, type
= PBM_MONO
;
8314 raw_p
= 1, type
= PBM_GRAY
;
8318 raw_p
= 1, type
= PBM_COLOR
;
8322 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8326 /* Read width, height, maximum color-component. Characters
8327 starting with `#' up to the end of a line are ignored. */
8328 width
= pbm_scan_number (&p
, end
);
8329 height
= pbm_scan_number (&p
, end
);
8331 if (type
!= PBM_MONO
)
8333 max_color_idx
= pbm_scan_number (&p
, end
);
8334 if (raw_p
&& max_color_idx
> 255)
8335 max_color_idx
= 255;
8340 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8343 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8344 &ximg
, &img
->pixmap
))
8347 /* Initialize the color hash table. */
8348 init_color_table ();
8350 if (type
== PBM_MONO
)
8353 struct image_keyword fmt
[PBM_LAST
];
8354 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8355 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8357 /* Parse the image specification. */
8358 bcopy (pbm_format
, fmt
, sizeof fmt
);
8359 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8361 /* Get foreground and background colors, maybe allocate colors. */
8362 if (fmt
[PBM_FOREGROUND
].count
8363 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8364 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8365 if (fmt
[PBM_BACKGROUND
].count
8366 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8367 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8369 for (y
= 0; y
< height
; ++y
)
8370 for (x
= 0; x
< width
; ++x
)
8380 g
= pbm_scan_number (&p
, end
);
8382 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8387 for (y
= 0; y
< height
; ++y
)
8388 for (x
= 0; x
< width
; ++x
)
8392 if (type
== PBM_GRAY
)
8393 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8402 r
= pbm_scan_number (&p
, end
);
8403 g
= pbm_scan_number (&p
, end
);
8404 b
= pbm_scan_number (&p
, end
);
8407 if (r
< 0 || g
< 0 || b
< 0)
8411 XDestroyImage (ximg
);
8412 image_error ("Invalid pixel value in image `%s'",
8417 /* RGB values are now in the range 0..max_color_idx.
8418 Scale this to the range 0..0xffff supported by X. */
8419 r
= (double) r
* 65535 / max_color_idx
;
8420 g
= (double) g
* 65535 / max_color_idx
;
8421 b
= (double) b
* 65535 / max_color_idx
;
8422 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8426 /* Store in IMG->colors the colors allocated for the image, and
8427 free the color table. */
8428 img
->colors
= colors_in_color_table (&img
->ncolors
);
8429 free_color_table ();
8431 /* Put the image into a pixmap. */
8432 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8433 x_destroy_x_image (ximg
);
8436 img
->height
= height
;
8445 /***********************************************************************
8447 ***********************************************************************/
8453 /* Function prototypes. */
8455 static int png_image_p
P_ ((Lisp_Object object
));
8456 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8458 /* The symbol `png' identifying images of this type. */
8462 /* Indices of image specification fields in png_format, below. */
8464 enum png_keyword_index
8478 /* Vector of image_keyword structures describing the format
8479 of valid user-defined image specifications. */
8481 static struct image_keyword png_format
[PNG_LAST
] =
8483 {":type", IMAGE_SYMBOL_VALUE
, 1},
8484 {":data", IMAGE_STRING_VALUE
, 0},
8485 {":file", IMAGE_STRING_VALUE
, 0},
8486 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8487 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8488 {":relief", IMAGE_INTEGER_VALUE
, 0},
8489 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8490 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8491 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8494 /* Structure describing the image type `png'. */
8496 static struct image_type png_type
=
8506 /* Return non-zero if OBJECT is a valid PNG image specification. */
8509 png_image_p (object
)
8512 struct image_keyword fmt
[PNG_LAST
];
8513 bcopy (png_format
, fmt
, sizeof fmt
);
8515 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8518 /* Must specify either the :data or :file keyword. */
8519 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8523 /* Error and warning handlers installed when the PNG library
8527 my_png_error (png_ptr
, msg
)
8528 png_struct
*png_ptr
;
8531 xassert (png_ptr
!= NULL
);
8532 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8533 longjmp (png_ptr
->jmpbuf
, 1);
8538 my_png_warning (png_ptr
, msg
)
8539 png_struct
*png_ptr
;
8542 xassert (png_ptr
!= NULL
);
8543 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8546 /* Memory source for PNG decoding. */
8548 struct png_memory_storage
8550 unsigned char *bytes
; /* The data */
8551 size_t len
; /* How big is it? */
8552 int index
; /* Where are we? */
8556 /* Function set as reader function when reading PNG image from memory.
8557 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8558 bytes from the input to DATA. */
8561 png_read_from_memory (png_ptr
, data
, length
)
8562 png_structp png_ptr
;
8566 struct png_memory_storage
*tbr
8567 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8569 if (length
> tbr
->len
- tbr
->index
)
8570 png_error (png_ptr
, "Read error");
8572 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8573 tbr
->index
= tbr
->index
+ length
;
8576 /* Load PNG image IMG for use on frame F. Value is non-zero if
8584 Lisp_Object file
, specified_file
;
8585 Lisp_Object specified_data
;
8587 XImage
*ximg
, *mask_img
= NULL
;
8588 struct gcpro gcpro1
;
8589 png_struct
*png_ptr
= NULL
;
8590 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8591 FILE *volatile fp
= NULL
;
8593 png_byte
* volatile pixels
= NULL
;
8594 png_byte
** volatile rows
= NULL
;
8595 png_uint_32 width
, height
;
8596 int bit_depth
, color_type
, interlace_type
;
8598 png_uint_32 row_bytes
;
8601 double screen_gamma
, image_gamma
;
8603 struct png_memory_storage tbr
; /* Data to be read */
8605 /* Find out what file to load. */
8606 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8607 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8611 if (NILP (specified_data
))
8613 file
= x_find_image_file (specified_file
);
8614 if (!STRINGP (file
))
8616 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8621 /* Open the image file. */
8622 fp
= fopen (XSTRING (file
)->data
, "rb");
8625 image_error ("Cannot open image file `%s'", file
, Qnil
);
8631 /* Check PNG signature. */
8632 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8633 || !png_check_sig (sig
, sizeof sig
))
8635 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8643 /* Read from memory. */
8644 tbr
.bytes
= XSTRING (specified_data
)->data
;
8645 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8648 /* Check PNG signature. */
8649 if (tbr
.len
< sizeof sig
8650 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8652 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8657 /* Need to skip past the signature. */
8658 tbr
.bytes
+= sizeof (sig
);
8661 /* Initialize read and info structs for PNG lib. */
8662 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8663 my_png_error
, my_png_warning
);
8666 if (fp
) fclose (fp
);
8671 info_ptr
= png_create_info_struct (png_ptr
);
8674 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8675 if (fp
) fclose (fp
);
8680 end_info
= png_create_info_struct (png_ptr
);
8683 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8684 if (fp
) fclose (fp
);
8689 /* Set error jump-back. We come back here when the PNG library
8690 detects an error. */
8691 if (setjmp (png_ptr
->jmpbuf
))
8695 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8698 if (fp
) fclose (fp
);
8703 /* Read image info. */
8704 if (!NILP (specified_data
))
8705 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
8707 png_init_io (png_ptr
, fp
);
8709 png_set_sig_bytes (png_ptr
, sizeof sig
);
8710 png_read_info (png_ptr
, info_ptr
);
8711 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8712 &interlace_type
, NULL
, NULL
);
8714 /* If image contains simply transparency data, we prefer to
8715 construct a clipping mask. */
8716 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8721 /* This function is easier to write if we only have to handle
8722 one data format: RGB or RGBA with 8 bits per channel. Let's
8723 transform other formats into that format. */
8725 /* Strip more than 8 bits per channel. */
8726 if (bit_depth
== 16)
8727 png_set_strip_16 (png_ptr
);
8729 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8731 png_set_expand (png_ptr
);
8733 /* Convert grayscale images to RGB. */
8734 if (color_type
== PNG_COLOR_TYPE_GRAY
8735 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
8736 png_set_gray_to_rgb (png_ptr
);
8738 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8739 gamma_str
= getenv ("SCREEN_GAMMA");
8740 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
8742 /* Tell the PNG lib to handle gamma correction for us. */
8744 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8745 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
8746 /* There is a special chunk in the image specifying the gamma. */
8747 png_set_sRGB (png_ptr
, info_ptr
, intent
);
8750 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
8751 /* Image contains gamma information. */
8752 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
8754 /* Use a default of 0.5 for the image gamma. */
8755 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
8757 /* Handle alpha channel by combining the image with a background
8758 color. Do this only if a real alpha channel is supplied. For
8759 simple transparency, we prefer a clipping mask. */
8762 png_color_16
*image_background
;
8764 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
8765 /* Image contains a background color with which to
8766 combine the image. */
8767 png_set_background (png_ptr
, image_background
,
8768 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
8771 /* Image does not contain a background color with which
8772 to combine the image data via an alpha channel. Use
8773 the frame's background instead. */
8776 png_color_16 frame_background
;
8778 cmap
= FRAME_X_COLORMAP (f
);
8779 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8780 x_query_color (f
, &color
);
8782 bzero (&frame_background
, sizeof frame_background
);
8783 frame_background
.red
= color
.red
;
8784 frame_background
.green
= color
.green
;
8785 frame_background
.blue
= color
.blue
;
8787 png_set_background (png_ptr
, &frame_background
,
8788 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8792 /* Update info structure. */
8793 png_read_update_info (png_ptr
, info_ptr
);
8795 /* Get number of channels. Valid values are 1 for grayscale images
8796 and images with a palette, 2 for grayscale images with transparency
8797 information (alpha channel), 3 for RGB images, and 4 for RGB
8798 images with alpha channel, i.e. RGBA. If conversions above were
8799 sufficient we should only have 3 or 4 channels here. */
8800 channels
= png_get_channels (png_ptr
, info_ptr
);
8801 xassert (channels
== 3 || channels
== 4);
8803 /* Number of bytes needed for one row of the image. */
8804 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
8806 /* Allocate memory for the image. */
8807 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
8808 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
8809 for (i
= 0; i
< height
; ++i
)
8810 rows
[i
] = pixels
+ i
* row_bytes
;
8812 /* Read the entire image. */
8813 png_read_image (png_ptr
, rows
);
8814 png_read_end (png_ptr
, info_ptr
);
8821 /* Create the X image and pixmap. */
8822 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
8826 /* Create an image and pixmap serving as mask if the PNG image
8827 contains an alpha channel. */
8830 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
8831 &mask_img
, &img
->mask
))
8833 x_destroy_x_image (ximg
);
8834 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
8839 /* Fill the X image and mask from PNG data. */
8840 init_color_table ();
8842 for (y
= 0; y
< height
; ++y
)
8844 png_byte
*p
= rows
[y
];
8846 for (x
= 0; x
< width
; ++x
)
8853 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8855 /* An alpha channel, aka mask channel, associates variable
8856 transparency with an image. Where other image formats
8857 support binary transparency---fully transparent or fully
8858 opaque---PNG allows up to 254 levels of partial transparency.
8859 The PNG library implements partial transparency by combining
8860 the image with a specified background color.
8862 I'm not sure how to handle this here nicely: because the
8863 background on which the image is displayed may change, for
8864 real alpha channel support, it would be necessary to create
8865 a new image for each possible background.
8867 What I'm doing now is that a mask is created if we have
8868 boolean transparency information. Otherwise I'm using
8869 the frame's background color to combine the image with. */
8874 XPutPixel (mask_img
, x
, y
, *p
> 0);
8880 /* Remember colors allocated for this image. */
8881 img
->colors
= colors_in_color_table (&img
->ncolors
);
8882 free_color_table ();
8885 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8890 img
->height
= height
;
8892 /* Put the image into the pixmap, then free the X image and its buffer. */
8893 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8894 x_destroy_x_image (ximg
);
8896 /* Same for the mask. */
8899 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8900 x_destroy_x_image (mask_img
);
8907 #endif /* HAVE_PNG != 0 */
8911 /***********************************************************************
8913 ***********************************************************************/
8917 /* Work around a warning about HAVE_STDLIB_H being redefined in
8919 #ifdef HAVE_STDLIB_H
8920 #define HAVE_STDLIB_H_1
8921 #undef HAVE_STDLIB_H
8922 #endif /* HAVE_STLIB_H */
8924 #include <jpeglib.h>
8928 #ifdef HAVE_STLIB_H_1
8929 #define HAVE_STDLIB_H 1
8932 static int jpeg_image_p
P_ ((Lisp_Object object
));
8933 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
8935 /* The symbol `jpeg' identifying images of this type. */
8939 /* Indices of image specification fields in gs_format, below. */
8941 enum jpeg_keyword_index
8950 JPEG_HEURISTIC_MASK
,
8955 /* Vector of image_keyword structures describing the format
8956 of valid user-defined image specifications. */
8958 static struct image_keyword jpeg_format
[JPEG_LAST
] =
8960 {":type", IMAGE_SYMBOL_VALUE
, 1},
8961 {":data", IMAGE_STRING_VALUE
, 0},
8962 {":file", IMAGE_STRING_VALUE
, 0},
8963 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8964 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8965 {":relief", IMAGE_INTEGER_VALUE
, 0},
8966 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8967 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8968 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8971 /* Structure describing the image type `jpeg'. */
8973 static struct image_type jpeg_type
=
8983 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8986 jpeg_image_p (object
)
8989 struct image_keyword fmt
[JPEG_LAST
];
8991 bcopy (jpeg_format
, fmt
, sizeof fmt
);
8993 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
8996 /* Must specify either the :data or :file keyword. */
8997 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9001 struct my_jpeg_error_mgr
9003 struct jpeg_error_mgr pub
;
9004 jmp_buf setjmp_buffer
;
9009 my_error_exit (cinfo
)
9012 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9013 longjmp (mgr
->setjmp_buffer
, 1);
9017 /* Init source method for JPEG data source manager. Called by
9018 jpeg_read_header() before any data is actually read. See
9019 libjpeg.doc from the JPEG lib distribution. */
9022 our_init_source (cinfo
)
9023 j_decompress_ptr cinfo
;
9028 /* Fill input buffer method for JPEG data source manager. Called
9029 whenever more data is needed. We read the whole image in one step,
9030 so this only adds a fake end of input marker at the end. */
9033 our_fill_input_buffer (cinfo
)
9034 j_decompress_ptr cinfo
;
9036 /* Insert a fake EOI marker. */
9037 struct jpeg_source_mgr
*src
= cinfo
->src
;
9038 static JOCTET buffer
[2];
9040 buffer
[0] = (JOCTET
) 0xFF;
9041 buffer
[1] = (JOCTET
) JPEG_EOI
;
9043 src
->next_input_byte
= buffer
;
9044 src
->bytes_in_buffer
= 2;
9049 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9050 is the JPEG data source manager. */
9053 our_skip_input_data (cinfo
, num_bytes
)
9054 j_decompress_ptr cinfo
;
9057 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9061 if (num_bytes
> src
->bytes_in_buffer
)
9062 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9064 src
->bytes_in_buffer
-= num_bytes
;
9065 src
->next_input_byte
+= num_bytes
;
9070 /* Method to terminate data source. Called by
9071 jpeg_finish_decompress() after all data has been processed. */
9074 our_term_source (cinfo
)
9075 j_decompress_ptr cinfo
;
9080 /* Set up the JPEG lib for reading an image from DATA which contains
9081 LEN bytes. CINFO is the decompression info structure created for
9082 reading the image. */
9085 jpeg_memory_src (cinfo
, data
, len
)
9086 j_decompress_ptr cinfo
;
9090 struct jpeg_source_mgr
*src
;
9092 if (cinfo
->src
== NULL
)
9094 /* First time for this JPEG object? */
9095 cinfo
->src
= (struct jpeg_source_mgr
*)
9096 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9097 sizeof (struct jpeg_source_mgr
));
9098 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9099 src
->next_input_byte
= data
;
9102 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9103 src
->init_source
= our_init_source
;
9104 src
->fill_input_buffer
= our_fill_input_buffer
;
9105 src
->skip_input_data
= our_skip_input_data
;
9106 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9107 src
->term_source
= our_term_source
;
9108 src
->bytes_in_buffer
= len
;
9109 src
->next_input_byte
= data
;
9113 /* Load image IMG for use on frame F. Patterned after example.c
9114 from the JPEG lib. */
9121 struct jpeg_decompress_struct cinfo
;
9122 struct my_jpeg_error_mgr mgr
;
9123 Lisp_Object file
, specified_file
;
9124 Lisp_Object specified_data
;
9125 FILE * volatile fp
= NULL
;
9127 int row_stride
, x
, y
;
9128 XImage
*ximg
= NULL
;
9130 unsigned long *colors
;
9132 struct gcpro gcpro1
;
9134 /* Open the JPEG file. */
9135 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9136 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9140 if (NILP (specified_data
))
9142 file
= x_find_image_file (specified_file
);
9143 if (!STRINGP (file
))
9145 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9150 fp
= fopen (XSTRING (file
)->data
, "r");
9153 image_error ("Cannot open `%s'", file
, Qnil
);
9159 /* Customize libjpeg's error handling to call my_error_exit when an
9160 error is detected. This function will perform a longjmp. */
9161 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9162 mgr
.pub
.error_exit
= my_error_exit
;
9164 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9168 /* Called from my_error_exit. Display a JPEG error. */
9169 char buffer
[JMSG_LENGTH_MAX
];
9170 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9171 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9172 build_string (buffer
));
9175 /* Close the input file and destroy the JPEG object. */
9177 fclose ((FILE *) fp
);
9178 jpeg_destroy_decompress (&cinfo
);
9180 /* If we already have an XImage, free that. */
9181 x_destroy_x_image (ximg
);
9183 /* Free pixmap and colors. */
9184 x_clear_image (f
, img
);
9190 /* Create the JPEG decompression object. Let it read from fp.
9191 Read the JPEG image header. */
9192 jpeg_create_decompress (&cinfo
);
9194 if (NILP (specified_data
))
9195 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9197 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
9198 STRING_BYTES (XSTRING (specified_data
)));
9200 jpeg_read_header (&cinfo
, TRUE
);
9202 /* Customize decompression so that color quantization will be used.
9203 Start decompression. */
9204 cinfo
.quantize_colors
= TRUE
;
9205 jpeg_start_decompress (&cinfo
);
9206 width
= img
->width
= cinfo
.output_width
;
9207 height
= img
->height
= cinfo
.output_height
;
9209 /* Create X image and pixmap. */
9210 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9211 longjmp (mgr
.setjmp_buffer
, 2);
9213 /* Allocate colors. When color quantization is used,
9214 cinfo.actual_number_of_colors has been set with the number of
9215 colors generated, and cinfo.colormap is a two-dimensional array
9216 of color indices in the range 0..cinfo.actual_number_of_colors.
9217 No more than 255 colors will be generated. */
9221 if (cinfo
.out_color_components
> 2)
9222 ir
= 0, ig
= 1, ib
= 2;
9223 else if (cinfo
.out_color_components
> 1)
9224 ir
= 0, ig
= 1, ib
= 0;
9226 ir
= 0, ig
= 0, ib
= 0;
9228 /* Use the color table mechanism because it handles colors that
9229 cannot be allocated nicely. Such colors will be replaced with
9230 a default color, and we don't have to care about which colors
9231 can be freed safely, and which can't. */
9232 init_color_table ();
9233 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9236 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9238 /* Multiply RGB values with 255 because X expects RGB values
9239 in the range 0..0xffff. */
9240 int r
= cinfo
.colormap
[ir
][i
] << 8;
9241 int g
= cinfo
.colormap
[ig
][i
] << 8;
9242 int b
= cinfo
.colormap
[ib
][i
] << 8;
9243 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9246 /* Remember those colors actually allocated. */
9247 img
->colors
= colors_in_color_table (&img
->ncolors
);
9248 free_color_table ();
9252 row_stride
= width
* cinfo
.output_components
;
9253 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9255 for (y
= 0; y
< height
; ++y
)
9257 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9258 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9259 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9263 jpeg_finish_decompress (&cinfo
);
9264 jpeg_destroy_decompress (&cinfo
);
9266 fclose ((FILE *) fp
);
9268 /* Put the image into the pixmap. */
9269 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9270 x_destroy_x_image (ximg
);
9275 #endif /* HAVE_JPEG */
9279 /***********************************************************************
9281 ***********************************************************************/
9287 static int tiff_image_p
P_ ((Lisp_Object object
));
9288 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9290 /* The symbol `tiff' identifying images of this type. */
9294 /* Indices of image specification fields in tiff_format, below. */
9296 enum tiff_keyword_index
9305 TIFF_HEURISTIC_MASK
,
9310 /* Vector of image_keyword structures describing the format
9311 of valid user-defined image specifications. */
9313 static struct image_keyword tiff_format
[TIFF_LAST
] =
9315 {":type", IMAGE_SYMBOL_VALUE
, 1},
9316 {":data", IMAGE_STRING_VALUE
, 0},
9317 {":file", IMAGE_STRING_VALUE
, 0},
9318 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9319 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9320 {":relief", IMAGE_INTEGER_VALUE
, 0},
9321 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9322 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9323 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9326 /* Structure describing the image type `tiff'. */
9328 static struct image_type tiff_type
=
9338 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9341 tiff_image_p (object
)
9344 struct image_keyword fmt
[TIFF_LAST
];
9345 bcopy (tiff_format
, fmt
, sizeof fmt
);
9347 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9350 /* Must specify either the :data or :file keyword. */
9351 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9355 /* Reading from a memory buffer for TIFF images Based on the PNG
9356 memory source, but we have to provide a lot of extra functions.
9359 We really only need to implement read and seek, but I am not
9360 convinced that the TIFF library is smart enough not to destroy
9361 itself if we only hand it the function pointers we need to
9366 unsigned char *bytes
;
9374 tiff_read_from_memory (data
, buf
, size
)
9379 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9381 if (size
> src
->len
- src
->index
)
9383 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9390 tiff_write_from_memory (data
, buf
, size
)
9400 tiff_seek_in_memory (data
, off
, whence
)
9405 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9410 case SEEK_SET
: /* Go from beginning of source. */
9414 case SEEK_END
: /* Go from end of source. */
9415 idx
= src
->len
+ off
;
9418 case SEEK_CUR
: /* Go from current position. */
9419 idx
= src
->index
+ off
;
9422 default: /* Invalid `whence'. */
9426 if (idx
> src
->len
|| idx
< 0)
9435 tiff_close_memory (data
)
9444 tiff_mmap_memory (data
, pbase
, psize
)
9449 /* It is already _IN_ memory. */
9455 tiff_unmap_memory (data
, base
, size
)
9460 /* We don't need to do this. */
9465 tiff_size_of_memory (data
)
9468 return ((tiff_memory_source
*) data
)->len
;
9472 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9480 Lisp_Object file
, specified_file
;
9481 Lisp_Object specified_data
;
9483 int width
, height
, x
, y
;
9487 struct gcpro gcpro1
;
9488 tiff_memory_source memsrc
;
9490 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9491 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9495 if (NILP (specified_data
))
9497 /* Read from a file */
9498 file
= x_find_image_file (specified_file
);
9499 if (!STRINGP (file
))
9501 image_error ("Cannot find image file `%s'", file
, Qnil
);
9506 /* Try to open the image file. */
9507 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9510 image_error ("Cannot open `%s'", file
, Qnil
);
9517 /* Memory source! */
9518 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9519 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9522 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9523 (TIFFReadWriteProc
) tiff_read_from_memory
,
9524 (TIFFReadWriteProc
) tiff_write_from_memory
,
9525 tiff_seek_in_memory
,
9527 tiff_size_of_memory
,
9533 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9539 /* Get width and height of the image, and allocate a raster buffer
9540 of width x height 32-bit values. */
9541 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9542 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9543 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9545 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9549 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9555 /* Create the X image and pixmap. */
9556 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9563 /* Initialize the color table. */
9564 init_color_table ();
9566 /* Process the pixel raster. Origin is in the lower-left corner. */
9567 for (y
= 0; y
< height
; ++y
)
9569 uint32
*row
= buf
+ y
* width
;
9571 for (x
= 0; x
< width
; ++x
)
9573 uint32 abgr
= row
[x
];
9574 int r
= TIFFGetR (abgr
) << 8;
9575 int g
= TIFFGetG (abgr
) << 8;
9576 int b
= TIFFGetB (abgr
) << 8;
9577 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9581 /* Remember the colors allocated for the image. Free the color table. */
9582 img
->colors
= colors_in_color_table (&img
->ncolors
);
9583 free_color_table ();
9585 /* Put the image into the pixmap, then free the X image and its buffer. */
9586 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9587 x_destroy_x_image (ximg
);
9591 img
->height
= height
;
9597 #endif /* HAVE_TIFF != 0 */
9601 /***********************************************************************
9603 ***********************************************************************/
9607 #include <gif_lib.h>
9609 static int gif_image_p
P_ ((Lisp_Object object
));
9610 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9612 /* The symbol `gif' identifying images of this type. */
9616 /* Indices of image specification fields in gif_format, below. */
9618 enum gif_keyword_index
9633 /* Vector of image_keyword structures describing the format
9634 of valid user-defined image specifications. */
9636 static struct image_keyword gif_format
[GIF_LAST
] =
9638 {":type", IMAGE_SYMBOL_VALUE
, 1},
9639 {":data", IMAGE_STRING_VALUE
, 0},
9640 {":file", IMAGE_STRING_VALUE
, 0},
9641 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9642 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9643 {":relief", IMAGE_INTEGER_VALUE
, 0},
9644 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9645 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9646 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9647 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
9650 /* Structure describing the image type `gif'. */
9652 static struct image_type gif_type
=
9662 /* Return non-zero if OBJECT is a valid GIF image specification. */
9665 gif_image_p (object
)
9668 struct image_keyword fmt
[GIF_LAST
];
9669 bcopy (gif_format
, fmt
, sizeof fmt
);
9671 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
9674 /* Must specify either the :data or :file keyword. */
9675 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
9679 /* Reading a GIF image from memory
9680 Based on the PNG memory stuff to a certain extent. */
9684 unsigned char *bytes
;
9691 /* Make the current memory source available to gif_read_from_memory.
9692 It's done this way because not all versions of libungif support
9693 a UserData field in the GifFileType structure. */
9694 static gif_memory_source
*current_gif_memory_src
;
9697 gif_read_from_memory (file
, buf
, len
)
9702 gif_memory_source
*src
= current_gif_memory_src
;
9704 if (len
> src
->len
- src
->index
)
9707 bcopy (src
->bytes
+ src
->index
, buf
, len
);
9713 /* Load GIF image IMG for use on frame F. Value is non-zero if
9721 Lisp_Object file
, specified_file
;
9722 Lisp_Object specified_data
;
9723 int rc
, width
, height
, x
, y
, i
;
9725 ColorMapObject
*gif_color_map
;
9726 unsigned long pixel_colors
[256];
9728 struct gcpro gcpro1
;
9730 int ino
, image_left
, image_top
, image_width
, image_height
;
9731 gif_memory_source memsrc
;
9732 unsigned char *raster
;
9734 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9735 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9739 if (NILP (specified_data
))
9741 file
= x_find_image_file (specified_file
);
9742 if (!STRINGP (file
))
9744 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9749 /* Open the GIF file. */
9750 gif
= DGifOpenFileName (XSTRING (file
)->data
);
9753 image_error ("Cannot open `%s'", file
, Qnil
);
9760 /* Read from memory! */
9761 current_gif_memory_src
= &memsrc
;
9762 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9763 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9766 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
9769 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
9775 /* Read entire contents. */
9776 rc
= DGifSlurp (gif
);
9777 if (rc
== GIF_ERROR
)
9779 image_error ("Error reading `%s'", img
->spec
, Qnil
);
9780 DGifCloseFile (gif
);
9785 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
9786 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
9787 if (ino
>= gif
->ImageCount
)
9789 image_error ("Invalid image number `%s' in image `%s'",
9791 DGifCloseFile (gif
);
9796 width
= img
->width
= gif
->SWidth
;
9797 height
= img
->height
= gif
->SHeight
;
9799 /* Create the X image and pixmap. */
9800 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9802 DGifCloseFile (gif
);
9807 /* Allocate colors. */
9808 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
9810 gif_color_map
= gif
->SColorMap
;
9811 init_color_table ();
9812 bzero (pixel_colors
, sizeof pixel_colors
);
9814 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
9816 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
9817 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
9818 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
9819 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9822 img
->colors
= colors_in_color_table (&img
->ncolors
);
9823 free_color_table ();
9825 /* Clear the part of the screen image that are not covered by
9826 the image from the GIF file. Full animated GIF support
9827 requires more than can be done here (see the gif89 spec,
9828 disposal methods). Let's simply assume that the part
9829 not covered by a sub-image is in the frame's background color. */
9830 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
9831 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
9832 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
9833 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
9835 for (y
= 0; y
< image_top
; ++y
)
9836 for (x
= 0; x
< width
; ++x
)
9837 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9839 for (y
= image_top
+ image_height
; y
< height
; ++y
)
9840 for (x
= 0; x
< width
; ++x
)
9841 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9843 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
9845 for (x
= 0; x
< image_left
; ++x
)
9846 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9847 for (x
= image_left
+ image_width
; x
< width
; ++x
)
9848 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9851 /* Read the GIF image into the X image. We use a local variable
9852 `raster' here because RasterBits below is a char *, and invites
9853 problems with bytes >= 0x80. */
9854 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
9856 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
9858 static int interlace_start
[] = {0, 4, 2, 1};
9859 static int interlace_increment
[] = {8, 8, 4, 2};
9861 int row
= interlace_start
[0];
9865 for (y
= 0; y
< image_height
; y
++)
9867 if (row
>= image_height
)
9869 row
= interlace_start
[++pass
];
9870 while (row
>= image_height
)
9871 row
= interlace_start
[++pass
];
9874 for (x
= 0; x
< image_width
; x
++)
9876 int i
= raster
[(y
* image_width
) + x
];
9877 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
9881 row
+= interlace_increment
[pass
];
9886 for (y
= 0; y
< image_height
; ++y
)
9887 for (x
= 0; x
< image_width
; ++x
)
9889 int i
= raster
[y
* image_width
+ x
];
9890 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
9894 DGifCloseFile (gif
);
9896 /* Put the image into the pixmap, then free the X image and its buffer. */
9897 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9898 x_destroy_x_image (ximg
);
9904 #endif /* HAVE_GIF != 0 */
9908 /***********************************************************************
9910 ***********************************************************************/
9912 static int gs_image_p
P_ ((Lisp_Object object
));
9913 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
9914 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
9916 /* The symbol `postscript' identifying images of this type. */
9918 Lisp_Object Qpostscript
;
9920 /* Keyword symbols. */
9922 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
9924 /* Indices of image specification fields in gs_format, below. */
9926 enum gs_keyword_index
9943 /* Vector of image_keyword structures describing the format
9944 of valid user-defined image specifications. */
9946 static struct image_keyword gs_format
[GS_LAST
] =
9948 {":type", IMAGE_SYMBOL_VALUE
, 1},
9949 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9950 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9951 {":file", IMAGE_STRING_VALUE
, 1},
9952 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9953 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9954 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9955 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9956 {":relief", IMAGE_INTEGER_VALUE
, 0},
9957 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9958 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9959 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9962 /* Structure describing the image type `ghostscript'. */
9964 static struct image_type gs_type
=
9974 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9977 gs_clear_image (f
, img
)
9981 /* IMG->data.ptr_val may contain a recorded colormap. */
9982 xfree (img
->data
.ptr_val
);
9983 x_clear_image (f
, img
);
9987 /* Return non-zero if OBJECT is a valid Ghostscript image
9994 struct image_keyword fmt
[GS_LAST
];
9998 bcopy (gs_format
, fmt
, sizeof fmt
);
10000 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10003 /* Bounding box must be a list or vector containing 4 integers. */
10004 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10007 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10008 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10013 else if (VECTORP (tem
))
10015 if (XVECTOR (tem
)->size
!= 4)
10017 for (i
= 0; i
< 4; ++i
)
10018 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10028 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10037 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10038 struct gcpro gcpro1
, gcpro2
;
10040 double in_width
, in_height
;
10041 Lisp_Object pixel_colors
= Qnil
;
10043 /* Compute pixel size of pixmap needed from the given size in the
10044 image specification. Sizes in the specification are in pt. 1 pt
10045 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10047 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10048 in_width
= XFASTINT (pt_width
) / 72.0;
10049 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10050 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10051 in_height
= XFASTINT (pt_height
) / 72.0;
10052 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10054 /* Create the pixmap. */
10055 xassert (img
->pixmap
== None
);
10056 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10057 img
->width
, img
->height
,
10058 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10062 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10066 /* Call the loader to fill the pixmap. It returns a process object
10067 if successful. We do not record_unwind_protect here because
10068 other places in redisplay like calling window scroll functions
10069 don't either. Let the Lisp loader use `unwind-protect' instead. */
10070 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10072 sprintf (buffer
, "%lu %lu",
10073 (unsigned long) FRAME_X_WINDOW (f
),
10074 (unsigned long) img
->pixmap
);
10075 window_and_pixmap_id
= build_string (buffer
);
10077 sprintf (buffer
, "%lu %lu",
10078 FRAME_FOREGROUND_PIXEL (f
),
10079 FRAME_BACKGROUND_PIXEL (f
));
10080 pixel_colors
= build_string (buffer
);
10082 XSETFRAME (frame
, f
);
10083 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10085 loader
= intern ("gs-load-image");
10087 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10088 make_number (img
->width
),
10089 make_number (img
->height
),
10090 window_and_pixmap_id
,
10093 return PROCESSP (img
->data
.lisp_val
);
10097 /* Kill the Ghostscript process that was started to fill PIXMAP on
10098 frame F. Called from XTread_socket when receiving an event
10099 telling Emacs that Ghostscript has finished drawing. */
10102 x_kill_gs_process (pixmap
, f
)
10106 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10110 /* Find the image containing PIXMAP. */
10111 for (i
= 0; i
< c
->used
; ++i
)
10112 if (c
->images
[i
]->pixmap
== pixmap
)
10115 /* Kill the GS process. We should have found PIXMAP in the image
10116 cache and its image should contain a process object. */
10117 xassert (i
< c
->used
);
10118 img
= c
->images
[i
];
10119 xassert (PROCESSP (img
->data
.lisp_val
));
10120 Fkill_process (img
->data
.lisp_val
, Qnil
);
10121 img
->data
.lisp_val
= Qnil
;
10123 /* On displays with a mutable colormap, figure out the colors
10124 allocated for the image by looking at the pixels of an XImage for
10126 class = FRAME_X_VISUAL (f
)->class;
10127 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10133 /* Try to get an XImage for img->pixmep. */
10134 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10135 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10140 /* Initialize the color table. */
10141 init_color_table ();
10143 /* For each pixel of the image, look its color up in the
10144 color table. After having done so, the color table will
10145 contain an entry for each color used by the image. */
10146 for (y
= 0; y
< img
->height
; ++y
)
10147 for (x
= 0; x
< img
->width
; ++x
)
10149 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10150 lookup_pixel_color (f
, pixel
);
10153 /* Record colors in the image. Free color table and XImage. */
10154 img
->colors
= colors_in_color_table (&img
->ncolors
);
10155 free_color_table ();
10156 XDestroyImage (ximg
);
10158 #if 0 /* This doesn't seem to be the case. If we free the colors
10159 here, we get a BadAccess later in x_clear_image when
10160 freeing the colors. */
10161 /* We have allocated colors once, but Ghostscript has also
10162 allocated colors on behalf of us. So, to get the
10163 reference counts right, free them once. */
10165 x_free_colors (f
, img
->colors
, img
->ncolors
);
10169 image_error ("Cannot get X image of `%s'; colors will not be freed",
10175 /* Now that we have the pixmap, compute mask and transform the
10176 image if requested. */
10178 postprocess_image (f
, img
);
10184 /***********************************************************************
10186 ***********************************************************************/
10188 DEFUN ("x-change-window-property", Fx_change_window_property
,
10189 Sx_change_window_property
, 2, 3, 0,
10190 "Change window property PROP to VALUE on the X window of FRAME.\n\
10191 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
10192 selected frame. Value is VALUE.")
10193 (prop
, value
, frame
)
10194 Lisp_Object frame
, prop
, value
;
10196 struct frame
*f
= check_x_frame (frame
);
10199 CHECK_STRING (prop
, 1);
10200 CHECK_STRING (value
, 2);
10203 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10204 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10205 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10206 XSTRING (value
)->data
, XSTRING (value
)->size
);
10208 /* Make sure the property is set when we return. */
10209 XFlush (FRAME_X_DISPLAY (f
));
10216 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10217 Sx_delete_window_property
, 1, 2, 0,
10218 "Remove window property PROP from X window of FRAME.\n\
10219 FRAME nil or omitted means use the selected frame. Value is PROP.")
10221 Lisp_Object prop
, frame
;
10223 struct frame
*f
= check_x_frame (frame
);
10226 CHECK_STRING (prop
, 1);
10228 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10229 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10231 /* Make sure the property is removed when we return. */
10232 XFlush (FRAME_X_DISPLAY (f
));
10239 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10241 "Value is the value of window property PROP on FRAME.\n\
10242 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
10243 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10246 Lisp_Object prop
, frame
;
10248 struct frame
*f
= check_x_frame (frame
);
10251 Lisp_Object prop_value
= Qnil
;
10252 char *tmp_data
= NULL
;
10255 unsigned long actual_size
, bytes_remaining
;
10257 CHECK_STRING (prop
, 1);
10259 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10260 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10261 prop_atom
, 0, 0, False
, XA_STRING
,
10262 &actual_type
, &actual_format
, &actual_size
,
10263 &bytes_remaining
, (unsigned char **) &tmp_data
);
10266 int size
= bytes_remaining
;
10271 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10272 prop_atom
, 0, bytes_remaining
,
10274 &actual_type
, &actual_format
,
10275 &actual_size
, &bytes_remaining
,
10276 (unsigned char **) &tmp_data
);
10278 prop_value
= make_string (tmp_data
, size
);
10289 /***********************************************************************
10291 ***********************************************************************/
10293 /* If non-null, an asynchronous timer that, when it expires, displays
10294 an hourglass cursor on all frames. */
10296 static struct atimer
*hourglass_atimer
;
10298 /* Non-zero means an hourglass cursor is currently shown. */
10300 static int hourglass_shown_p
;
10302 /* Number of seconds to wait before displaying an hourglass cursor. */
10304 static Lisp_Object Vhourglass_delay
;
10306 /* Default number of seconds to wait before displaying an hourglass
10309 #define DEFAULT_HOURGLASS_DELAY 1
10311 /* Function prototypes. */
10313 static void show_hourglass
P_ ((struct atimer
*));
10314 static void hide_hourglass
P_ ((void));
10317 /* Cancel a currently active hourglass timer, and start a new one. */
10323 int secs
, usecs
= 0;
10325 cancel_hourglass ();
10327 if (INTEGERP (Vhourglass_delay
)
10328 && XINT (Vhourglass_delay
) > 0)
10329 secs
= XFASTINT (Vhourglass_delay
);
10330 else if (FLOATP (Vhourglass_delay
)
10331 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10334 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10335 secs
= XFASTINT (tem
);
10336 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10339 secs
= DEFAULT_HOURGLASS_DELAY
;
10341 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10342 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10343 show_hourglass
, NULL
);
10347 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10351 cancel_hourglass ()
10353 if (hourglass_atimer
)
10355 cancel_atimer (hourglass_atimer
);
10356 hourglass_atimer
= NULL
;
10359 if (hourglass_shown_p
)
10364 /* Timer function of hourglass_atimer. TIMER is equal to
10367 Display an hourglass pointer on all frames by mapping the frames'
10368 hourglass_window. Set the hourglass_p flag in the frames'
10369 output_data.x structure to indicate that an hourglass cursor is
10370 shown on the frames. */
10373 show_hourglass (timer
)
10374 struct atimer
*timer
;
10376 /* The timer implementation will cancel this timer automatically
10377 after this function has run. Set hourglass_atimer to null
10378 so that we know the timer doesn't have to be canceled. */
10379 hourglass_atimer
= NULL
;
10381 if (!hourglass_shown_p
)
10383 Lisp_Object rest
, frame
;
10387 FOR_EACH_FRAME (rest
, frame
)
10389 struct frame
*f
= XFRAME (frame
);
10391 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10393 Display
*dpy
= FRAME_X_DISPLAY (f
);
10395 #ifdef USE_X_TOOLKIT
10396 if (f
->output_data
.x
->widget
)
10398 if (FRAME_OUTER_WINDOW (f
))
10401 f
->output_data
.x
->hourglass_p
= 1;
10403 if (!f
->output_data
.x
->hourglass_window
)
10405 unsigned long mask
= CWCursor
;
10406 XSetWindowAttributes attrs
;
10408 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10410 f
->output_data
.x
->hourglass_window
10411 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10412 0, 0, 32000, 32000, 0, 0,
10418 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10424 hourglass_shown_p
= 1;
10430 /* Hide the hourglass pointer on all frames, if it is currently
10436 if (hourglass_shown_p
)
10438 Lisp_Object rest
, frame
;
10441 FOR_EACH_FRAME (rest
, frame
)
10443 struct frame
*f
= XFRAME (frame
);
10446 /* Watch out for newly created frames. */
10447 && f
->output_data
.x
->hourglass_window
)
10449 XUnmapWindow (FRAME_X_DISPLAY (f
),
10450 f
->output_data
.x
->hourglass_window
);
10451 /* Sync here because XTread_socket looks at the
10452 hourglass_p flag that is reset to zero below. */
10453 XSync (FRAME_X_DISPLAY (f
), False
);
10454 f
->output_data
.x
->hourglass_p
= 0;
10458 hourglass_shown_p
= 0;
10465 /***********************************************************************
10467 ***********************************************************************/
10469 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10470 Lisp_Object
, Lisp_Object
));
10471 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10472 Lisp_Object
, int, int, int *, int *));
10474 /* The frame of a currently visible tooltip. */
10476 Lisp_Object tip_frame
;
10478 /* If non-nil, a timer started that hides the last tooltip when it
10481 Lisp_Object tip_timer
;
10484 /* If non-nil, a vector of 3 elements containing the last args
10485 with which x-show-tip was called. See there. */
10487 Lisp_Object last_show_tip_args
;
10489 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10491 Lisp_Object Vx_max_tooltip_size
;
10495 unwind_create_tip_frame (frame
)
10498 Lisp_Object deleted
;
10500 deleted
= unwind_create_frame (frame
);
10501 if (EQ (deleted
, Qt
))
10511 /* Create a frame for a tooltip on the display described by DPYINFO.
10512 PARMS is a list of frame parameters. TEXT is the string to
10513 display in the tip frame. Value is the frame.
10515 Note that functions called here, esp. x_default_parameter can
10516 signal errors, for instance when a specified color name is
10517 undefined. We have to make sure that we're in a consistent state
10518 when this happens. */
10521 x_create_tip_frame (dpyinfo
, parms
, text
)
10522 struct x_display_info
*dpyinfo
;
10523 Lisp_Object parms
, text
;
10526 Lisp_Object frame
, tem
;
10528 long window_prompting
= 0;
10530 int count
= BINDING_STACK_SIZE ();
10531 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10533 int face_change_count_before
= face_change_count
;
10534 Lisp_Object buffer
;
10535 struct buffer
*old_buffer
;
10539 /* Use this general default value to start with until we know if
10540 this frame has a specified name. */
10541 Vx_resource_name
= Vinvocation_name
;
10543 #ifdef MULTI_KBOARD
10544 kb
= dpyinfo
->kboard
;
10546 kb
= &the_only_kboard
;
10549 /* Get the name of the frame to use for resource lookup. */
10550 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10551 if (!STRINGP (name
)
10552 && !EQ (name
, Qunbound
)
10554 error ("Invalid frame name--not a string or nil");
10555 Vx_resource_name
= name
;
10558 GCPRO3 (parms
, name
, frame
);
10559 f
= make_frame (1);
10560 XSETFRAME (frame
, f
);
10562 buffer
= Fget_buffer_create (build_string (" *tip*"));
10563 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10564 old_buffer
= current_buffer
;
10565 set_buffer_internal_1 (XBUFFER (buffer
));
10566 current_buffer
->truncate_lines
= Qnil
;
10568 Finsert (1, &text
);
10569 set_buffer_internal_1 (old_buffer
);
10571 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10572 record_unwind_protect (unwind_create_tip_frame
, frame
);
10574 /* By setting the output method, we're essentially saying that
10575 the frame is live, as per FRAME_LIVE_P. If we get a signal
10576 from this point on, x_destroy_window might screw up reference
10578 f
->output_method
= output_x_window
;
10579 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10580 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10581 f
->output_data
.x
->icon_bitmap
= -1;
10582 f
->output_data
.x
->fontset
= -1;
10583 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10584 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10585 f
->icon_name
= Qnil
;
10586 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10588 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
10589 dpyinfo_refcount
= dpyinfo
->reference_count
;
10590 #endif /* GLYPH_DEBUG */
10591 #ifdef MULTI_KBOARD
10592 FRAME_KBOARD (f
) = kb
;
10594 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10595 f
->output_data
.x
->explicit_parent
= 0;
10597 /* These colors will be set anyway later, but it's important
10598 to get the color reference counts right, so initialize them! */
10601 struct gcpro gcpro1
;
10603 black
= build_string ("black");
10605 f
->output_data
.x
->foreground_pixel
10606 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10607 f
->output_data
.x
->background_pixel
10608 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10609 f
->output_data
.x
->cursor_pixel
10610 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10611 f
->output_data
.x
->cursor_foreground_pixel
10612 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10613 f
->output_data
.x
->border_pixel
10614 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10615 f
->output_data
.x
->mouse_pixel
10616 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10620 /* Set the name; the functions to which we pass f expect the name to
10622 if (EQ (name
, Qunbound
) || NILP (name
))
10624 f
->name
= build_string (dpyinfo
->x_id_name
);
10625 f
->explicit_name
= 0;
10630 f
->explicit_name
= 1;
10631 /* use the frame's title when getting resources for this frame. */
10632 specbind (Qx_resource_name
, name
);
10635 /* Extract the window parameters from the supplied values that are
10636 needed to determine window geometry. */
10640 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
10643 /* First, try whatever font the caller has specified. */
10644 if (STRINGP (font
))
10646 tem
= Fquery_fontset (font
, Qnil
);
10648 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
10650 font
= x_new_font (f
, XSTRING (font
)->data
);
10653 /* Try out a font which we hope has bold and italic variations. */
10654 if (!STRINGP (font
))
10655 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10656 if (!STRINGP (font
))
10657 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10658 if (! STRINGP (font
))
10659 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10660 if (! STRINGP (font
))
10661 /* This was formerly the first thing tried, but it finds too many fonts
10662 and takes too long. */
10663 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10664 /* If those didn't work, look for something which will at least work. */
10665 if (! STRINGP (font
))
10666 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10668 if (! STRINGP (font
))
10669 font
= build_string ("fixed");
10671 x_default_parameter (f
, parms
, Qfont
, font
,
10672 "font", "Font", RES_TYPE_STRING
);
10675 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
10676 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
10678 /* This defaults to 2 in order to match xterm. We recognize either
10679 internalBorderWidth or internalBorder (which is what xterm calls
10681 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10685 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
10686 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
10687 if (! EQ (value
, Qunbound
))
10688 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
10692 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
10693 "internalBorderWidth", "internalBorderWidth",
10696 /* Also do the stuff which must be set before the window exists. */
10697 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
10698 "foreground", "Foreground", RES_TYPE_STRING
);
10699 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
10700 "background", "Background", RES_TYPE_STRING
);
10701 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
10702 "pointerColor", "Foreground", RES_TYPE_STRING
);
10703 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
10704 "cursorColor", "Foreground", RES_TYPE_STRING
);
10705 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
10706 "borderColor", "BorderColor", RES_TYPE_STRING
);
10708 /* Init faces before x_default_parameter is called for scroll-bar
10709 parameters because that function calls x_set_scroll_bar_width,
10710 which calls change_frame_size, which calls Fset_window_buffer,
10711 which runs hooks, which call Fvertical_motion. At the end, we
10712 end up in init_iterator with a null face cache, which should not
10714 init_frame_faces (f
);
10716 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10717 window_prompting
= x_figure_window_size (f
, parms
);
10719 if (window_prompting
& XNegative
)
10721 if (window_prompting
& YNegative
)
10722 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
10724 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
10728 if (window_prompting
& YNegative
)
10729 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
10731 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10734 f
->output_data
.x
->size_hint_flags
= window_prompting
;
10736 XSetWindowAttributes attrs
;
10737 unsigned long mask
;
10740 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
10741 if (DoesSaveUnders (dpyinfo
->screen
))
10742 mask
|= CWSaveUnder
;
10744 /* Window managers look at the override-redirect flag to determine
10745 whether or net to give windows a decoration (Xlib spec, chapter
10747 attrs
.override_redirect
= True
;
10748 attrs
.save_under
= True
;
10749 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
10750 /* Arrange for getting MapNotify and UnmapNotify events. */
10751 attrs
.event_mask
= StructureNotifyMask
;
10753 = FRAME_X_WINDOW (f
)
10754 = XCreateWindow (FRAME_X_DISPLAY (f
),
10755 FRAME_X_DISPLAY_INFO (f
)->root_window
,
10756 /* x, y, width, height */
10760 CopyFromParent
, InputOutput
, CopyFromParent
,
10767 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
10768 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10769 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
10770 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10771 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
10772 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
10774 /* Dimensions, especially f->height, must be done via change_frame_size.
10775 Change will not be effected unless different from the current
10778 height
= f
->height
;
10780 SET_FRAME_WIDTH (f
, 0);
10781 change_frame_size (f
, height
, width
, 1, 0, 0);
10783 /* Set up faces after all frame parameters are known. This call
10784 also merges in face attributes specified for new frames.
10786 Frame parameters may be changed if .Xdefaults contains
10787 specifications for the default font. For example, if there is an
10788 `Emacs.default.attributeBackground: pink', the `background-color'
10789 attribute of the frame get's set, which let's the internal border
10790 of the tooltip frame appear in pink. Prevent this. */
10792 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
10794 /* Set tip_frame here, so that */
10796 call1 (Qface_set_after_frame_default
, frame
);
10798 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
10799 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
10807 /* It is now ok to make the frame official even if we get an error
10808 below. And the frame needs to be on Vframe_list or making it
10809 visible won't work. */
10810 Vframe_list
= Fcons (frame
, Vframe_list
);
10812 /* Now that the frame is official, it counts as a reference to
10814 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
10816 /* Setting attributes of faces of the tooltip frame from resources
10817 and similar will increment face_change_count, which leads to the
10818 clearing of all current matrices. Since this isn't necessary
10819 here, avoid it by resetting face_change_count to the value it
10820 had before we created the tip frame. */
10821 face_change_count
= face_change_count_before
;
10823 /* Discard the unwind_protect. */
10824 return unbind_to (count
, frame
);
10828 /* Compute where to display tip frame F. PARMS is the list of frame
10829 parameters for F. DX and DY are specified offsets from the current
10830 location of the mouse. WIDTH and HEIGHT are the width and height
10831 of the tooltip. Return coordinates relative to the root window of
10832 the display in *ROOT_X, and *ROOT_Y. */
10835 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
10837 Lisp_Object parms
, dx
, dy
;
10839 int *root_x
, *root_y
;
10841 Lisp_Object left
, top
;
10843 Window root
, child
;
10846 /* User-specified position? */
10847 left
= Fcdr (Fassq (Qleft
, parms
));
10848 top
= Fcdr (Fassq (Qtop
, parms
));
10850 /* Move the tooltip window where the mouse pointer is. Resize and
10852 if (!INTEGERP (left
) && !INTEGERP (top
))
10855 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
10856 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
10860 if (INTEGERP (top
))
10861 *root_y
= XINT (top
);
10862 else if (*root_y
+ XINT (dy
) - height
< 0)
10863 *root_y
-= XINT (dy
);
10867 *root_y
+= XINT (dy
);
10870 if (INTEGERP (left
))
10871 *root_x
= XINT (left
);
10872 else if (*root_x
+ XINT (dx
) + width
> FRAME_X_DISPLAY_INFO (f
)->width
)
10873 *root_x
-= width
+ XINT (dx
);
10875 *root_x
+= XINT (dx
);
10879 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
10880 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10881 A tooltip window is a small X window displaying a string.\n\
10883 FRAME nil or omitted means use the selected frame.\n\
10885 PARMS is an optional list of frame parameters which can be\n\
10886 used to change the tooltip's appearance.\n\
10888 Automatically hide the tooltip after TIMEOUT seconds.\n\
10889 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10891 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10892 the tooltip is displayed at that x-position. Otherwise it is\n\
10893 displayed at the mouse position, with offset DX added (default is 5 if\n\
10894 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10895 parameter is specified, it determines the y-position of the tooltip\n\
10896 window, otherwise it is displayed at the mouse position, with offset\n\
10897 DY added (default is -10).\n\
10899 A tooltip's maximum size is specified by `x-max-tooltip-size'.\n\
10900 Text larger than the specified size is clipped.")
10901 (string
, frame
, parms
, timeout
, dx
, dy
)
10902 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
10906 Lisp_Object buffer
, top
, left
, max_width
, max_height
;
10907 int root_x
, root_y
;
10908 struct buffer
*old_buffer
;
10909 struct text_pos pos
;
10910 int i
, width
, height
;
10911 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
10912 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
10913 int count
= BINDING_STACK_SIZE ();
10915 specbind (Qinhibit_redisplay
, Qt
);
10917 GCPRO4 (string
, parms
, frame
, timeout
);
10919 CHECK_STRING (string
, 0);
10920 f
= check_x_frame (frame
);
10921 if (NILP (timeout
))
10922 timeout
= make_number (5);
10924 CHECK_NATNUM (timeout
, 2);
10927 dx
= make_number (5);
10929 CHECK_NUMBER (dx
, 5);
10932 dy
= make_number (-10);
10934 CHECK_NUMBER (dy
, 6);
10936 if (NILP (last_show_tip_args
))
10937 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
10939 if (!NILP (tip_frame
))
10941 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
10942 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
10943 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
10945 if (EQ (frame
, last_frame
)
10946 && !NILP (Fequal (last_string
, string
))
10947 && !NILP (Fequal (last_parms
, parms
)))
10949 struct frame
*f
= XFRAME (tip_frame
);
10951 /* Only DX and DY have changed. */
10952 if (!NILP (tip_timer
))
10954 Lisp_Object timer
= tip_timer
;
10956 call1 (Qcancel_timer
, timer
);
10960 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
10961 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
10962 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10969 /* Hide a previous tip, if any. */
10972 ASET (last_show_tip_args
, 0, string
);
10973 ASET (last_show_tip_args
, 1, frame
);
10974 ASET (last_show_tip_args
, 2, parms
);
10976 /* Add default values to frame parameters. */
10977 if (NILP (Fassq (Qname
, parms
)))
10978 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
10979 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10980 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
10981 if (NILP (Fassq (Qborder_width
, parms
)))
10982 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
10983 if (NILP (Fassq (Qborder_color
, parms
)))
10984 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
10985 if (NILP (Fassq (Qbackground_color
, parms
)))
10986 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
10989 /* Create a frame for the tooltip, and record it in the global
10990 variable tip_frame. */
10991 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
10992 f
= XFRAME (frame
);
10994 /* Set up the frame's root window. */
10995 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
10996 w
->left
= w
->top
= make_number (0);
10998 if (CONSP (Vx_max_tooltip_size
)
10999 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11000 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11001 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11002 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11004 w
->width
= XCAR (Vx_max_tooltip_size
);
11005 w
->height
= XCDR (Vx_max_tooltip_size
);
11009 w
->width
= make_number (80);
11010 w
->height
= make_number (40);
11013 f
->window_width
= XINT (w
->width
);
11015 w
->pseudo_window_p
= 1;
11017 /* Display the tooltip text in a temporary buffer. */
11018 old_buffer
= current_buffer
;
11019 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11020 current_buffer
->truncate_lines
= Qnil
;
11021 clear_glyph_matrix (w
->desired_matrix
);
11022 clear_glyph_matrix (w
->current_matrix
);
11023 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11024 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11026 /* Compute width and height of the tooltip. */
11027 width
= height
= 0;
11028 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11030 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11031 struct glyph
*last
;
11034 /* Stop at the first empty row at the end. */
11035 if (!row
->enabled_p
|| !row
->displays_text_p
)
11038 /* Let the row go over the full width of the frame. */
11039 row
->full_width_p
= 1;
11041 /* There's a glyph at the end of rows that is used to place
11042 the cursor there. Don't include the width of this glyph. */
11043 if (row
->used
[TEXT_AREA
])
11045 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11046 row_width
= row
->pixel_width
- last
->pixel_width
;
11049 row_width
= row
->pixel_width
;
11051 height
+= row
->height
;
11052 width
= max (width
, row_width
);
11055 /* Add the frame's internal border to the width and height the X
11056 window should have. */
11057 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11058 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11060 /* Move the tooltip window where the mouse pointer is. Resize and
11062 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11065 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11066 root_x
, root_y
, width
, height
);
11067 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11070 /* Draw into the window. */
11071 w
->must_be_updated_p
= 1;
11072 update_single_window (w
, 1);
11074 /* Restore original current buffer. */
11075 set_buffer_internal_1 (old_buffer
);
11076 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11079 /* Let the tip disappear after timeout seconds. */
11080 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11081 intern ("x-hide-tip"));
11084 return unbind_to (count
, Qnil
);
11088 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11089 "Hide the current tooltip window, if there is any.\n\
11090 Value is t is tooltip was open, nil otherwise.")
11094 Lisp_Object deleted
, frame
, timer
;
11095 struct gcpro gcpro1
, gcpro2
;
11097 /* Return quickly if nothing to do. */
11098 if (NILP (tip_timer
) && NILP (tip_frame
))
11103 GCPRO2 (frame
, timer
);
11104 tip_frame
= tip_timer
= deleted
= Qnil
;
11106 count
= BINDING_STACK_SIZE ();
11107 specbind (Qinhibit_redisplay
, Qt
);
11108 specbind (Qinhibit_quit
, Qt
);
11111 call1 (Qcancel_timer
, timer
);
11113 if (FRAMEP (frame
))
11115 Fdelete_frame (frame
, Qnil
);
11119 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11120 redisplay procedure is not called when a tip frame over menu
11121 items is unmapped. Redisplay the menu manually... */
11123 struct frame
*f
= SELECTED_FRAME ();
11124 Widget w
= f
->output_data
.x
->menubar_widget
;
11125 extern void xlwmenu_redisplay
P_ ((Widget
));
11127 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11131 xlwmenu_redisplay (w
);
11135 #endif /* USE_LUCID */
11139 return unbind_to (count
, deleted
);
11144 /***********************************************************************
11145 File selection dialog
11146 ***********************************************************************/
11150 /* Callback for "OK" and "Cancel" on file selection dialog. */
11153 file_dialog_cb (widget
, client_data
, call_data
)
11155 XtPointer call_data
, client_data
;
11157 int *result
= (int *) client_data
;
11158 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11159 *result
= cb
->reason
;
11163 /* Callback for unmapping a file selection dialog. This is used to
11164 capture the case where a dialog is closed via a window manager's
11165 closer button, for example. Using a XmNdestroyCallback didn't work
11169 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11171 XtPointer call_data
, client_data
;
11173 int *result
= (int *) client_data
;
11174 *result
= XmCR_CANCEL
;
11178 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11179 "Read file name, prompting with PROMPT in directory DIR.\n\
11180 Use a file selection dialog.\n\
11181 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
11182 specified. Don't let the user enter a file name in the file\n\
11183 selection dialog's entry field, if MUSTMATCH is non-nil.")
11184 (prompt
, dir
, default_filename
, mustmatch
)
11185 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11188 struct frame
*f
= SELECTED_FRAME ();
11189 Lisp_Object file
= Qnil
;
11190 Widget dialog
, text
, list
, help
;
11193 extern XtAppContext Xt_app_con
;
11195 XmString dir_xmstring
, pattern_xmstring
;
11196 int popup_activated_flag
;
11197 int count
= specpdl_ptr
- specpdl
;
11198 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11200 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11201 CHECK_STRING (prompt
, 0);
11202 CHECK_STRING (dir
, 1);
11204 /* Prevent redisplay. */
11205 specbind (Qinhibit_redisplay
, Qt
);
11209 /* Create the dialog with PROMPT as title, using DIR as initial
11210 directory and using "*" as pattern. */
11211 dir
= Fexpand_file_name (dir
, Qnil
);
11212 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
11213 pattern_xmstring
= XmStringCreateLocalized ("*");
11215 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
11216 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11217 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11218 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11219 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11220 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11222 XmStringFree (dir_xmstring
);
11223 XmStringFree (pattern_xmstring
);
11225 /* Add callbacks for OK and Cancel. */
11226 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11227 (XtPointer
) &result
);
11228 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11229 (XtPointer
) &result
);
11230 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11231 (XtPointer
) &result
);
11233 /* Disable the help button since we can't display help. */
11234 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11235 XtSetSensitive (help
, False
);
11237 /* Mark OK button as default. */
11238 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11239 XmNshowAsDefault
, True
, NULL
);
11241 /* If MUSTMATCH is non-nil, disable the file entry field of the
11242 dialog, so that the user must select a file from the files list
11243 box. We can't remove it because we wouldn't have a way to get at
11244 the result file name, then. */
11245 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11246 if (!NILP (mustmatch
))
11249 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11250 XtSetSensitive (text
, False
);
11251 XtSetSensitive (label
, False
);
11254 /* Manage the dialog, so that list boxes get filled. */
11255 XtManageChild (dialog
);
11257 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11258 must include the path for this to work. */
11259 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11260 if (STRINGP (default_filename
))
11262 XmString default_xmstring
;
11266 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
11268 if (!XmListItemExists (list
, default_xmstring
))
11270 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11271 XmListAddItem (list
, default_xmstring
, 0);
11275 item_pos
= XmListItemPos (list
, default_xmstring
);
11276 XmStringFree (default_xmstring
);
11278 /* Select the item and scroll it into view. */
11279 XmListSelectPos (list
, item_pos
, True
);
11280 XmListSetPos (list
, item_pos
);
11283 /* Process events until the user presses Cancel or OK. Block
11284 and unblock input here so that we get a chance of processing
11288 while (result
== 0)
11291 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11296 /* Get the result. */
11297 if (result
== XmCR_OK
)
11302 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11303 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11304 XmStringFree (text
);
11305 file
= build_string (data
);
11312 XtUnmanageChild (dialog
);
11313 XtDestroyWidget (dialog
);
11317 /* Make "Cancel" equivalent to C-g. */
11319 Fsignal (Qquit
, Qnil
);
11321 return unbind_to (count
, file
);
11324 #endif /* USE_MOTIF */
11328 /***********************************************************************
11330 ***********************************************************************/
11332 #ifdef HAVE_XKBGETKEYBOARD
11333 #include <X11/XKBlib.h>
11334 #include <X11/keysym.h>
11337 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11338 Sx_backspace_delete_keys_p
, 0, 1, 0,
11339 "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
11340 FRAME nil means use the selected frame.\n\
11341 Value is t if we know that both keys are present, and are mapped to the\n\
11346 #ifdef HAVE_XKBGETKEYBOARD
11348 struct frame
*f
= check_x_frame (frame
);
11349 Display
*dpy
= FRAME_X_DISPLAY (f
);
11350 Lisp_Object have_keys
;
11351 int major
, minor
, op
, event
, error
;
11355 /* Check library version in case we're dynamically linked. */
11356 major
= XkbMajorVersion
;
11357 minor
= XkbMinorVersion
;
11358 if (!XkbLibraryVersion (&major
, &minor
))
11364 /* Check that the server supports XKB. */
11365 major
= XkbMajorVersion
;
11366 minor
= XkbMinorVersion
;
11367 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11374 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11377 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11379 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11381 for (i
= kb
->min_key_code
;
11382 (i
< kb
->max_key_code
11383 && (delete_keycode
== 0 || backspace_keycode
== 0));
11386 /* The XKB symbolic key names can be seen most easily in
11387 the PS file generated by `xkbprint -label name
11389 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11390 delete_keycode
= i
;
11391 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11392 backspace_keycode
= i
;
11395 XkbFreeNames (kb
, 0, True
);
11398 XkbFreeClientMap (kb
, 0, True
);
11401 && backspace_keycode
11402 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11403 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11408 #else /* not HAVE_XKBGETKEYBOARD */
11410 #endif /* not HAVE_XKBGETKEYBOARD */
11415 /***********************************************************************
11417 ***********************************************************************/
11422 /* This is zero if not using X windows. */
11425 /* The section below is built by the lisp expression at the top of the file,
11426 just above where these variables are declared. */
11427 /*&&& init symbols here &&&*/
11428 Qauto_raise
= intern ("auto-raise");
11429 staticpro (&Qauto_raise
);
11430 Qauto_lower
= intern ("auto-lower");
11431 staticpro (&Qauto_lower
);
11432 Qbar
= intern ("bar");
11434 Qborder_color
= intern ("border-color");
11435 staticpro (&Qborder_color
);
11436 Qborder_width
= intern ("border-width");
11437 staticpro (&Qborder_width
);
11438 Qbox
= intern ("box");
11440 Qcursor_color
= intern ("cursor-color");
11441 staticpro (&Qcursor_color
);
11442 Qcursor_type
= intern ("cursor-type");
11443 staticpro (&Qcursor_type
);
11444 Qgeometry
= intern ("geometry");
11445 staticpro (&Qgeometry
);
11446 Qicon_left
= intern ("icon-left");
11447 staticpro (&Qicon_left
);
11448 Qicon_top
= intern ("icon-top");
11449 staticpro (&Qicon_top
);
11450 Qicon_type
= intern ("icon-type");
11451 staticpro (&Qicon_type
);
11452 Qicon_name
= intern ("icon-name");
11453 staticpro (&Qicon_name
);
11454 Qinternal_border_width
= intern ("internal-border-width");
11455 staticpro (&Qinternal_border_width
);
11456 Qleft
= intern ("left");
11457 staticpro (&Qleft
);
11458 Qright
= intern ("right");
11459 staticpro (&Qright
);
11460 Qmouse_color
= intern ("mouse-color");
11461 staticpro (&Qmouse_color
);
11462 Qnone
= intern ("none");
11463 staticpro (&Qnone
);
11464 Qparent_id
= intern ("parent-id");
11465 staticpro (&Qparent_id
);
11466 Qscroll_bar_width
= intern ("scroll-bar-width");
11467 staticpro (&Qscroll_bar_width
);
11468 Qsuppress_icon
= intern ("suppress-icon");
11469 staticpro (&Qsuppress_icon
);
11470 Qundefined_color
= intern ("undefined-color");
11471 staticpro (&Qundefined_color
);
11472 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11473 staticpro (&Qvertical_scroll_bars
);
11474 Qvisibility
= intern ("visibility");
11475 staticpro (&Qvisibility
);
11476 Qwindow_id
= intern ("window-id");
11477 staticpro (&Qwindow_id
);
11478 Qouter_window_id
= intern ("outer-window-id");
11479 staticpro (&Qouter_window_id
);
11480 Qx_frame_parameter
= intern ("x-frame-parameter");
11481 staticpro (&Qx_frame_parameter
);
11482 Qx_resource_name
= intern ("x-resource-name");
11483 staticpro (&Qx_resource_name
);
11484 Quser_position
= intern ("user-position");
11485 staticpro (&Quser_position
);
11486 Quser_size
= intern ("user-size");
11487 staticpro (&Quser_size
);
11488 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11489 staticpro (&Qscroll_bar_foreground
);
11490 Qscroll_bar_background
= intern ("scroll-bar-background");
11491 staticpro (&Qscroll_bar_background
);
11492 Qscreen_gamma
= intern ("screen-gamma");
11493 staticpro (&Qscreen_gamma
);
11494 Qline_spacing
= intern ("line-spacing");
11495 staticpro (&Qline_spacing
);
11496 Qcenter
= intern ("center");
11497 staticpro (&Qcenter
);
11498 Qcompound_text
= intern ("compound-text");
11499 staticpro (&Qcompound_text
);
11500 Qcancel_timer
= intern ("cancel-timer");
11501 staticpro (&Qcancel_timer
);
11502 Qwait_for_wm
= intern ("wait-for-wm");
11503 staticpro (&Qwait_for_wm
);
11504 /* This is the end of symbol initialization. */
11506 /* Text property `display' should be nonsticky by default. */
11507 Vtext_property_default_nonsticky
11508 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11511 Qlaplace
= intern ("laplace");
11512 staticpro (&Qlaplace
);
11513 Qemboss
= intern ("emboss");
11514 staticpro (&Qemboss
);
11515 Qedge_detection
= intern ("edge-detection");
11516 staticpro (&Qedge_detection
);
11517 Qheuristic
= intern ("heuristic");
11518 staticpro (&Qheuristic
);
11519 QCmatrix
= intern (":matrix");
11520 staticpro (&QCmatrix
);
11521 QCcolor_adjustment
= intern (":color-adjustment");
11522 staticpro (&QCcolor_adjustment
);
11523 QCmask
= intern (":mask");
11524 staticpro (&QCmask
);
11526 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11527 staticpro (&Qface_set_after_frame_default
);
11529 Fput (Qundefined_color
, Qerror_conditions
,
11530 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11531 Fput (Qundefined_color
, Qerror_message
,
11532 build_string ("Undefined color"));
11534 init_x_parm_symbols ();
11536 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11537 "Non-nil means always draw a cross over disabled images.\n\
11538 Disabled images are those having an `:conversion disabled' property.\n\
11539 A cross is always drawn on black & white displays.");
11540 cross_disabled_images
= 0;
11542 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11543 "List of directories to search for bitmap files for X.");
11544 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11546 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11547 "The shape of the pointer when over text.\n\
11548 Changing the value does not affect existing frames\n\
11549 unless you set the mouse color.");
11550 Vx_pointer_shape
= Qnil
;
11552 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11553 "The name Emacs uses to look up X resources.\n\
11554 `x-get-resource' uses this as the first component of the instance name\n\
11555 when requesting resource values.\n\
11556 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11557 was invoked, or to the value specified with the `-name' or `-rn'\n\
11558 switches, if present.\n\
11560 It may be useful to bind this variable locally around a call\n\
11561 to `x-get-resource'. See also the variable `x-resource-class'.");
11562 Vx_resource_name
= Qnil
;
11564 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11565 "The class Emacs uses to look up X resources.\n\
11566 `x-get-resource' uses this as the first component of the instance class\n\
11567 when requesting resource values.\n\
11568 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11570 Setting this variable permanently is not a reasonable thing to do,\n\
11571 but binding this variable locally around a call to `x-get-resource'\n\
11572 is a reasonable practice. See also the variable `x-resource-name'.");
11573 Vx_resource_class
= build_string (EMACS_CLASS
);
11575 #if 0 /* This doesn't really do anything. */
11576 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11577 "The shape of the pointer when not over text.\n\
11578 This variable takes effect when you create a new frame\n\
11579 or when you set the mouse color.");
11581 Vx_nontext_pointer_shape
= Qnil
;
11583 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
11584 "The shape of the pointer when Emacs is busy.\n\
11585 This variable takes effect when you create a new frame\n\
11586 or when you set the mouse color.");
11587 Vx_hourglass_pointer_shape
= Qnil
;
11589 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
11590 "Non-zero means Emacs displays an hourglass pointer on window systems.");
11591 display_hourglass_p
= 1;
11593 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
11594 "*Seconds to wait before displaying an hourglass pointer.\n\
11595 Value must be an integer or float.");
11596 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
11598 #if 0 /* This doesn't really do anything. */
11599 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
11600 "The shape of the pointer when over the mode line.\n\
11601 This variable takes effect when you create a new frame\n\
11602 or when you set the mouse color.");
11604 Vx_mode_pointer_shape
= Qnil
;
11606 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11607 &Vx_sensitive_text_pointer_shape
,
11608 "The shape of the pointer when over mouse-sensitive text.\n\
11609 This variable takes effect when you create a new frame\n\
11610 or when you set the mouse color.");
11611 Vx_sensitive_text_pointer_shape
= Qnil
;
11613 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11614 &Vx_window_horizontal_drag_shape
,
11615 "Pointer shape to use for indicating a window can be dragged horizontally.\n\
11616 This variable takes effect when you create a new frame\n\
11617 or when you set the mouse color.");
11618 Vx_window_horizontal_drag_shape
= Qnil
;
11620 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
11621 "A string indicating the foreground color of the cursor box.");
11622 Vx_cursor_fore_pixel
= Qnil
;
11624 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
11625 "Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).\n\
11626 Text larger than this is clipped.");
11627 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
11629 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
11630 "Non-nil if no X window manager is in use.\n\
11631 Emacs doesn't try to figure this out; this is always nil\n\
11632 unless you set it to something else.");
11633 /* We don't have any way to find this out, so set it to nil
11634 and maybe the user would like to set it to t. */
11635 Vx_no_window_manager
= Qnil
;
11637 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11638 &Vx_pixel_size_width_font_regexp
,
11639 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11641 Since Emacs gets width of a font matching with this regexp from\n\
11642 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11643 such a font. This is especially effective for such large fonts as\n\
11644 Chinese, Japanese, and Korean.");
11645 Vx_pixel_size_width_font_regexp
= Qnil
;
11647 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
11648 "Time after which cached images are removed from the cache.\n\
11649 When an image has not been displayed this many seconds, remove it\n\
11650 from the image cache. Value must be an integer or nil with nil\n\
11651 meaning don't clear the cache.");
11652 Vimage_cache_eviction_delay
= make_number (30 * 60);
11654 #ifdef USE_X_TOOLKIT
11655 Fprovide (intern ("x-toolkit"));
11658 Fprovide (intern ("motif"));
11660 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
11661 "Version info for LessTif/Motif.");
11662 Vmotif_version_string
= build_string (XmVERSION_STRING
);
11663 #endif /* USE_MOTIF */
11664 #endif /* USE_X_TOOLKIT */
11666 defsubr (&Sx_get_resource
);
11668 /* X window properties. */
11669 defsubr (&Sx_change_window_property
);
11670 defsubr (&Sx_delete_window_property
);
11671 defsubr (&Sx_window_property
);
11673 defsubr (&Sxw_display_color_p
);
11674 defsubr (&Sx_display_grayscale_p
);
11675 defsubr (&Sxw_color_defined_p
);
11676 defsubr (&Sxw_color_values
);
11677 defsubr (&Sx_server_max_request_size
);
11678 defsubr (&Sx_server_vendor
);
11679 defsubr (&Sx_server_version
);
11680 defsubr (&Sx_display_pixel_width
);
11681 defsubr (&Sx_display_pixel_height
);
11682 defsubr (&Sx_display_mm_width
);
11683 defsubr (&Sx_display_mm_height
);
11684 defsubr (&Sx_display_screens
);
11685 defsubr (&Sx_display_planes
);
11686 defsubr (&Sx_display_color_cells
);
11687 defsubr (&Sx_display_visual_class
);
11688 defsubr (&Sx_display_backing_store
);
11689 defsubr (&Sx_display_save_under
);
11690 defsubr (&Sx_parse_geometry
);
11691 defsubr (&Sx_create_frame
);
11692 defsubr (&Sx_open_connection
);
11693 defsubr (&Sx_close_connection
);
11694 defsubr (&Sx_display_list
);
11695 defsubr (&Sx_synchronize
);
11696 defsubr (&Sx_focus_frame
);
11697 defsubr (&Sx_backspace_delete_keys_p
);
11699 /* Setting callback functions for fontset handler. */
11700 get_font_info_func
= x_get_font_info
;
11702 #if 0 /* This function pointer doesn't seem to be used anywhere.
11703 And the pointer assigned has the wrong type, anyway. */
11704 list_fonts_func
= x_list_fonts
;
11707 load_font_func
= x_load_font
;
11708 find_ccl_program_func
= x_find_ccl_program
;
11709 query_font_func
= x_query_font
;
11710 set_frame_fontset_func
= x_set_font
;
11711 check_window_system_func
= check_x
;
11714 Qxbm
= intern ("xbm");
11716 QCtype
= intern (":type");
11717 staticpro (&QCtype
);
11718 QCconversion
= intern (":conversion");
11719 staticpro (&QCconversion
);
11720 QCheuristic_mask
= intern (":heuristic-mask");
11721 staticpro (&QCheuristic_mask
);
11722 QCcolor_symbols
= intern (":color-symbols");
11723 staticpro (&QCcolor_symbols
);
11724 QCascent
= intern (":ascent");
11725 staticpro (&QCascent
);
11726 QCmargin
= intern (":margin");
11727 staticpro (&QCmargin
);
11728 QCrelief
= intern (":relief");
11729 staticpro (&QCrelief
);
11730 Qpostscript
= intern ("postscript");
11731 staticpro (&Qpostscript
);
11732 QCloader
= intern (":loader");
11733 staticpro (&QCloader
);
11734 QCbounding_box
= intern (":bounding-box");
11735 staticpro (&QCbounding_box
);
11736 QCpt_width
= intern (":pt-width");
11737 staticpro (&QCpt_width
);
11738 QCpt_height
= intern (":pt-height");
11739 staticpro (&QCpt_height
);
11740 QCindex
= intern (":index");
11741 staticpro (&QCindex
);
11742 Qpbm
= intern ("pbm");
11746 Qxpm
= intern ("xpm");
11751 Qjpeg
= intern ("jpeg");
11752 staticpro (&Qjpeg
);
11756 Qtiff
= intern ("tiff");
11757 staticpro (&Qtiff
);
11761 Qgif
= intern ("gif");
11766 Qpng
= intern ("png");
11770 defsubr (&Sclear_image_cache
);
11771 defsubr (&Simage_size
);
11772 defsubr (&Simage_mask_p
);
11774 hourglass_atimer
= NULL
;
11775 hourglass_shown_p
= 0;
11777 defsubr (&Sx_show_tip
);
11778 defsubr (&Sx_hide_tip
);
11780 staticpro (&tip_timer
);
11782 staticpro (&tip_frame
);
11784 last_show_tip_args
= Qnil
;
11785 staticpro (&last_show_tip_args
);
11788 defsubr (&Sx_file_dialog
);
11796 image_types
= NULL
;
11797 Vimage_types
= Qnil
;
11799 define_image_type (&xbm_type
);
11800 define_image_type (&gs_type
);
11801 define_image_type (&pbm_type
);
11804 define_image_type (&xpm_type
);
11808 define_image_type (&jpeg_type
);
11812 define_image_type (&tiff_type
);
11816 define_image_type (&gif_type
);
11820 define_image_type (&png_type
);
11824 #endif /* HAVE_X_WINDOWS */