1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
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. */
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
40 #include "intervals.h"
41 #include "dispextern.h"
43 #include "blockinput.h"
49 #include "termhooks.h"
55 #include <sys/types.h>
59 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
60 #include "bitmaps/gray.xbm"
62 #include <X11/bitmaps/gray>
65 #include "[.bitmaps]gray.xbm"
69 #include <X11/Shell.h>
72 #include <X11/Xaw/Paned.h>
73 #include <X11/Xaw/Label.h>
74 #endif /* USE_MOTIF */
77 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
86 #include "../lwlib/lwlib.h"
90 #include <Xm/DialogS.h>
91 #include <Xm/FileSB.h>
94 /* Do the EDITRES protocol if running X11R5
95 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
97 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
99 extern void _XEditResCheckMessages ();
100 #endif /* R5 + Athena */
102 /* Unique id counter for widgets created by the Lucid Widget Library. */
104 extern LWLIB_ID widget_id_tick
;
107 /* This is part of a kludge--see lwlib/xlwmenu.c. */
108 extern XFontStruct
*xlwmenu_default_font
;
111 extern void free_frame_menubar ();
112 extern double atof ();
116 /* LessTif/Motif version info. */
118 static Lisp_Object Vmotif_version_string
;
120 #endif /* USE_MOTIF */
122 #endif /* USE_X_TOOLKIT */
124 #define min(a,b) ((a) < (b) ? (a) : (b))
125 #define max(a,b) ((a) > (b) ? (a) : (b))
128 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
130 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
133 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
134 it, and including `bitmaps/gray' more than once is a problem when
135 config.h defines `static' as an empty replacement string. */
137 int gray_bitmap_width
= gray_width
;
138 int gray_bitmap_height
= gray_height
;
139 char *gray_bitmap_bits
= gray_bits
;
141 /* The name we're using in resource queries. Most often "emacs". */
143 Lisp_Object Vx_resource_name
;
145 /* The application class we're using in resource queries.
148 Lisp_Object Vx_resource_class
;
150 /* Non-zero means we're allowed to display an hourglass cursor. */
152 int display_hourglass_p
;
154 /* The background and shape of the mouse pointer, and shape when not
155 over text or in the modeline. */
157 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
158 Lisp_Object Vx_hourglass_pointer_shape
;
160 /* The shape when over mouse-sensitive text. */
162 Lisp_Object Vx_sensitive_text_pointer_shape
;
164 /* If non-nil, the pointer shape to indicate that windows can be
165 dragged horizontally. */
167 Lisp_Object Vx_window_horizontal_drag_shape
;
169 /* Color of chars displayed in cursor box. */
171 Lisp_Object Vx_cursor_fore_pixel
;
173 /* Nonzero if using X. */
177 /* Non nil if no window manager is in use. */
179 Lisp_Object Vx_no_window_manager
;
181 /* Search path for bitmap files. */
183 Lisp_Object Vx_bitmap_file_path
;
185 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
187 Lisp_Object Vx_pixel_size_width_font_regexp
;
189 Lisp_Object Qauto_raise
;
190 Lisp_Object Qauto_lower
;
192 Lisp_Object Qborder_color
;
193 Lisp_Object Qborder_width
;
195 Lisp_Object Qcursor_color
;
196 Lisp_Object Qcursor_type
;
197 Lisp_Object Qgeometry
;
198 Lisp_Object Qicon_left
;
199 Lisp_Object Qicon_top
;
200 Lisp_Object Qicon_type
;
201 Lisp_Object Qicon_name
;
202 Lisp_Object Qinternal_border_width
;
205 Lisp_Object Qmouse_color
;
207 Lisp_Object Qouter_window_id
;
208 Lisp_Object Qparent_id
;
209 Lisp_Object Qscroll_bar_width
;
210 Lisp_Object Qsuppress_icon
;
211 extern Lisp_Object Qtop
;
212 Lisp_Object Qundefined_color
;
213 Lisp_Object Qvertical_scroll_bars
;
214 Lisp_Object Qvisibility
;
215 Lisp_Object Qwindow_id
;
216 Lisp_Object Qx_frame_parameter
;
217 Lisp_Object Qx_resource_name
;
218 Lisp_Object Quser_position
;
219 Lisp_Object Quser_size
;
220 extern Lisp_Object Qdisplay
;
221 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
222 Lisp_Object Qscreen_gamma
, Qline_spacing
, Qcenter
;
223 Lisp_Object Qcompound_text
, Qcancel_timer
;
224 Lisp_Object Qwait_for_wm
;
226 /* The below are defined in frame.c. */
228 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
229 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
230 extern Lisp_Object Qtool_bar_lines
;
232 extern Lisp_Object Vwindow_system_version
;
234 Lisp_Object Qface_set_after_frame_default
;
237 int image_cache_refcount
, dpyinfo_refcount
;
242 /* Error if we are not connected to X. */
248 error ("X windows are not in use or not initialized");
251 /* Nonzero if we can use mouse menus.
252 You should not call this unless HAVE_MENUS is defined. */
260 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
261 and checking validity for X. */
264 check_x_frame (frame
)
270 frame
= selected_frame
;
271 CHECK_LIVE_FRAME (frame
, 0);
274 error ("Non-X frame used");
278 /* Let the user specify an X display with a frame.
279 nil stands for the selected frame--or, if that is not an X frame,
280 the first X display on the list. */
282 static struct x_display_info
*
283 check_x_display_info (frame
)
286 struct x_display_info
*dpyinfo
= NULL
;
290 struct frame
*sf
= XFRAME (selected_frame
);
292 if (FRAME_X_P (sf
) && FRAME_LIVE_P (sf
))
293 dpyinfo
= FRAME_X_DISPLAY_INFO (sf
);
294 else if (x_display_list
!= 0)
295 dpyinfo
= x_display_list
;
297 error ("X windows are not in use or not initialized");
299 else if (STRINGP (frame
))
300 dpyinfo
= x_display_info_for_name (frame
);
305 CHECK_LIVE_FRAME (frame
, 0);
308 error ("Non-X frame used");
309 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
316 /* Return the Emacs frame-object corresponding to an X window.
317 It could be the frame's main window or an icon window. */
319 /* This function can be called during GC, so use GC_xxx type test macros. */
322 x_window_to_frame (dpyinfo
, wdesc
)
323 struct x_display_info
*dpyinfo
;
326 Lisp_Object tail
, frame
;
329 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
332 if (!GC_FRAMEP (frame
))
335 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
337 if (f
->output_data
.x
->hourglass_window
== wdesc
)
340 if ((f
->output_data
.x
->edit_widget
341 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
342 /* A tooltip frame? */
343 || (!f
->output_data
.x
->edit_widget
344 && FRAME_X_WINDOW (f
) == wdesc
)
345 || f
->output_data
.x
->icon_desc
== wdesc
)
347 #else /* not USE_X_TOOLKIT */
348 if (FRAME_X_WINDOW (f
) == wdesc
349 || f
->output_data
.x
->icon_desc
== wdesc
)
351 #endif /* not USE_X_TOOLKIT */
357 /* Like x_window_to_frame but also compares the window with the widget's
361 x_any_window_to_frame (dpyinfo
, wdesc
)
362 struct x_display_info
*dpyinfo
;
365 Lisp_Object tail
, frame
;
366 struct frame
*f
, *found
;
370 for (tail
= Vframe_list
; GC_CONSP (tail
) && !found
; tail
= XCDR (tail
))
373 if (!GC_FRAMEP (frame
))
377 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
379 /* This frame matches if the window is any of its widgets. */
380 x
= f
->output_data
.x
;
381 if (x
->hourglass_window
== wdesc
)
385 if (wdesc
== XtWindow (x
->widget
)
386 || wdesc
== XtWindow (x
->column_widget
)
387 || wdesc
== XtWindow (x
->edit_widget
))
389 /* Match if the window is this frame's menubar. */
390 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
393 else if (FRAME_X_WINDOW (f
) == wdesc
)
394 /* A tooltip frame. */
402 /* Likewise, but exclude the menu bar widget. */
405 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
406 struct x_display_info
*dpyinfo
;
409 Lisp_Object tail
, frame
;
413 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
416 if (!GC_FRAMEP (frame
))
419 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
421 x
= f
->output_data
.x
;
422 /* This frame matches if the window is any of its widgets. */
423 if (x
->hourglass_window
== wdesc
)
427 if (wdesc
== XtWindow (x
->widget
)
428 || wdesc
== XtWindow (x
->column_widget
)
429 || wdesc
== XtWindow (x
->edit_widget
))
432 else if (FRAME_X_WINDOW (f
) == wdesc
)
433 /* A tooltip frame. */
439 /* Likewise, but consider only the menu bar widget. */
442 x_menubar_window_to_frame (dpyinfo
, wdesc
)
443 struct x_display_info
*dpyinfo
;
446 Lisp_Object tail
, frame
;
450 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
453 if (!GC_FRAMEP (frame
))
456 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
458 x
= f
->output_data
.x
;
459 /* Match if the window is this frame's menubar. */
460 if (x
->menubar_widget
461 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
467 /* Return the frame whose principal (outermost) window is WDESC.
468 If WDESC is some other (smaller) window, we return 0. */
471 x_top_window_to_frame (dpyinfo
, wdesc
)
472 struct x_display_info
*dpyinfo
;
475 Lisp_Object tail
, frame
;
479 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
482 if (!GC_FRAMEP (frame
))
485 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
487 x
= f
->output_data
.x
;
491 /* This frame matches if the window is its topmost widget. */
492 if (wdesc
== XtWindow (x
->widget
))
494 #if 0 /* I don't know why it did this,
495 but it seems logically wrong,
496 and it causes trouble for MapNotify events. */
497 /* Match if the window is this frame's menubar. */
498 if (x
->menubar_widget
499 && wdesc
== XtWindow (x
->menubar_widget
))
503 else if (FRAME_X_WINDOW (f
) == wdesc
)
509 #endif /* USE_X_TOOLKIT */
513 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
514 id, which is just an int that this section returns. Bitmaps are
515 reference counted so they can be shared among frames.
517 Bitmap indices are guaranteed to be > 0, so a negative number can
518 be used to indicate no bitmap.
520 If you use x_create_bitmap_from_data, then you must keep track of
521 the bitmaps yourself. That is, creating a bitmap from the same
522 data more than once will not be caught. */
525 /* Functions to access the contents of a bitmap, given an id. */
528 x_bitmap_height (f
, id
)
532 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
536 x_bitmap_width (f
, id
)
540 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
544 x_bitmap_pixmap (f
, id
)
548 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
552 /* Allocate a new bitmap record. Returns index of new record. */
555 x_allocate_bitmap_record (f
)
558 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
561 if (dpyinfo
->bitmaps
== NULL
)
563 dpyinfo
->bitmaps_size
= 10;
565 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
566 dpyinfo
->bitmaps_last
= 1;
570 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
571 return ++dpyinfo
->bitmaps_last
;
573 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
574 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
577 dpyinfo
->bitmaps_size
*= 2;
579 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
580 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
581 return ++dpyinfo
->bitmaps_last
;
584 /* Add one reference to the reference count of the bitmap with id ID. */
587 x_reference_bitmap (f
, id
)
591 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
594 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
597 x_create_bitmap_from_data (f
, bits
, width
, height
)
600 unsigned int width
, height
;
602 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
606 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
607 bits
, width
, height
);
612 id
= x_allocate_bitmap_record (f
);
613 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
614 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
615 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
616 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
617 dpyinfo
->bitmaps
[id
- 1].height
= height
;
618 dpyinfo
->bitmaps
[id
- 1].width
= width
;
623 /* Create bitmap from file FILE for frame F. */
626 x_create_bitmap_from_file (f
, file
)
630 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
631 unsigned int width
, height
;
633 int xhot
, yhot
, result
, id
;
638 /* Look for an existing bitmap with the same name. */
639 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
641 if (dpyinfo
->bitmaps
[id
].refcount
642 && dpyinfo
->bitmaps
[id
].file
643 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
645 ++dpyinfo
->bitmaps
[id
].refcount
;
650 /* Search bitmap-file-path for the file, if appropriate. */
651 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
656 filename
= (char *) XSTRING (found
)->data
;
658 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
659 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
660 if (result
!= BitmapSuccess
)
663 id
= x_allocate_bitmap_record (f
);
664 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
665 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
666 dpyinfo
->bitmaps
[id
- 1].file
667 = (char *) xmalloc (STRING_BYTES (XSTRING (file
)) + 1);
668 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
669 dpyinfo
->bitmaps
[id
- 1].height
= height
;
670 dpyinfo
->bitmaps
[id
- 1].width
= width
;
671 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
676 /* Remove reference to bitmap with id number ID. */
679 x_destroy_bitmap (f
, id
)
683 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
687 --dpyinfo
->bitmaps
[id
- 1].refcount
;
688 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
691 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
692 if (dpyinfo
->bitmaps
[id
- 1].file
)
694 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
695 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
702 /* Free all the bitmaps for the display specified by DPYINFO. */
705 x_destroy_all_bitmaps (dpyinfo
)
706 struct x_display_info
*dpyinfo
;
709 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
710 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
712 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
713 if (dpyinfo
->bitmaps
[i
].file
)
714 xfree (dpyinfo
->bitmaps
[i
].file
);
716 dpyinfo
->bitmaps_last
= 0;
719 /* Connect the frame-parameter names for X frames
720 to the ways of passing the parameter values to the window system.
722 The name of a parameter, as a Lisp symbol,
723 has an `x-frame-parameter' property which is an integer in Lisp
724 that is an index in this table. */
726 struct x_frame_parm_table
729 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
732 static Lisp_Object unwind_create_frame
P_ ((Lisp_Object
));
733 static Lisp_Object unwind_create_tip_frame
P_ ((Lisp_Object
));
734 static void x_change_window_heights
P_ ((Lisp_Object
, int));
735 static void x_disable_image
P_ ((struct frame
*, struct image
*));
736 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
737 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
738 static void x_set_wait_for_wm
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
739 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
740 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
741 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
742 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
743 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
744 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
745 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
746 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
747 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
748 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
750 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
751 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
752 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
753 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
755 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
756 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
757 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
758 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
759 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
760 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
761 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
763 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
765 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
770 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
771 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
773 static void init_color_table
P_ ((void));
774 static void free_color_table
P_ ((void));
775 static unsigned long *colors_in_color_table
P_ ((int *n
));
776 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
777 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
781 static struct x_frame_parm_table x_frame_parms
[] =
783 "auto-raise", x_set_autoraise
,
784 "auto-lower", x_set_autolower
,
785 "background-color", x_set_background_color
,
786 "border-color", x_set_border_color
,
787 "border-width", x_set_border_width
,
788 "cursor-color", x_set_cursor_color
,
789 "cursor-type", x_set_cursor_type
,
791 "foreground-color", x_set_foreground_color
,
792 "icon-name", x_set_icon_name
,
793 "icon-type", x_set_icon_type
,
794 "internal-border-width", x_set_internal_border_width
,
795 "menu-bar-lines", x_set_menu_bar_lines
,
796 "mouse-color", x_set_mouse_color
,
797 "name", x_explicitly_set_name
,
798 "scroll-bar-width", x_set_scroll_bar_width
,
799 "title", x_set_title
,
800 "unsplittable", x_set_unsplittable
,
801 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
802 "visibility", x_set_visibility
,
803 "tool-bar-lines", x_set_tool_bar_lines
,
804 "scroll-bar-foreground", x_set_scroll_bar_foreground
,
805 "scroll-bar-background", x_set_scroll_bar_background
,
806 "screen-gamma", x_set_screen_gamma
,
807 "line-spacing", x_set_line_spacing
,
808 "wait-for-wm", x_set_wait_for_wm
811 /* Attach the `x-frame-parameter' properties to
812 the Lisp symbol names of parameters relevant to X. */
815 init_x_parm_symbols ()
819 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
820 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
824 /* Change the parameters of frame F as specified by ALIST.
825 If a parameter is not specially recognized, do nothing special;
826 otherwise call the `x_set_...' function for that parameter.
827 Except for certain geometry properties, always call store_frame_param
828 to store the new value in the parameter alist. */
831 x_set_frame_parameters (f
, alist
)
837 /* If both of these parameters are present, it's more efficient to
838 set them both at once. So we wait until we've looked at the
839 entire list before we set them. */
843 Lisp_Object left
, top
;
845 /* Same with these. */
846 Lisp_Object icon_left
, icon_top
;
848 /* Record in these vectors all the parms specified. */
852 int left_no_change
= 0, top_no_change
= 0;
853 int icon_left_no_change
= 0, icon_top_no_change
= 0;
855 struct gcpro gcpro1
, gcpro2
;
858 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
861 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
862 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
864 /* Extract parm names and values into those vectors. */
867 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
872 parms
[i
] = Fcar (elt
);
873 values
[i
] = Fcdr (elt
);
876 /* TAIL and ALIST are not used again below here. */
879 GCPRO2 (*parms
, *values
);
883 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
884 because their values appear in VALUES and strings are not valid. */
885 top
= left
= Qunbound
;
886 icon_left
= icon_top
= Qunbound
;
888 /* Provide default values for HEIGHT and WIDTH. */
889 if (FRAME_NEW_WIDTH (f
))
890 width
= FRAME_NEW_WIDTH (f
);
892 width
= FRAME_WIDTH (f
);
894 if (FRAME_NEW_HEIGHT (f
))
895 height
= FRAME_NEW_HEIGHT (f
);
897 height
= FRAME_HEIGHT (f
);
899 /* Process foreground_color and background_color before anything else.
900 They are independent of other properties, but other properties (e.g.,
901 cursor_color) are dependent upon them. */
902 for (p
= 0; p
< i
; p
++)
904 Lisp_Object prop
, val
;
908 if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
910 register Lisp_Object param_index
, old_value
;
912 param_index
= Fget (prop
, Qx_frame_parameter
);
913 old_value
= get_frame_param (f
, prop
);
914 store_frame_param (f
, prop
, val
);
915 if (NATNUMP (param_index
)
916 && (XFASTINT (param_index
)
917 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
918 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
922 /* Now process them in reverse of specified order. */
923 for (i
--; i
>= 0; i
--)
925 Lisp_Object prop
, val
;
930 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
931 width
= XFASTINT (val
);
932 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
933 height
= XFASTINT (val
);
934 else if (EQ (prop
, Qtop
))
936 else if (EQ (prop
, Qleft
))
938 else if (EQ (prop
, Qicon_top
))
940 else if (EQ (prop
, Qicon_left
))
942 else if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
943 /* Processed above. */
947 register Lisp_Object param_index
, old_value
;
949 param_index
= Fget (prop
, Qx_frame_parameter
);
950 old_value
= get_frame_param (f
, prop
);
951 store_frame_param (f
, prop
, val
);
952 if (NATNUMP (param_index
)
953 && (XFASTINT (param_index
)
954 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
955 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
959 /* Don't die if just one of these was set. */
960 if (EQ (left
, Qunbound
))
963 if (f
->output_data
.x
->left_pos
< 0)
964 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
966 XSETINT (left
, f
->output_data
.x
->left_pos
);
968 if (EQ (top
, Qunbound
))
971 if (f
->output_data
.x
->top_pos
< 0)
972 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
974 XSETINT (top
, f
->output_data
.x
->top_pos
);
977 /* If one of the icon positions was not set, preserve or default it. */
978 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
980 icon_left_no_change
= 1;
981 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
982 if (NILP (icon_left
))
983 XSETINT (icon_left
, 0);
985 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
987 icon_top_no_change
= 1;
988 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
990 XSETINT (icon_top
, 0);
993 /* Don't set these parameters unless they've been explicitly
994 specified. The window might be mapped or resized while we're in
995 this function, and we don't want to override that unless the lisp
996 code has asked for it.
998 Don't set these parameters unless they actually differ from the
999 window's current parameters; the window may not actually exist
1004 check_frame_size (f
, &height
, &width
);
1006 XSETFRAME (frame
, f
);
1008 if (width
!= FRAME_WIDTH (f
)
1009 || height
!= FRAME_HEIGHT (f
)
1010 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
1011 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1013 if ((!NILP (left
) || !NILP (top
))
1014 && ! (left_no_change
&& top_no_change
)
1015 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1016 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1021 /* Record the signs. */
1022 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1023 if (EQ (left
, Qminus
))
1024 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1025 else if (INTEGERP (left
))
1027 leftpos
= XINT (left
);
1029 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1031 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1032 && CONSP (XCDR (left
))
1033 && INTEGERP (XCAR (XCDR (left
))))
1035 leftpos
= - XINT (XCAR (XCDR (left
)));
1036 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1038 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1039 && CONSP (XCDR (left
))
1040 && INTEGERP (XCAR (XCDR (left
))))
1042 leftpos
= XINT (XCAR (XCDR (left
)));
1045 if (EQ (top
, Qminus
))
1046 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1047 else if (INTEGERP (top
))
1049 toppos
= XINT (top
);
1051 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1053 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1054 && CONSP (XCDR (top
))
1055 && INTEGERP (XCAR (XCDR (top
))))
1057 toppos
= - XINT (XCAR (XCDR (top
)));
1058 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1060 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1061 && CONSP (XCDR (top
))
1062 && INTEGERP (XCAR (XCDR (top
))))
1064 toppos
= XINT (XCAR (XCDR (top
)));
1068 /* Store the numeric value of the position. */
1069 f
->output_data
.x
->top_pos
= toppos
;
1070 f
->output_data
.x
->left_pos
= leftpos
;
1072 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1074 /* Actually set that position, and convert to absolute. */
1075 x_set_offset (f
, leftpos
, toppos
, -1);
1078 if ((!NILP (icon_left
) || !NILP (icon_top
))
1079 && ! (icon_left_no_change
&& icon_top_no_change
))
1080 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1086 /* Store the screen positions of frame F into XPTR and YPTR.
1087 These are the positions of the containing window manager window,
1088 not Emacs's own window. */
1091 x_real_positions (f
, xptr
, yptr
)
1098 /* This is pretty gross, but seems to be the easiest way out of
1099 the problem that arises when restarting window-managers. */
1101 #ifdef USE_X_TOOLKIT
1102 Window outer
= (f
->output_data
.x
->widget
1103 ? XtWindow (f
->output_data
.x
->widget
)
1104 : FRAME_X_WINDOW (f
));
1106 Window outer
= f
->output_data
.x
->window_desc
;
1108 Window tmp_root_window
;
1109 Window
*tmp_children
;
1110 unsigned int tmp_nchildren
;
1114 int count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1115 Window outer_window
;
1117 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
1118 &f
->output_data
.x
->parent_desc
,
1119 &tmp_children
, &tmp_nchildren
);
1120 XFree ((char *) tmp_children
);
1124 /* Find the position of the outside upper-left corner of
1125 the inner window, with respect to the outer window. */
1126 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
1127 outer_window
= f
->output_data
.x
->parent_desc
;
1129 outer_window
= outer
;
1131 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1133 /* From-window, to-window. */
1135 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1137 /* From-position, to-position. */
1138 0, 0, &win_x
, &win_y
,
1143 /* It is possible for the window returned by the XQueryNotify
1144 to become invalid by the time we call XTranslateCoordinates.
1145 That can happen when you restart some window managers.
1146 If so, we get an error in XTranslateCoordinates.
1147 Detect that and try the whole thing over. */
1148 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1150 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1154 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1161 /* Insert a description of internally-recorded parameters of frame X
1162 into the parameter alist *ALISTPTR that is to be given to the user.
1163 Only parameters that are specific to the X window system
1164 and whose values are not correctly recorded in the frame's
1165 param_alist need to be considered here. */
1168 x_report_frame_params (f
, alistptr
)
1170 Lisp_Object
*alistptr
;
1175 /* Represent negative positions (off the top or left screen edge)
1176 in a way that Fmodify_frame_parameters will understand correctly. */
1177 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1178 if (f
->output_data
.x
->left_pos
>= 0)
1179 store_in_alist (alistptr
, Qleft
, tem
);
1181 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1183 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1184 if (f
->output_data
.x
->top_pos
>= 0)
1185 store_in_alist (alistptr
, Qtop
, tem
);
1187 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1189 store_in_alist (alistptr
, Qborder_width
,
1190 make_number (f
->output_data
.x
->border_width
));
1191 store_in_alist (alistptr
, Qinternal_border_width
,
1192 make_number (f
->output_data
.x
->internal_border_width
));
1193 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1194 store_in_alist (alistptr
, Qwindow_id
,
1195 build_string (buf
));
1196 #ifdef USE_X_TOOLKIT
1197 /* Tooltip frame may not have this widget. */
1198 if (f
->output_data
.x
->widget
)
1200 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1201 store_in_alist (alistptr
, Qouter_window_id
,
1202 build_string (buf
));
1203 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1204 FRAME_SAMPLE_VISIBILITY (f
);
1205 store_in_alist (alistptr
, Qvisibility
,
1206 (FRAME_VISIBLE_P (f
) ? Qt
1207 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1208 store_in_alist (alistptr
, Qdisplay
,
1209 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1211 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1214 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1215 store_in_alist (alistptr
, Qparent_id
, tem
);
1220 /* Gamma-correct COLOR on frame F. */
1223 gamma_correct (f
, color
)
1229 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1230 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1231 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1236 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1237 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1238 allocate the color. Value is zero if COLOR_NAME is invalid, or
1239 no color could be allocated. */
1242 x_defined_color (f
, color_name
, color
, alloc_p
)
1249 Display
*dpy
= FRAME_X_DISPLAY (f
);
1250 Colormap cmap
= FRAME_X_COLORMAP (f
);
1253 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1254 if (success_p
&& alloc_p
)
1255 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1262 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1263 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1264 Signal an error if color can't be allocated. */
1267 x_decode_color (f
, color_name
, mono_color
)
1269 Lisp_Object color_name
;
1274 CHECK_STRING (color_name
, 0);
1276 #if 0 /* Don't do this. It's wrong when we're not using the default
1277 colormap, it makes freeing difficult, and it's probably not
1278 an important optimization. */
1279 if (strcmp (XSTRING (color_name
)->data
, "black") == 0)
1280 return BLACK_PIX_DEFAULT (f
);
1281 else if (strcmp (XSTRING (color_name
)->data
, "white") == 0)
1282 return WHITE_PIX_DEFAULT (f
);
1285 /* Return MONO_COLOR for monochrome frames. */
1286 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1289 /* x_defined_color is responsible for coping with failures
1290 by looking for a near-miss. */
1291 if (x_defined_color (f
, XSTRING (color_name
)->data
, &cdef
, 1))
1294 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1295 Fcons (color_name
, Qnil
)));
1301 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1302 the previous value of that parameter, NEW_VALUE is the new value. */
1305 x_set_line_spacing (f
, new_value
, old_value
)
1307 Lisp_Object new_value
, old_value
;
1309 if (NILP (new_value
))
1310 f
->extra_line_spacing
= 0;
1311 else if (NATNUMP (new_value
))
1312 f
->extra_line_spacing
= XFASTINT (new_value
);
1314 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1315 Fcons (new_value
, Qnil
)));
1316 if (FRAME_VISIBLE_P (f
))
1321 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1322 the previous value of that parameter, NEW_VALUE is the new value.
1323 See also the comment of wait_for_wm in struct x_output. */
1326 x_set_wait_for_wm (f
, new_value
, old_value
)
1328 Lisp_Object new_value
, old_value
;
1330 f
->output_data
.x
->wait_for_wm
= !NILP (new_value
);
1334 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1335 the previous value of that parameter, NEW_VALUE is the new
1339 x_set_screen_gamma (f
, new_value
, old_value
)
1341 Lisp_Object new_value
, old_value
;
1343 if (NILP (new_value
))
1345 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1346 /* The value 0.4545 is the normal viewing gamma. */
1347 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1349 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1350 Fcons (new_value
, Qnil
)));
1352 clear_face_cache (0);
1356 /* Functions called only from `x_set_frame_param'
1357 to set individual parameters.
1359 If FRAME_X_WINDOW (f) is 0,
1360 the frame is being created and its X-window does not exist yet.
1361 In that case, just record the parameter's new value
1362 in the standard place; do not attempt to change the window. */
1365 x_set_foreground_color (f
, arg
, oldval
)
1367 Lisp_Object arg
, oldval
;
1369 struct x_output
*x
= f
->output_data
.x
;
1370 unsigned long fg
, old_fg
;
1372 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1373 old_fg
= x
->foreground_pixel
;
1374 x
->foreground_pixel
= fg
;
1376 if (FRAME_X_WINDOW (f
) != 0)
1378 Display
*dpy
= FRAME_X_DISPLAY (f
);
1381 XSetForeground (dpy
, x
->normal_gc
, fg
);
1382 XSetBackground (dpy
, x
->reverse_gc
, fg
);
1384 if (x
->cursor_pixel
== old_fg
)
1386 unload_color (f
, x
->cursor_pixel
);
1387 x
->cursor_pixel
= x_copy_color (f
, fg
);
1388 XSetBackground (dpy
, x
->cursor_gc
, x
->cursor_pixel
);
1393 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1395 if (FRAME_VISIBLE_P (f
))
1399 unload_color (f
, old_fg
);
1403 x_set_background_color (f
, arg
, oldval
)
1405 Lisp_Object arg
, oldval
;
1407 struct x_output
*x
= f
->output_data
.x
;
1410 bg
= x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1411 unload_color (f
, x
->background_pixel
);
1412 x
->background_pixel
= bg
;
1414 if (FRAME_X_WINDOW (f
) != 0)
1416 Display
*dpy
= FRAME_X_DISPLAY (f
);
1419 XSetBackground (dpy
, x
->normal_gc
, bg
);
1420 XSetForeground (dpy
, x
->reverse_gc
, bg
);
1421 XSetWindowBackground (dpy
, FRAME_X_WINDOW (f
), bg
);
1422 XSetForeground (dpy
, x
->cursor_gc
, bg
);
1424 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1425 toolkit scroll bars. */
1428 for (bar
= FRAME_SCROLL_BARS (f
);
1430 bar
= XSCROLL_BAR (bar
)->next
)
1432 Window window
= SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
));
1433 XSetWindowBackground (dpy
, window
, bg
);
1436 #endif /* USE_TOOLKIT_SCROLL_BARS */
1439 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1441 if (FRAME_VISIBLE_P (f
))
1447 x_set_mouse_color (f
, arg
, oldval
)
1449 Lisp_Object arg
, oldval
;
1451 struct x_output
*x
= f
->output_data
.x
;
1452 Display
*dpy
= FRAME_X_DISPLAY (f
);
1453 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1454 Cursor hourglass_cursor
, horizontal_drag_cursor
;
1456 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1457 unsigned long mask_color
= x
->background_pixel
;
1459 /* Don't let pointers be invisible. */
1460 if (mask_color
== pixel
)
1462 x_free_colors (f
, &pixel
, 1);
1463 pixel
= x_copy_color (f
, x
->foreground_pixel
);
1466 unload_color (f
, x
->mouse_pixel
);
1467 x
->mouse_pixel
= pixel
;
1471 /* It's not okay to crash if the user selects a screwy cursor. */
1472 count
= x_catch_errors (dpy
);
1474 if (!NILP (Vx_pointer_shape
))
1476 CHECK_NUMBER (Vx_pointer_shape
, 0);
1477 cursor
= XCreateFontCursor (dpy
, XINT (Vx_pointer_shape
));
1480 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1481 x_check_errors (dpy
, "bad text pointer cursor: %s");
1483 if (!NILP (Vx_nontext_pointer_shape
))
1485 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1487 = XCreateFontCursor (dpy
, XINT (Vx_nontext_pointer_shape
));
1490 nontext_cursor
= XCreateFontCursor (dpy
, XC_left_ptr
);
1491 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1493 if (!NILP (Vx_hourglass_pointer_shape
))
1495 CHECK_NUMBER (Vx_hourglass_pointer_shape
, 0);
1497 = XCreateFontCursor (dpy
, XINT (Vx_hourglass_pointer_shape
));
1500 hourglass_cursor
= XCreateFontCursor (dpy
, XC_watch
);
1501 x_check_errors (dpy
, "bad hourglass pointer cursor: %s");
1503 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1504 if (!NILP (Vx_mode_pointer_shape
))
1506 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1507 mode_cursor
= XCreateFontCursor (dpy
, XINT (Vx_mode_pointer_shape
));
1510 mode_cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1511 x_check_errors (dpy
, "bad modeline pointer cursor: %s");
1513 if (!NILP (Vx_sensitive_text_pointer_shape
))
1515 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1517 = XCreateFontCursor (dpy
, XINT (Vx_sensitive_text_pointer_shape
));
1520 cross_cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
1522 if (!NILP (Vx_window_horizontal_drag_shape
))
1524 CHECK_NUMBER (Vx_window_horizontal_drag_shape
, 0);
1525 horizontal_drag_cursor
1526 = XCreateFontCursor (dpy
, XINT (Vx_window_horizontal_drag_shape
));
1529 horizontal_drag_cursor
1530 = XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
1532 /* Check and report errors with the above calls. */
1533 x_check_errors (dpy
, "can't set cursor shape: %s");
1534 x_uncatch_errors (dpy
, count
);
1537 XColor fore_color
, back_color
;
1539 fore_color
.pixel
= x
->mouse_pixel
;
1540 x_query_color (f
, &fore_color
);
1541 back_color
.pixel
= mask_color
;
1542 x_query_color (f
, &back_color
);
1544 XRecolorCursor (dpy
, cursor
, &fore_color
, &back_color
);
1545 XRecolorCursor (dpy
, nontext_cursor
, &fore_color
, &back_color
);
1546 XRecolorCursor (dpy
, mode_cursor
, &fore_color
, &back_color
);
1547 XRecolorCursor (dpy
, cross_cursor
, &fore_color
, &back_color
);
1548 XRecolorCursor (dpy
, hourglass_cursor
, &fore_color
, &back_color
);
1549 XRecolorCursor (dpy
, horizontal_drag_cursor
, &fore_color
, &back_color
);
1552 if (FRAME_X_WINDOW (f
) != 0)
1553 XDefineCursor (dpy
, FRAME_X_WINDOW (f
), cursor
);
1555 if (cursor
!= x
->text_cursor
1556 && x
->text_cursor
!= 0)
1557 XFreeCursor (dpy
, x
->text_cursor
);
1558 x
->text_cursor
= cursor
;
1560 if (nontext_cursor
!= x
->nontext_cursor
1561 && x
->nontext_cursor
!= 0)
1562 XFreeCursor (dpy
, x
->nontext_cursor
);
1563 x
->nontext_cursor
= nontext_cursor
;
1565 if (hourglass_cursor
!= x
->hourglass_cursor
1566 && x
->hourglass_cursor
!= 0)
1567 XFreeCursor (dpy
, x
->hourglass_cursor
);
1568 x
->hourglass_cursor
= hourglass_cursor
;
1570 if (mode_cursor
!= x
->modeline_cursor
1571 && x
->modeline_cursor
!= 0)
1572 XFreeCursor (dpy
, f
->output_data
.x
->modeline_cursor
);
1573 x
->modeline_cursor
= mode_cursor
;
1575 if (cross_cursor
!= x
->cross_cursor
1576 && x
->cross_cursor
!= 0)
1577 XFreeCursor (dpy
, x
->cross_cursor
);
1578 x
->cross_cursor
= cross_cursor
;
1580 if (horizontal_drag_cursor
!= x
->horizontal_drag_cursor
1581 && x
->horizontal_drag_cursor
!= 0)
1582 XFreeCursor (dpy
, x
->horizontal_drag_cursor
);
1583 x
->horizontal_drag_cursor
= horizontal_drag_cursor
;
1588 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1592 x_set_cursor_color (f
, arg
, oldval
)
1594 Lisp_Object arg
, oldval
;
1596 unsigned long fore_pixel
, pixel
;
1597 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1598 struct x_output
*x
= f
->output_data
.x
;
1600 if (!NILP (Vx_cursor_fore_pixel
))
1602 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1603 WHITE_PIX_DEFAULT (f
));
1604 fore_pixel_allocated_p
= 1;
1607 fore_pixel
= x
->background_pixel
;
1609 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1610 pixel_allocated_p
= 1;
1612 /* Make sure that the cursor color differs from the background color. */
1613 if (pixel
== x
->background_pixel
)
1615 if (pixel_allocated_p
)
1617 x_free_colors (f
, &pixel
, 1);
1618 pixel_allocated_p
= 0;
1621 pixel
= x
->mouse_pixel
;
1622 if (pixel
== fore_pixel
)
1624 if (fore_pixel_allocated_p
)
1626 x_free_colors (f
, &fore_pixel
, 1);
1627 fore_pixel_allocated_p
= 0;
1629 fore_pixel
= x
->background_pixel
;
1633 unload_color (f
, x
->cursor_foreground_pixel
);
1634 if (!fore_pixel_allocated_p
)
1635 fore_pixel
= x_copy_color (f
, fore_pixel
);
1636 x
->cursor_foreground_pixel
= fore_pixel
;
1638 unload_color (f
, x
->cursor_pixel
);
1639 if (!pixel_allocated_p
)
1640 pixel
= x_copy_color (f
, pixel
);
1641 x
->cursor_pixel
= pixel
;
1643 if (FRAME_X_WINDOW (f
) != 0)
1646 XSetBackground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, x
->cursor_pixel
);
1647 XSetForeground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, fore_pixel
);
1650 if (FRAME_VISIBLE_P (f
))
1652 x_update_cursor (f
, 0);
1653 x_update_cursor (f
, 1);
1657 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1660 /* Set the border-color of frame F to value described by ARG.
1661 ARG can be a string naming a color.
1662 The border-color is used for the border that is drawn by the X server.
1663 Note that this does not fully take effect if done before
1664 F has an x-window; it must be redone when the window is created.
1666 Note: this is done in two routines because of the way X10 works.
1668 Note: under X11, this is normally the province of the window manager,
1669 and so emacs' border colors may be overridden. */
1672 x_set_border_color (f
, arg
, oldval
)
1674 Lisp_Object arg
, oldval
;
1678 CHECK_STRING (arg
, 0);
1679 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1680 x_set_border_pixel (f
, pix
);
1681 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1684 /* Set the border-color of frame F to pixel value PIX.
1685 Note that this does not fully take effect if done before
1686 F has an x-window. */
1689 x_set_border_pixel (f
, pix
)
1693 unload_color (f
, f
->output_data
.x
->border_pixel
);
1694 f
->output_data
.x
->border_pixel
= pix
;
1696 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1699 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1700 (unsigned long)pix
);
1703 if (FRAME_VISIBLE_P (f
))
1709 /* Value is the internal representation of the specified cursor type
1710 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1711 of the bar cursor. */
1713 enum text_cursor_kinds
1714 x_specified_cursor_type (arg
, width
)
1718 enum text_cursor_kinds type
;
1725 else if (CONSP (arg
)
1726 && EQ (XCAR (arg
), Qbar
)
1727 && INTEGERP (XCDR (arg
))
1728 && XINT (XCDR (arg
)) >= 0)
1731 *width
= XINT (XCDR (arg
));
1733 else if (NILP (arg
))
1736 /* Treat anything unknown as "box cursor".
1737 It was bad to signal an error; people have trouble fixing
1738 .Xdefaults with Emacs, when it has something bad in it. */
1739 type
= FILLED_BOX_CURSOR
;
1745 x_set_cursor_type (f
, arg
, oldval
)
1747 Lisp_Object arg
, oldval
;
1751 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1752 f
->output_data
.x
->cursor_width
= width
;
1754 /* Make sure the cursor gets redrawn. This is overkill, but how
1755 often do people change cursor types? */
1756 update_mode_lines
++;
1760 x_set_icon_type (f
, arg
, oldval
)
1762 Lisp_Object arg
, oldval
;
1768 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1771 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1776 result
= x_text_icon (f
,
1777 (char *) XSTRING ((!NILP (f
->icon_name
)
1781 result
= x_bitmap_icon (f
, arg
);
1786 error ("No icon window available");
1789 XFlush (FRAME_X_DISPLAY (f
));
1793 /* Return non-nil if frame F wants a bitmap icon. */
1801 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1809 x_set_icon_name (f
, arg
, oldval
)
1811 Lisp_Object arg
, oldval
;
1817 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1820 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1825 if (f
->output_data
.x
->icon_bitmap
!= 0)
1830 result
= x_text_icon (f
,
1831 (char *) XSTRING ((!NILP (f
->icon_name
)
1840 error ("No icon window available");
1843 XFlush (FRAME_X_DISPLAY (f
));
1848 x_set_font (f
, arg
, oldval
)
1850 Lisp_Object arg
, oldval
;
1853 Lisp_Object fontset_name
;
1855 int old_fontset
= f
->output_data
.x
->fontset
;
1857 CHECK_STRING (arg
, 1);
1859 fontset_name
= Fquery_fontset (arg
, Qnil
);
1862 result
= (STRINGP (fontset_name
)
1863 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1864 : x_new_font (f
, XSTRING (arg
)->data
));
1867 if (EQ (result
, Qnil
))
1868 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1869 else if (EQ (result
, Qt
))
1870 error ("The characters of the given font have varying widths");
1871 else if (STRINGP (result
))
1873 if (STRINGP (fontset_name
))
1875 /* Fontset names are built from ASCII font names, so the
1876 names may be equal despite there was a change. */
1877 if (old_fontset
== f
->output_data
.x
->fontset
)
1880 else if (!NILP (Fequal (result
, oldval
)))
1883 store_frame_param (f
, Qfont
, result
);
1884 recompute_basic_faces (f
);
1889 do_pending_window_change (0);
1891 /* Don't call `face-set-after-frame-default' when faces haven't been
1892 initialized yet. This is the case when called from
1893 Fx_create_frame. In that case, the X widget or window doesn't
1894 exist either, and we can end up in x_report_frame_params with a
1895 null widget which gives a segfault. */
1896 if (FRAME_FACE_CACHE (f
))
1898 XSETFRAME (frame
, f
);
1899 call1 (Qface_set_after_frame_default
, frame
);
1904 x_set_border_width (f
, arg
, oldval
)
1906 Lisp_Object arg
, oldval
;
1908 CHECK_NUMBER (arg
, 0);
1910 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1913 if (FRAME_X_WINDOW (f
) != 0)
1914 error ("Cannot change the border width of a window");
1916 f
->output_data
.x
->border_width
= XINT (arg
);
1920 x_set_internal_border_width (f
, arg
, oldval
)
1922 Lisp_Object arg
, oldval
;
1924 int old
= f
->output_data
.x
->internal_border_width
;
1926 CHECK_NUMBER (arg
, 0);
1927 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1928 if (f
->output_data
.x
->internal_border_width
< 0)
1929 f
->output_data
.x
->internal_border_width
= 0;
1931 #ifdef USE_X_TOOLKIT
1932 if (f
->output_data
.x
->edit_widget
)
1933 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1936 if (f
->output_data
.x
->internal_border_width
== old
)
1939 if (FRAME_X_WINDOW (f
) != 0)
1941 x_set_window_size (f
, 0, f
->width
, f
->height
);
1942 SET_FRAME_GARBAGED (f
);
1943 do_pending_window_change (0);
1946 SET_FRAME_GARBAGED (f
);
1950 x_set_visibility (f
, value
, oldval
)
1952 Lisp_Object value
, oldval
;
1955 XSETFRAME (frame
, f
);
1958 Fmake_frame_invisible (frame
, Qt
);
1959 else if (EQ (value
, Qicon
))
1960 Ficonify_frame (frame
);
1962 Fmake_frame_visible (frame
);
1966 /* Change window heights in windows rooted in WINDOW by N lines. */
1969 x_change_window_heights (window
, n
)
1973 struct window
*w
= XWINDOW (window
);
1975 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1976 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1978 if (INTEGERP (w
->orig_top
))
1979 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
1980 if (INTEGERP (w
->orig_height
))
1981 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
1983 /* Handle just the top child in a vertical split. */
1984 if (!NILP (w
->vchild
))
1985 x_change_window_heights (w
->vchild
, n
);
1987 /* Adjust all children in a horizontal split. */
1988 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1990 w
= XWINDOW (window
);
1991 x_change_window_heights (window
, n
);
1996 x_set_menu_bar_lines (f
, value
, oldval
)
1998 Lisp_Object value
, oldval
;
2001 #ifndef USE_X_TOOLKIT
2002 int olines
= FRAME_MENU_BAR_LINES (f
);
2005 /* Right now, menu bars don't work properly in minibuf-only frames;
2006 most of the commands try to apply themselves to the minibuffer
2007 frame itself, and get an error because you can't switch buffers
2008 in or split the minibuffer window. */
2009 if (FRAME_MINIBUF_ONLY_P (f
))
2012 if (INTEGERP (value
))
2013 nlines
= XINT (value
);
2017 /* Make sure we redisplay all windows in this frame. */
2018 windows_or_buffers_changed
++;
2020 #ifdef USE_X_TOOLKIT
2021 FRAME_MENU_BAR_LINES (f
) = 0;
2024 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2025 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2026 /* Make sure next redisplay shows the menu bar. */
2027 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2031 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2032 free_frame_menubar (f
);
2033 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2035 f
->output_data
.x
->menubar_widget
= 0;
2037 #else /* not USE_X_TOOLKIT */
2038 FRAME_MENU_BAR_LINES (f
) = nlines
;
2039 x_change_window_heights (f
->root_window
, nlines
- olines
);
2040 #endif /* not USE_X_TOOLKIT */
2045 /* Set the number of lines used for the tool bar of frame F to VALUE.
2046 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2047 is the old number of tool bar lines. This function changes the
2048 height of all windows on frame F to match the new tool bar height.
2049 The frame's height doesn't change. */
2052 x_set_tool_bar_lines (f
, value
, oldval
)
2054 Lisp_Object value
, oldval
;
2056 int delta
, nlines
, root_height
;
2057 Lisp_Object root_window
;
2059 /* Treat tool bars like menu bars. */
2060 if (FRAME_MINIBUF_ONLY_P (f
))
2063 /* Use VALUE only if an integer >= 0. */
2064 if (INTEGERP (value
) && XINT (value
) >= 0)
2065 nlines
= XFASTINT (value
);
2069 /* Make sure we redisplay all windows in this frame. */
2070 ++windows_or_buffers_changed
;
2072 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2074 /* Don't resize the tool-bar to more than we have room for. */
2075 root_window
= FRAME_ROOT_WINDOW (f
);
2076 root_height
= XINT (XWINDOW (root_window
)->height
);
2077 if (root_height
- delta
< 1)
2079 delta
= root_height
- 1;
2080 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2083 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2084 x_change_window_heights (root_window
, delta
);
2087 /* We also have to make sure that the internal border at the top of
2088 the frame, below the menu bar or tool bar, is redrawn when the
2089 tool bar disappears. This is so because the internal border is
2090 below the tool bar if one is displayed, but is below the menu bar
2091 if there isn't a tool bar. The tool bar draws into the area
2092 below the menu bar. */
2093 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2097 clear_current_matrices (f
);
2098 updating_frame
= NULL
;
2101 /* If the tool bar gets smaller, the internal border below it
2102 has to be cleared. It was formerly part of the display
2103 of the larger tool bar, and updating windows won't clear it. */
2106 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2107 int width
= PIXEL_WIDTH (f
);
2108 int y
= nlines
* CANON_Y_UNIT (f
);
2111 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2112 0, y
, width
, height
, False
);
2115 if (WINDOWP (f
->tool_bar_window
))
2116 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2121 /* Set the foreground color for scroll bars on frame F to VALUE.
2122 VALUE should be a string, a color name. If it isn't a string or
2123 isn't a valid color name, do nothing. OLDVAL is the old value of
2124 the frame parameter. */
2127 x_set_scroll_bar_foreground (f
, value
, oldval
)
2129 Lisp_Object value
, oldval
;
2131 unsigned long pixel
;
2133 if (STRINGP (value
))
2134 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2138 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2139 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2141 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2142 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2144 /* Remove all scroll bars because they have wrong colors. */
2145 if (condemn_scroll_bars_hook
)
2146 (*condemn_scroll_bars_hook
) (f
);
2147 if (judge_scroll_bars_hook
)
2148 (*judge_scroll_bars_hook
) (f
);
2150 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2156 /* Set the background color for scroll bars on frame F to VALUE VALUE
2157 should be a string, a color name. If it isn't a string or isn't a
2158 valid color name, do nothing. OLDVAL is the old value of the frame
2162 x_set_scroll_bar_background (f
, value
, oldval
)
2164 Lisp_Object value
, oldval
;
2166 unsigned long pixel
;
2168 if (STRINGP (value
))
2169 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2173 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2174 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2176 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2177 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2179 /* Remove all scroll bars because they have wrong colors. */
2180 if (condemn_scroll_bars_hook
)
2181 (*condemn_scroll_bars_hook
) (f
);
2182 if (judge_scroll_bars_hook
)
2183 (*judge_scroll_bars_hook
) (f
);
2185 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2191 /* Encode Lisp string STRING as a text in a format appropriate for
2192 XICCC (X Inter Client Communication Conventions).
2194 If STRING contains only ASCII characters, do no conversion and
2195 return the string data of STRING. Otherwise, encode the text by
2196 CODING_SYSTEM, and return a newly allocated memory area which
2197 should be freed by `xfree' by a caller.
2199 SELECTIONP non-zero means the string is being encoded for an X
2200 selection, so it is safe to run pre-write conversions (which
2203 Store the byte length of resulting text in *TEXT_BYTES.
2205 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2206 which means that the `encoding' of the result can be `STRING'.
2207 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2208 the result should be `COMPOUND_TEXT'. */
2211 x_encode_text (string
, coding_system
, selectionp
, text_bytes
, stringp
)
2212 Lisp_Object string
, coding_system
;
2213 int *text_bytes
, *stringp
;
2216 unsigned char *str
= XSTRING (string
)->data
;
2217 int chars
= XSTRING (string
)->size
;
2218 int bytes
= STRING_BYTES (XSTRING (string
));
2222 struct coding_system coding
;
2224 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2225 if (charset_info
== 0)
2227 /* No multibyte character in OBJ. We need not encode it. */
2228 *text_bytes
= bytes
;
2233 setup_coding_system (coding_system
, &coding
);
2235 && SYMBOLP (coding
.pre_write_conversion
)
2236 && !NILP (Ffboundp (coding
.pre_write_conversion
)))
2238 string
= run_pre_post_conversion_on_str (string
, &coding
, 1);
2239 str
= XSTRING (string
)->data
;
2240 chars
= XSTRING (string
)->size
;
2241 bytes
= STRING_BYTES (XSTRING (string
));
2243 coding
.src_multibyte
= 1;
2244 coding
.dst_multibyte
= 0;
2245 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2246 if (coding
.type
== coding_type_iso2022
)
2247 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2248 /* We suppress producing escape sequences for composition. */
2249 coding
.composing
= COMPOSITION_DISABLED
;
2250 bufsize
= encoding_buffer_size (&coding
, bytes
);
2251 buf
= (unsigned char *) xmalloc (bufsize
);
2252 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2253 *text_bytes
= coding
.produced
;
2254 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2259 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2262 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2263 name; if NAME is a string, set F's name to NAME and set
2264 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2266 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2267 suggesting a new name, which lisp code should override; if
2268 F->explicit_name is set, ignore the new name; otherwise, set it. */
2271 x_set_name (f
, name
, explicit)
2276 /* Make sure that requests from lisp code override requests from
2277 Emacs redisplay code. */
2280 /* If we're switching from explicit to implicit, we had better
2281 update the mode lines and thereby update the title. */
2282 if (f
->explicit_name
&& NILP (name
))
2283 update_mode_lines
= 1;
2285 f
->explicit_name
= ! NILP (name
);
2287 else if (f
->explicit_name
)
2290 /* If NAME is nil, set the name to the x_id_name. */
2293 /* Check for no change needed in this very common case
2294 before we do any consing. */
2295 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2296 XSTRING (f
->name
)->data
))
2298 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2301 CHECK_STRING (name
, 0);
2303 /* Don't change the name if it's already NAME. */
2304 if (! NILP (Fstring_equal (name
, f
->name
)))
2309 /* For setting the frame title, the title parameter should override
2310 the name parameter. */
2311 if (! NILP (f
->title
))
2314 if (FRAME_X_WINDOW (f
))
2319 XTextProperty text
, icon
;
2321 Lisp_Object coding_system
;
2323 coding_system
= Qcompound_text
;
2324 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2325 text
.encoding
= (stringp
? XA_STRING
2326 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2328 text
.nitems
= bytes
;
2330 if (NILP (f
->icon_name
))
2336 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2338 icon
.encoding
= (stringp
? XA_STRING
2339 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2341 icon
.nitems
= bytes
;
2343 #ifdef USE_X_TOOLKIT
2344 XSetWMName (FRAME_X_DISPLAY (f
),
2345 XtWindow (f
->output_data
.x
->widget
), &text
);
2346 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2348 #else /* not USE_X_TOOLKIT */
2349 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2350 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2351 #endif /* not USE_X_TOOLKIT */
2352 if (!NILP (f
->icon_name
)
2353 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2355 if (text
.value
!= XSTRING (name
)->data
)
2358 #else /* not HAVE_X11R4 */
2359 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2360 XSTRING (name
)->data
);
2361 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2362 XSTRING (name
)->data
);
2363 #endif /* not HAVE_X11R4 */
2368 /* This function should be called when the user's lisp code has
2369 specified a name for the frame; the name will override any set by the
2372 x_explicitly_set_name (f
, arg
, oldval
)
2374 Lisp_Object arg
, oldval
;
2376 x_set_name (f
, arg
, 1);
2379 /* This function should be called by Emacs redisplay code to set the
2380 name; names set this way will never override names set by the user's
2383 x_implicitly_set_name (f
, arg
, oldval
)
2385 Lisp_Object arg
, oldval
;
2387 x_set_name (f
, arg
, 0);
2390 /* Change the title of frame F to NAME.
2391 If NAME is nil, use the frame name as the title.
2393 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2394 name; if NAME is a string, set F's name to NAME and set
2395 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2397 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2398 suggesting a new name, which lisp code should override; if
2399 F->explicit_name is set, ignore the new name; otherwise, set it. */
2402 x_set_title (f
, name
, old_name
)
2404 Lisp_Object name
, old_name
;
2406 /* Don't change the title if it's already NAME. */
2407 if (EQ (name
, f
->title
))
2410 update_mode_lines
= 1;
2417 CHECK_STRING (name
, 0);
2419 if (FRAME_X_WINDOW (f
))
2424 XTextProperty text
, icon
;
2426 Lisp_Object coding_system
;
2428 coding_system
= Qcompound_text
;
2429 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2430 text
.encoding
= (stringp
? XA_STRING
2431 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2433 text
.nitems
= bytes
;
2435 if (NILP (f
->icon_name
))
2441 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2443 icon
.encoding
= (stringp
? XA_STRING
2444 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2446 icon
.nitems
= bytes
;
2448 #ifdef USE_X_TOOLKIT
2449 XSetWMName (FRAME_X_DISPLAY (f
),
2450 XtWindow (f
->output_data
.x
->widget
), &text
);
2451 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2453 #else /* not USE_X_TOOLKIT */
2454 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2455 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2456 #endif /* not USE_X_TOOLKIT */
2457 if (!NILP (f
->icon_name
)
2458 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2460 if (text
.value
!= XSTRING (name
)->data
)
2463 #else /* not HAVE_X11R4 */
2464 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2465 XSTRING (name
)->data
);
2466 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2467 XSTRING (name
)->data
);
2468 #endif /* not HAVE_X11R4 */
2474 x_set_autoraise (f
, arg
, oldval
)
2476 Lisp_Object arg
, oldval
;
2478 f
->auto_raise
= !EQ (Qnil
, arg
);
2482 x_set_autolower (f
, arg
, oldval
)
2484 Lisp_Object arg
, oldval
;
2486 f
->auto_lower
= !EQ (Qnil
, arg
);
2490 x_set_unsplittable (f
, arg
, oldval
)
2492 Lisp_Object arg
, oldval
;
2494 f
->no_split
= !NILP (arg
);
2498 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2500 Lisp_Object arg
, oldval
;
2502 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2503 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2504 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2505 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2507 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2509 ? vertical_scroll_bar_none
2511 ? vertical_scroll_bar_right
2512 : vertical_scroll_bar_left
);
2514 /* We set this parameter before creating the X window for the
2515 frame, so we can get the geometry right from the start.
2516 However, if the window hasn't been created yet, we shouldn't
2517 call x_set_window_size. */
2518 if (FRAME_X_WINDOW (f
))
2519 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2520 do_pending_window_change (0);
2525 x_set_scroll_bar_width (f
, arg
, oldval
)
2527 Lisp_Object arg
, oldval
;
2529 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2533 #ifdef USE_TOOLKIT_SCROLL_BARS
2534 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2535 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2536 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2537 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2539 /* Make the actual width at least 14 pixels and a multiple of a
2541 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2543 /* Use all of that space (aside from required margins) for the
2545 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2548 if (FRAME_X_WINDOW (f
))
2549 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2550 do_pending_window_change (0);
2552 else if (INTEGERP (arg
) && XINT (arg
) > 0
2553 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2555 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2556 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2558 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2559 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2560 if (FRAME_X_WINDOW (f
))
2561 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2564 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2565 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2566 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2571 /* Subroutines of creating an X frame. */
2573 /* Make sure that Vx_resource_name is set to a reasonable value.
2574 Fix it up, or set it to `emacs' if it is too hopeless. */
2577 validate_x_resource_name ()
2580 /* Number of valid characters in the resource name. */
2582 /* Number of invalid characters in the resource name. */
2587 if (!STRINGP (Vx_resource_class
))
2588 Vx_resource_class
= build_string (EMACS_CLASS
);
2590 if (STRINGP (Vx_resource_name
))
2592 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2595 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2597 /* Only letters, digits, - and _ are valid in resource names.
2598 Count the valid characters and count the invalid ones. */
2599 for (i
= 0; i
< len
; i
++)
2602 if (! ((c
>= 'a' && c
<= 'z')
2603 || (c
>= 'A' && c
<= 'Z')
2604 || (c
>= '0' && c
<= '9')
2605 || c
== '-' || c
== '_'))
2612 /* Not a string => completely invalid. */
2613 bad_count
= 5, good_count
= 0;
2615 /* If name is valid already, return. */
2619 /* If name is entirely invalid, or nearly so, use `emacs'. */
2621 || (good_count
== 1 && bad_count
> 0))
2623 Vx_resource_name
= build_string ("emacs");
2627 /* Name is partly valid. Copy it and replace the invalid characters
2628 with underscores. */
2630 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2632 for (i
= 0; i
< len
; i
++)
2634 int c
= XSTRING (new)->data
[i
];
2635 if (! ((c
>= 'a' && c
<= 'z')
2636 || (c
>= 'A' && c
<= 'Z')
2637 || (c
>= '0' && c
<= '9')
2638 || c
== '-' || c
== '_'))
2639 XSTRING (new)->data
[i
] = '_';
2644 extern char *x_get_string_resource ();
2646 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2647 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2648 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2649 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2650 the name specified by the `-name' or `-rn' command-line arguments.\n\
2652 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2653 class, respectively. You must specify both of them or neither.\n\
2654 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2655 and the class is `Emacs.CLASS.SUBCLASS'.")
2656 (attribute
, class, component
, subclass
)
2657 Lisp_Object attribute
, class, component
, subclass
;
2659 register char *value
;
2665 CHECK_STRING (attribute
, 0);
2666 CHECK_STRING (class, 0);
2668 if (!NILP (component
))
2669 CHECK_STRING (component
, 1);
2670 if (!NILP (subclass
))
2671 CHECK_STRING (subclass
, 2);
2672 if (NILP (component
) != NILP (subclass
))
2673 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2675 validate_x_resource_name ();
2677 /* Allocate space for the components, the dots which separate them,
2678 and the final '\0'. Make them big enough for the worst case. */
2679 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2680 + (STRINGP (component
)
2681 ? STRING_BYTES (XSTRING (component
)) : 0)
2682 + STRING_BYTES (XSTRING (attribute
))
2685 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2686 + STRING_BYTES (XSTRING (class))
2687 + (STRINGP (subclass
)
2688 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2691 /* Start with emacs.FRAMENAME for the name (the specific one)
2692 and with `Emacs' for the class key (the general one). */
2693 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2694 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2696 strcat (class_key
, ".");
2697 strcat (class_key
, XSTRING (class)->data
);
2699 if (!NILP (component
))
2701 strcat (class_key
, ".");
2702 strcat (class_key
, XSTRING (subclass
)->data
);
2704 strcat (name_key
, ".");
2705 strcat (name_key
, XSTRING (component
)->data
);
2708 strcat (name_key
, ".");
2709 strcat (name_key
, XSTRING (attribute
)->data
);
2711 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2712 name_key
, class_key
);
2714 if (value
!= (char *) 0)
2715 return build_string (value
);
2720 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2723 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2724 struct x_display_info
*dpyinfo
;
2725 Lisp_Object attribute
, class, component
, subclass
;
2727 register char *value
;
2731 CHECK_STRING (attribute
, 0);
2732 CHECK_STRING (class, 0);
2734 if (!NILP (component
))
2735 CHECK_STRING (component
, 1);
2736 if (!NILP (subclass
))
2737 CHECK_STRING (subclass
, 2);
2738 if (NILP (component
) != NILP (subclass
))
2739 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2741 validate_x_resource_name ();
2743 /* Allocate space for the components, the dots which separate them,
2744 and the final '\0'. Make them big enough for the worst case. */
2745 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2746 + (STRINGP (component
)
2747 ? STRING_BYTES (XSTRING (component
)) : 0)
2748 + STRING_BYTES (XSTRING (attribute
))
2751 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2752 + STRING_BYTES (XSTRING (class))
2753 + (STRINGP (subclass
)
2754 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2757 /* Start with emacs.FRAMENAME for the name (the specific one)
2758 and with `Emacs' for the class key (the general one). */
2759 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2760 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2762 strcat (class_key
, ".");
2763 strcat (class_key
, XSTRING (class)->data
);
2765 if (!NILP (component
))
2767 strcat (class_key
, ".");
2768 strcat (class_key
, XSTRING (subclass
)->data
);
2770 strcat (name_key
, ".");
2771 strcat (name_key
, XSTRING (component
)->data
);
2774 strcat (name_key
, ".");
2775 strcat (name_key
, XSTRING (attribute
)->data
);
2777 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2779 if (value
!= (char *) 0)
2780 return build_string (value
);
2785 /* Used when C code wants a resource value. */
2788 x_get_resource_string (attribute
, class)
2789 char *attribute
, *class;
2793 struct frame
*sf
= SELECTED_FRAME ();
2795 /* Allocate space for the components, the dots which separate them,
2796 and the final '\0'. */
2797 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2798 + strlen (attribute
) + 2);
2799 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2800 + strlen (class) + 2);
2802 sprintf (name_key
, "%s.%s",
2803 XSTRING (Vinvocation_name
)->data
,
2805 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2807 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2808 name_key
, class_key
);
2811 /* Types we might convert a resource string into. */
2821 /* Return the value of parameter PARAM.
2823 First search ALIST, then Vdefault_frame_alist, then the X defaults
2824 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2826 Convert the resource to the type specified by desired_type.
2828 If no default is specified, return Qunbound. If you call
2829 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2830 and don't let it get stored in any Lisp-visible variables! */
2833 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2834 struct x_display_info
*dpyinfo
;
2835 Lisp_Object alist
, param
;
2838 enum resource_types type
;
2840 register Lisp_Object tem
;
2842 tem
= Fassq (param
, alist
);
2844 tem
= Fassq (param
, Vdefault_frame_alist
);
2850 tem
= display_x_get_resource (dpyinfo
,
2851 build_string (attribute
),
2852 build_string (class),
2860 case RES_TYPE_NUMBER
:
2861 return make_number (atoi (XSTRING (tem
)->data
));
2863 case RES_TYPE_FLOAT
:
2864 return make_float (atof (XSTRING (tem
)->data
));
2866 case RES_TYPE_BOOLEAN
:
2867 tem
= Fdowncase (tem
);
2868 if (!strcmp (XSTRING (tem
)->data
, "on")
2869 || !strcmp (XSTRING (tem
)->data
, "true"))
2874 case RES_TYPE_STRING
:
2877 case RES_TYPE_SYMBOL
:
2878 /* As a special case, we map the values `true' and `on'
2879 to Qt, and `false' and `off' to Qnil. */
2882 lower
= Fdowncase (tem
);
2883 if (!strcmp (XSTRING (lower
)->data
, "on")
2884 || !strcmp (XSTRING (lower
)->data
, "true"))
2886 else if (!strcmp (XSTRING (lower
)->data
, "off")
2887 || !strcmp (XSTRING (lower
)->data
, "false"))
2890 return Fintern (tem
, Qnil
);
2903 /* Like x_get_arg, but also record the value in f->param_alist. */
2906 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2908 Lisp_Object alist
, param
;
2911 enum resource_types type
;
2915 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2916 attribute
, class, type
);
2918 store_frame_param (f
, param
, value
);
2923 /* Record in frame F the specified or default value according to ALIST
2924 of the parameter named PROP (a Lisp symbol).
2925 If no value is specified for PROP, look for an X default for XPROP
2926 on the frame named NAME.
2927 If that is not found either, use the value DEFLT. */
2930 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2937 enum resource_types type
;
2941 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2942 if (EQ (tem
, Qunbound
))
2944 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2949 /* Record in frame F the specified or default value according to ALIST
2950 of the parameter named PROP (a Lisp symbol). If no value is
2951 specified for PROP, look for an X default for XPROP on the frame
2952 named NAME. If that is not found either, use the value DEFLT. */
2955 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2964 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2967 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
2968 if (EQ (tem
, Qunbound
))
2970 #ifdef USE_TOOLKIT_SCROLL_BARS
2972 /* See if an X resource for the scroll bar color has been
2974 tem
= display_x_get_resource (dpyinfo
,
2975 build_string (foreground_p
2979 build_string ("verticalScrollBar"),
2983 /* If nothing has been specified, scroll bars will use a
2984 toolkit-dependent default. Because these defaults are
2985 difficult to get at without actually creating a scroll
2986 bar, use nil to indicate that no color has been
2991 #else /* not USE_TOOLKIT_SCROLL_BARS */
2995 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2998 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3004 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3005 "Parse an X-style geometry string STRING.\n\
3006 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
3007 The properties returned may include `top', `left', `height', and `width'.\n\
3008 The value of `left' or `top' may be an integer,\n\
3009 or a list (+ N) meaning N pixels relative to top/left corner,\n\
3010 or a list (- N) meaning -N pixels relative to bottom/right corner.")
3015 unsigned int width
, height
;
3018 CHECK_STRING (string
, 0);
3020 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
3021 &x
, &y
, &width
, &height
);
3024 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3025 error ("Must specify both x and y position, or neither");
3029 if (geometry
& XValue
)
3031 Lisp_Object element
;
3033 if (x
>= 0 && (geometry
& XNegative
))
3034 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3035 else if (x
< 0 && ! (geometry
& XNegative
))
3036 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3038 element
= Fcons (Qleft
, make_number (x
));
3039 result
= Fcons (element
, result
);
3042 if (geometry
& YValue
)
3044 Lisp_Object element
;
3046 if (y
>= 0 && (geometry
& YNegative
))
3047 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3048 else if (y
< 0 && ! (geometry
& YNegative
))
3049 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3051 element
= Fcons (Qtop
, make_number (y
));
3052 result
= Fcons (element
, result
);
3055 if (geometry
& WidthValue
)
3056 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3057 if (geometry
& HeightValue
)
3058 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3063 /* Calculate the desired size and position of this window,
3064 and return the flags saying which aspects were specified.
3066 This function does not make the coordinates positive. */
3068 #define DEFAULT_ROWS 40
3069 #define DEFAULT_COLS 80
3072 x_figure_window_size (f
, parms
)
3076 register Lisp_Object tem0
, tem1
, tem2
;
3077 long window_prompting
= 0;
3078 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3080 /* Default values if we fall through.
3081 Actually, if that happens we should get
3082 window manager prompting. */
3083 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3084 f
->height
= DEFAULT_ROWS
;
3085 /* Window managers expect that if program-specified
3086 positions are not (0,0), they're intentional, not defaults. */
3087 f
->output_data
.x
->top_pos
= 0;
3088 f
->output_data
.x
->left_pos
= 0;
3090 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3091 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3092 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3093 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3095 if (!EQ (tem0
, Qunbound
))
3097 CHECK_NUMBER (tem0
, 0);
3098 f
->height
= XINT (tem0
);
3100 if (!EQ (tem1
, Qunbound
))
3102 CHECK_NUMBER (tem1
, 0);
3103 SET_FRAME_WIDTH (f
, XINT (tem1
));
3105 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3106 window_prompting
|= USSize
;
3108 window_prompting
|= PSize
;
3111 f
->output_data
.x
->vertical_scroll_bar_extra
3112 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3114 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3115 f
->output_data
.x
->flags_areas_extra
3116 = FRAME_FLAGS_AREA_WIDTH (f
);
3117 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3118 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3120 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3121 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3122 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3123 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3125 if (EQ (tem0
, Qminus
))
3127 f
->output_data
.x
->top_pos
= 0;
3128 window_prompting
|= YNegative
;
3130 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3131 && CONSP (XCDR (tem0
))
3132 && INTEGERP (XCAR (XCDR (tem0
))))
3134 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3135 window_prompting
|= YNegative
;
3137 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3138 && CONSP (XCDR (tem0
))
3139 && INTEGERP (XCAR (XCDR (tem0
))))
3141 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3143 else if (EQ (tem0
, Qunbound
))
3144 f
->output_data
.x
->top_pos
= 0;
3147 CHECK_NUMBER (tem0
, 0);
3148 f
->output_data
.x
->top_pos
= XINT (tem0
);
3149 if (f
->output_data
.x
->top_pos
< 0)
3150 window_prompting
|= YNegative
;
3153 if (EQ (tem1
, Qminus
))
3155 f
->output_data
.x
->left_pos
= 0;
3156 window_prompting
|= XNegative
;
3158 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3159 && CONSP (XCDR (tem1
))
3160 && INTEGERP (XCAR (XCDR (tem1
))))
3162 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3163 window_prompting
|= XNegative
;
3165 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3166 && CONSP (XCDR (tem1
))
3167 && INTEGERP (XCAR (XCDR (tem1
))))
3169 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3171 else if (EQ (tem1
, Qunbound
))
3172 f
->output_data
.x
->left_pos
= 0;
3175 CHECK_NUMBER (tem1
, 0);
3176 f
->output_data
.x
->left_pos
= XINT (tem1
);
3177 if (f
->output_data
.x
->left_pos
< 0)
3178 window_prompting
|= XNegative
;
3181 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3182 window_prompting
|= USPosition
;
3184 window_prompting
|= PPosition
;
3187 return window_prompting
;
3190 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3193 XSetWMProtocols (dpy
, w
, protocols
, count
)
3200 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3201 if (prop
== None
) return False
;
3202 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3203 (unsigned char *) protocols
, count
);
3206 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3208 #ifdef USE_X_TOOLKIT
3210 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3211 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3212 already be present because of the toolkit (Motif adds some of them,
3213 for example, but Xt doesn't). */
3216 hack_wm_protocols (f
, widget
)
3220 Display
*dpy
= XtDisplay (widget
);
3221 Window w
= XtWindow (widget
);
3222 int need_delete
= 1;
3228 Atom type
, *atoms
= 0;
3230 unsigned long nitems
= 0;
3231 unsigned long bytes_after
;
3233 if ((XGetWindowProperty (dpy
, w
,
3234 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3235 (long)0, (long)100, False
, XA_ATOM
,
3236 &type
, &format
, &nitems
, &bytes_after
,
3237 (unsigned char **) &atoms
)
3239 && format
== 32 && type
== XA_ATOM
)
3243 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3245 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3247 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3250 if (atoms
) XFree ((char *) atoms
);
3256 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3258 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3260 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3262 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3263 XA_ATOM
, 32, PropModeAppend
,
3264 (unsigned char *) props
, count
);
3272 /* Support routines for XIC (X Input Context). */
3276 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3277 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3280 /* Supported XIM styles, ordered by preferenc. */
3282 static XIMStyle supported_xim_styles
[] =
3284 XIMPreeditPosition
| XIMStatusArea
,
3285 XIMPreeditPosition
| XIMStatusNothing
,
3286 XIMPreeditPosition
| XIMStatusNone
,
3287 XIMPreeditNothing
| XIMStatusArea
,
3288 XIMPreeditNothing
| XIMStatusNothing
,
3289 XIMPreeditNothing
| XIMStatusNone
,
3290 XIMPreeditNone
| XIMStatusArea
,
3291 XIMPreeditNone
| XIMStatusNothing
,
3292 XIMPreeditNone
| XIMStatusNone
,
3297 /* Create an X fontset on frame F with base font name
3301 xic_create_xfontset (f
, base_fontname
)
3303 char *base_fontname
;
3306 char **missing_list
;
3310 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3311 base_fontname
, &missing_list
,
3312 &missing_count
, &def_string
);
3314 XFreeStringList (missing_list
);
3316 /* No need to free def_string. */
3321 /* Value is the best input style, given user preferences USER (already
3322 checked to be supported by Emacs), and styles supported by the
3323 input method XIM. */
3326 best_xim_style (user
, xim
)
3332 for (i
= 0; i
< user
->count_styles
; ++i
)
3333 for (j
= 0; j
< xim
->count_styles
; ++j
)
3334 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3335 return user
->supported_styles
[i
];
3337 /* Return the default style. */
3338 return XIMPreeditNothing
| XIMStatusNothing
;
3341 /* Create XIC for frame F. */
3343 static XIMStyle xic_style
;
3346 create_frame_xic (f
)
3351 XFontSet xfs
= NULL
;
3356 xim
= FRAME_X_XIM (f
);
3361 XVaNestedList preedit_attr
;
3362 XVaNestedList status_attr
;
3363 char *base_fontname
;
3366 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3367 spot
.x
= 0; spot
.y
= 1;
3368 /* Create X fontset. */
3369 fontset
= FRAME_FONTSET (f
);
3371 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3374 /* Determine the base fontname from the ASCII font name of
3376 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3377 char *p
= ascii_font
;
3380 for (i
= 0; *p
; p
++)
3383 /* As the font name doesn't conform to XLFD, we can't
3384 modify it to get a suitable base fontname for the
3386 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3389 int len
= strlen (ascii_font
) + 1;
3392 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3401 base_fontname
= (char *) alloca (len
);
3402 bzero (base_fontname
, len
);
3403 strcpy (base_fontname
, "-*-*-");
3404 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3405 strcat (base_fontname
, "*-*-*-*-*-*-*");
3408 xfs
= xic_create_xfontset (f
, base_fontname
);
3410 /* Determine XIC style. */
3413 XIMStyles supported_list
;
3414 supported_list
.count_styles
= (sizeof supported_xim_styles
3415 / sizeof supported_xim_styles
[0]);
3416 supported_list
.supported_styles
= supported_xim_styles
;
3417 xic_style
= best_xim_style (&supported_list
,
3418 FRAME_X_XIM_STYLES (f
));
3421 preedit_attr
= XVaCreateNestedList (0,
3424 FRAME_FOREGROUND_PIXEL (f
),
3426 FRAME_BACKGROUND_PIXEL (f
),
3427 (xic_style
& XIMPreeditPosition
3432 status_attr
= XVaCreateNestedList (0,
3438 FRAME_FOREGROUND_PIXEL (f
),
3440 FRAME_BACKGROUND_PIXEL (f
),
3443 xic
= XCreateIC (xim
,
3444 XNInputStyle
, xic_style
,
3445 XNClientWindow
, FRAME_X_WINDOW(f
),
3446 XNFocusWindow
, FRAME_X_WINDOW(f
),
3447 XNStatusAttributes
, status_attr
,
3448 XNPreeditAttributes
, preedit_attr
,
3450 XFree (preedit_attr
);
3451 XFree (status_attr
);
3454 FRAME_XIC (f
) = xic
;
3455 FRAME_XIC_STYLE (f
) = xic_style
;
3456 FRAME_XIC_FONTSET (f
) = xfs
;
3460 /* Destroy XIC and free XIC fontset of frame F, if any. */
3466 if (FRAME_XIC (f
) == NULL
)
3469 XDestroyIC (FRAME_XIC (f
));
3470 if (FRAME_XIC_FONTSET (f
))
3471 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3473 FRAME_XIC (f
) = NULL
;
3474 FRAME_XIC_FONTSET (f
) = NULL
;
3478 /* Place preedit area for XIC of window W's frame to specified
3479 pixel position X/Y. X and Y are relative to window W. */
3482 xic_set_preeditarea (w
, x
, y
)
3486 struct frame
*f
= XFRAME (w
->frame
);
3490 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3491 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3492 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3493 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3498 /* Place status area for XIC in bottom right corner of frame F.. */
3501 xic_set_statusarea (f
)
3504 XIC xic
= FRAME_XIC (f
);
3509 /* Negotiate geometry of status area. If input method has existing
3510 status area, use its current size. */
3511 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3512 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3513 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3516 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3517 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3520 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3522 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3523 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3527 area
.width
= needed
->width
;
3528 area
.height
= needed
->height
;
3529 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3530 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3531 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3534 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3535 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3540 /* Set X fontset for XIC of frame F, using base font name
3541 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3544 xic_set_xfontset (f
, base_fontname
)
3546 char *base_fontname
;
3551 xfs
= xic_create_xfontset (f
, base_fontname
);
3553 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3554 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3555 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3556 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3557 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3560 if (FRAME_XIC_FONTSET (f
))
3561 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3562 FRAME_XIC_FONTSET (f
) = xfs
;
3565 #endif /* HAVE_X_I18N */
3569 #ifdef USE_X_TOOLKIT
3571 /* Create and set up the X widget for frame F. */
3574 x_window (f
, window_prompting
, minibuffer_only
)
3576 long window_prompting
;
3577 int minibuffer_only
;
3579 XClassHint class_hints
;
3580 XSetWindowAttributes attributes
;
3581 unsigned long attribute_mask
;
3582 Widget shell_widget
;
3584 Widget frame_widget
;
3590 /* Use the resource name as the top-level widget name
3591 for looking up resources. Make a non-Lisp copy
3592 for the window manager, so GC relocation won't bother it.
3594 Elsewhere we specify the window name for the window manager. */
3597 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3598 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3599 strcpy (f
->namebuf
, str
);
3603 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3604 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3605 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3606 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3607 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3608 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3609 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3610 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3611 applicationShellWidgetClass
,
3612 FRAME_X_DISPLAY (f
), al
, ac
);
3614 f
->output_data
.x
->widget
= shell_widget
;
3615 /* maybe_set_screen_title_format (shell_widget); */
3617 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3618 (widget_value
*) NULL
,
3619 shell_widget
, False
,
3623 (lw_callback
) NULL
);
3626 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3627 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3628 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3629 XtSetValues (pane_widget
, al
, ac
);
3630 f
->output_data
.x
->column_widget
= pane_widget
;
3632 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3633 the emacs screen when changing menubar. This reduces flickering. */
3636 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3637 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3638 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3639 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3640 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3641 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3642 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3643 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3644 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3647 f
->output_data
.x
->edit_widget
= frame_widget
;
3649 XtManageChild (frame_widget
);
3651 /* Do some needed geometry management. */
3654 char *tem
, shell_position
[32];
3657 int extra_borders
= 0;
3659 = (f
->output_data
.x
->menubar_widget
3660 ? (f
->output_data
.x
->menubar_widget
->core
.height
3661 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3664 #if 0 /* Experimentally, we now get the right results
3665 for -geometry -0-0 without this. 24 Aug 96, rms. */
3666 if (FRAME_EXTERNAL_MENU_BAR (f
))
3669 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3670 menubar_size
+= ibw
;
3674 f
->output_data
.x
->menubar_height
= menubar_size
;
3677 /* Motif seems to need this amount added to the sizes
3678 specified for the shell widget. The Athena/Lucid widgets don't.
3679 Both conclusions reached experimentally. -- rms. */
3680 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3681 &extra_borders
, NULL
);
3685 /* Convert our geometry parameters into a geometry string
3687 Note that we do not specify here whether the position
3688 is a user-specified or program-specified one.
3689 We pass that information later, in x_wm_set_size_hints. */
3691 int left
= f
->output_data
.x
->left_pos
;
3692 int xneg
= window_prompting
& XNegative
;
3693 int top
= f
->output_data
.x
->top_pos
;
3694 int yneg
= window_prompting
& YNegative
;
3700 if (window_prompting
& USPosition
)
3701 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3702 PIXEL_WIDTH (f
) + extra_borders
,
3703 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3704 (xneg
? '-' : '+'), left
,
3705 (yneg
? '-' : '+'), top
);
3707 sprintf (shell_position
, "=%dx%d",
3708 PIXEL_WIDTH (f
) + extra_borders
,
3709 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3712 len
= strlen (shell_position
) + 1;
3713 /* We don't free this because we don't know whether
3714 it is safe to free it while the frame exists.
3715 It isn't worth the trouble of arranging to free it
3716 when the frame is deleted. */
3717 tem
= (char *) xmalloc (len
);
3718 strncpy (tem
, shell_position
, len
);
3719 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3720 XtSetValues (shell_widget
, al
, ac
);
3723 XtManageChild (pane_widget
);
3724 XtRealizeWidget (shell_widget
);
3726 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3728 validate_x_resource_name ();
3730 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3731 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3732 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3735 FRAME_XIC (f
) = NULL
;
3737 create_frame_xic (f
);
3741 f
->output_data
.x
->wm_hints
.input
= True
;
3742 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3743 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3744 &f
->output_data
.x
->wm_hints
);
3746 hack_wm_protocols (f
, shell_widget
);
3749 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3752 /* Do a stupid property change to force the server to generate a
3753 PropertyNotify event so that the event_stream server timestamp will
3754 be initialized to something relevant to the time we created the window.
3756 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3757 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3758 XA_ATOM
, 32, PropModeAppend
,
3759 (unsigned char*) NULL
, 0);
3761 /* Make all the standard events reach the Emacs frame. */
3762 attributes
.event_mask
= STANDARD_EVENT_SET
;
3767 /* XIM server might require some X events. */
3768 unsigned long fevent
= NoEventMask
;
3769 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3770 attributes
.event_mask
|= fevent
;
3772 #endif /* HAVE_X_I18N */
3774 attribute_mask
= CWEventMask
;
3775 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3776 attribute_mask
, &attributes
);
3778 XtMapWidget (frame_widget
);
3780 /* x_set_name normally ignores requests to set the name if the
3781 requested name is the same as the current name. This is the one
3782 place where that assumption isn't correct; f->name is set, but
3783 the X server hasn't been told. */
3786 int explicit = f
->explicit_name
;
3788 f
->explicit_name
= 0;
3791 x_set_name (f
, name
, explicit);
3794 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3795 f
->output_data
.x
->text_cursor
);
3799 /* This is a no-op, except under Motif. Make sure main areas are
3800 set to something reasonable, in case we get an error later. */
3801 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3804 #else /* not USE_X_TOOLKIT */
3806 /* Create and set up the X window for frame F. */
3813 XClassHint class_hints
;
3814 XSetWindowAttributes attributes
;
3815 unsigned long attribute_mask
;
3817 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3818 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3819 attributes
.bit_gravity
= StaticGravity
;
3820 attributes
.backing_store
= NotUseful
;
3821 attributes
.save_under
= True
;
3822 attributes
.event_mask
= STANDARD_EVENT_SET
;
3823 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3824 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3829 = XCreateWindow (FRAME_X_DISPLAY (f
),
3830 f
->output_data
.x
->parent_desc
,
3831 f
->output_data
.x
->left_pos
,
3832 f
->output_data
.x
->top_pos
,
3833 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3834 f
->output_data
.x
->border_width
,
3835 CopyFromParent
, /* depth */
3836 InputOutput
, /* class */
3838 attribute_mask
, &attributes
);
3842 create_frame_xic (f
);
3845 /* XIM server might require some X events. */
3846 unsigned long fevent
= NoEventMask
;
3847 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3848 attributes
.event_mask
|= fevent
;
3849 attribute_mask
= CWEventMask
;
3850 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3851 attribute_mask
, &attributes
);
3854 #endif /* HAVE_X_I18N */
3856 validate_x_resource_name ();
3858 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3859 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3860 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3862 /* The menubar is part of the ordinary display;
3863 it does not count in addition to the height of the window. */
3864 f
->output_data
.x
->menubar_height
= 0;
3866 /* This indicates that we use the "Passive Input" input model.
3867 Unless we do this, we don't get the Focus{In,Out} events that we
3868 need to draw the cursor correctly. Accursed bureaucrats.
3869 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3871 f
->output_data
.x
->wm_hints
.input
= True
;
3872 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3873 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3874 &f
->output_data
.x
->wm_hints
);
3875 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3877 /* Request "save yourself" and "delete window" commands from wm. */
3880 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3881 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3882 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3885 /* x_set_name normally ignores requests to set the name if the
3886 requested name is the same as the current name. This is the one
3887 place where that assumption isn't correct; f->name is set, but
3888 the X server hasn't been told. */
3891 int explicit = f
->explicit_name
;
3893 f
->explicit_name
= 0;
3896 x_set_name (f
, name
, explicit);
3899 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3900 f
->output_data
.x
->text_cursor
);
3904 if (FRAME_X_WINDOW (f
) == 0)
3905 error ("Unable to create window");
3908 #endif /* not USE_X_TOOLKIT */
3910 /* Handle the icon stuff for this window. Perhaps later we might
3911 want an x_set_icon_position which can be called interactively as
3919 Lisp_Object icon_x
, icon_y
;
3920 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3922 /* Set the position of the icon. Note that twm groups all
3923 icons in an icon window. */
3924 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3925 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3926 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3928 CHECK_NUMBER (icon_x
, 0);
3929 CHECK_NUMBER (icon_y
, 0);
3931 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3932 error ("Both left and top icon corners of icon must be specified");
3936 if (! EQ (icon_x
, Qunbound
))
3937 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3939 /* Start up iconic or window? */
3940 x_wm_set_window_state
3941 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3946 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3953 /* Make the GCs needed for this window, setting the
3954 background, border and mouse colors; also create the
3955 mouse cursor and the gray border tile. */
3957 static char cursor_bits
[] =
3959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3969 XGCValues gc_values
;
3973 /* Create the GCs of this frame.
3974 Note that many default values are used. */
3977 gc_values
.font
= f
->output_data
.x
->font
->fid
;
3978 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
3979 gc_values
.background
= f
->output_data
.x
->background_pixel
;
3980 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
3981 f
->output_data
.x
->normal_gc
3982 = XCreateGC (FRAME_X_DISPLAY (f
),
3984 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
3987 /* Reverse video style. */
3988 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3989 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
3990 f
->output_data
.x
->reverse_gc
3991 = XCreateGC (FRAME_X_DISPLAY (f
),
3993 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
3996 /* Cursor has cursor-color background, background-color foreground. */
3997 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3998 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
3999 gc_values
.fill_style
= FillOpaqueStippled
;
4001 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4002 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4003 cursor_bits
, 16, 16);
4004 f
->output_data
.x
->cursor_gc
4005 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4006 (GCFont
| GCForeground
| GCBackground
4007 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
4011 f
->output_data
.x
->white_relief
.gc
= 0;
4012 f
->output_data
.x
->black_relief
.gc
= 0;
4014 /* Create the gray border tile used when the pointer is not in
4015 the frame. Since this depends on the frame's pixel values,
4016 this must be done on a per-frame basis. */
4017 f
->output_data
.x
->border_tile
4018 = (XCreatePixmapFromBitmapData
4019 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
4020 gray_bits
, gray_width
, gray_height
,
4021 f
->output_data
.x
->foreground_pixel
,
4022 f
->output_data
.x
->background_pixel
,
4023 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4029 /* Free what was was allocated in x_make_gc. */
4035 Display
*dpy
= FRAME_X_DISPLAY (f
);
4039 if (f
->output_data
.x
->normal_gc
)
4041 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4042 f
->output_data
.x
->normal_gc
= 0;
4045 if (f
->output_data
.x
->reverse_gc
)
4047 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4048 f
->output_data
.x
->reverse_gc
= 0;
4051 if (f
->output_data
.x
->cursor_gc
)
4053 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4054 f
->output_data
.x
->cursor_gc
= 0;
4057 if (f
->output_data
.x
->border_tile
)
4059 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4060 f
->output_data
.x
->border_tile
= 0;
4067 /* Handler for signals raised during x_create_frame and
4068 x_create_top_frame. FRAME is the frame which is partially
4072 unwind_create_frame (frame
)
4075 struct frame
*f
= XFRAME (frame
);
4077 /* If frame is ``official'', nothing to do. */
4078 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4081 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4084 x_free_frame_resources (f
);
4086 /* Check that reference counts are indeed correct. */
4087 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4088 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4096 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4098 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
4099 Returns an Emacs frame object.\n\
4100 ALIST is an alist of frame parameters.\n\
4101 If the parameters specify that the frame should not have a minibuffer,\n\
4102 and do not specify a specific minibuffer window to use,\n\
4103 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
4104 be shared by the new frame.\n\
4106 This function is an internal primitive--use `make-frame' instead.")
4111 Lisp_Object frame
, tem
;
4113 int minibuffer_only
= 0;
4114 long window_prompting
= 0;
4116 int count
= BINDING_STACK_SIZE ();
4117 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4118 Lisp_Object display
;
4119 struct x_display_info
*dpyinfo
= NULL
;
4125 /* Use this general default value to start with
4126 until we know if this frame has a specified name. */
4127 Vx_resource_name
= Vinvocation_name
;
4129 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4130 if (EQ (display
, Qunbound
))
4132 dpyinfo
= check_x_display_info (display
);
4134 kb
= dpyinfo
->kboard
;
4136 kb
= &the_only_kboard
;
4139 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4141 && ! EQ (name
, Qunbound
)
4143 error ("Invalid frame name--not a string or nil");
4146 Vx_resource_name
= name
;
4148 /* See if parent window is specified. */
4149 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4150 if (EQ (parent
, Qunbound
))
4152 if (! NILP (parent
))
4153 CHECK_NUMBER (parent
, 0);
4155 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4156 /* No need to protect DISPLAY because that's not used after passing
4157 it to make_frame_without_minibuffer. */
4159 GCPRO4 (parms
, parent
, name
, frame
);
4160 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4162 if (EQ (tem
, Qnone
) || NILP (tem
))
4163 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4164 else if (EQ (tem
, Qonly
))
4166 f
= make_minibuffer_frame ();
4167 minibuffer_only
= 1;
4169 else if (WINDOWP (tem
))
4170 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4174 XSETFRAME (frame
, f
);
4176 /* Note that X Windows does support scroll bars. */
4177 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4179 f
->output_method
= output_x_window
;
4180 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4181 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4182 f
->output_data
.x
->icon_bitmap
= -1;
4183 f
->output_data
.x
->fontset
= -1;
4184 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4185 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4186 record_unwind_protect (unwind_create_frame
, frame
);
4189 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4191 if (! STRINGP (f
->icon_name
))
4192 f
->icon_name
= Qnil
;
4194 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4196 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4197 dpyinfo_refcount
= dpyinfo
->reference_count
;
4198 #endif /* GLYPH_DEBUG */
4200 FRAME_KBOARD (f
) = kb
;
4203 /* These colors will be set anyway later, but it's important
4204 to get the color reference counts right, so initialize them! */
4207 struct gcpro gcpro1
;
4209 /* Function x_decode_color can signal an error. Make
4210 sure to initialize color slots so that we won't try
4211 to free colors we haven't allocated. */
4212 f
->output_data
.x
->foreground_pixel
= -1;
4213 f
->output_data
.x
->background_pixel
= -1;
4214 f
->output_data
.x
->cursor_pixel
= -1;
4215 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4216 f
->output_data
.x
->border_pixel
= -1;
4217 f
->output_data
.x
->mouse_pixel
= -1;
4219 black
= build_string ("black");
4221 f
->output_data
.x
->foreground_pixel
4222 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4223 f
->output_data
.x
->background_pixel
4224 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4225 f
->output_data
.x
->cursor_pixel
4226 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4227 f
->output_data
.x
->cursor_foreground_pixel
4228 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4229 f
->output_data
.x
->border_pixel
4230 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4231 f
->output_data
.x
->mouse_pixel
4232 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4236 /* Specify the parent under which to make this X window. */
4240 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4241 f
->output_data
.x
->explicit_parent
= 1;
4245 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4246 f
->output_data
.x
->explicit_parent
= 0;
4249 /* Set the name; the functions to which we pass f expect the name to
4251 if (EQ (name
, Qunbound
) || NILP (name
))
4253 f
->name
= build_string (dpyinfo
->x_id_name
);
4254 f
->explicit_name
= 0;
4259 f
->explicit_name
= 1;
4260 /* use the frame's title when getting resources for this frame. */
4261 specbind (Qx_resource_name
, name
);
4264 /* Extract the window parameters from the supplied values
4265 that are needed to determine window geometry. */
4269 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4272 /* First, try whatever font the caller has specified. */
4275 tem
= Fquery_fontset (font
, Qnil
);
4277 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4279 font
= x_new_font (f
, XSTRING (font
)->data
);
4282 /* Try out a font which we hope has bold and italic variations. */
4283 if (!STRINGP (font
))
4284 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4285 if (!STRINGP (font
))
4286 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4287 if (! STRINGP (font
))
4288 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4289 if (! STRINGP (font
))
4290 /* This was formerly the first thing tried, but it finds too many fonts
4291 and takes too long. */
4292 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4293 /* If those didn't work, look for something which will at least work. */
4294 if (! STRINGP (font
))
4295 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4297 if (! STRINGP (font
))
4298 font
= build_string ("fixed");
4300 x_default_parameter (f
, parms
, Qfont
, font
,
4301 "font", "Font", RES_TYPE_STRING
);
4305 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4306 whereby it fails to get any font. */
4307 xlwmenu_default_font
= f
->output_data
.x
->font
;
4310 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4311 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4313 /* This defaults to 2 in order to match xterm. We recognize either
4314 internalBorderWidth or internalBorder (which is what xterm calls
4316 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4320 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4321 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4322 if (! EQ (value
, Qunbound
))
4323 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4326 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4327 "internalBorderWidth", "internalBorderWidth",
4329 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4330 "verticalScrollBars", "ScrollBars",
4333 /* Also do the stuff which must be set before the window exists. */
4334 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4335 "foreground", "Foreground", RES_TYPE_STRING
);
4336 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4337 "background", "Background", RES_TYPE_STRING
);
4338 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4339 "pointerColor", "Foreground", RES_TYPE_STRING
);
4340 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4341 "cursorColor", "Foreground", RES_TYPE_STRING
);
4342 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4343 "borderColor", "BorderColor", RES_TYPE_STRING
);
4344 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4345 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4346 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4347 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4349 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4350 "scrollBarForeground",
4351 "ScrollBarForeground", 1);
4352 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4353 "scrollBarBackground",
4354 "ScrollBarBackground", 0);
4356 /* Init faces before x_default_parameter is called for scroll-bar
4357 parameters because that function calls x_set_scroll_bar_width,
4358 which calls change_frame_size, which calls Fset_window_buffer,
4359 which runs hooks, which call Fvertical_motion. At the end, we
4360 end up in init_iterator with a null face cache, which should not
4362 init_frame_faces (f
);
4364 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4365 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4366 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4367 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4368 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4369 "bufferPredicate", "BufferPredicate",
4371 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4372 "title", "Title", RES_TYPE_STRING
);
4373 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4374 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4376 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4378 /* Add the tool-bar height to the initial frame height so that the
4379 user gets a text display area of the size he specified with -g or
4380 via .Xdefaults. Later changes of the tool-bar height don't
4381 change the frame size. This is done so that users can create
4382 tall Emacs frames without having to guess how tall the tool-bar
4384 if (FRAME_TOOL_BAR_LINES (f
))
4386 int margin
, relief
, bar_height
;
4388 relief
= (tool_bar_button_relief
> 0
4389 ? tool_bar_button_relief
4390 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4392 if (INTEGERP (Vtool_bar_button_margin
)
4393 && XINT (Vtool_bar_button_margin
) > 0)
4394 margin
= XFASTINT (Vtool_bar_button_margin
);
4395 else if (CONSP (Vtool_bar_button_margin
)
4396 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4397 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4398 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4402 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4403 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4406 /* Compute the size of the X window. */
4407 window_prompting
= x_figure_window_size (f
, parms
);
4409 if (window_prompting
& XNegative
)
4411 if (window_prompting
& YNegative
)
4412 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4414 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4418 if (window_prompting
& YNegative
)
4419 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4421 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4424 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4426 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4427 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4429 /* Create the X widget or window. */
4430 #ifdef USE_X_TOOLKIT
4431 x_window (f
, window_prompting
, minibuffer_only
);
4439 /* Now consider the frame official. */
4440 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4441 Vframe_list
= Fcons (frame
, Vframe_list
);
4443 /* We need to do this after creating the X window, so that the
4444 icon-creation functions can say whose icon they're describing. */
4445 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4446 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4448 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4449 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4450 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4451 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4452 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4453 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4454 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4455 "scrollBarWidth", "ScrollBarWidth",
4458 /* Dimensions, especially f->height, must be done via change_frame_size.
4459 Change will not be effected unless different from the current
4465 SET_FRAME_WIDTH (f
, 0);
4466 change_frame_size (f
, height
, width
, 1, 0, 0);
4468 /* Set up faces after all frame parameters are known. This call
4469 also merges in face attributes specified for new frames. If we
4470 don't do this, the `menu' face for instance won't have the right
4471 colors, and the menu bar won't appear in the specified colors for
4473 call1 (Qface_set_after_frame_default
, frame
);
4475 #ifdef USE_X_TOOLKIT
4476 /* Create the menu bar. */
4477 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4479 /* If this signals an error, we haven't set size hints for the
4480 frame and we didn't make it visible. */
4481 initialize_frame_menubar (f
);
4483 /* This is a no-op, except under Motif where it arranges the
4484 main window for the widgets on it. */
4485 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4486 f
->output_data
.x
->menubar_widget
,
4487 f
->output_data
.x
->edit_widget
);
4489 #endif /* USE_X_TOOLKIT */
4491 /* Tell the server what size and position, etc, we want, and how
4492 badly we want them. This should be done after we have the menu
4493 bar so that its size can be taken into account. */
4495 x_wm_set_size_hint (f
, window_prompting
, 0);
4498 /* Make the window appear on the frame and enable display, unless
4499 the caller says not to. However, with explicit parent, Emacs
4500 cannot control visibility, so don't try. */
4501 if (! f
->output_data
.x
->explicit_parent
)
4503 Lisp_Object visibility
;
4505 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4507 if (EQ (visibility
, Qunbound
))
4510 if (EQ (visibility
, Qicon
))
4511 x_iconify_frame (f
);
4512 else if (! NILP (visibility
))
4513 x_make_frame_visible (f
);
4515 /* Must have been Qnil. */
4521 /* Make sure windows on this frame appear in calls to next-window
4522 and similar functions. */
4523 Vwindow_list
= Qnil
;
4525 return unbind_to (count
, frame
);
4529 /* FRAME is used only to get a handle on the X display. We don't pass the
4530 display info directly because we're called from frame.c, which doesn't
4531 know about that structure. */
4534 x_get_focus_frame (frame
)
4535 struct frame
*frame
;
4537 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4539 if (! dpyinfo
->x_focus_frame
)
4542 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4547 /* In certain situations, when the window manager follows a
4548 click-to-focus policy, there seems to be no way around calling
4549 XSetInputFocus to give another frame the input focus .
4551 In an ideal world, XSetInputFocus should generally be avoided so
4552 that applications don't interfere with the window manager's focus
4553 policy. But I think it's okay to use when it's clearly done
4554 following a user-command. */
4556 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4557 "Set the input focus to FRAME.\n\
4558 FRAME nil means use the selected frame.")
4562 struct frame
*f
= check_x_frame (frame
);
4563 Display
*dpy
= FRAME_X_DISPLAY (f
);
4567 count
= x_catch_errors (dpy
);
4568 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4569 RevertToParent
, CurrentTime
);
4570 x_uncatch_errors (dpy
, count
);
4577 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4578 "Internal function called by `color-defined-p', which see.")
4580 Lisp_Object color
, frame
;
4583 FRAME_PTR f
= check_x_frame (frame
);
4585 CHECK_STRING (color
, 1);
4587 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4593 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4594 "Internal function called by `color-values', which see.")
4596 Lisp_Object color
, frame
;
4599 FRAME_PTR f
= check_x_frame (frame
);
4601 CHECK_STRING (color
, 1);
4603 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4607 rgb
[0] = make_number (foo
.red
);
4608 rgb
[1] = make_number (foo
.green
);
4609 rgb
[2] = make_number (foo
.blue
);
4610 return Flist (3, rgb
);
4616 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4617 "Internal function called by `display-color-p', which see.")
4619 Lisp_Object display
;
4621 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4623 if (dpyinfo
->n_planes
<= 2)
4626 switch (dpyinfo
->visual
->class)
4639 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4641 "Return t if the X display supports shades of gray.\n\
4642 Note that color displays do support shades of gray.\n\
4643 The optional argument DISPLAY specifies which display to ask about.\n\
4644 DISPLAY should be either a frame or a display name (a string).\n\
4645 If omitted or nil, that stands for the selected frame's display.")
4647 Lisp_Object display
;
4649 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4651 if (dpyinfo
->n_planes
<= 1)
4654 switch (dpyinfo
->visual
->class)
4669 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4671 "Returns the width in pixels of the X display DISPLAY.\n\
4672 The optional argument DISPLAY specifies which display to ask about.\n\
4673 DISPLAY should be either a frame or a display name (a string).\n\
4674 If omitted or nil, that stands for the selected frame's display.")
4676 Lisp_Object display
;
4678 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4680 return make_number (dpyinfo
->width
);
4683 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4684 Sx_display_pixel_height
, 0, 1, 0,
4685 "Returns the height in pixels of the X display DISPLAY.\n\
4686 The optional argument DISPLAY specifies which display to ask about.\n\
4687 DISPLAY should be either a frame or a display name (a string).\n\
4688 If omitted or nil, that stands for the selected frame's display.")
4690 Lisp_Object display
;
4692 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4694 return make_number (dpyinfo
->height
);
4697 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4699 "Returns the number of bitplanes of the X display DISPLAY.\n\
4700 The optional argument DISPLAY specifies which display to ask about.\n\
4701 DISPLAY should be either a frame or a display name (a string).\n\
4702 If omitted or nil, that stands for the selected frame's display.")
4704 Lisp_Object display
;
4706 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4708 return make_number (dpyinfo
->n_planes
);
4711 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4713 "Returns the number of color cells of the X display DISPLAY.\n\
4714 The optional argument DISPLAY specifies which display to ask about.\n\
4715 DISPLAY should be either a frame or a display name (a string).\n\
4716 If omitted or nil, that stands for the selected frame's display.")
4718 Lisp_Object display
;
4720 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4722 return make_number (DisplayCells (dpyinfo
->display
,
4723 XScreenNumberOfScreen (dpyinfo
->screen
)));
4726 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4727 Sx_server_max_request_size
,
4729 "Returns the maximum request size of the X server of display DISPLAY.\n\
4730 The optional argument DISPLAY specifies which display to ask about.\n\
4731 DISPLAY should be either a frame or a display name (a string).\n\
4732 If omitted or nil, that stands for the selected frame's display.")
4734 Lisp_Object display
;
4736 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4738 return make_number (MAXREQUEST (dpyinfo
->display
));
4741 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4742 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4743 The optional argument DISPLAY specifies which display to ask about.\n\
4744 DISPLAY should be either a frame or a display name (a string).\n\
4745 If omitted or nil, that stands for the selected frame's display.")
4747 Lisp_Object display
;
4749 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4750 char *vendor
= ServerVendor (dpyinfo
->display
);
4752 if (! vendor
) vendor
= "";
4753 return build_string (vendor
);
4756 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4757 "Returns the version numbers of the X server of display DISPLAY.\n\
4758 The value is a list of three integers: the major and minor\n\
4759 version numbers of the X Protocol in use, and the vendor-specific release\n\
4760 number. See also the function `x-server-vendor'.\n\n\
4761 The optional argument DISPLAY specifies which display to ask about.\n\
4762 DISPLAY should be either a frame or a display name (a string).\n\
4763 If omitted or nil, that stands for the selected frame's display.")
4765 Lisp_Object display
;
4767 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4768 Display
*dpy
= dpyinfo
->display
;
4770 return Fcons (make_number (ProtocolVersion (dpy
)),
4771 Fcons (make_number (ProtocolRevision (dpy
)),
4772 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4775 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4776 "Returns the number of screens on the X server of display DISPLAY.\n\
4777 The optional argument DISPLAY specifies which display to ask about.\n\
4778 DISPLAY should be either a frame or a display name (a string).\n\
4779 If omitted or nil, that stands for the selected frame's display.")
4781 Lisp_Object display
;
4783 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4785 return make_number (ScreenCount (dpyinfo
->display
));
4788 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4789 "Returns the height in millimeters of the X display DISPLAY.\n\
4790 The optional argument DISPLAY specifies which display to ask about.\n\
4791 DISPLAY should be either a frame or a display name (a string).\n\
4792 If omitted or nil, that stands for the selected frame's display.")
4794 Lisp_Object display
;
4796 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4798 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4801 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4802 "Returns the width in millimeters of the X display DISPLAY.\n\
4803 The optional argument DISPLAY specifies which display to ask about.\n\
4804 DISPLAY should be either a frame or a display name (a string).\n\
4805 If omitted or nil, that stands for the selected frame's display.")
4807 Lisp_Object display
;
4809 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4811 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4814 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4815 Sx_display_backing_store
, 0, 1, 0,
4816 "Returns an indication of whether X display DISPLAY does backing store.\n\
4817 The value may be `always', `when-mapped', or `not-useful'.\n\
4818 The optional argument DISPLAY specifies which display to ask about.\n\
4819 DISPLAY should be either a frame or a display name (a string).\n\
4820 If omitted or nil, that stands for the selected frame's display.")
4822 Lisp_Object display
;
4824 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4827 switch (DoesBackingStore (dpyinfo
->screen
))
4830 result
= intern ("always");
4834 result
= intern ("when-mapped");
4838 result
= intern ("not-useful");
4842 error ("Strange value for BackingStore parameter of screen");
4849 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4850 Sx_display_visual_class
, 0, 1, 0,
4851 "Returns the visual class of the X display DISPLAY.\n\
4852 The value is one of the symbols `static-gray', `gray-scale',\n\
4853 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4854 The optional argument DISPLAY specifies which display to ask about.\n\
4855 DISPLAY should be either a frame or a display name (a string).\n\
4856 If omitted or nil, that stands for the selected frame's display.")
4858 Lisp_Object display
;
4860 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4863 switch (dpyinfo
->visual
->class)
4866 result
= intern ("static-gray");
4869 result
= intern ("gray-scale");
4872 result
= intern ("static-color");
4875 result
= intern ("pseudo-color");
4878 result
= intern ("true-color");
4881 result
= intern ("direct-color");
4884 error ("Display has an unknown visual class");
4891 DEFUN ("x-display-save-under", Fx_display_save_under
,
4892 Sx_display_save_under
, 0, 1, 0,
4893 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4894 The optional argument DISPLAY specifies which display to ask about.\n\
4895 DISPLAY should be either a frame or a display name (a string).\n\
4896 If omitted or nil, that stands for the selected frame's display.")
4898 Lisp_Object display
;
4900 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4902 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4910 register struct frame
*f
;
4912 return PIXEL_WIDTH (f
);
4917 register struct frame
*f
;
4919 return PIXEL_HEIGHT (f
);
4924 register struct frame
*f
;
4926 return FONT_WIDTH (f
->output_data
.x
->font
);
4931 register struct frame
*f
;
4933 return f
->output_data
.x
->line_height
;
4938 register struct frame
*f
;
4940 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4945 /************************************************************************
4947 ************************************************************************/
4950 /* Mapping visual names to visuals. */
4952 static struct visual_class
4959 {"StaticGray", StaticGray
},
4960 {"GrayScale", GrayScale
},
4961 {"StaticColor", StaticColor
},
4962 {"PseudoColor", PseudoColor
},
4963 {"TrueColor", TrueColor
},
4964 {"DirectColor", DirectColor
},
4969 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4971 /* Value is the screen number of screen SCR. This is a substitute for
4972 the X function with the same name when that doesn't exist. */
4975 XScreenNumberOfScreen (scr
)
4976 register Screen
*scr
;
4978 Display
*dpy
= scr
->display
;
4981 for (i
= 0; i
< dpy
->nscreens
; ++i
)
4982 if (scr
== dpy
->screens
+ i
)
4988 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4991 /* Select the visual that should be used on display DPYINFO. Set
4992 members of DPYINFO appropriately. Called from x_term_init. */
4995 select_visual (dpyinfo
)
4996 struct x_display_info
*dpyinfo
;
4998 Display
*dpy
= dpyinfo
->display
;
4999 Screen
*screen
= dpyinfo
->screen
;
5002 /* See if a visual is specified. */
5003 value
= display_x_get_resource (dpyinfo
,
5004 build_string ("visualClass"),
5005 build_string ("VisualClass"),
5007 if (STRINGP (value
))
5009 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5010 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5011 depth, a decimal number. NAME is compared with case ignored. */
5012 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
5017 strcpy (s
, XSTRING (value
)->data
);
5018 dash
= index (s
, '-');
5021 dpyinfo
->n_planes
= atoi (dash
+ 1);
5025 /* We won't find a matching visual with depth 0, so that
5026 an error will be printed below. */
5027 dpyinfo
->n_planes
= 0;
5029 /* Determine the visual class. */
5030 for (i
= 0; visual_classes
[i
].name
; ++i
)
5031 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5033 class = visual_classes
[i
].class;
5037 /* Look up a matching visual for the specified class. */
5039 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5040 dpyinfo
->n_planes
, class, &vinfo
))
5041 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
5043 dpyinfo
->visual
= vinfo
.visual
;
5048 XVisualInfo
*vinfo
, vinfo_template
;
5050 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5053 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5055 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5057 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5058 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5059 &vinfo_template
, &n_visuals
);
5061 fatal ("Can't get proper X visual info");
5063 dpyinfo
->n_planes
= vinfo
->depth
;
5064 XFree ((char *) vinfo
);
5069 /* Return the X display structure for the display named NAME.
5070 Open a new connection if necessary. */
5072 struct x_display_info
*
5073 x_display_info_for_name (name
)
5077 struct x_display_info
*dpyinfo
;
5079 CHECK_STRING (name
, 0);
5081 if (! EQ (Vwindow_system
, intern ("x")))
5082 error ("Not using X Windows");
5084 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5086 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5089 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5094 /* Use this general default value to start with. */
5095 Vx_resource_name
= Vinvocation_name
;
5097 validate_x_resource_name ();
5099 dpyinfo
= x_term_init (name
, (char *)0,
5100 (char *) XSTRING (Vx_resource_name
)->data
);
5103 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5106 XSETFASTINT (Vwindow_system_version
, 11);
5112 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5113 1, 3, 0, "Open a connection to an X server.\n\
5114 DISPLAY is the name of the display to connect to.\n\
5115 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5116 If the optional third arg MUST-SUCCEED is non-nil,\n\
5117 terminate Emacs if we can't open the connection.")
5118 (display
, xrm_string
, must_succeed
)
5119 Lisp_Object display
, xrm_string
, must_succeed
;
5121 unsigned char *xrm_option
;
5122 struct x_display_info
*dpyinfo
;
5124 CHECK_STRING (display
, 0);
5125 if (! NILP (xrm_string
))
5126 CHECK_STRING (xrm_string
, 1);
5128 if (! EQ (Vwindow_system
, intern ("x")))
5129 error ("Not using X Windows");
5131 if (! NILP (xrm_string
))
5132 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5134 xrm_option
= (unsigned char *) 0;
5136 validate_x_resource_name ();
5138 /* This is what opens the connection and sets x_current_display.
5139 This also initializes many symbols, such as those used for input. */
5140 dpyinfo
= x_term_init (display
, xrm_option
,
5141 (char *) XSTRING (Vx_resource_name
)->data
);
5145 if (!NILP (must_succeed
))
5146 fatal ("Cannot connect to X server %s.\n\
5147 Check the DISPLAY environment variable or use `-d'.\n\
5148 Also use the `xhost' program to verify that it is set to permit\n\
5149 connections from your machine.\n",
5150 XSTRING (display
)->data
);
5152 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5157 XSETFASTINT (Vwindow_system_version
, 11);
5161 DEFUN ("x-close-connection", Fx_close_connection
,
5162 Sx_close_connection
, 1, 1, 0,
5163 "Close the connection to DISPLAY's X server.\n\
5164 For DISPLAY, specify either a frame or a display name (a string).\n\
5165 If DISPLAY is nil, that stands for the selected frame's display.")
5167 Lisp_Object display
;
5169 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5172 if (dpyinfo
->reference_count
> 0)
5173 error ("Display still has frames on it");
5176 /* Free the fonts in the font table. */
5177 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5178 if (dpyinfo
->font_table
[i
].name
)
5180 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5181 xfree (dpyinfo
->font_table
[i
].full_name
);
5182 xfree (dpyinfo
->font_table
[i
].name
);
5183 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5186 x_destroy_all_bitmaps (dpyinfo
);
5187 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5189 #ifdef USE_X_TOOLKIT
5190 XtCloseDisplay (dpyinfo
->display
);
5192 XCloseDisplay (dpyinfo
->display
);
5195 x_delete_display (dpyinfo
);
5201 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5202 "Return the list of display names that Emacs has connections to.")
5205 Lisp_Object tail
, result
;
5208 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5209 result
= Fcons (XCAR (XCAR (tail
)), result
);
5214 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5215 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5216 If ON is nil, allow buffering of requests.\n\
5217 Turning on synchronization prohibits the Xlib routines from buffering\n\
5218 requests and seriously degrades performance, but makes debugging much\n\
5220 The optional second argument DISPLAY specifies which display to act on.\n\
5221 DISPLAY should be either a frame or a display name (a string).\n\
5222 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5224 Lisp_Object display
, on
;
5226 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5228 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5233 /* Wait for responses to all X commands issued so far for frame F. */
5240 XSync (FRAME_X_DISPLAY (f
), False
);
5245 /***********************************************************************
5247 ***********************************************************************/
5249 /* Value is the number of elements of vector VECTOR. */
5251 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5253 /* List of supported image types. Use define_image_type to add new
5254 types. Use lookup_image_type to find a type for a given symbol. */
5256 static struct image_type
*image_types
;
5258 /* The symbol `image' which is the car of the lists used to represent
5261 extern Lisp_Object Qimage
;
5263 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5269 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5270 extern Lisp_Object QCdata
;
5271 Lisp_Object QCtype
, QCascent
, QCmargin
, QCrelief
;
5272 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5273 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5275 /* Other symbols. */
5277 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5279 /* Time in seconds after which images should be removed from the cache
5280 if not displayed. */
5282 Lisp_Object Vimage_cache_eviction_delay
;
5284 /* Function prototypes. */
5286 static void define_image_type
P_ ((struct image_type
*type
));
5287 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5288 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5289 static void x_laplace
P_ ((struct frame
*, struct image
*));
5290 static void x_emboss
P_ ((struct frame
*, struct image
*));
5291 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5295 /* Define a new image type from TYPE. This adds a copy of TYPE to
5296 image_types and adds the symbol *TYPE->type to Vimage_types. */
5299 define_image_type (type
)
5300 struct image_type
*type
;
5302 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5303 The initialized data segment is read-only. */
5304 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5305 bcopy (type
, p
, sizeof *p
);
5306 p
->next
= image_types
;
5308 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5312 /* Look up image type SYMBOL, and return a pointer to its image_type
5313 structure. Value is null if SYMBOL is not a known image type. */
5315 static INLINE
struct image_type
*
5316 lookup_image_type (symbol
)
5319 struct image_type
*type
;
5321 for (type
= image_types
; type
; type
= type
->next
)
5322 if (EQ (symbol
, *type
->type
))
5329 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5330 valid image specification is a list whose car is the symbol
5331 `image', and whose rest is a property list. The property list must
5332 contain a value for key `:type'. That value must be the name of a
5333 supported image type. The rest of the property list depends on the
5337 valid_image_p (object
)
5342 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5346 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5347 if (EQ (XCAR (tem
), QCtype
))
5350 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5352 struct image_type
*type
;
5353 type
= lookup_image_type (XCAR (tem
));
5355 valid_p
= type
->valid_p (object
);
5366 /* Log error message with format string FORMAT and argument ARG.
5367 Signaling an error, e.g. when an image cannot be loaded, is not a
5368 good idea because this would interrupt redisplay, and the error
5369 message display would lead to another redisplay. This function
5370 therefore simply displays a message. */
5373 image_error (format
, arg1
, arg2
)
5375 Lisp_Object arg1
, arg2
;
5377 add_to_log (format
, arg1
, arg2
);
5382 /***********************************************************************
5383 Image specifications
5384 ***********************************************************************/
5386 enum image_value_type
5388 IMAGE_DONT_CHECK_VALUE_TYPE
,
5390 IMAGE_STRING_OR_NIL_VALUE
,
5392 IMAGE_POSITIVE_INTEGER_VALUE
,
5393 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5394 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5396 IMAGE_INTEGER_VALUE
,
5397 IMAGE_FUNCTION_VALUE
,
5402 /* Structure used when parsing image specifications. */
5404 struct image_keyword
5406 /* Name of keyword. */
5409 /* The type of value allowed. */
5410 enum image_value_type type
;
5412 /* Non-zero means key must be present. */
5415 /* Used to recognize duplicate keywords in a property list. */
5418 /* The value that was found. */
5423 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5425 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5428 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5429 has the format (image KEYWORD VALUE ...). One of the keyword/
5430 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5431 image_keywords structures of size NKEYWORDS describing other
5432 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5435 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5437 struct image_keyword
*keywords
;
5444 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5447 plist
= XCDR (spec
);
5448 while (CONSP (plist
))
5450 Lisp_Object key
, value
;
5452 /* First element of a pair must be a symbol. */
5454 plist
= XCDR (plist
);
5458 /* There must follow a value. */
5461 value
= XCAR (plist
);
5462 plist
= XCDR (plist
);
5464 /* Find key in KEYWORDS. Error if not found. */
5465 for (i
= 0; i
< nkeywords
; ++i
)
5466 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5472 /* Record that we recognized the keyword. If a keywords
5473 was found more than once, it's an error. */
5474 keywords
[i
].value
= value
;
5475 ++keywords
[i
].count
;
5477 if (keywords
[i
].count
> 1)
5480 /* Check type of value against allowed type. */
5481 switch (keywords
[i
].type
)
5483 case IMAGE_STRING_VALUE
:
5484 if (!STRINGP (value
))
5488 case IMAGE_STRING_OR_NIL_VALUE
:
5489 if (!STRINGP (value
) && !NILP (value
))
5493 case IMAGE_SYMBOL_VALUE
:
5494 if (!SYMBOLP (value
))
5498 case IMAGE_POSITIVE_INTEGER_VALUE
:
5499 if (!INTEGERP (value
) || XINT (value
) <= 0)
5503 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5504 if (INTEGERP (value
) && XINT (value
) >= 0)
5507 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5508 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5512 case IMAGE_ASCENT_VALUE
:
5513 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5515 else if (INTEGERP (value
)
5516 && XINT (value
) >= 0
5517 && XINT (value
) <= 100)
5521 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5522 if (!INTEGERP (value
) || XINT (value
) < 0)
5526 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5529 case IMAGE_FUNCTION_VALUE
:
5530 value
= indirect_function (value
);
5532 || COMPILEDP (value
)
5533 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5537 case IMAGE_NUMBER_VALUE
:
5538 if (!INTEGERP (value
) && !FLOATP (value
))
5542 case IMAGE_INTEGER_VALUE
:
5543 if (!INTEGERP (value
))
5547 case IMAGE_BOOL_VALUE
:
5548 if (!NILP (value
) && !EQ (value
, Qt
))
5557 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5561 /* Check that all mandatory fields are present. */
5562 for (i
= 0; i
< nkeywords
; ++i
)
5563 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5566 return NILP (plist
);
5570 /* Return the value of KEY in image specification SPEC. Value is nil
5571 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5572 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5575 image_spec_value (spec
, key
, found
)
5576 Lisp_Object spec
, key
;
5581 xassert (valid_image_p (spec
));
5583 for (tail
= XCDR (spec
);
5584 CONSP (tail
) && CONSP (XCDR (tail
));
5585 tail
= XCDR (XCDR (tail
)))
5587 if (EQ (XCAR (tail
), key
))
5591 return XCAR (XCDR (tail
));
5601 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5602 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5603 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5604 size in canonical character units.\n\
5605 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5606 or omitted means use the selected frame.")
5607 (spec
, pixels
, frame
)
5608 Lisp_Object spec
, pixels
, frame
;
5613 if (valid_image_p (spec
))
5615 struct frame
*f
= check_x_frame (frame
);
5616 int id
= lookup_image (f
, spec
);
5617 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5618 int width
= img
->width
+ 2 * img
->hmargin
;
5619 int height
= img
->height
+ 2 * img
->vmargin
;
5622 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5623 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5625 size
= Fcons (make_number (width
), make_number (height
));
5628 error ("Invalid image specification");
5634 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5635 "Return t if image SPEC has a mask bitmap.\n\
5636 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5637 or omitted means use the selected frame.")
5639 Lisp_Object spec
, frame
;
5644 if (valid_image_p (spec
))
5646 struct frame
*f
= check_x_frame (frame
);
5647 int id
= lookup_image (f
, spec
);
5648 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5653 error ("Invalid image specification");
5660 /***********************************************************************
5661 Image type independent image structures
5662 ***********************************************************************/
5664 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5665 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5668 /* Allocate and return a new image structure for image specification
5669 SPEC. SPEC has a hash value of HASH. */
5671 static struct image
*
5672 make_image (spec
, hash
)
5676 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5678 xassert (valid_image_p (spec
));
5679 bzero (img
, sizeof *img
);
5680 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5681 xassert (img
->type
!= NULL
);
5683 img
->data
.lisp_val
= Qnil
;
5684 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5690 /* Free image IMG which was used on frame F, including its resources. */
5699 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5701 /* Remove IMG from the hash table of its cache. */
5703 img
->prev
->next
= img
->next
;
5705 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5708 img
->next
->prev
= img
->prev
;
5710 c
->images
[img
->id
] = NULL
;
5712 /* Free resources, then free IMG. */
5713 img
->type
->free (f
, img
);
5719 /* Prepare image IMG for display on frame F. Must be called before
5720 drawing an image. */
5723 prepare_image_for_display (f
, img
)
5729 /* We're about to display IMG, so set its timestamp to `now'. */
5731 img
->timestamp
= EMACS_SECS (t
);
5733 /* If IMG doesn't have a pixmap yet, load it now, using the image
5734 type dependent loader function. */
5735 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5736 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5740 /* Value is the number of pixels for the ascent of image IMG when
5741 drawn in face FACE. */
5744 image_ascent (img
, face
)
5748 int height
= img
->height
+ img
->vmargin
;
5751 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5754 /* This expression is arranged so that if the image can't be
5755 exactly centered, it will be moved slightly up. This is
5756 because a typical font is `top-heavy' (due to the presence
5757 uppercase letters), so the image placement should err towards
5758 being top-heavy too. It also just generally looks better. */
5759 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5761 ascent
= height
/ 2;
5764 ascent
= height
* img
->ascent
/ 100.0;
5771 /***********************************************************************
5772 Helper functions for X image types
5773 ***********************************************************************/
5775 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
5777 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5778 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5780 Lisp_Object color_name
,
5781 unsigned long dflt
));
5784 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5785 free the pixmap if any. MASK_P non-zero means clear the mask
5786 pixmap if any. COLORS_P non-zero means free colors allocated for
5787 the image, if any. */
5790 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
5793 int pixmap_p
, mask_p
, colors_p
;
5795 if (pixmap_p
&& img
->pixmap
)
5797 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5801 if (mask_p
&& img
->mask
)
5803 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5807 if (colors_p
&& img
->ncolors
)
5809 x_free_colors (f
, img
->colors
, img
->ncolors
);
5810 xfree (img
->colors
);
5816 /* Free X resources of image IMG which is used on frame F. */
5819 x_clear_image (f
, img
)
5824 x_clear_image_1 (f
, img
, 1, 1, 1);
5829 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5830 cannot be allocated, use DFLT. Add a newly allocated color to
5831 IMG->colors, so that it can be freed again. Value is the pixel
5834 static unsigned long
5835 x_alloc_image_color (f
, img
, color_name
, dflt
)
5838 Lisp_Object color_name
;
5842 unsigned long result
;
5844 xassert (STRINGP (color_name
));
5846 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
5848 /* This isn't called frequently so we get away with simply
5849 reallocating the color vector to the needed size, here. */
5852 (unsigned long *) xrealloc (img
->colors
,
5853 img
->ncolors
* sizeof *img
->colors
);
5854 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5855 result
= color
.pixel
;
5865 /***********************************************************************
5867 ***********************************************************************/
5869 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
5870 static void postprocess_image
P_ ((struct frame
*, struct image
*));
5873 /* Return a new, initialized image cache that is allocated from the
5874 heap. Call free_image_cache to free an image cache. */
5876 struct image_cache
*
5879 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
5882 bzero (c
, sizeof *c
);
5884 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
5885 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
5886 c
->buckets
= (struct image
**) xmalloc (size
);
5887 bzero (c
->buckets
, size
);
5892 /* Free image cache of frame F. Be aware that X frames share images
5896 free_image_cache (f
)
5899 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5904 /* Cache should not be referenced by any frame when freed. */
5905 xassert (c
->refcount
== 0);
5907 for (i
= 0; i
< c
->used
; ++i
)
5908 free_image (f
, c
->images
[i
]);
5912 FRAME_X_IMAGE_CACHE (f
) = NULL
;
5917 /* Clear image cache of frame F. FORCE_P non-zero means free all
5918 images. FORCE_P zero means clear only images that haven't been
5919 displayed for some time. Should be called from time to time to
5920 reduce the number of loaded images. If image-eviction-seconds is
5921 non-nil, this frees images in the cache which weren't displayed for
5922 at least that many seconds. */
5925 clear_image_cache (f
, force_p
)
5929 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5931 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
5938 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
5940 /* Block input so that we won't be interrupted by a SIGIO
5941 while being in an inconsistent state. */
5944 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
5946 struct image
*img
= c
->images
[i
];
5948 && (force_p
|| img
->timestamp
< old
))
5950 free_image (f
, img
);
5955 /* We may be clearing the image cache because, for example,
5956 Emacs was iconified for a longer period of time. In that
5957 case, current matrices may still contain references to
5958 images freed above. So, clear these matrices. */
5961 Lisp_Object tail
, frame
;
5963 FOR_EACH_FRAME (tail
, frame
)
5965 struct frame
*f
= XFRAME (frame
);
5967 && FRAME_X_IMAGE_CACHE (f
) == c
)
5968 clear_current_matrices (f
);
5971 ++windows_or_buffers_changed
;
5979 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
5981 "Clear the image cache of FRAME.\n\
5982 FRAME nil or omitted means use the selected frame.\n\
5983 FRAME t means clear the image caches of all frames.")
5991 FOR_EACH_FRAME (tail
, frame
)
5992 if (FRAME_X_P (XFRAME (frame
)))
5993 clear_image_cache (XFRAME (frame
), 1);
5996 clear_image_cache (check_x_frame (frame
), 1);
6002 /* Compute masks and transform image IMG on frame F, as specified
6003 by the image's specification, */
6006 postprocess_image (f
, img
)
6010 /* Manipulation of the image's mask. */
6013 Lisp_Object conversion
, spec
;
6018 /* `:heuristic-mask t'
6020 means build a mask heuristically.
6021 `:heuristic-mask (R G B)'
6022 `:mask (heuristic (R G B))'
6023 means build a mask from color (R G B) in the
6026 means remove a mask, if any. */
6028 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6030 x_build_heuristic_mask (f
, img
, mask
);
6035 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6037 if (EQ (mask
, Qheuristic
))
6038 x_build_heuristic_mask (f
, img
, Qt
);
6039 else if (CONSP (mask
)
6040 && EQ (XCAR (mask
), Qheuristic
))
6042 if (CONSP (XCDR (mask
)))
6043 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6045 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6047 else if (NILP (mask
) && found_p
&& img
->mask
)
6049 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6055 /* Should we apply an image transformation algorithm? */
6056 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6057 if (EQ (conversion
, Qdisabled
))
6058 x_disable_image (f
, img
);
6059 else if (EQ (conversion
, Qlaplace
))
6061 else if (EQ (conversion
, Qemboss
))
6063 else if (CONSP (conversion
)
6064 && EQ (XCAR (conversion
), Qedge_detection
))
6067 tem
= XCDR (conversion
);
6069 x_edge_detection (f
, img
,
6070 Fplist_get (tem
, QCmatrix
),
6071 Fplist_get (tem
, QCcolor_adjustment
));
6077 /* Return the id of image with Lisp specification SPEC on frame F.
6078 SPEC must be a valid Lisp image specification (see valid_image_p). */
6081 lookup_image (f
, spec
)
6085 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6089 struct gcpro gcpro1
;
6092 /* F must be a window-system frame, and SPEC must be a valid image
6094 xassert (FRAME_WINDOW_P (f
));
6095 xassert (valid_image_p (spec
));
6099 /* Look up SPEC in the hash table of the image cache. */
6100 hash
= sxhash (spec
, 0);
6101 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6103 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6104 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6107 /* If not found, create a new image and cache it. */
6110 extern Lisp_Object Qpostscript
;
6113 img
= make_image (spec
, hash
);
6114 cache_image (f
, img
);
6115 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6117 /* If we can't load the image, and we don't have a width and
6118 height, use some arbitrary width and height so that we can
6119 draw a rectangle for it. */
6120 if (img
->load_failed_p
)
6124 value
= image_spec_value (spec
, QCwidth
, NULL
);
6125 img
->width
= (INTEGERP (value
)
6126 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6127 value
= image_spec_value (spec
, QCheight
, NULL
);
6128 img
->height
= (INTEGERP (value
)
6129 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6133 /* Handle image type independent image attributes
6134 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
6135 Lisp_Object ascent
, margin
, relief
;
6137 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6138 if (INTEGERP (ascent
))
6139 img
->ascent
= XFASTINT (ascent
);
6140 else if (EQ (ascent
, Qcenter
))
6141 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6143 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6144 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6145 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6146 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6147 && INTEGERP (XCDR (margin
)))
6149 if (XINT (XCAR (margin
)) > 0)
6150 img
->hmargin
= XFASTINT (XCAR (margin
));
6151 if (XINT (XCDR (margin
)) > 0)
6152 img
->vmargin
= XFASTINT (XCDR (margin
));
6155 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6156 if (INTEGERP (relief
))
6158 img
->relief
= XINT (relief
);
6159 img
->hmargin
+= abs (img
->relief
);
6160 img
->vmargin
+= abs (img
->relief
);
6163 /* Do image transformations and compute masks, unless we
6164 don't have the image yet. */
6165 if (!EQ (*img
->type
->type
, Qpostscript
))
6166 postprocess_image (f
, img
);
6170 xassert (!interrupt_input_blocked
);
6173 /* We're using IMG, so set its timestamp to `now'. */
6174 EMACS_GET_TIME (now
);
6175 img
->timestamp
= EMACS_SECS (now
);
6179 /* Value is the image id. */
6184 /* Cache image IMG in the image cache of frame F. */
6187 cache_image (f
, img
)
6191 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6194 /* Find a free slot in c->images. */
6195 for (i
= 0; i
< c
->used
; ++i
)
6196 if (c
->images
[i
] == NULL
)
6199 /* If no free slot found, maybe enlarge c->images. */
6200 if (i
== c
->used
&& c
->used
== c
->size
)
6203 c
->images
= (struct image
**) xrealloc (c
->images
,
6204 c
->size
* sizeof *c
->images
);
6207 /* Add IMG to c->images, and assign IMG an id. */
6213 /* Add IMG to the cache's hash table. */
6214 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6215 img
->next
= c
->buckets
[i
];
6217 img
->next
->prev
= img
;
6219 c
->buckets
[i
] = img
;
6223 /* Call FN on every image in the image cache of frame F. Used to mark
6224 Lisp Objects in the image cache. */
6227 forall_images_in_image_cache (f
, fn
)
6229 void (*fn
) P_ ((struct image
*img
));
6231 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6233 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6237 for (i
= 0; i
< c
->used
; ++i
)
6246 /***********************************************************************
6248 ***********************************************************************/
6250 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6251 XImage
**, Pixmap
*));
6252 static void x_destroy_x_image
P_ ((XImage
*));
6253 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6256 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6257 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6258 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6259 via xmalloc. Print error messages via image_error if an error
6260 occurs. Value is non-zero if successful. */
6263 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6265 int width
, height
, depth
;
6269 Display
*display
= FRAME_X_DISPLAY (f
);
6270 Screen
*screen
= FRAME_X_SCREEN (f
);
6271 Window window
= FRAME_X_WINDOW (f
);
6273 xassert (interrupt_input_blocked
);
6276 depth
= DefaultDepthOfScreen (screen
);
6277 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6278 depth
, ZPixmap
, 0, NULL
, width
, height
,
6279 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6282 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6286 /* Allocate image raster. */
6287 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6289 /* Allocate a pixmap of the same size. */
6290 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6291 if (*pixmap
== None
)
6293 x_destroy_x_image (*ximg
);
6295 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6303 /* Destroy XImage XIMG. Free XIMG->data. */
6306 x_destroy_x_image (ximg
)
6309 xassert (interrupt_input_blocked
);
6314 XDestroyImage (ximg
);
6319 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6320 are width and height of both the image and pixmap. */
6323 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6330 xassert (interrupt_input_blocked
);
6331 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6332 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6333 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6338 /***********************************************************************
6340 ***********************************************************************/
6342 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6343 static char *slurp_file
P_ ((char *, int *));
6346 /* Find image file FILE. Look in data-directory, then
6347 x-bitmap-file-path. Value is the full name of the file found, or
6348 nil if not found. */
6351 x_find_image_file (file
)
6354 Lisp_Object file_found
, search_path
;
6355 struct gcpro gcpro1
, gcpro2
;
6359 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6360 GCPRO2 (file_found
, search_path
);
6362 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6363 fd
= openp (search_path
, file
, "", &file_found
, 0);
6375 /* Read FILE into memory. Value is a pointer to a buffer allocated
6376 with xmalloc holding FILE's contents. Value is null if an error
6377 occurred. *SIZE is set to the size of the file. */
6380 slurp_file (file
, size
)
6388 if (stat (file
, &st
) == 0
6389 && (fp
= fopen (file
, "r")) != NULL
6390 && (buf
= (char *) xmalloc (st
.st_size
),
6391 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6412 /***********************************************************************
6414 ***********************************************************************/
6416 static int xbm_scan
P_ ((char **, char *, char *, int *));
6417 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6418 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6420 static int xbm_image_p
P_ ((Lisp_Object object
));
6421 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6423 static int xbm_file_p
P_ ((Lisp_Object
));
6426 /* Indices of image specification fields in xbm_format, below. */
6428 enum xbm_keyword_index
6446 /* Vector of image_keyword structures describing the format
6447 of valid XBM image specifications. */
6449 static struct image_keyword xbm_format
[XBM_LAST
] =
6451 {":type", IMAGE_SYMBOL_VALUE
, 1},
6452 {":file", IMAGE_STRING_VALUE
, 0},
6453 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6454 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6455 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6456 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6457 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6458 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6459 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6460 {":relief", IMAGE_INTEGER_VALUE
, 0},
6461 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6462 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6463 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6466 /* Structure describing the image type XBM. */
6468 static struct image_type xbm_type
=
6477 /* Tokens returned from xbm_scan. */
6486 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6487 A valid specification is a list starting with the symbol `image'
6488 The rest of the list is a property list which must contain an
6491 If the specification specifies a file to load, it must contain
6492 an entry `:file FILENAME' where FILENAME is a string.
6494 If the specification is for a bitmap loaded from memory it must
6495 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6496 WIDTH and HEIGHT are integers > 0. DATA may be:
6498 1. a string large enough to hold the bitmap data, i.e. it must
6499 have a size >= (WIDTH + 7) / 8 * HEIGHT
6501 2. a bool-vector of size >= WIDTH * HEIGHT
6503 3. a vector of strings or bool-vectors, one for each line of the
6506 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6507 may not be specified in this case because they are defined in the
6510 Both the file and data forms may contain the additional entries
6511 `:background COLOR' and `:foreground COLOR'. If not present,
6512 foreground and background of the frame on which the image is
6513 displayed is used. */
6516 xbm_image_p (object
)
6519 struct image_keyword kw
[XBM_LAST
];
6521 bcopy (xbm_format
, kw
, sizeof kw
);
6522 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6525 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6527 if (kw
[XBM_FILE
].count
)
6529 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6532 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6534 /* In-memory XBM file. */
6535 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6543 /* Entries for `:width', `:height' and `:data' must be present. */
6544 if (!kw
[XBM_WIDTH
].count
6545 || !kw
[XBM_HEIGHT
].count
6546 || !kw
[XBM_DATA
].count
)
6549 data
= kw
[XBM_DATA
].value
;
6550 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6551 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6553 /* Check type of data, and width and height against contents of
6559 /* Number of elements of the vector must be >= height. */
6560 if (XVECTOR (data
)->size
< height
)
6563 /* Each string or bool-vector in data must be large enough
6564 for one line of the image. */
6565 for (i
= 0; i
< height
; ++i
)
6567 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6571 if (XSTRING (elt
)->size
6572 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6575 else if (BOOL_VECTOR_P (elt
))
6577 if (XBOOL_VECTOR (elt
)->size
< width
)
6584 else if (STRINGP (data
))
6586 if (XSTRING (data
)->size
6587 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6590 else if (BOOL_VECTOR_P (data
))
6592 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6603 /* Scan a bitmap file. FP is the stream to read from. Value is
6604 either an enumerator from enum xbm_token, or a character for a
6605 single-character token, or 0 at end of file. If scanning an
6606 identifier, store the lexeme of the identifier in SVAL. If
6607 scanning a number, store its value in *IVAL. */
6610 xbm_scan (s
, end
, sval
, ival
)
6619 /* Skip white space. */
6620 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6625 else if (isdigit (c
))
6627 int value
= 0, digit
;
6629 if (c
== '0' && *s
< end
)
6632 if (c
== 'x' || c
== 'X')
6639 else if (c
>= 'a' && c
<= 'f')
6640 digit
= c
- 'a' + 10;
6641 else if (c
>= 'A' && c
<= 'F')
6642 digit
= c
- 'A' + 10;
6645 value
= 16 * value
+ digit
;
6648 else if (isdigit (c
))
6652 && (c
= *(*s
)++, isdigit (c
)))
6653 value
= 8 * value
+ c
- '0';
6660 && (c
= *(*s
)++, isdigit (c
)))
6661 value
= 10 * value
+ c
- '0';
6669 else if (isalpha (c
) || c
== '_')
6673 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6680 else if (c
== '/' && **s
== '*')
6682 /* C-style comment. */
6684 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6697 /* Replacement for XReadBitmapFileData which isn't available under old
6698 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6699 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6700 the image. Return in *DATA the bitmap data allocated with xmalloc.
6701 Value is non-zero if successful. DATA null means just test if
6702 CONTENTS looks like an in-memory XBM file. */
6705 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
6706 char *contents
, *end
;
6707 int *width
, *height
;
6708 unsigned char **data
;
6711 char buffer
[BUFSIZ
];
6714 int bytes_per_line
, i
, nbytes
;
6720 LA1 = xbm_scan (&s, end, buffer, &value)
6722 #define expect(TOKEN) \
6723 if (LA1 != (TOKEN)) \
6728 #define expect_ident(IDENT) \
6729 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6734 *width
= *height
= -1;
6737 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
6739 /* Parse defines for width, height and hot-spots. */
6743 expect_ident ("define");
6744 expect (XBM_TK_IDENT
);
6746 if (LA1
== XBM_TK_NUMBER
);
6748 char *p
= strrchr (buffer
, '_');
6749 p
= p
? p
+ 1 : buffer
;
6750 if (strcmp (p
, "width") == 0)
6752 else if (strcmp (p
, "height") == 0)
6755 expect (XBM_TK_NUMBER
);
6758 if (*width
< 0 || *height
< 0)
6760 else if (data
== NULL
)
6763 /* Parse bits. Must start with `static'. */
6764 expect_ident ("static");
6765 if (LA1
== XBM_TK_IDENT
)
6767 if (strcmp (buffer
, "unsigned") == 0)
6770 expect_ident ("char");
6772 else if (strcmp (buffer
, "short") == 0)
6776 if (*width
% 16 && *width
% 16 < 9)
6779 else if (strcmp (buffer
, "char") == 0)
6787 expect (XBM_TK_IDENT
);
6793 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6794 nbytes
= bytes_per_line
* *height
;
6795 p
= *data
= (char *) xmalloc (nbytes
);
6799 for (i
= 0; i
< nbytes
; i
+= 2)
6802 expect (XBM_TK_NUMBER
);
6805 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6808 if (LA1
== ',' || LA1
== '}')
6816 for (i
= 0; i
< nbytes
; ++i
)
6819 expect (XBM_TK_NUMBER
);
6823 if (LA1
== ',' || LA1
== '}')
6848 /* Load XBM image IMG which will be displayed on frame F from buffer
6849 CONTENTS. END is the end of the buffer. Value is non-zero if
6853 xbm_load_image (f
, img
, contents
, end
)
6856 char *contents
, *end
;
6859 unsigned char *data
;
6862 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
6865 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6866 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6867 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6870 xassert (img
->width
> 0 && img
->height
> 0);
6872 /* Get foreground and background colors, maybe allocate colors. */
6873 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
6875 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
6877 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6879 background
= x_alloc_image_color (f
, img
, value
, background
);
6882 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6885 img
->width
, img
->height
,
6886 foreground
, background
,
6890 if (img
->pixmap
== None
)
6892 x_clear_image (f
, img
);
6893 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
6899 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6905 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6912 return (STRINGP (data
)
6913 && xbm_read_bitmap_data (XSTRING (data
)->data
,
6914 (XSTRING (data
)->data
6915 + STRING_BYTES (XSTRING (data
))),
6920 /* Fill image IMG which is used on frame F with pixmap data. Value is
6921 non-zero if successful. */
6929 Lisp_Object file_name
;
6931 xassert (xbm_image_p (img
->spec
));
6933 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6934 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
6935 if (STRINGP (file_name
))
6940 struct gcpro gcpro1
;
6942 file
= x_find_image_file (file_name
);
6944 if (!STRINGP (file
))
6946 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
6951 contents
= slurp_file (XSTRING (file
)->data
, &size
);
6952 if (contents
== NULL
)
6954 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6959 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
6964 struct image_keyword fmt
[XBM_LAST
];
6967 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6968 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6971 int in_memory_file_p
= 0;
6973 /* See if data looks like an in-memory XBM file. */
6974 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6975 in_memory_file_p
= xbm_file_p (data
);
6977 /* Parse the image specification. */
6978 bcopy (xbm_format
, fmt
, sizeof fmt
);
6979 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
6982 /* Get specified width, and height. */
6983 if (!in_memory_file_p
)
6985 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
6986 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
6987 xassert (img
->width
> 0 && img
->height
> 0);
6990 /* Get foreground and background colors, maybe allocate colors. */
6991 if (fmt
[XBM_FOREGROUND
].count
6992 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
6993 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
6995 if (fmt
[XBM_BACKGROUND
].count
6996 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
6997 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7000 if (in_memory_file_p
)
7001 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
7002 (XSTRING (data
)->data
7003 + STRING_BYTES (XSTRING (data
))));
7010 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7012 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7013 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7015 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7017 bcopy (XSTRING (line
)->data
, p
, nbytes
);
7019 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7022 else if (STRINGP (data
))
7023 bits
= XSTRING (data
)->data
;
7025 bits
= XBOOL_VECTOR (data
)->data
;
7027 /* Create the pixmap. */
7028 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7030 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7033 img
->width
, img
->height
,
7034 foreground
, background
,
7040 image_error ("Unable to create pixmap for XBM image `%s'",
7042 x_clear_image (f
, img
);
7052 /***********************************************************************
7054 ***********************************************************************/
7058 static int xpm_image_p
P_ ((Lisp_Object object
));
7059 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7060 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7062 #include "X11/xpm.h"
7064 /* The symbol `xpm' identifying XPM-format images. */
7068 /* Indices of image specification fields in xpm_format, below. */
7070 enum xpm_keyword_index
7085 /* Vector of image_keyword structures describing the format
7086 of valid XPM image specifications. */
7088 static struct image_keyword xpm_format
[XPM_LAST
] =
7090 {":type", IMAGE_SYMBOL_VALUE
, 1},
7091 {":file", IMAGE_STRING_VALUE
, 0},
7092 {":data", IMAGE_STRING_VALUE
, 0},
7093 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7094 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7095 {":relief", IMAGE_INTEGER_VALUE
, 0},
7096 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7097 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7098 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7099 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7102 /* Structure describing the image type XBM. */
7104 static struct image_type xpm_type
=
7114 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7115 functions for allocating image colors. Our own functions handle
7116 color allocation failures more gracefully than the ones on the XPM
7119 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7120 #define ALLOC_XPM_COLORS
7123 #ifdef ALLOC_XPM_COLORS
7125 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7126 static void xpm_free_color_cache
P_ ((void));
7127 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7128 static int xpm_color_bucket
P_ ((char *));
7129 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7132 /* An entry in a hash table used to cache color definitions of named
7133 colors. This cache is necessary to speed up XPM image loading in
7134 case we do color allocations ourselves. Without it, we would need
7135 a call to XParseColor per pixel in the image. */
7137 struct xpm_cached_color
7139 /* Next in collision chain. */
7140 struct xpm_cached_color
*next
;
7142 /* Color definition (RGB and pixel color). */
7149 /* The hash table used for the color cache, and its bucket vector
7152 #define XPM_COLOR_CACHE_BUCKETS 1001
7153 struct xpm_cached_color
**xpm_color_cache
;
7155 /* Initialize the color cache. */
7158 xpm_init_color_cache (f
, attrs
)
7160 XpmAttributes
*attrs
;
7162 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7163 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7164 memset (xpm_color_cache
, 0, nbytes
);
7165 init_color_table ();
7167 if (attrs
->valuemask
& XpmColorSymbols
)
7172 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7173 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7174 attrs
->colorsymbols
[i
].value
, &color
))
7176 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7178 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7184 /* Free the color cache. */
7187 xpm_free_color_cache ()
7189 struct xpm_cached_color
*p
, *next
;
7192 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7193 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7199 xfree (xpm_color_cache
);
7200 xpm_color_cache
= NULL
;
7201 free_color_table ();
7205 /* Return the bucket index for color named COLOR_NAME in the color
7209 xpm_color_bucket (color_name
)
7215 for (s
= color_name
; *s
; ++s
)
7217 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7221 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7222 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7225 static struct xpm_cached_color
*
7226 xpm_cache_color (f
, color_name
, color
, bucket
)
7233 struct xpm_cached_color
*p
;
7236 bucket
= xpm_color_bucket (color_name
);
7238 nbytes
= sizeof *p
+ strlen (color_name
);
7239 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7240 strcpy (p
->name
, color_name
);
7242 p
->next
= xpm_color_cache
[bucket
];
7243 xpm_color_cache
[bucket
] = p
;
7248 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7249 return the cached definition in *COLOR. Otherwise, make a new
7250 entry in the cache and allocate the color. Value is zero if color
7251 allocation failed. */
7254 xpm_lookup_color (f
, color_name
, color
)
7259 struct xpm_cached_color
*p
;
7260 int h
= xpm_color_bucket (color_name
);
7262 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7263 if (strcmp (p
->name
, color_name
) == 0)
7268 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7271 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7273 p
= xpm_cache_color (f
, color_name
, color
, h
);
7280 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7281 CLOSURE is a pointer to the frame on which we allocate the
7282 color. Return in *COLOR the allocated color. Value is non-zero
7286 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7293 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7297 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7298 is a pointer to the frame on which we allocate the color. Value is
7299 non-zero if successful. */
7302 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7312 #endif /* ALLOC_XPM_COLORS */
7315 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7316 for XPM images. Such a list must consist of conses whose car and
7320 xpm_valid_color_symbols_p (color_symbols
)
7321 Lisp_Object color_symbols
;
7323 while (CONSP (color_symbols
))
7325 Lisp_Object sym
= XCAR (color_symbols
);
7327 || !STRINGP (XCAR (sym
))
7328 || !STRINGP (XCDR (sym
)))
7330 color_symbols
= XCDR (color_symbols
);
7333 return NILP (color_symbols
);
7337 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7340 xpm_image_p (object
)
7343 struct image_keyword fmt
[XPM_LAST
];
7344 bcopy (xpm_format
, fmt
, sizeof fmt
);
7345 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7346 /* Either `:file' or `:data' must be present. */
7347 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7348 /* Either no `:color-symbols' or it's a list of conses
7349 whose car and cdr are strings. */
7350 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7351 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7355 /* Load image IMG which will be displayed on frame F. Value is
7356 non-zero if successful. */
7364 XpmAttributes attrs
;
7365 Lisp_Object specified_file
, color_symbols
;
7367 /* Configure the XPM lib. Use the visual of frame F. Allocate
7368 close colors. Return colors allocated. */
7369 bzero (&attrs
, sizeof attrs
);
7370 attrs
.visual
= FRAME_X_VISUAL (f
);
7371 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7372 attrs
.valuemask
|= XpmVisual
;
7373 attrs
.valuemask
|= XpmColormap
;
7375 #ifdef ALLOC_XPM_COLORS
7376 /* Allocate colors with our own functions which handle
7377 failing color allocation more gracefully. */
7378 attrs
.color_closure
= f
;
7379 attrs
.alloc_color
= xpm_alloc_color
;
7380 attrs
.free_colors
= xpm_free_colors
;
7381 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7382 #else /* not ALLOC_XPM_COLORS */
7383 /* Let the XPM lib allocate colors. */
7384 attrs
.valuemask
|= XpmReturnAllocPixels
;
7385 #ifdef XpmAllocCloseColors
7386 attrs
.alloc_close_colors
= 1;
7387 attrs
.valuemask
|= XpmAllocCloseColors
;
7388 #else /* not XpmAllocCloseColors */
7389 attrs
.closeness
= 600;
7390 attrs
.valuemask
|= XpmCloseness
;
7391 #endif /* not XpmAllocCloseColors */
7392 #endif /* ALLOC_XPM_COLORS */
7394 /* If image specification contains symbolic color definitions, add
7395 these to `attrs'. */
7396 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7397 if (CONSP (color_symbols
))
7400 XpmColorSymbol
*xpm_syms
;
7403 attrs
.valuemask
|= XpmColorSymbols
;
7405 /* Count number of symbols. */
7406 attrs
.numsymbols
= 0;
7407 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7410 /* Allocate an XpmColorSymbol array. */
7411 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7412 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7413 bzero (xpm_syms
, size
);
7414 attrs
.colorsymbols
= xpm_syms
;
7416 /* Fill the color symbol array. */
7417 for (tail
= color_symbols
, i
= 0;
7419 ++i
, tail
= XCDR (tail
))
7421 Lisp_Object name
= XCAR (XCAR (tail
));
7422 Lisp_Object color
= XCDR (XCAR (tail
));
7423 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7424 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7425 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7426 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7430 /* Create a pixmap for the image, either from a file, or from a
7431 string buffer containing data in the same format as an XPM file. */
7432 #ifdef ALLOC_XPM_COLORS
7433 xpm_init_color_cache (f
, &attrs
);
7436 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7437 if (STRINGP (specified_file
))
7439 Lisp_Object file
= x_find_image_file (specified_file
);
7440 if (!STRINGP (file
))
7442 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7446 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7447 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7452 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7453 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7454 XSTRING (buffer
)->data
,
7455 &img
->pixmap
, &img
->mask
,
7459 if (rc
== XpmSuccess
)
7461 #ifdef ALLOC_XPM_COLORS
7462 img
->colors
= colors_in_color_table (&img
->ncolors
);
7463 #else /* not ALLOC_XPM_COLORS */
7466 img
->ncolors
= attrs
.nalloc_pixels
;
7467 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7468 * sizeof *img
->colors
);
7469 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7471 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7472 #ifdef DEBUG_X_COLORS
7473 register_color (img
->colors
[i
]);
7476 #endif /* not ALLOC_XPM_COLORS */
7478 img
->width
= attrs
.width
;
7479 img
->height
= attrs
.height
;
7480 xassert (img
->width
> 0 && img
->height
> 0);
7482 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7483 XpmFreeAttributes (&attrs
);
7490 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7493 case XpmFileInvalid
:
7494 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7498 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7501 case XpmColorFailed
:
7502 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7506 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7511 #ifdef ALLOC_XPM_COLORS
7512 xpm_free_color_cache ();
7514 return rc
== XpmSuccess
;
7517 #endif /* HAVE_XPM != 0 */
7520 /***********************************************************************
7522 ***********************************************************************/
7524 /* An entry in the color table mapping an RGB color to a pixel color. */
7529 unsigned long pixel
;
7531 /* Next in color table collision list. */
7532 struct ct_color
*next
;
7535 /* The bucket vector size to use. Must be prime. */
7539 /* Value is a hash of the RGB color given by R, G, and B. */
7541 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7543 /* The color hash table. */
7545 struct ct_color
**ct_table
;
7547 /* Number of entries in the color table. */
7549 int ct_colors_allocated
;
7551 /* Initialize the color table. */
7556 int size
= CT_SIZE
* sizeof (*ct_table
);
7557 ct_table
= (struct ct_color
**) xmalloc (size
);
7558 bzero (ct_table
, size
);
7559 ct_colors_allocated
= 0;
7563 /* Free memory associated with the color table. */
7569 struct ct_color
*p
, *next
;
7571 for (i
= 0; i
< CT_SIZE
; ++i
)
7572 for (p
= ct_table
[i
]; p
; p
= next
)
7583 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7584 entry for that color already is in the color table, return the
7585 pixel color of that entry. Otherwise, allocate a new color for R,
7586 G, B, and make an entry in the color table. */
7588 static unsigned long
7589 lookup_rgb_color (f
, r
, g
, b
)
7593 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7594 int i
= hash
% CT_SIZE
;
7597 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7598 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7611 cmap
= FRAME_X_COLORMAP (f
);
7612 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7616 ++ct_colors_allocated
;
7618 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7622 p
->pixel
= color
.pixel
;
7623 p
->next
= ct_table
[i
];
7627 return FRAME_FOREGROUND_PIXEL (f
);
7634 /* Look up pixel color PIXEL which is used on frame F in the color
7635 table. If not already present, allocate it. Value is PIXEL. */
7637 static unsigned long
7638 lookup_pixel_color (f
, pixel
)
7640 unsigned long pixel
;
7642 int i
= pixel
% CT_SIZE
;
7645 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7646 if (p
->pixel
== pixel
)
7655 cmap
= FRAME_X_COLORMAP (f
);
7656 color
.pixel
= pixel
;
7657 x_query_color (f
, &color
);
7658 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7662 ++ct_colors_allocated
;
7664 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7669 p
->next
= ct_table
[i
];
7673 return FRAME_FOREGROUND_PIXEL (f
);
7680 /* Value is a vector of all pixel colors contained in the color table,
7681 allocated via xmalloc. Set *N to the number of colors. */
7683 static unsigned long *
7684 colors_in_color_table (n
)
7689 unsigned long *colors
;
7691 if (ct_colors_allocated
== 0)
7698 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7700 *n
= ct_colors_allocated
;
7702 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7703 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7704 colors
[j
++] = p
->pixel
;
7712 /***********************************************************************
7714 ***********************************************************************/
7716 static void x_laplace_write_row
P_ ((struct frame
*, long *,
7717 int, XImage
*, int));
7718 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
7719 XColor
*, int, XImage
*, int));
7720 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
7721 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
7722 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
7724 /* Non-zero means draw a cross on images having `:conversion
7727 int cross_disabled_images
;
7729 /* Edge detection matrices for different edge-detection
7732 static int emboss_matrix
[9] = {
7734 2, -1, 0, /* y - 1 */
7736 0, 1, -2 /* y + 1 */
7739 static int laplace_matrix
[9] = {
7741 1, 0, 0, /* y - 1 */
7743 0, 0, -1 /* y + 1 */
7746 /* Value is the intensity of the color whose red/green/blue values
7749 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7752 /* On frame F, return an array of XColor structures describing image
7753 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7754 non-zero means also fill the red/green/blue members of the XColor
7755 structures. Value is a pointer to the array of XColors structures,
7756 allocated with xmalloc; it must be freed by the caller. */
7759 x_to_xcolors (f
, img
, rgb_p
)
7768 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
7770 /* Get the X image IMG->pixmap. */
7771 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7772 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7774 /* Fill the `pixel' members of the XColor array. I wished there
7775 were an easy and portable way to circumvent XGetPixel. */
7777 for (y
= 0; y
< img
->height
; ++y
)
7781 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7782 p
->pixel
= XGetPixel (ximg
, x
, y
);
7785 x_query_colors (f
, row
, img
->width
);
7788 XDestroyImage (ximg
);
7793 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7794 RGB members are set. F is the frame on which this all happens.
7795 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7798 x_from_xcolors (f
, img
, colors
)
7808 init_color_table ();
7810 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
7813 for (y
= 0; y
< img
->height
; ++y
)
7814 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7816 unsigned long pixel
;
7817 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
7818 XPutPixel (oimg
, x
, y
, pixel
);
7822 x_clear_image_1 (f
, img
, 1, 0, 1);
7824 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7825 x_destroy_x_image (oimg
);
7826 img
->pixmap
= pixmap
;
7827 img
->colors
= colors_in_color_table (&img
->ncolors
);
7828 free_color_table ();
7832 /* On frame F, perform edge-detection on image IMG.
7834 MATRIX is a nine-element array specifying the transformation
7835 matrix. See emboss_matrix for an example.
7837 COLOR_ADJUST is a color adjustment added to each pixel of the
7841 x_detect_edges (f
, img
, matrix
, color_adjust
)
7844 int matrix
[9], color_adjust
;
7846 XColor
*colors
= x_to_xcolors (f
, img
, 1);
7850 for (i
= sum
= 0; i
< 9; ++i
)
7851 sum
+= abs (matrix
[i
]);
7853 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7855 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
7857 for (y
= 0; y
< img
->height
; ++y
)
7859 p
= COLOR (new, 0, y
);
7860 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7861 p
= COLOR (new, img
->width
- 1, y
);
7862 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7865 for (x
= 1; x
< img
->width
- 1; ++x
)
7867 p
= COLOR (new, x
, 0);
7868 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7869 p
= COLOR (new, x
, img
->height
- 1);
7870 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7873 for (y
= 1; y
< img
->height
- 1; ++y
)
7875 p
= COLOR (new, 1, y
);
7877 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
7879 int r
, g
, b
, y1
, x1
;
7882 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
7883 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
7886 XColor
*t
= COLOR (colors
, x1
, y1
);
7887 r
+= matrix
[i
] * t
->red
;
7888 g
+= matrix
[i
] * t
->green
;
7889 b
+= matrix
[i
] * t
->blue
;
7892 r
= (r
/ sum
+ color_adjust
) & 0xffff;
7893 g
= (g
/ sum
+ color_adjust
) & 0xffff;
7894 b
= (b
/ sum
+ color_adjust
) & 0xffff;
7895 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
7900 x_from_xcolors (f
, img
, new);
7906 /* Perform the pre-defined `emboss' edge-detection on image IMG
7914 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
7918 /* Perform the pre-defined `laplace' edge-detection on image IMG
7926 x_detect_edges (f
, img
, laplace_matrix
, 45000);
7930 /* Perform edge-detection on image IMG on frame F, with specified
7931 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7933 MATRIX must be either
7935 - a list of at least 9 numbers in row-major form
7936 - a vector of at least 9 numbers
7938 COLOR_ADJUST nil means use a default; otherwise it must be a
7942 x_edge_detection (f
, img
, matrix
, color_adjust
)
7945 Lisp_Object matrix
, color_adjust
;
7953 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
7954 ++i
, matrix
= XCDR (matrix
))
7955 trans
[i
] = XFLOATINT (XCAR (matrix
));
7957 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
7959 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
7960 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
7963 if (NILP (color_adjust
))
7964 color_adjust
= make_number (0xffff / 2);
7966 if (i
== 9 && NUMBERP (color_adjust
))
7967 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
7971 /* Transform image IMG on frame F so that it looks disabled. */
7974 x_disable_image (f
, img
)
7978 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7980 if (dpyinfo
->n_planes
>= 2)
7982 /* Color (or grayscale). Convert to gray, and equalize. Just
7983 drawing such images with a stipple can look very odd, so
7984 we're using this method instead. */
7985 XColor
*colors
= x_to_xcolors (f
, img
, 1);
7987 const int h
= 15000;
7988 const int l
= 30000;
7990 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
7994 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
7995 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
7996 p
->red
= p
->green
= p
->blue
= i2
;
7999 x_from_xcolors (f
, img
, colors
);
8002 /* Draw a cross over the disabled image, if we must or if we
8004 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
8006 Display
*dpy
= FRAME_X_DISPLAY (f
);
8009 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
8010 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
8011 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
8012 img
->width
- 1, img
->height
- 1);
8013 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
8019 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
8020 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8021 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8022 img
->width
- 1, img
->height
- 1);
8023 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8031 /* Build a mask for image IMG which is used on frame F. FILE is the
8032 name of an image file, for error messages. HOW determines how to
8033 determine the background color of IMG. If it is a list '(R G B)',
8034 with R, G, and B being integers >= 0, take that as the color of the
8035 background. Otherwise, determine the background color of IMG
8036 heuristically. Value is non-zero if successful. */
8039 x_build_heuristic_mask (f
, img
, how
)
8044 Display
*dpy
= FRAME_X_DISPLAY (f
);
8045 XImage
*ximg
, *mask_img
;
8046 int x
, y
, rc
, look_at_corners_p
;
8047 unsigned long bg
= 0;
8051 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8055 /* Create an image and pixmap serving as mask. */
8056 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8057 &mask_img
, &img
->mask
);
8061 /* Get the X image of IMG->pixmap. */
8062 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8065 /* Determine the background color of ximg. If HOW is `(R G B)'
8066 take that as color. Otherwise, try to determine the color
8068 look_at_corners_p
= 1;
8074 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
8076 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8080 if (i
== 3 && NILP (how
))
8082 char color_name
[30];
8083 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8084 bg
= x_alloc_image_color (f
, img
, build_string (color_name
), 0);
8085 look_at_corners_p
= 0;
8089 if (look_at_corners_p
)
8091 unsigned long corners
[4];
8094 /* Get the colors at the corners of ximg. */
8095 corners
[0] = XGetPixel (ximg
, 0, 0);
8096 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
8097 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
8098 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
8100 /* Choose the most frequently found color as background. */
8101 for (i
= best_count
= 0; i
< 4; ++i
)
8105 for (j
= n
= 0; j
< 4; ++j
)
8106 if (corners
[i
] == corners
[j
])
8110 bg
= corners
[i
], best_count
= n
;
8114 /* Set all bits in mask_img to 1 whose color in ximg is different
8115 from the background color bg. */
8116 for (y
= 0; y
< img
->height
; ++y
)
8117 for (x
= 0; x
< img
->width
; ++x
)
8118 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8120 /* Put mask_img into img->mask. */
8121 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8122 x_destroy_x_image (mask_img
);
8123 XDestroyImage (ximg
);
8130 /***********************************************************************
8131 PBM (mono, gray, color)
8132 ***********************************************************************/
8134 static int pbm_image_p
P_ ((Lisp_Object object
));
8135 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8136 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8138 /* The symbol `pbm' identifying images of this type. */
8142 /* Indices of image specification fields in gs_format, below. */
8144 enum pbm_keyword_index
8160 /* Vector of image_keyword structures describing the format
8161 of valid user-defined image specifications. */
8163 static struct image_keyword pbm_format
[PBM_LAST
] =
8165 {":type", IMAGE_SYMBOL_VALUE
, 1},
8166 {":file", IMAGE_STRING_VALUE
, 0},
8167 {":data", IMAGE_STRING_VALUE
, 0},
8168 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8169 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8170 {":relief", IMAGE_INTEGER_VALUE
, 0},
8171 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8172 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8173 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8174 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8175 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8178 /* Structure describing the image type `pbm'. */
8180 static struct image_type pbm_type
=
8190 /* Return non-zero if OBJECT is a valid PBM image specification. */
8193 pbm_image_p (object
)
8196 struct image_keyword fmt
[PBM_LAST
];
8198 bcopy (pbm_format
, fmt
, sizeof fmt
);
8200 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8203 /* Must specify either :data or :file. */
8204 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8208 /* Scan a decimal number from *S and return it. Advance *S while
8209 reading the number. END is the end of the string. Value is -1 at
8213 pbm_scan_number (s
, end
)
8214 unsigned char **s
, *end
;
8216 int c
= 0, val
= -1;
8220 /* Skip white-space. */
8221 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8226 /* Skip comment to end of line. */
8227 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8230 else if (isdigit (c
))
8232 /* Read decimal number. */
8234 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8235 val
= 10 * val
+ c
- '0';
8246 /* Load PBM image IMG for use on frame F. */
8254 int width
, height
, max_color_idx
= 0;
8256 Lisp_Object file
, specified_file
;
8257 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8258 struct gcpro gcpro1
;
8259 unsigned char *contents
= NULL
;
8260 unsigned char *end
, *p
;
8263 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8267 if (STRINGP (specified_file
))
8269 file
= x_find_image_file (specified_file
);
8270 if (!STRINGP (file
))
8272 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8277 contents
= slurp_file (XSTRING (file
)->data
, &size
);
8278 if (contents
== NULL
)
8280 image_error ("Error reading `%s'", file
, Qnil
);
8286 end
= contents
+ size
;
8291 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8292 p
= XSTRING (data
)->data
;
8293 end
= p
+ STRING_BYTES (XSTRING (data
));
8296 /* Check magic number. */
8297 if (end
- p
< 2 || *p
++ != 'P')
8299 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8309 raw_p
= 0, type
= PBM_MONO
;
8313 raw_p
= 0, type
= PBM_GRAY
;
8317 raw_p
= 0, type
= PBM_COLOR
;
8321 raw_p
= 1, type
= PBM_MONO
;
8325 raw_p
= 1, type
= PBM_GRAY
;
8329 raw_p
= 1, type
= PBM_COLOR
;
8333 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8337 /* Read width, height, maximum color-component. Characters
8338 starting with `#' up to the end of a line are ignored. */
8339 width
= pbm_scan_number (&p
, end
);
8340 height
= pbm_scan_number (&p
, end
);
8342 if (type
!= PBM_MONO
)
8344 max_color_idx
= pbm_scan_number (&p
, end
);
8345 if (raw_p
&& max_color_idx
> 255)
8346 max_color_idx
= 255;
8351 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8354 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8355 &ximg
, &img
->pixmap
))
8358 /* Initialize the color hash table. */
8359 init_color_table ();
8361 if (type
== PBM_MONO
)
8364 struct image_keyword fmt
[PBM_LAST
];
8365 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8366 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8368 /* Parse the image specification. */
8369 bcopy (pbm_format
, fmt
, sizeof fmt
);
8370 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8372 /* Get foreground and background colors, maybe allocate colors. */
8373 if (fmt
[PBM_FOREGROUND
].count
8374 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8375 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8376 if (fmt
[PBM_BACKGROUND
].count
8377 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8378 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8380 for (y
= 0; y
< height
; ++y
)
8381 for (x
= 0; x
< width
; ++x
)
8391 g
= pbm_scan_number (&p
, end
);
8393 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8398 for (y
= 0; y
< height
; ++y
)
8399 for (x
= 0; x
< width
; ++x
)
8403 if (type
== PBM_GRAY
)
8404 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8413 r
= pbm_scan_number (&p
, end
);
8414 g
= pbm_scan_number (&p
, end
);
8415 b
= pbm_scan_number (&p
, end
);
8418 if (r
< 0 || g
< 0 || b
< 0)
8422 XDestroyImage (ximg
);
8423 image_error ("Invalid pixel value in image `%s'",
8428 /* RGB values are now in the range 0..max_color_idx.
8429 Scale this to the range 0..0xffff supported by X. */
8430 r
= (double) r
* 65535 / max_color_idx
;
8431 g
= (double) g
* 65535 / max_color_idx
;
8432 b
= (double) b
* 65535 / max_color_idx
;
8433 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8437 /* Store in IMG->colors the colors allocated for the image, and
8438 free the color table. */
8439 img
->colors
= colors_in_color_table (&img
->ncolors
);
8440 free_color_table ();
8442 /* Put the image into a pixmap. */
8443 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8444 x_destroy_x_image (ximg
);
8447 img
->height
= height
;
8456 /***********************************************************************
8458 ***********************************************************************/
8464 /* Function prototypes. */
8466 static int png_image_p
P_ ((Lisp_Object object
));
8467 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8469 /* The symbol `png' identifying images of this type. */
8473 /* Indices of image specification fields in png_format, below. */
8475 enum png_keyword_index
8489 /* Vector of image_keyword structures describing the format
8490 of valid user-defined image specifications. */
8492 static struct image_keyword png_format
[PNG_LAST
] =
8494 {":type", IMAGE_SYMBOL_VALUE
, 1},
8495 {":data", IMAGE_STRING_VALUE
, 0},
8496 {":file", IMAGE_STRING_VALUE
, 0},
8497 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8498 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8499 {":relief", IMAGE_INTEGER_VALUE
, 0},
8500 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8501 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8502 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8505 /* Structure describing the image type `png'. */
8507 static struct image_type png_type
=
8517 /* Return non-zero if OBJECT is a valid PNG image specification. */
8520 png_image_p (object
)
8523 struct image_keyword fmt
[PNG_LAST
];
8524 bcopy (png_format
, fmt
, sizeof fmt
);
8526 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8529 /* Must specify either the :data or :file keyword. */
8530 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8534 /* Error and warning handlers installed when the PNG library
8538 my_png_error (png_ptr
, msg
)
8539 png_struct
*png_ptr
;
8542 xassert (png_ptr
!= NULL
);
8543 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8544 longjmp (png_ptr
->jmpbuf
, 1);
8549 my_png_warning (png_ptr
, msg
)
8550 png_struct
*png_ptr
;
8553 xassert (png_ptr
!= NULL
);
8554 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8557 /* Memory source for PNG decoding. */
8559 struct png_memory_storage
8561 unsigned char *bytes
; /* The data */
8562 size_t len
; /* How big is it? */
8563 int index
; /* Where are we? */
8567 /* Function set as reader function when reading PNG image from memory.
8568 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8569 bytes from the input to DATA. */
8572 png_read_from_memory (png_ptr
, data
, length
)
8573 png_structp png_ptr
;
8577 struct png_memory_storage
*tbr
8578 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8580 if (length
> tbr
->len
- tbr
->index
)
8581 png_error (png_ptr
, "Read error");
8583 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8584 tbr
->index
= tbr
->index
+ length
;
8587 /* Load PNG image IMG for use on frame F. Value is non-zero if
8595 Lisp_Object file
, specified_file
;
8596 Lisp_Object specified_data
;
8598 XImage
*ximg
, *mask_img
= NULL
;
8599 struct gcpro gcpro1
;
8600 png_struct
*png_ptr
= NULL
;
8601 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8602 FILE *volatile fp
= NULL
;
8604 png_byte
* volatile pixels
= NULL
;
8605 png_byte
** volatile rows
= NULL
;
8606 png_uint_32 width
, height
;
8607 int bit_depth
, color_type
, interlace_type
;
8609 png_uint_32 row_bytes
;
8612 double screen_gamma
, image_gamma
;
8614 struct png_memory_storage tbr
; /* Data to be read */
8616 /* Find out what file to load. */
8617 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8618 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8622 if (NILP (specified_data
))
8624 file
= x_find_image_file (specified_file
);
8625 if (!STRINGP (file
))
8627 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8632 /* Open the image file. */
8633 fp
= fopen (XSTRING (file
)->data
, "rb");
8636 image_error ("Cannot open image file `%s'", file
, Qnil
);
8642 /* Check PNG signature. */
8643 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8644 || !png_check_sig (sig
, sizeof sig
))
8646 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8654 /* Read from memory. */
8655 tbr
.bytes
= XSTRING (specified_data
)->data
;
8656 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8659 /* Check PNG signature. */
8660 if (tbr
.len
< sizeof sig
8661 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8663 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8668 /* Need to skip past the signature. */
8669 tbr
.bytes
+= sizeof (sig
);
8672 /* Initialize read and info structs for PNG lib. */
8673 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8674 my_png_error
, my_png_warning
);
8677 if (fp
) fclose (fp
);
8682 info_ptr
= png_create_info_struct (png_ptr
);
8685 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8686 if (fp
) fclose (fp
);
8691 end_info
= png_create_info_struct (png_ptr
);
8694 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8695 if (fp
) fclose (fp
);
8700 /* Set error jump-back. We come back here when the PNG library
8701 detects an error. */
8702 if (setjmp (png_ptr
->jmpbuf
))
8706 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8709 if (fp
) fclose (fp
);
8714 /* Read image info. */
8715 if (!NILP (specified_data
))
8716 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
8718 png_init_io (png_ptr
, fp
);
8720 png_set_sig_bytes (png_ptr
, sizeof sig
);
8721 png_read_info (png_ptr
, info_ptr
);
8722 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8723 &interlace_type
, NULL
, NULL
);
8725 /* If image contains simply transparency data, we prefer to
8726 construct a clipping mask. */
8727 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8732 /* This function is easier to write if we only have to handle
8733 one data format: RGB or RGBA with 8 bits per channel. Let's
8734 transform other formats into that format. */
8736 /* Strip more than 8 bits per channel. */
8737 if (bit_depth
== 16)
8738 png_set_strip_16 (png_ptr
);
8740 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8742 png_set_expand (png_ptr
);
8744 /* Convert grayscale images to RGB. */
8745 if (color_type
== PNG_COLOR_TYPE_GRAY
8746 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
8747 png_set_gray_to_rgb (png_ptr
);
8749 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8750 gamma_str
= getenv ("SCREEN_GAMMA");
8751 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
8753 /* Tell the PNG lib to handle gamma correction for us. */
8755 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8756 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
8757 /* There is a special chunk in the image specifying the gamma. */
8758 png_set_sRGB (png_ptr
, info_ptr
, intent
);
8761 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
8762 /* Image contains gamma information. */
8763 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
8765 /* Use a default of 0.5 for the image gamma. */
8766 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
8768 /* Handle alpha channel by combining the image with a background
8769 color. Do this only if a real alpha channel is supplied. For
8770 simple transparency, we prefer a clipping mask. */
8773 png_color_16
*image_background
;
8775 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
8776 /* Image contains a background color with which to
8777 combine the image. */
8778 png_set_background (png_ptr
, image_background
,
8779 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
8782 /* Image does not contain a background color with which
8783 to combine the image data via an alpha channel. Use
8784 the frame's background instead. */
8787 png_color_16 frame_background
;
8789 cmap
= FRAME_X_COLORMAP (f
);
8790 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8791 x_query_color (f
, &color
);
8793 bzero (&frame_background
, sizeof frame_background
);
8794 frame_background
.red
= color
.red
;
8795 frame_background
.green
= color
.green
;
8796 frame_background
.blue
= color
.blue
;
8798 png_set_background (png_ptr
, &frame_background
,
8799 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8803 /* Update info structure. */
8804 png_read_update_info (png_ptr
, info_ptr
);
8806 /* Get number of channels. Valid values are 1 for grayscale images
8807 and images with a palette, 2 for grayscale images with transparency
8808 information (alpha channel), 3 for RGB images, and 4 for RGB
8809 images with alpha channel, i.e. RGBA. If conversions above were
8810 sufficient we should only have 3 or 4 channels here. */
8811 channels
= png_get_channels (png_ptr
, info_ptr
);
8812 xassert (channels
== 3 || channels
== 4);
8814 /* Number of bytes needed for one row of the image. */
8815 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
8817 /* Allocate memory for the image. */
8818 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
8819 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
8820 for (i
= 0; i
< height
; ++i
)
8821 rows
[i
] = pixels
+ i
* row_bytes
;
8823 /* Read the entire image. */
8824 png_read_image (png_ptr
, rows
);
8825 png_read_end (png_ptr
, info_ptr
);
8832 /* Create the X image and pixmap. */
8833 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
8837 /* Create an image and pixmap serving as mask if the PNG image
8838 contains an alpha channel. */
8841 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
8842 &mask_img
, &img
->mask
))
8844 x_destroy_x_image (ximg
);
8845 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
8850 /* Fill the X image and mask from PNG data. */
8851 init_color_table ();
8853 for (y
= 0; y
< height
; ++y
)
8855 png_byte
*p
= rows
[y
];
8857 for (x
= 0; x
< width
; ++x
)
8864 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8866 /* An alpha channel, aka mask channel, associates variable
8867 transparency with an image. Where other image formats
8868 support binary transparency---fully transparent or fully
8869 opaque---PNG allows up to 254 levels of partial transparency.
8870 The PNG library implements partial transparency by combining
8871 the image with a specified background color.
8873 I'm not sure how to handle this here nicely: because the
8874 background on which the image is displayed may change, for
8875 real alpha channel support, it would be necessary to create
8876 a new image for each possible background.
8878 What I'm doing now is that a mask is created if we have
8879 boolean transparency information. Otherwise I'm using
8880 the frame's background color to combine the image with. */
8885 XPutPixel (mask_img
, x
, y
, *p
> 0);
8891 /* Remember colors allocated for this image. */
8892 img
->colors
= colors_in_color_table (&img
->ncolors
);
8893 free_color_table ();
8896 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8901 img
->height
= height
;
8903 /* Put the image into the pixmap, then free the X image and its buffer. */
8904 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8905 x_destroy_x_image (ximg
);
8907 /* Same for the mask. */
8910 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8911 x_destroy_x_image (mask_img
);
8918 #endif /* HAVE_PNG != 0 */
8922 /***********************************************************************
8924 ***********************************************************************/
8928 /* Work around a warning about HAVE_STDLIB_H being redefined in
8930 #ifdef HAVE_STDLIB_H
8931 #define HAVE_STDLIB_H_1
8932 #undef HAVE_STDLIB_H
8933 #endif /* HAVE_STLIB_H */
8935 #include <jpeglib.h>
8939 #ifdef HAVE_STLIB_H_1
8940 #define HAVE_STDLIB_H 1
8943 static int jpeg_image_p
P_ ((Lisp_Object object
));
8944 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
8946 /* The symbol `jpeg' identifying images of this type. */
8950 /* Indices of image specification fields in gs_format, below. */
8952 enum jpeg_keyword_index
8961 JPEG_HEURISTIC_MASK
,
8966 /* Vector of image_keyword structures describing the format
8967 of valid user-defined image specifications. */
8969 static struct image_keyword jpeg_format
[JPEG_LAST
] =
8971 {":type", IMAGE_SYMBOL_VALUE
, 1},
8972 {":data", IMAGE_STRING_VALUE
, 0},
8973 {":file", IMAGE_STRING_VALUE
, 0},
8974 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8975 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8976 {":relief", IMAGE_INTEGER_VALUE
, 0},
8977 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8978 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8979 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8982 /* Structure describing the image type `jpeg'. */
8984 static struct image_type jpeg_type
=
8994 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8997 jpeg_image_p (object
)
9000 struct image_keyword fmt
[JPEG_LAST
];
9002 bcopy (jpeg_format
, fmt
, sizeof fmt
);
9004 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
9007 /* Must specify either the :data or :file keyword. */
9008 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9012 struct my_jpeg_error_mgr
9014 struct jpeg_error_mgr pub
;
9015 jmp_buf setjmp_buffer
;
9020 my_error_exit (cinfo
)
9023 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9024 longjmp (mgr
->setjmp_buffer
, 1);
9028 /* Init source method for JPEG data source manager. Called by
9029 jpeg_read_header() before any data is actually read. See
9030 libjpeg.doc from the JPEG lib distribution. */
9033 our_init_source (cinfo
)
9034 j_decompress_ptr cinfo
;
9039 /* Fill input buffer method for JPEG data source manager. Called
9040 whenever more data is needed. We read the whole image in one step,
9041 so this only adds a fake end of input marker at the end. */
9044 our_fill_input_buffer (cinfo
)
9045 j_decompress_ptr cinfo
;
9047 /* Insert a fake EOI marker. */
9048 struct jpeg_source_mgr
*src
= cinfo
->src
;
9049 static JOCTET buffer
[2];
9051 buffer
[0] = (JOCTET
) 0xFF;
9052 buffer
[1] = (JOCTET
) JPEG_EOI
;
9054 src
->next_input_byte
= buffer
;
9055 src
->bytes_in_buffer
= 2;
9060 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9061 is the JPEG data source manager. */
9064 our_skip_input_data (cinfo
, num_bytes
)
9065 j_decompress_ptr cinfo
;
9068 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9072 if (num_bytes
> src
->bytes_in_buffer
)
9073 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9075 src
->bytes_in_buffer
-= num_bytes
;
9076 src
->next_input_byte
+= num_bytes
;
9081 /* Method to terminate data source. Called by
9082 jpeg_finish_decompress() after all data has been processed. */
9085 our_term_source (cinfo
)
9086 j_decompress_ptr cinfo
;
9091 /* Set up the JPEG lib for reading an image from DATA which contains
9092 LEN bytes. CINFO is the decompression info structure created for
9093 reading the image. */
9096 jpeg_memory_src (cinfo
, data
, len
)
9097 j_decompress_ptr cinfo
;
9101 struct jpeg_source_mgr
*src
;
9103 if (cinfo
->src
== NULL
)
9105 /* First time for this JPEG object? */
9106 cinfo
->src
= (struct jpeg_source_mgr
*)
9107 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9108 sizeof (struct jpeg_source_mgr
));
9109 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9110 src
->next_input_byte
= data
;
9113 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9114 src
->init_source
= our_init_source
;
9115 src
->fill_input_buffer
= our_fill_input_buffer
;
9116 src
->skip_input_data
= our_skip_input_data
;
9117 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9118 src
->term_source
= our_term_source
;
9119 src
->bytes_in_buffer
= len
;
9120 src
->next_input_byte
= data
;
9124 /* Load image IMG for use on frame F. Patterned after example.c
9125 from the JPEG lib. */
9132 struct jpeg_decompress_struct cinfo
;
9133 struct my_jpeg_error_mgr mgr
;
9134 Lisp_Object file
, specified_file
;
9135 Lisp_Object specified_data
;
9136 FILE * volatile fp
= NULL
;
9138 int row_stride
, x
, y
;
9139 XImage
*ximg
= NULL
;
9141 unsigned long *colors
;
9143 struct gcpro gcpro1
;
9145 /* Open the JPEG file. */
9146 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9147 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9151 if (NILP (specified_data
))
9153 file
= x_find_image_file (specified_file
);
9154 if (!STRINGP (file
))
9156 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9161 fp
= fopen (XSTRING (file
)->data
, "r");
9164 image_error ("Cannot open `%s'", file
, Qnil
);
9170 /* Customize libjpeg's error handling to call my_error_exit when an
9171 error is detected. This function will perform a longjmp. */
9172 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9173 mgr
.pub
.error_exit
= my_error_exit
;
9175 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9179 /* Called from my_error_exit. Display a JPEG error. */
9180 char buffer
[JMSG_LENGTH_MAX
];
9181 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9182 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9183 build_string (buffer
));
9186 /* Close the input file and destroy the JPEG object. */
9188 fclose ((FILE *) fp
);
9189 jpeg_destroy_decompress (&cinfo
);
9191 /* If we already have an XImage, free that. */
9192 x_destroy_x_image (ximg
);
9194 /* Free pixmap and colors. */
9195 x_clear_image (f
, img
);
9201 /* Create the JPEG decompression object. Let it read from fp.
9202 Read the JPEG image header. */
9203 jpeg_create_decompress (&cinfo
);
9205 if (NILP (specified_data
))
9206 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9208 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
9209 STRING_BYTES (XSTRING (specified_data
)));
9211 jpeg_read_header (&cinfo
, TRUE
);
9213 /* Customize decompression so that color quantization will be used.
9214 Start decompression. */
9215 cinfo
.quantize_colors
= TRUE
;
9216 jpeg_start_decompress (&cinfo
);
9217 width
= img
->width
= cinfo
.output_width
;
9218 height
= img
->height
= cinfo
.output_height
;
9220 /* Create X image and pixmap. */
9221 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9222 longjmp (mgr
.setjmp_buffer
, 2);
9224 /* Allocate colors. When color quantization is used,
9225 cinfo.actual_number_of_colors has been set with the number of
9226 colors generated, and cinfo.colormap is a two-dimensional array
9227 of color indices in the range 0..cinfo.actual_number_of_colors.
9228 No more than 255 colors will be generated. */
9232 if (cinfo
.out_color_components
> 2)
9233 ir
= 0, ig
= 1, ib
= 2;
9234 else if (cinfo
.out_color_components
> 1)
9235 ir
= 0, ig
= 1, ib
= 0;
9237 ir
= 0, ig
= 0, ib
= 0;
9239 /* Use the color table mechanism because it handles colors that
9240 cannot be allocated nicely. Such colors will be replaced with
9241 a default color, and we don't have to care about which colors
9242 can be freed safely, and which can't. */
9243 init_color_table ();
9244 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9247 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9249 /* Multiply RGB values with 255 because X expects RGB values
9250 in the range 0..0xffff. */
9251 int r
= cinfo
.colormap
[ir
][i
] << 8;
9252 int g
= cinfo
.colormap
[ig
][i
] << 8;
9253 int b
= cinfo
.colormap
[ib
][i
] << 8;
9254 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9257 /* Remember those colors actually allocated. */
9258 img
->colors
= colors_in_color_table (&img
->ncolors
);
9259 free_color_table ();
9263 row_stride
= width
* cinfo
.output_components
;
9264 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9266 for (y
= 0; y
< height
; ++y
)
9268 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9269 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9270 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9274 jpeg_finish_decompress (&cinfo
);
9275 jpeg_destroy_decompress (&cinfo
);
9277 fclose ((FILE *) fp
);
9279 /* Put the image into the pixmap. */
9280 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9281 x_destroy_x_image (ximg
);
9286 #endif /* HAVE_JPEG */
9290 /***********************************************************************
9292 ***********************************************************************/
9298 static int tiff_image_p
P_ ((Lisp_Object object
));
9299 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9301 /* The symbol `tiff' identifying images of this type. */
9305 /* Indices of image specification fields in tiff_format, below. */
9307 enum tiff_keyword_index
9316 TIFF_HEURISTIC_MASK
,
9321 /* Vector of image_keyword structures describing the format
9322 of valid user-defined image specifications. */
9324 static struct image_keyword tiff_format
[TIFF_LAST
] =
9326 {":type", IMAGE_SYMBOL_VALUE
, 1},
9327 {":data", IMAGE_STRING_VALUE
, 0},
9328 {":file", IMAGE_STRING_VALUE
, 0},
9329 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9330 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9331 {":relief", IMAGE_INTEGER_VALUE
, 0},
9332 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9333 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9334 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9337 /* Structure describing the image type `tiff'. */
9339 static struct image_type tiff_type
=
9349 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9352 tiff_image_p (object
)
9355 struct image_keyword fmt
[TIFF_LAST
];
9356 bcopy (tiff_format
, fmt
, sizeof fmt
);
9358 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9361 /* Must specify either the :data or :file keyword. */
9362 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9366 /* Reading from a memory buffer for TIFF images Based on the PNG
9367 memory source, but we have to provide a lot of extra functions.
9370 We really only need to implement read and seek, but I am not
9371 convinced that the TIFF library is smart enough not to destroy
9372 itself if we only hand it the function pointers we need to
9377 unsigned char *bytes
;
9385 tiff_read_from_memory (data
, buf
, size
)
9390 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9392 if (size
> src
->len
- src
->index
)
9394 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9401 tiff_write_from_memory (data
, buf
, size
)
9411 tiff_seek_in_memory (data
, off
, whence
)
9416 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9421 case SEEK_SET
: /* Go from beginning of source. */
9425 case SEEK_END
: /* Go from end of source. */
9426 idx
= src
->len
+ off
;
9429 case SEEK_CUR
: /* Go from current position. */
9430 idx
= src
->index
+ off
;
9433 default: /* Invalid `whence'. */
9437 if (idx
> src
->len
|| idx
< 0)
9446 tiff_close_memory (data
)
9455 tiff_mmap_memory (data
, pbase
, psize
)
9460 /* It is already _IN_ memory. */
9466 tiff_unmap_memory (data
, base
, size
)
9471 /* We don't need to do this. */
9476 tiff_size_of_memory (data
)
9479 return ((tiff_memory_source
*) data
)->len
;
9483 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9491 Lisp_Object file
, specified_file
;
9492 Lisp_Object specified_data
;
9494 int width
, height
, x
, y
;
9498 struct gcpro gcpro1
;
9499 tiff_memory_source memsrc
;
9501 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9502 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9506 if (NILP (specified_data
))
9508 /* Read from a file */
9509 file
= x_find_image_file (specified_file
);
9510 if (!STRINGP (file
))
9512 image_error ("Cannot find image file `%s'", file
, Qnil
);
9517 /* Try to open the image file. */
9518 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9521 image_error ("Cannot open `%s'", file
, Qnil
);
9528 /* Memory source! */
9529 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9530 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9533 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9534 (TIFFReadWriteProc
) tiff_read_from_memory
,
9535 (TIFFReadWriteProc
) tiff_write_from_memory
,
9536 tiff_seek_in_memory
,
9538 tiff_size_of_memory
,
9544 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9550 /* Get width and height of the image, and allocate a raster buffer
9551 of width x height 32-bit values. */
9552 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9553 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9554 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9556 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9560 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9566 /* Create the X image and pixmap. */
9567 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9574 /* Initialize the color table. */
9575 init_color_table ();
9577 /* Process the pixel raster. Origin is in the lower-left corner. */
9578 for (y
= 0; y
< height
; ++y
)
9580 uint32
*row
= buf
+ y
* width
;
9582 for (x
= 0; x
< width
; ++x
)
9584 uint32 abgr
= row
[x
];
9585 int r
= TIFFGetR (abgr
) << 8;
9586 int g
= TIFFGetG (abgr
) << 8;
9587 int b
= TIFFGetB (abgr
) << 8;
9588 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9592 /* Remember the colors allocated for the image. Free the color table. */
9593 img
->colors
= colors_in_color_table (&img
->ncolors
);
9594 free_color_table ();
9596 /* Put the image into the pixmap, then free the X image and its buffer. */
9597 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9598 x_destroy_x_image (ximg
);
9602 img
->height
= height
;
9608 #endif /* HAVE_TIFF != 0 */
9612 /***********************************************************************
9614 ***********************************************************************/
9618 #include <gif_lib.h>
9620 static int gif_image_p
P_ ((Lisp_Object object
));
9621 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9623 /* The symbol `gif' identifying images of this type. */
9627 /* Indices of image specification fields in gif_format, below. */
9629 enum gif_keyword_index
9644 /* Vector of image_keyword structures describing the format
9645 of valid user-defined image specifications. */
9647 static struct image_keyword gif_format
[GIF_LAST
] =
9649 {":type", IMAGE_SYMBOL_VALUE
, 1},
9650 {":data", IMAGE_STRING_VALUE
, 0},
9651 {":file", IMAGE_STRING_VALUE
, 0},
9652 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9653 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9654 {":relief", IMAGE_INTEGER_VALUE
, 0},
9655 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9656 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9657 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9658 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
9661 /* Structure describing the image type `gif'. */
9663 static struct image_type gif_type
=
9673 /* Return non-zero if OBJECT is a valid GIF image specification. */
9676 gif_image_p (object
)
9679 struct image_keyword fmt
[GIF_LAST
];
9680 bcopy (gif_format
, fmt
, sizeof fmt
);
9682 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
9685 /* Must specify either the :data or :file keyword. */
9686 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
9690 /* Reading a GIF image from memory
9691 Based on the PNG memory stuff to a certain extent. */
9695 unsigned char *bytes
;
9702 /* Make the current memory source available to gif_read_from_memory.
9703 It's done this way because not all versions of libungif support
9704 a UserData field in the GifFileType structure. */
9705 static gif_memory_source
*current_gif_memory_src
;
9708 gif_read_from_memory (file
, buf
, len
)
9713 gif_memory_source
*src
= current_gif_memory_src
;
9715 if (len
> src
->len
- src
->index
)
9718 bcopy (src
->bytes
+ src
->index
, buf
, len
);
9724 /* Load GIF image IMG for use on frame F. Value is non-zero if
9732 Lisp_Object file
, specified_file
;
9733 Lisp_Object specified_data
;
9734 int rc
, width
, height
, x
, y
, i
;
9736 ColorMapObject
*gif_color_map
;
9737 unsigned long pixel_colors
[256];
9739 struct gcpro gcpro1
;
9741 int ino
, image_left
, image_top
, image_width
, image_height
;
9742 gif_memory_source memsrc
;
9743 unsigned char *raster
;
9745 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9746 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9750 if (NILP (specified_data
))
9752 file
= x_find_image_file (specified_file
);
9753 if (!STRINGP (file
))
9755 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9760 /* Open the GIF file. */
9761 gif
= DGifOpenFileName (XSTRING (file
)->data
);
9764 image_error ("Cannot open `%s'", file
, Qnil
);
9771 /* Read from memory! */
9772 current_gif_memory_src
= &memsrc
;
9773 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9774 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9777 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
9780 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
9786 /* Read entire contents. */
9787 rc
= DGifSlurp (gif
);
9788 if (rc
== GIF_ERROR
)
9790 image_error ("Error reading `%s'", img
->spec
, Qnil
);
9791 DGifCloseFile (gif
);
9796 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
9797 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
9798 if (ino
>= gif
->ImageCount
)
9800 image_error ("Invalid image number `%s' in image `%s'",
9802 DGifCloseFile (gif
);
9807 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
9808 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
9810 /* Create the X image and pixmap. */
9811 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9813 DGifCloseFile (gif
);
9818 /* Allocate colors. */
9819 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
9821 gif_color_map
= gif
->SColorMap
;
9822 init_color_table ();
9823 bzero (pixel_colors
, sizeof pixel_colors
);
9825 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
9827 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
9828 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
9829 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
9830 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9833 img
->colors
= colors_in_color_table (&img
->ncolors
);
9834 free_color_table ();
9836 /* Clear the part of the screen image that are not covered by
9837 the image from the GIF file. Full animated GIF support
9838 requires more than can be done here (see the gif89 spec,
9839 disposal methods). Let's simply assume that the part
9840 not covered by a sub-image is in the frame's background color. */
9841 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
9842 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
9843 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
9844 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
9846 for (y
= 0; y
< image_top
; ++y
)
9847 for (x
= 0; x
< width
; ++x
)
9848 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9850 for (y
= image_top
+ image_height
; y
< height
; ++y
)
9851 for (x
= 0; x
< width
; ++x
)
9852 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9854 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
9856 for (x
= 0; x
< image_left
; ++x
)
9857 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9858 for (x
= image_left
+ image_width
; x
< width
; ++x
)
9859 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9862 /* Read the GIF image into the X image. We use a local variable
9863 `raster' here because RasterBits below is a char *, and invites
9864 problems with bytes >= 0x80. */
9865 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
9867 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
9869 static int interlace_start
[] = {0, 4, 2, 1};
9870 static int interlace_increment
[] = {8, 8, 4, 2};
9872 int row
= interlace_start
[0];
9876 for (y
= 0; y
< image_height
; y
++)
9878 if (row
>= image_height
)
9880 row
= interlace_start
[++pass
];
9881 while (row
>= image_height
)
9882 row
= interlace_start
[++pass
];
9885 for (x
= 0; x
< image_width
; x
++)
9887 int i
= raster
[(y
* image_width
) + x
];
9888 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
9892 row
+= interlace_increment
[pass
];
9897 for (y
= 0; y
< image_height
; ++y
)
9898 for (x
= 0; x
< image_width
; ++x
)
9900 int i
= raster
[y
* image_width
+ x
];
9901 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
9905 DGifCloseFile (gif
);
9907 /* Put the image into the pixmap, then free the X image and its buffer. */
9908 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9909 x_destroy_x_image (ximg
);
9915 #endif /* HAVE_GIF != 0 */
9919 /***********************************************************************
9921 ***********************************************************************/
9923 static int gs_image_p
P_ ((Lisp_Object object
));
9924 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
9925 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
9927 /* The symbol `postscript' identifying images of this type. */
9929 Lisp_Object Qpostscript
;
9931 /* Keyword symbols. */
9933 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
9935 /* Indices of image specification fields in gs_format, below. */
9937 enum gs_keyword_index
9954 /* Vector of image_keyword structures describing the format
9955 of valid user-defined image specifications. */
9957 static struct image_keyword gs_format
[GS_LAST
] =
9959 {":type", IMAGE_SYMBOL_VALUE
, 1},
9960 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9961 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9962 {":file", IMAGE_STRING_VALUE
, 1},
9963 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9964 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9965 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9966 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9967 {":relief", IMAGE_INTEGER_VALUE
, 0},
9968 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9969 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9970 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9973 /* Structure describing the image type `ghostscript'. */
9975 static struct image_type gs_type
=
9985 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9988 gs_clear_image (f
, img
)
9992 /* IMG->data.ptr_val may contain a recorded colormap. */
9993 xfree (img
->data
.ptr_val
);
9994 x_clear_image (f
, img
);
9998 /* Return non-zero if OBJECT is a valid Ghostscript image
10002 gs_image_p (object
)
10003 Lisp_Object object
;
10005 struct image_keyword fmt
[GS_LAST
];
10009 bcopy (gs_format
, fmt
, sizeof fmt
);
10011 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10014 /* Bounding box must be a list or vector containing 4 integers. */
10015 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10018 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10019 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10024 else if (VECTORP (tem
))
10026 if (XVECTOR (tem
)->size
!= 4)
10028 for (i
= 0; i
< 4; ++i
)
10029 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10039 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10048 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10049 struct gcpro gcpro1
, gcpro2
;
10051 double in_width
, in_height
;
10052 Lisp_Object pixel_colors
= Qnil
;
10054 /* Compute pixel size of pixmap needed from the given size in the
10055 image specification. Sizes in the specification are in pt. 1 pt
10056 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10058 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10059 in_width
= XFASTINT (pt_width
) / 72.0;
10060 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10061 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10062 in_height
= XFASTINT (pt_height
) / 72.0;
10063 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10065 /* Create the pixmap. */
10066 xassert (img
->pixmap
== None
);
10067 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10068 img
->width
, img
->height
,
10069 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10073 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10077 /* Call the loader to fill the pixmap. It returns a process object
10078 if successful. We do not record_unwind_protect here because
10079 other places in redisplay like calling window scroll functions
10080 don't either. Let the Lisp loader use `unwind-protect' instead. */
10081 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10083 sprintf (buffer
, "%lu %lu",
10084 (unsigned long) FRAME_X_WINDOW (f
),
10085 (unsigned long) img
->pixmap
);
10086 window_and_pixmap_id
= build_string (buffer
);
10088 sprintf (buffer
, "%lu %lu",
10089 FRAME_FOREGROUND_PIXEL (f
),
10090 FRAME_BACKGROUND_PIXEL (f
));
10091 pixel_colors
= build_string (buffer
);
10093 XSETFRAME (frame
, f
);
10094 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10096 loader
= intern ("gs-load-image");
10098 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10099 make_number (img
->width
),
10100 make_number (img
->height
),
10101 window_and_pixmap_id
,
10104 return PROCESSP (img
->data
.lisp_val
);
10108 /* Kill the Ghostscript process that was started to fill PIXMAP on
10109 frame F. Called from XTread_socket when receiving an event
10110 telling Emacs that Ghostscript has finished drawing. */
10113 x_kill_gs_process (pixmap
, f
)
10117 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10121 /* Find the image containing PIXMAP. */
10122 for (i
= 0; i
< c
->used
; ++i
)
10123 if (c
->images
[i
]->pixmap
== pixmap
)
10126 /* Should someone in between have cleared the image cache, for
10127 instance, give up. */
10131 /* Kill the GS process. We should have found PIXMAP in the image
10132 cache and its image should contain a process object. */
10133 img
= c
->images
[i
];
10134 xassert (PROCESSP (img
->data
.lisp_val
));
10135 Fkill_process (img
->data
.lisp_val
, Qnil
);
10136 img
->data
.lisp_val
= Qnil
;
10138 /* On displays with a mutable colormap, figure out the colors
10139 allocated for the image by looking at the pixels of an XImage for
10141 class = FRAME_X_VISUAL (f
)->class;
10142 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10148 /* Try to get an XImage for img->pixmep. */
10149 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10150 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10155 /* Initialize the color table. */
10156 init_color_table ();
10158 /* For each pixel of the image, look its color up in the
10159 color table. After having done so, the color table will
10160 contain an entry for each color used by the image. */
10161 for (y
= 0; y
< img
->height
; ++y
)
10162 for (x
= 0; x
< img
->width
; ++x
)
10164 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10165 lookup_pixel_color (f
, pixel
);
10168 /* Record colors in the image. Free color table and XImage. */
10169 img
->colors
= colors_in_color_table (&img
->ncolors
);
10170 free_color_table ();
10171 XDestroyImage (ximg
);
10173 #if 0 /* This doesn't seem to be the case. If we free the colors
10174 here, we get a BadAccess later in x_clear_image when
10175 freeing the colors. */
10176 /* We have allocated colors once, but Ghostscript has also
10177 allocated colors on behalf of us. So, to get the
10178 reference counts right, free them once. */
10180 x_free_colors (f
, img
->colors
, img
->ncolors
);
10184 image_error ("Cannot get X image of `%s'; colors will not be freed",
10190 /* Now that we have the pixmap, compute mask and transform the
10191 image if requested. */
10193 postprocess_image (f
, img
);
10199 /***********************************************************************
10201 ***********************************************************************/
10203 DEFUN ("x-change-window-property", Fx_change_window_property
,
10204 Sx_change_window_property
, 2, 3, 0,
10205 "Change window property PROP to VALUE on the X window of FRAME.\n\
10206 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
10207 selected frame. Value is VALUE.")
10208 (prop
, value
, frame
)
10209 Lisp_Object frame
, prop
, value
;
10211 struct frame
*f
= check_x_frame (frame
);
10214 CHECK_STRING (prop
, 1);
10215 CHECK_STRING (value
, 2);
10218 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10219 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10220 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10221 XSTRING (value
)->data
, XSTRING (value
)->size
);
10223 /* Make sure the property is set when we return. */
10224 XFlush (FRAME_X_DISPLAY (f
));
10231 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10232 Sx_delete_window_property
, 1, 2, 0,
10233 "Remove window property PROP from X window of FRAME.\n\
10234 FRAME nil or omitted means use the selected frame. Value is PROP.")
10236 Lisp_Object prop
, frame
;
10238 struct frame
*f
= check_x_frame (frame
);
10241 CHECK_STRING (prop
, 1);
10243 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10244 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10246 /* Make sure the property is removed when we return. */
10247 XFlush (FRAME_X_DISPLAY (f
));
10254 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10256 "Value is the value of window property PROP on FRAME.\n\
10257 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
10258 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10261 Lisp_Object prop
, frame
;
10263 struct frame
*f
= check_x_frame (frame
);
10266 Lisp_Object prop_value
= Qnil
;
10267 char *tmp_data
= NULL
;
10270 unsigned long actual_size
, bytes_remaining
;
10272 CHECK_STRING (prop
, 1);
10274 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10275 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10276 prop_atom
, 0, 0, False
, XA_STRING
,
10277 &actual_type
, &actual_format
, &actual_size
,
10278 &bytes_remaining
, (unsigned char **) &tmp_data
);
10281 int size
= bytes_remaining
;
10286 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10287 prop_atom
, 0, bytes_remaining
,
10289 &actual_type
, &actual_format
,
10290 &actual_size
, &bytes_remaining
,
10291 (unsigned char **) &tmp_data
);
10292 if (rc
== Success
&& tmp_data
)
10293 prop_value
= make_string (tmp_data
, size
);
10304 /***********************************************************************
10306 ***********************************************************************/
10308 /* If non-null, an asynchronous timer that, when it expires, displays
10309 an hourglass cursor on all frames. */
10311 static struct atimer
*hourglass_atimer
;
10313 /* Non-zero means an hourglass cursor is currently shown. */
10315 static int hourglass_shown_p
;
10317 /* Number of seconds to wait before displaying an hourglass cursor. */
10319 static Lisp_Object Vhourglass_delay
;
10321 /* Default number of seconds to wait before displaying an hourglass
10324 #define DEFAULT_HOURGLASS_DELAY 1
10326 /* Function prototypes. */
10328 static void show_hourglass
P_ ((struct atimer
*));
10329 static void hide_hourglass
P_ ((void));
10332 /* Cancel a currently active hourglass timer, and start a new one. */
10338 int secs
, usecs
= 0;
10340 cancel_hourglass ();
10342 if (INTEGERP (Vhourglass_delay
)
10343 && XINT (Vhourglass_delay
) > 0)
10344 secs
= XFASTINT (Vhourglass_delay
);
10345 else if (FLOATP (Vhourglass_delay
)
10346 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10349 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10350 secs
= XFASTINT (tem
);
10351 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10354 secs
= DEFAULT_HOURGLASS_DELAY
;
10356 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10357 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10358 show_hourglass
, NULL
);
10362 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10366 cancel_hourglass ()
10368 if (hourglass_atimer
)
10370 cancel_atimer (hourglass_atimer
);
10371 hourglass_atimer
= NULL
;
10374 if (hourglass_shown_p
)
10379 /* Timer function of hourglass_atimer. TIMER is equal to
10382 Display an hourglass pointer on all frames by mapping the frames'
10383 hourglass_window. Set the hourglass_p flag in the frames'
10384 output_data.x structure to indicate that an hourglass cursor is
10385 shown on the frames. */
10388 show_hourglass (timer
)
10389 struct atimer
*timer
;
10391 /* The timer implementation will cancel this timer automatically
10392 after this function has run. Set hourglass_atimer to null
10393 so that we know the timer doesn't have to be canceled. */
10394 hourglass_atimer
= NULL
;
10396 if (!hourglass_shown_p
)
10398 Lisp_Object rest
, frame
;
10402 FOR_EACH_FRAME (rest
, frame
)
10404 struct frame
*f
= XFRAME (frame
);
10406 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10408 Display
*dpy
= FRAME_X_DISPLAY (f
);
10410 #ifdef USE_X_TOOLKIT
10411 if (f
->output_data
.x
->widget
)
10413 if (FRAME_OUTER_WINDOW (f
))
10416 f
->output_data
.x
->hourglass_p
= 1;
10418 if (!f
->output_data
.x
->hourglass_window
)
10420 unsigned long mask
= CWCursor
;
10421 XSetWindowAttributes attrs
;
10423 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10425 f
->output_data
.x
->hourglass_window
10426 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10427 0, 0, 32000, 32000, 0, 0,
10433 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10439 hourglass_shown_p
= 1;
10445 /* Hide the hourglass pointer on all frames, if it is currently
10451 if (hourglass_shown_p
)
10453 Lisp_Object rest
, frame
;
10456 FOR_EACH_FRAME (rest
, frame
)
10458 struct frame
*f
= XFRAME (frame
);
10461 /* Watch out for newly created frames. */
10462 && f
->output_data
.x
->hourglass_window
)
10464 XUnmapWindow (FRAME_X_DISPLAY (f
),
10465 f
->output_data
.x
->hourglass_window
);
10466 /* Sync here because XTread_socket looks at the
10467 hourglass_p flag that is reset to zero below. */
10468 XSync (FRAME_X_DISPLAY (f
), False
);
10469 f
->output_data
.x
->hourglass_p
= 0;
10473 hourglass_shown_p
= 0;
10480 /***********************************************************************
10482 ***********************************************************************/
10484 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10485 Lisp_Object
, Lisp_Object
));
10486 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10487 Lisp_Object
, int, int, int *, int *));
10489 /* The frame of a currently visible tooltip. */
10491 Lisp_Object tip_frame
;
10493 /* If non-nil, a timer started that hides the last tooltip when it
10496 Lisp_Object tip_timer
;
10499 /* If non-nil, a vector of 3 elements containing the last args
10500 with which x-show-tip was called. See there. */
10502 Lisp_Object last_show_tip_args
;
10504 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10506 Lisp_Object Vx_max_tooltip_size
;
10510 unwind_create_tip_frame (frame
)
10513 Lisp_Object deleted
;
10515 deleted
= unwind_create_frame (frame
);
10516 if (EQ (deleted
, Qt
))
10526 /* Create a frame for a tooltip on the display described by DPYINFO.
10527 PARMS is a list of frame parameters. TEXT is the string to
10528 display in the tip frame. Value is the frame.
10530 Note that functions called here, esp. x_default_parameter can
10531 signal errors, for instance when a specified color name is
10532 undefined. We have to make sure that we're in a consistent state
10533 when this happens. */
10536 x_create_tip_frame (dpyinfo
, parms
, text
)
10537 struct x_display_info
*dpyinfo
;
10538 Lisp_Object parms
, text
;
10541 Lisp_Object frame
, tem
;
10543 long window_prompting
= 0;
10545 int count
= BINDING_STACK_SIZE ();
10546 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10548 int face_change_count_before
= face_change_count
;
10549 Lisp_Object buffer
;
10550 struct buffer
*old_buffer
;
10554 /* Use this general default value to start with until we know if
10555 this frame has a specified name. */
10556 Vx_resource_name
= Vinvocation_name
;
10558 #ifdef MULTI_KBOARD
10559 kb
= dpyinfo
->kboard
;
10561 kb
= &the_only_kboard
;
10564 /* Get the name of the frame to use for resource lookup. */
10565 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10566 if (!STRINGP (name
)
10567 && !EQ (name
, Qunbound
)
10569 error ("Invalid frame name--not a string or nil");
10570 Vx_resource_name
= name
;
10573 GCPRO3 (parms
, name
, frame
);
10574 f
= make_frame (1);
10575 XSETFRAME (frame
, f
);
10577 buffer
= Fget_buffer_create (build_string (" *tip*"));
10578 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10579 old_buffer
= current_buffer
;
10580 set_buffer_internal_1 (XBUFFER (buffer
));
10581 current_buffer
->truncate_lines
= Qnil
;
10583 Finsert (1, &text
);
10584 set_buffer_internal_1 (old_buffer
);
10586 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10587 record_unwind_protect (unwind_create_tip_frame
, frame
);
10589 /* By setting the output method, we're essentially saying that
10590 the frame is live, as per FRAME_LIVE_P. If we get a signal
10591 from this point on, x_destroy_window might screw up reference
10593 f
->output_method
= output_x_window
;
10594 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10595 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10596 f
->output_data
.x
->icon_bitmap
= -1;
10597 f
->output_data
.x
->fontset
= -1;
10598 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10599 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10600 f
->icon_name
= Qnil
;
10601 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10603 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
10604 dpyinfo_refcount
= dpyinfo
->reference_count
;
10605 #endif /* GLYPH_DEBUG */
10606 #ifdef MULTI_KBOARD
10607 FRAME_KBOARD (f
) = kb
;
10609 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10610 f
->output_data
.x
->explicit_parent
= 0;
10612 /* These colors will be set anyway later, but it's important
10613 to get the color reference counts right, so initialize them! */
10616 struct gcpro gcpro1
;
10618 black
= build_string ("black");
10620 f
->output_data
.x
->foreground_pixel
10621 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10622 f
->output_data
.x
->background_pixel
10623 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10624 f
->output_data
.x
->cursor_pixel
10625 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10626 f
->output_data
.x
->cursor_foreground_pixel
10627 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10628 f
->output_data
.x
->border_pixel
10629 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10630 f
->output_data
.x
->mouse_pixel
10631 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10635 /* Set the name; the functions to which we pass f expect the name to
10637 if (EQ (name
, Qunbound
) || NILP (name
))
10639 f
->name
= build_string (dpyinfo
->x_id_name
);
10640 f
->explicit_name
= 0;
10645 f
->explicit_name
= 1;
10646 /* use the frame's title when getting resources for this frame. */
10647 specbind (Qx_resource_name
, name
);
10650 /* Extract the window parameters from the supplied values that are
10651 needed to determine window geometry. */
10655 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
10658 /* First, try whatever font the caller has specified. */
10659 if (STRINGP (font
))
10661 tem
= Fquery_fontset (font
, Qnil
);
10663 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
10665 font
= x_new_font (f
, XSTRING (font
)->data
);
10668 /* Try out a font which we hope has bold and italic variations. */
10669 if (!STRINGP (font
))
10670 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10671 if (!STRINGP (font
))
10672 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10673 if (! STRINGP (font
))
10674 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10675 if (! STRINGP (font
))
10676 /* This was formerly the first thing tried, but it finds too many fonts
10677 and takes too long. */
10678 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10679 /* If those didn't work, look for something which will at least work. */
10680 if (! STRINGP (font
))
10681 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10683 if (! STRINGP (font
))
10684 font
= build_string ("fixed");
10686 x_default_parameter (f
, parms
, Qfont
, font
,
10687 "font", "Font", RES_TYPE_STRING
);
10690 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
10691 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
10693 /* This defaults to 2 in order to match xterm. We recognize either
10694 internalBorderWidth or internalBorder (which is what xterm calls
10696 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10700 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
10701 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
10702 if (! EQ (value
, Qunbound
))
10703 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
10707 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
10708 "internalBorderWidth", "internalBorderWidth",
10711 /* Also do the stuff which must be set before the window exists. */
10712 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
10713 "foreground", "Foreground", RES_TYPE_STRING
);
10714 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
10715 "background", "Background", RES_TYPE_STRING
);
10716 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
10717 "pointerColor", "Foreground", RES_TYPE_STRING
);
10718 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
10719 "cursorColor", "Foreground", RES_TYPE_STRING
);
10720 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
10721 "borderColor", "BorderColor", RES_TYPE_STRING
);
10723 /* Init faces before x_default_parameter is called for scroll-bar
10724 parameters because that function calls x_set_scroll_bar_width,
10725 which calls change_frame_size, which calls Fset_window_buffer,
10726 which runs hooks, which call Fvertical_motion. At the end, we
10727 end up in init_iterator with a null face cache, which should not
10729 init_frame_faces (f
);
10731 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10732 window_prompting
= x_figure_window_size (f
, parms
);
10734 if (window_prompting
& XNegative
)
10736 if (window_prompting
& YNegative
)
10737 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
10739 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
10743 if (window_prompting
& YNegative
)
10744 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
10746 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10749 f
->output_data
.x
->size_hint_flags
= window_prompting
;
10751 XSetWindowAttributes attrs
;
10752 unsigned long mask
;
10755 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
10756 if (DoesSaveUnders (dpyinfo
->screen
))
10757 mask
|= CWSaveUnder
;
10759 /* Window managers look at the override-redirect flag to determine
10760 whether or net to give windows a decoration (Xlib spec, chapter
10762 attrs
.override_redirect
= True
;
10763 attrs
.save_under
= True
;
10764 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
10765 /* Arrange for getting MapNotify and UnmapNotify events. */
10766 attrs
.event_mask
= StructureNotifyMask
;
10768 = FRAME_X_WINDOW (f
)
10769 = XCreateWindow (FRAME_X_DISPLAY (f
),
10770 FRAME_X_DISPLAY_INFO (f
)->root_window
,
10771 /* x, y, width, height */
10775 CopyFromParent
, InputOutput
, CopyFromParent
,
10782 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
10783 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10784 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
10785 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10786 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
10787 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
10789 /* Dimensions, especially f->height, must be done via change_frame_size.
10790 Change will not be effected unless different from the current
10793 height
= f
->height
;
10795 SET_FRAME_WIDTH (f
, 0);
10796 change_frame_size (f
, height
, width
, 1, 0, 0);
10798 /* Set up faces after all frame parameters are known. This call
10799 also merges in face attributes specified for new frames.
10801 Frame parameters may be changed if .Xdefaults contains
10802 specifications for the default font. For example, if there is an
10803 `Emacs.default.attributeBackground: pink', the `background-color'
10804 attribute of the frame get's set, which let's the internal border
10805 of the tooltip frame appear in pink. Prevent this. */
10807 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
10809 /* Set tip_frame here, so that */
10811 call1 (Qface_set_after_frame_default
, frame
);
10813 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
10814 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
10822 /* It is now ok to make the frame official even if we get an error
10823 below. And the frame needs to be on Vframe_list or making it
10824 visible won't work. */
10825 Vframe_list
= Fcons (frame
, Vframe_list
);
10827 /* Now that the frame is official, it counts as a reference to
10829 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
10831 /* Setting attributes of faces of the tooltip frame from resources
10832 and similar will increment face_change_count, which leads to the
10833 clearing of all current matrices. Since this isn't necessary
10834 here, avoid it by resetting face_change_count to the value it
10835 had before we created the tip frame. */
10836 face_change_count
= face_change_count_before
;
10838 /* Discard the unwind_protect. */
10839 return unbind_to (count
, frame
);
10843 /* Compute where to display tip frame F. PARMS is the list of frame
10844 parameters for F. DX and DY are specified offsets from the current
10845 location of the mouse. WIDTH and HEIGHT are the width and height
10846 of the tooltip. Return coordinates relative to the root window of
10847 the display in *ROOT_X, and *ROOT_Y. */
10850 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
10852 Lisp_Object parms
, dx
, dy
;
10854 int *root_x
, *root_y
;
10856 Lisp_Object left
, top
;
10858 Window root
, child
;
10861 /* User-specified position? */
10862 left
= Fcdr (Fassq (Qleft
, parms
));
10863 top
= Fcdr (Fassq (Qtop
, parms
));
10865 /* Move the tooltip window where the mouse pointer is. Resize and
10867 if (!INTEGERP (left
) && !INTEGERP (top
))
10870 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
10871 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
10875 if (INTEGERP (top
))
10876 *root_y
= XINT (top
);
10877 else if (*root_y
+ XINT (dy
) - height
< 0)
10878 *root_y
-= XINT (dy
);
10882 *root_y
+= XINT (dy
);
10885 if (INTEGERP (left
))
10886 *root_x
= XINT (left
);
10887 else if (*root_x
+ XINT (dx
) + width
> FRAME_X_DISPLAY_INFO (f
)->width
)
10888 *root_x
-= width
+ XINT (dx
);
10890 *root_x
+= XINT (dx
);
10894 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
10895 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10896 A tooltip window is a small X window displaying a string.\n\
10898 FRAME nil or omitted means use the selected frame.\n\
10900 PARMS is an optional list of frame parameters which can be\n\
10901 used to change the tooltip's appearance.\n\
10903 Automatically hide the tooltip after TIMEOUT seconds.\n\
10904 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10906 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10907 the tooltip is displayed at that x-position. Otherwise it is\n\
10908 displayed at the mouse position, with offset DX added (default is 5 if\n\
10909 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10910 parameter is specified, it determines the y-position of the tooltip\n\
10911 window, otherwise it is displayed at the mouse position, with offset\n\
10912 DY added (default is -10).\n\
10914 A tooltip's maximum size is specified by `x-max-tooltip-size'.\n\
10915 Text larger than the specified size is clipped.")
10916 (string
, frame
, parms
, timeout
, dx
, dy
)
10917 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
10921 Lisp_Object buffer
, top
, left
, max_width
, max_height
;
10922 int root_x
, root_y
;
10923 struct buffer
*old_buffer
;
10924 struct text_pos pos
;
10925 int i
, width
, height
;
10926 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
10927 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
10928 int count
= BINDING_STACK_SIZE ();
10930 specbind (Qinhibit_redisplay
, Qt
);
10932 GCPRO4 (string
, parms
, frame
, timeout
);
10934 CHECK_STRING (string
, 0);
10935 f
= check_x_frame (frame
);
10936 if (NILP (timeout
))
10937 timeout
= make_number (5);
10939 CHECK_NATNUM (timeout
, 2);
10942 dx
= make_number (5);
10944 CHECK_NUMBER (dx
, 5);
10947 dy
= make_number (-10);
10949 CHECK_NUMBER (dy
, 6);
10951 if (NILP (last_show_tip_args
))
10952 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
10954 if (!NILP (tip_frame
))
10956 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
10957 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
10958 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
10960 if (EQ (frame
, last_frame
)
10961 && !NILP (Fequal (last_string
, string
))
10962 && !NILP (Fequal (last_parms
, parms
)))
10964 struct frame
*f
= XFRAME (tip_frame
);
10966 /* Only DX and DY have changed. */
10967 if (!NILP (tip_timer
))
10969 Lisp_Object timer
= tip_timer
;
10971 call1 (Qcancel_timer
, timer
);
10975 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
10976 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
10977 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10984 /* Hide a previous tip, if any. */
10987 ASET (last_show_tip_args
, 0, string
);
10988 ASET (last_show_tip_args
, 1, frame
);
10989 ASET (last_show_tip_args
, 2, parms
);
10991 /* Add default values to frame parameters. */
10992 if (NILP (Fassq (Qname
, parms
)))
10993 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
10994 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10995 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
10996 if (NILP (Fassq (Qborder_width
, parms
)))
10997 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
10998 if (NILP (Fassq (Qborder_color
, parms
)))
10999 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
11000 if (NILP (Fassq (Qbackground_color
, parms
)))
11001 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
11004 /* Create a frame for the tooltip, and record it in the global
11005 variable tip_frame. */
11006 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
11007 f
= XFRAME (frame
);
11009 /* Set up the frame's root window. */
11010 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
11011 w
->left
= w
->top
= make_number (0);
11013 if (CONSP (Vx_max_tooltip_size
)
11014 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11015 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11016 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11017 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11019 w
->width
= XCAR (Vx_max_tooltip_size
);
11020 w
->height
= XCDR (Vx_max_tooltip_size
);
11024 w
->width
= make_number (80);
11025 w
->height
= make_number (40);
11028 f
->window_width
= XINT (w
->width
);
11030 w
->pseudo_window_p
= 1;
11032 /* Display the tooltip text in a temporary buffer. */
11033 old_buffer
= current_buffer
;
11034 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11035 current_buffer
->truncate_lines
= Qnil
;
11036 clear_glyph_matrix (w
->desired_matrix
);
11037 clear_glyph_matrix (w
->current_matrix
);
11038 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11039 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11041 /* Compute width and height of the tooltip. */
11042 width
= height
= 0;
11043 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11045 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11046 struct glyph
*last
;
11049 /* Stop at the first empty row at the end. */
11050 if (!row
->enabled_p
|| !row
->displays_text_p
)
11053 /* Let the row go over the full width of the frame. */
11054 row
->full_width_p
= 1;
11056 /* There's a glyph at the end of rows that is used to place
11057 the cursor there. Don't include the width of this glyph. */
11058 if (row
->used
[TEXT_AREA
])
11060 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11061 row_width
= row
->pixel_width
- last
->pixel_width
;
11064 row_width
= row
->pixel_width
;
11066 height
+= row
->height
;
11067 width
= max (width
, row_width
);
11070 /* Add the frame's internal border to the width and height the X
11071 window should have. */
11072 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11073 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11075 /* Move the tooltip window where the mouse pointer is. Resize and
11077 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11080 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11081 root_x
, root_y
, width
, height
);
11082 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11085 /* Draw into the window. */
11086 w
->must_be_updated_p
= 1;
11087 update_single_window (w
, 1);
11089 /* Restore original current buffer. */
11090 set_buffer_internal_1 (old_buffer
);
11091 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11094 /* Let the tip disappear after timeout seconds. */
11095 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11096 intern ("x-hide-tip"));
11099 return unbind_to (count
, Qnil
);
11103 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11104 "Hide the current tooltip window, if there is any.\n\
11105 Value is t is tooltip was open, nil otherwise.")
11109 Lisp_Object deleted
, frame
, timer
;
11110 struct gcpro gcpro1
, gcpro2
;
11112 /* Return quickly if nothing to do. */
11113 if (NILP (tip_timer
) && NILP (tip_frame
))
11118 GCPRO2 (frame
, timer
);
11119 tip_frame
= tip_timer
= deleted
= Qnil
;
11121 count
= BINDING_STACK_SIZE ();
11122 specbind (Qinhibit_redisplay
, Qt
);
11123 specbind (Qinhibit_quit
, Qt
);
11126 call1 (Qcancel_timer
, timer
);
11128 if (FRAMEP (frame
))
11130 Fdelete_frame (frame
, Qnil
);
11134 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11135 redisplay procedure is not called when a tip frame over menu
11136 items is unmapped. Redisplay the menu manually... */
11138 struct frame
*f
= SELECTED_FRAME ();
11139 Widget w
= f
->output_data
.x
->menubar_widget
;
11140 extern void xlwmenu_redisplay
P_ ((Widget
));
11142 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11146 xlwmenu_redisplay (w
);
11150 #endif /* USE_LUCID */
11154 return unbind_to (count
, deleted
);
11159 /***********************************************************************
11160 File selection dialog
11161 ***********************************************************************/
11165 /* Callback for "OK" and "Cancel" on file selection dialog. */
11168 file_dialog_cb (widget
, client_data
, call_data
)
11170 XtPointer call_data
, client_data
;
11172 int *result
= (int *) client_data
;
11173 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11174 *result
= cb
->reason
;
11178 /* Callback for unmapping a file selection dialog. This is used to
11179 capture the case where a dialog is closed via a window manager's
11180 closer button, for example. Using a XmNdestroyCallback didn't work
11184 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11186 XtPointer call_data
, client_data
;
11188 int *result
= (int *) client_data
;
11189 *result
= XmCR_CANCEL
;
11193 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11194 "Read file name, prompting with PROMPT in directory DIR.\n\
11195 Use a file selection dialog.\n\
11196 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
11197 specified. Don't let the user enter a file name in the file\n\
11198 selection dialog's entry field, if MUSTMATCH is non-nil.")
11199 (prompt
, dir
, default_filename
, mustmatch
)
11200 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11203 struct frame
*f
= SELECTED_FRAME ();
11204 Lisp_Object file
= Qnil
;
11205 Widget dialog
, text
, list
, help
;
11208 extern XtAppContext Xt_app_con
;
11210 XmString dir_xmstring
, pattern_xmstring
;
11211 int popup_activated_flag
;
11212 int count
= specpdl_ptr
- specpdl
;
11213 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11215 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11216 CHECK_STRING (prompt
, 0);
11217 CHECK_STRING (dir
, 1);
11219 /* Prevent redisplay. */
11220 specbind (Qinhibit_redisplay
, Qt
);
11224 /* Create the dialog with PROMPT as title, using DIR as initial
11225 directory and using "*" as pattern. */
11226 dir
= Fexpand_file_name (dir
, Qnil
);
11227 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
11228 pattern_xmstring
= XmStringCreateLocalized ("*");
11230 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
11231 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11232 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11233 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11234 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11235 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11237 XmStringFree (dir_xmstring
);
11238 XmStringFree (pattern_xmstring
);
11240 /* Add callbacks for OK and Cancel. */
11241 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11242 (XtPointer
) &result
);
11243 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11244 (XtPointer
) &result
);
11245 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11246 (XtPointer
) &result
);
11248 /* Disable the help button since we can't display help. */
11249 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11250 XtSetSensitive (help
, False
);
11252 /* Mark OK button as default. */
11253 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11254 XmNshowAsDefault
, True
, NULL
);
11256 /* If MUSTMATCH is non-nil, disable the file entry field of the
11257 dialog, so that the user must select a file from the files list
11258 box. We can't remove it because we wouldn't have a way to get at
11259 the result file name, then. */
11260 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11261 if (!NILP (mustmatch
))
11264 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11265 XtSetSensitive (text
, False
);
11266 XtSetSensitive (label
, False
);
11269 /* Manage the dialog, so that list boxes get filled. */
11270 XtManageChild (dialog
);
11272 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11273 must include the path for this to work. */
11274 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11275 if (STRINGP (default_filename
))
11277 XmString default_xmstring
;
11281 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
11283 if (!XmListItemExists (list
, default_xmstring
))
11285 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11286 XmListAddItem (list
, default_xmstring
, 0);
11290 item_pos
= XmListItemPos (list
, default_xmstring
);
11291 XmStringFree (default_xmstring
);
11293 /* Select the item and scroll it into view. */
11294 XmListSelectPos (list
, item_pos
, True
);
11295 XmListSetPos (list
, item_pos
);
11298 /* Process events until the user presses Cancel or OK. Block
11299 and unblock input here so that we get a chance of processing
11303 while (result
== 0)
11306 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11311 /* Get the result. */
11312 if (result
== XmCR_OK
)
11317 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11318 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11319 XmStringFree (text
);
11320 file
= build_string (data
);
11327 XtUnmanageChild (dialog
);
11328 XtDestroyWidget (dialog
);
11332 /* Make "Cancel" equivalent to C-g. */
11334 Fsignal (Qquit
, Qnil
);
11336 return unbind_to (count
, file
);
11339 #endif /* USE_MOTIF */
11343 /***********************************************************************
11345 ***********************************************************************/
11347 #ifdef HAVE_XKBGETKEYBOARD
11348 #include <X11/XKBlib.h>
11349 #include <X11/keysym.h>
11352 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11353 Sx_backspace_delete_keys_p
, 0, 1, 0,
11354 "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
11355 FRAME nil means use the selected frame.\n\
11356 Value is t if we know that both keys are present, and are mapped to the\n\
11361 #ifdef HAVE_XKBGETKEYBOARD
11363 struct frame
*f
= check_x_frame (frame
);
11364 Display
*dpy
= FRAME_X_DISPLAY (f
);
11365 Lisp_Object have_keys
;
11366 int major
, minor
, op
, event
, error
;
11370 /* Check library version in case we're dynamically linked. */
11371 major
= XkbMajorVersion
;
11372 minor
= XkbMinorVersion
;
11373 if (!XkbLibraryVersion (&major
, &minor
))
11379 /* Check that the server supports XKB. */
11380 major
= XkbMajorVersion
;
11381 minor
= XkbMinorVersion
;
11382 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11389 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11392 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11394 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11396 for (i
= kb
->min_key_code
;
11397 (i
< kb
->max_key_code
11398 && (delete_keycode
== 0 || backspace_keycode
== 0));
11401 /* The XKB symbolic key names can be seen most easily in
11402 the PS file generated by `xkbprint -label name
11404 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11405 delete_keycode
= i
;
11406 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11407 backspace_keycode
= i
;
11410 XkbFreeNames (kb
, 0, True
);
11413 XkbFreeClientMap (kb
, 0, True
);
11416 && backspace_keycode
11417 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11418 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11423 #else /* not HAVE_XKBGETKEYBOARD */
11425 #endif /* not HAVE_XKBGETKEYBOARD */
11430 /***********************************************************************
11432 ***********************************************************************/
11437 /* This is zero if not using X windows. */
11440 /* The section below is built by the lisp expression at the top of the file,
11441 just above where these variables are declared. */
11442 /*&&& init symbols here &&&*/
11443 Qauto_raise
= intern ("auto-raise");
11444 staticpro (&Qauto_raise
);
11445 Qauto_lower
= intern ("auto-lower");
11446 staticpro (&Qauto_lower
);
11447 Qbar
= intern ("bar");
11449 Qborder_color
= intern ("border-color");
11450 staticpro (&Qborder_color
);
11451 Qborder_width
= intern ("border-width");
11452 staticpro (&Qborder_width
);
11453 Qbox
= intern ("box");
11455 Qcursor_color
= intern ("cursor-color");
11456 staticpro (&Qcursor_color
);
11457 Qcursor_type
= intern ("cursor-type");
11458 staticpro (&Qcursor_type
);
11459 Qgeometry
= intern ("geometry");
11460 staticpro (&Qgeometry
);
11461 Qicon_left
= intern ("icon-left");
11462 staticpro (&Qicon_left
);
11463 Qicon_top
= intern ("icon-top");
11464 staticpro (&Qicon_top
);
11465 Qicon_type
= intern ("icon-type");
11466 staticpro (&Qicon_type
);
11467 Qicon_name
= intern ("icon-name");
11468 staticpro (&Qicon_name
);
11469 Qinternal_border_width
= intern ("internal-border-width");
11470 staticpro (&Qinternal_border_width
);
11471 Qleft
= intern ("left");
11472 staticpro (&Qleft
);
11473 Qright
= intern ("right");
11474 staticpro (&Qright
);
11475 Qmouse_color
= intern ("mouse-color");
11476 staticpro (&Qmouse_color
);
11477 Qnone
= intern ("none");
11478 staticpro (&Qnone
);
11479 Qparent_id
= intern ("parent-id");
11480 staticpro (&Qparent_id
);
11481 Qscroll_bar_width
= intern ("scroll-bar-width");
11482 staticpro (&Qscroll_bar_width
);
11483 Qsuppress_icon
= intern ("suppress-icon");
11484 staticpro (&Qsuppress_icon
);
11485 Qundefined_color
= intern ("undefined-color");
11486 staticpro (&Qundefined_color
);
11487 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11488 staticpro (&Qvertical_scroll_bars
);
11489 Qvisibility
= intern ("visibility");
11490 staticpro (&Qvisibility
);
11491 Qwindow_id
= intern ("window-id");
11492 staticpro (&Qwindow_id
);
11493 Qouter_window_id
= intern ("outer-window-id");
11494 staticpro (&Qouter_window_id
);
11495 Qx_frame_parameter
= intern ("x-frame-parameter");
11496 staticpro (&Qx_frame_parameter
);
11497 Qx_resource_name
= intern ("x-resource-name");
11498 staticpro (&Qx_resource_name
);
11499 Quser_position
= intern ("user-position");
11500 staticpro (&Quser_position
);
11501 Quser_size
= intern ("user-size");
11502 staticpro (&Quser_size
);
11503 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11504 staticpro (&Qscroll_bar_foreground
);
11505 Qscroll_bar_background
= intern ("scroll-bar-background");
11506 staticpro (&Qscroll_bar_background
);
11507 Qscreen_gamma
= intern ("screen-gamma");
11508 staticpro (&Qscreen_gamma
);
11509 Qline_spacing
= intern ("line-spacing");
11510 staticpro (&Qline_spacing
);
11511 Qcenter
= intern ("center");
11512 staticpro (&Qcenter
);
11513 Qcompound_text
= intern ("compound-text");
11514 staticpro (&Qcompound_text
);
11515 Qcancel_timer
= intern ("cancel-timer");
11516 staticpro (&Qcancel_timer
);
11517 Qwait_for_wm
= intern ("wait-for-wm");
11518 staticpro (&Qwait_for_wm
);
11519 /* This is the end of symbol initialization. */
11521 /* Text property `display' should be nonsticky by default. */
11522 Vtext_property_default_nonsticky
11523 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11526 Qlaplace
= intern ("laplace");
11527 staticpro (&Qlaplace
);
11528 Qemboss
= intern ("emboss");
11529 staticpro (&Qemboss
);
11530 Qedge_detection
= intern ("edge-detection");
11531 staticpro (&Qedge_detection
);
11532 Qheuristic
= intern ("heuristic");
11533 staticpro (&Qheuristic
);
11534 QCmatrix
= intern (":matrix");
11535 staticpro (&QCmatrix
);
11536 QCcolor_adjustment
= intern (":color-adjustment");
11537 staticpro (&QCcolor_adjustment
);
11538 QCmask
= intern (":mask");
11539 staticpro (&QCmask
);
11541 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11542 staticpro (&Qface_set_after_frame_default
);
11544 Fput (Qundefined_color
, Qerror_conditions
,
11545 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11546 Fput (Qundefined_color
, Qerror_message
,
11547 build_string ("Undefined color"));
11549 init_x_parm_symbols ();
11551 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11552 "Non-nil means always draw a cross over disabled images.\n\
11553 Disabled images are those having an `:conversion disabled' property.\n\
11554 A cross is always drawn on black & white displays.");
11555 cross_disabled_images
= 0;
11557 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11558 "List of directories to search for bitmap files for X.");
11559 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11561 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11562 "The shape of the pointer when over text.\n\
11563 Changing the value does not affect existing frames\n\
11564 unless you set the mouse color.");
11565 Vx_pointer_shape
= Qnil
;
11567 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11568 "The name Emacs uses to look up X resources.\n\
11569 `x-get-resource' uses this as the first component of the instance name\n\
11570 when requesting resource values.\n\
11571 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11572 was invoked, or to the value specified with the `-name' or `-rn'\n\
11573 switches, if present.\n\
11575 It may be useful to bind this variable locally around a call\n\
11576 to `x-get-resource'. See also the variable `x-resource-class'.");
11577 Vx_resource_name
= Qnil
;
11579 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11580 "The class Emacs uses to look up X resources.\n\
11581 `x-get-resource' uses this as the first component of the instance class\n\
11582 when requesting resource values.\n\
11583 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11585 Setting this variable permanently is not a reasonable thing to do,\n\
11586 but binding this variable locally around a call to `x-get-resource'\n\
11587 is a reasonable practice. See also the variable `x-resource-name'.");
11588 Vx_resource_class
= build_string (EMACS_CLASS
);
11590 #if 0 /* This doesn't really do anything. */
11591 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11592 "The shape of the pointer when not over text.\n\
11593 This variable takes effect when you create a new frame\n\
11594 or when you set the mouse color.");
11596 Vx_nontext_pointer_shape
= Qnil
;
11598 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
11599 "The shape of the pointer when Emacs is busy.\n\
11600 This variable takes effect when you create a new frame\n\
11601 or when you set the mouse color.");
11602 Vx_hourglass_pointer_shape
= Qnil
;
11604 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
11605 "Non-zero means Emacs displays an hourglass pointer on window systems.");
11606 display_hourglass_p
= 1;
11608 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
11609 "*Seconds to wait before displaying an hourglass pointer.\n\
11610 Value must be an integer or float.");
11611 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
11613 #if 0 /* This doesn't really do anything. */
11614 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
11615 "The shape of the pointer when over the mode line.\n\
11616 This variable takes effect when you create a new frame\n\
11617 or when you set the mouse color.");
11619 Vx_mode_pointer_shape
= Qnil
;
11621 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11622 &Vx_sensitive_text_pointer_shape
,
11623 "The shape of the pointer when over mouse-sensitive text.\n\
11624 This variable takes effect when you create a new frame\n\
11625 or when you set the mouse color.");
11626 Vx_sensitive_text_pointer_shape
= Qnil
;
11628 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11629 &Vx_window_horizontal_drag_shape
,
11630 "Pointer shape to use for indicating a window can be dragged horizontally.\n\
11631 This variable takes effect when you create a new frame\n\
11632 or when you set the mouse color.");
11633 Vx_window_horizontal_drag_shape
= Qnil
;
11635 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
11636 "A string indicating the foreground color of the cursor box.");
11637 Vx_cursor_fore_pixel
= Qnil
;
11639 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
11640 "Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).\n\
11641 Text larger than this is clipped.");
11642 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
11644 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
11645 "Non-nil if no X window manager is in use.\n\
11646 Emacs doesn't try to figure this out; this is always nil\n\
11647 unless you set it to something else.");
11648 /* We don't have any way to find this out, so set it to nil
11649 and maybe the user would like to set it to t. */
11650 Vx_no_window_manager
= Qnil
;
11652 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11653 &Vx_pixel_size_width_font_regexp
,
11654 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11656 Since Emacs gets width of a font matching with this regexp from\n\
11657 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11658 such a font. This is especially effective for such large fonts as\n\
11659 Chinese, Japanese, and Korean.");
11660 Vx_pixel_size_width_font_regexp
= Qnil
;
11662 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
11663 "Time after which cached images are removed from the cache.\n\
11664 When an image has not been displayed this many seconds, remove it\n\
11665 from the image cache. Value must be an integer or nil with nil\n\
11666 meaning don't clear the cache.");
11667 Vimage_cache_eviction_delay
= make_number (30 * 60);
11669 #ifdef USE_X_TOOLKIT
11670 Fprovide (intern ("x-toolkit"));
11673 Fprovide (intern ("motif"));
11675 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
11676 "Version info for LessTif/Motif.");
11677 Vmotif_version_string
= build_string (XmVERSION_STRING
);
11678 #endif /* USE_MOTIF */
11679 #endif /* USE_X_TOOLKIT */
11681 defsubr (&Sx_get_resource
);
11683 /* X window properties. */
11684 defsubr (&Sx_change_window_property
);
11685 defsubr (&Sx_delete_window_property
);
11686 defsubr (&Sx_window_property
);
11688 defsubr (&Sxw_display_color_p
);
11689 defsubr (&Sx_display_grayscale_p
);
11690 defsubr (&Sxw_color_defined_p
);
11691 defsubr (&Sxw_color_values
);
11692 defsubr (&Sx_server_max_request_size
);
11693 defsubr (&Sx_server_vendor
);
11694 defsubr (&Sx_server_version
);
11695 defsubr (&Sx_display_pixel_width
);
11696 defsubr (&Sx_display_pixel_height
);
11697 defsubr (&Sx_display_mm_width
);
11698 defsubr (&Sx_display_mm_height
);
11699 defsubr (&Sx_display_screens
);
11700 defsubr (&Sx_display_planes
);
11701 defsubr (&Sx_display_color_cells
);
11702 defsubr (&Sx_display_visual_class
);
11703 defsubr (&Sx_display_backing_store
);
11704 defsubr (&Sx_display_save_under
);
11705 defsubr (&Sx_parse_geometry
);
11706 defsubr (&Sx_create_frame
);
11707 defsubr (&Sx_open_connection
);
11708 defsubr (&Sx_close_connection
);
11709 defsubr (&Sx_display_list
);
11710 defsubr (&Sx_synchronize
);
11711 defsubr (&Sx_focus_frame
);
11712 defsubr (&Sx_backspace_delete_keys_p
);
11714 /* Setting callback functions for fontset handler. */
11715 get_font_info_func
= x_get_font_info
;
11717 #if 0 /* This function pointer doesn't seem to be used anywhere.
11718 And the pointer assigned has the wrong type, anyway. */
11719 list_fonts_func
= x_list_fonts
;
11722 load_font_func
= x_load_font
;
11723 find_ccl_program_func
= x_find_ccl_program
;
11724 query_font_func
= x_query_font
;
11725 set_frame_fontset_func
= x_set_font
;
11726 check_window_system_func
= check_x
;
11729 Qxbm
= intern ("xbm");
11731 QCtype
= intern (":type");
11732 staticpro (&QCtype
);
11733 QCconversion
= intern (":conversion");
11734 staticpro (&QCconversion
);
11735 QCheuristic_mask
= intern (":heuristic-mask");
11736 staticpro (&QCheuristic_mask
);
11737 QCcolor_symbols
= intern (":color-symbols");
11738 staticpro (&QCcolor_symbols
);
11739 QCascent
= intern (":ascent");
11740 staticpro (&QCascent
);
11741 QCmargin
= intern (":margin");
11742 staticpro (&QCmargin
);
11743 QCrelief
= intern (":relief");
11744 staticpro (&QCrelief
);
11745 Qpostscript
= intern ("postscript");
11746 staticpro (&Qpostscript
);
11747 QCloader
= intern (":loader");
11748 staticpro (&QCloader
);
11749 QCbounding_box
= intern (":bounding-box");
11750 staticpro (&QCbounding_box
);
11751 QCpt_width
= intern (":pt-width");
11752 staticpro (&QCpt_width
);
11753 QCpt_height
= intern (":pt-height");
11754 staticpro (&QCpt_height
);
11755 QCindex
= intern (":index");
11756 staticpro (&QCindex
);
11757 Qpbm
= intern ("pbm");
11761 Qxpm
= intern ("xpm");
11766 Qjpeg
= intern ("jpeg");
11767 staticpro (&Qjpeg
);
11771 Qtiff
= intern ("tiff");
11772 staticpro (&Qtiff
);
11776 Qgif
= intern ("gif");
11781 Qpng
= intern ("png");
11785 defsubr (&Sclear_image_cache
);
11786 defsubr (&Simage_size
);
11787 defsubr (&Simage_mask_p
);
11789 hourglass_atimer
= NULL
;
11790 hourglass_shown_p
= 0;
11792 defsubr (&Sx_show_tip
);
11793 defsubr (&Sx_hide_tip
);
11795 staticpro (&tip_timer
);
11797 staticpro (&tip_frame
);
11799 last_show_tip_args
= Qnil
;
11800 staticpro (&last_show_tip_args
);
11803 defsubr (&Sx_file_dialog
);
11811 image_types
= NULL
;
11812 Vimage_types
= Qnil
;
11814 define_image_type (&xbm_type
);
11815 define_image_type (&gs_type
);
11816 define_image_type (&pbm_type
);
11819 define_image_type (&xpm_type
);
11823 define_image_type (&jpeg_type
);
11827 define_image_type (&tiff_type
);
11831 define_image_type (&gif_type
);
11835 define_image_type (&png_type
);
11839 #endif /* HAVE_X_WINDOWS */