1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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 */
125 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
127 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
130 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
131 it, and including `bitmaps/gray' more than once is a problem when
132 config.h defines `static' as an empty replacement string. */
134 int gray_bitmap_width
= gray_width
;
135 int gray_bitmap_height
= gray_height
;
136 char *gray_bitmap_bits
= gray_bits
;
138 /* The name we're using in resource queries. Most often "emacs". */
140 Lisp_Object Vx_resource_name
;
142 /* The application class we're using in resource queries.
145 Lisp_Object Vx_resource_class
;
147 /* Non-zero means we're allowed to display an hourglass cursor. */
149 int display_hourglass_p
;
151 /* The background and shape of the mouse pointer, and shape when not
152 over text or in the modeline. */
154 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
155 Lisp_Object Vx_hourglass_pointer_shape
;
157 /* The shape when over mouse-sensitive text. */
159 Lisp_Object Vx_sensitive_text_pointer_shape
;
161 /* If non-nil, the pointer shape to indicate that windows can be
162 dragged horizontally. */
164 Lisp_Object Vx_window_horizontal_drag_shape
;
166 /* Color of chars displayed in cursor box. */
168 Lisp_Object Vx_cursor_fore_pixel
;
170 /* Nonzero if using X. */
174 /* Non nil if no window manager is in use. */
176 Lisp_Object Vx_no_window_manager
;
178 /* Search path for bitmap files. */
180 Lisp_Object Vx_bitmap_file_path
;
182 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
184 Lisp_Object Vx_pixel_size_width_font_regexp
;
186 Lisp_Object Qauto_raise
;
187 Lisp_Object Qauto_lower
;
189 Lisp_Object Qborder_color
;
190 Lisp_Object Qborder_width
;
192 Lisp_Object Qcursor_color
;
193 Lisp_Object Qcursor_type
;
194 Lisp_Object Qgeometry
;
195 Lisp_Object Qicon_left
;
196 Lisp_Object Qicon_top
;
197 Lisp_Object Qicon_type
;
198 Lisp_Object Qicon_name
;
199 Lisp_Object Qinternal_border_width
;
202 Lisp_Object Qmouse_color
;
204 Lisp_Object Qouter_window_id
;
205 Lisp_Object Qparent_id
;
206 Lisp_Object Qscroll_bar_width
;
207 Lisp_Object Qsuppress_icon
;
208 extern Lisp_Object Qtop
;
209 Lisp_Object Qundefined_color
;
210 Lisp_Object Qvertical_scroll_bars
;
211 Lisp_Object Qvisibility
;
212 Lisp_Object Qwindow_id
;
213 Lisp_Object Qx_frame_parameter
;
214 Lisp_Object Qx_resource_name
;
215 Lisp_Object Quser_position
;
216 Lisp_Object Quser_size
;
217 extern Lisp_Object Qdisplay
;
218 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
219 Lisp_Object Qscreen_gamma
, Qline_spacing
, Qcenter
;
220 Lisp_Object Qcompound_text
, Qcancel_timer
;
221 Lisp_Object Qwait_for_wm
;
223 /* The below are defined in frame.c. */
225 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
226 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
227 extern Lisp_Object Qtool_bar_lines
;
229 extern Lisp_Object Vwindow_system_version
;
231 Lisp_Object Qface_set_after_frame_default
;
234 int image_cache_refcount
, dpyinfo_refcount
;
239 /* Error if we are not connected to X. */
245 error ("X windows are not in use or not initialized");
248 /* Nonzero if we can use mouse menus.
249 You should not call this unless HAVE_MENUS is defined. */
257 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
258 and checking validity for X. */
261 check_x_frame (frame
)
267 frame
= selected_frame
;
268 CHECK_LIVE_FRAME (frame
);
271 error ("Non-X frame used");
275 /* Let the user specify an X display with a frame.
276 nil stands for the selected frame--or, if that is not an X frame,
277 the first X display on the list. */
279 static struct x_display_info
*
280 check_x_display_info (frame
)
283 struct x_display_info
*dpyinfo
= NULL
;
287 struct frame
*sf
= XFRAME (selected_frame
);
289 if (FRAME_X_P (sf
) && FRAME_LIVE_P (sf
))
290 dpyinfo
= FRAME_X_DISPLAY_INFO (sf
);
291 else if (x_display_list
!= 0)
292 dpyinfo
= x_display_list
;
294 error ("X windows are not in use or not initialized");
296 else if (STRINGP (frame
))
297 dpyinfo
= x_display_info_for_name (frame
);
302 CHECK_LIVE_FRAME (frame
);
305 error ("Non-X frame used");
306 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
313 /* Return the Emacs frame-object corresponding to an X window.
314 It could be the frame's main window or an icon window. */
316 /* This function can be called during GC, so use GC_xxx type test macros. */
319 x_window_to_frame (dpyinfo
, wdesc
)
320 struct x_display_info
*dpyinfo
;
323 Lisp_Object tail
, frame
;
326 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
329 if (!GC_FRAMEP (frame
))
332 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
334 if (f
->output_data
.x
->hourglass_window
== wdesc
)
337 if ((f
->output_data
.x
->edit_widget
338 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
339 /* A tooltip frame? */
340 || (!f
->output_data
.x
->edit_widget
341 && FRAME_X_WINDOW (f
) == wdesc
)
342 || f
->output_data
.x
->icon_desc
== wdesc
)
344 #else /* not USE_X_TOOLKIT */
345 if (FRAME_X_WINDOW (f
) == wdesc
346 || f
->output_data
.x
->icon_desc
== wdesc
)
348 #endif /* not USE_X_TOOLKIT */
354 /* Like x_window_to_frame but also compares the window with the widget's
358 x_any_window_to_frame (dpyinfo
, wdesc
)
359 struct x_display_info
*dpyinfo
;
362 Lisp_Object tail
, frame
;
363 struct frame
*f
, *found
;
367 for (tail
= Vframe_list
; GC_CONSP (tail
) && !found
; tail
= XCDR (tail
))
370 if (!GC_FRAMEP (frame
))
374 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
376 /* This frame matches if the window is any of its widgets. */
377 x
= f
->output_data
.x
;
378 if (x
->hourglass_window
== wdesc
)
382 if (wdesc
== XtWindow (x
->widget
)
383 || wdesc
== XtWindow (x
->column_widget
)
384 || wdesc
== XtWindow (x
->edit_widget
))
386 /* Match if the window is this frame's menubar. */
387 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
390 else if (FRAME_X_WINDOW (f
) == wdesc
)
391 /* A tooltip frame. */
399 /* Likewise, but exclude the menu bar widget. */
402 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
403 struct x_display_info
*dpyinfo
;
406 Lisp_Object tail
, frame
;
410 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
413 if (!GC_FRAMEP (frame
))
416 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
418 x
= f
->output_data
.x
;
419 /* This frame matches if the window is any of its widgets. */
420 if (x
->hourglass_window
== wdesc
)
424 if (wdesc
== XtWindow (x
->widget
)
425 || wdesc
== XtWindow (x
->column_widget
)
426 || wdesc
== XtWindow (x
->edit_widget
))
429 else if (FRAME_X_WINDOW (f
) == wdesc
)
430 /* A tooltip frame. */
436 /* Likewise, but consider only the menu bar widget. */
439 x_menubar_window_to_frame (dpyinfo
, wdesc
)
440 struct x_display_info
*dpyinfo
;
443 Lisp_Object tail
, frame
;
447 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
450 if (!GC_FRAMEP (frame
))
453 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
455 x
= f
->output_data
.x
;
456 /* Match if the window is this frame's menubar. */
457 if (x
->menubar_widget
458 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
464 /* Return the frame whose principal (outermost) window is WDESC.
465 If WDESC is some other (smaller) window, we return 0. */
468 x_top_window_to_frame (dpyinfo
, wdesc
)
469 struct x_display_info
*dpyinfo
;
472 Lisp_Object tail
, frame
;
476 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
479 if (!GC_FRAMEP (frame
))
482 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
484 x
= f
->output_data
.x
;
488 /* This frame matches if the window is its topmost widget. */
489 if (wdesc
== XtWindow (x
->widget
))
491 #if 0 /* I don't know why it did this,
492 but it seems logically wrong,
493 and it causes trouble for MapNotify events. */
494 /* Match if the window is this frame's menubar. */
495 if (x
->menubar_widget
496 && wdesc
== XtWindow (x
->menubar_widget
))
500 else if (FRAME_X_WINDOW (f
) == wdesc
)
506 #endif /* USE_X_TOOLKIT */
510 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
511 id, which is just an int that this section returns. Bitmaps are
512 reference counted so they can be shared among frames.
514 Bitmap indices are guaranteed to be > 0, so a negative number can
515 be used to indicate no bitmap.
517 If you use x_create_bitmap_from_data, then you must keep track of
518 the bitmaps yourself. That is, creating a bitmap from the same
519 data more than once will not be caught. */
522 /* Functions to access the contents of a bitmap, given an id. */
525 x_bitmap_height (f
, id
)
529 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
533 x_bitmap_width (f
, id
)
537 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
541 x_bitmap_pixmap (f
, id
)
545 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
549 /* Allocate a new bitmap record. Returns index of new record. */
552 x_allocate_bitmap_record (f
)
555 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
558 if (dpyinfo
->bitmaps
== NULL
)
560 dpyinfo
->bitmaps_size
= 10;
562 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
563 dpyinfo
->bitmaps_last
= 1;
567 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
568 return ++dpyinfo
->bitmaps_last
;
570 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
571 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
574 dpyinfo
->bitmaps_size
*= 2;
576 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
577 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
578 return ++dpyinfo
->bitmaps_last
;
581 /* Add one reference to the reference count of the bitmap with id ID. */
584 x_reference_bitmap (f
, id
)
588 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
591 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
594 x_create_bitmap_from_data (f
, bits
, width
, height
)
597 unsigned int width
, height
;
599 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
603 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
604 bits
, width
, height
);
609 id
= x_allocate_bitmap_record (f
);
610 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
611 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
612 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
613 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
614 dpyinfo
->bitmaps
[id
- 1].height
= height
;
615 dpyinfo
->bitmaps
[id
- 1].width
= width
;
620 /* Create bitmap from file FILE for frame F. */
623 x_create_bitmap_from_file (f
, file
)
627 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
628 unsigned int width
, height
;
630 int xhot
, yhot
, result
, id
;
635 /* Look for an existing bitmap with the same name. */
636 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
638 if (dpyinfo
->bitmaps
[id
].refcount
639 && dpyinfo
->bitmaps
[id
].file
640 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
642 ++dpyinfo
->bitmaps
[id
].refcount
;
647 /* Search bitmap-file-path for the file, if appropriate. */
648 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, 0);
653 filename
= (char *) XSTRING (found
)->data
;
655 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
656 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
657 if (result
!= BitmapSuccess
)
660 id
= x_allocate_bitmap_record (f
);
661 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
662 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
663 dpyinfo
->bitmaps
[id
- 1].file
664 = (char *) xmalloc (STRING_BYTES (XSTRING (file
)) + 1);
665 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
666 dpyinfo
->bitmaps
[id
- 1].height
= height
;
667 dpyinfo
->bitmaps
[id
- 1].width
= width
;
668 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
673 /* Remove reference to bitmap with id number ID. */
676 x_destroy_bitmap (f
, id
)
680 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
684 --dpyinfo
->bitmaps
[id
- 1].refcount
;
685 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
688 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
689 if (dpyinfo
->bitmaps
[id
- 1].file
)
691 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
692 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
699 /* Free all the bitmaps for the display specified by DPYINFO. */
702 x_destroy_all_bitmaps (dpyinfo
)
703 struct x_display_info
*dpyinfo
;
706 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
707 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
709 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
710 if (dpyinfo
->bitmaps
[i
].file
)
711 xfree (dpyinfo
->bitmaps
[i
].file
);
713 dpyinfo
->bitmaps_last
= 0;
716 /* Connect the frame-parameter names for X frames
717 to the ways of passing the parameter values to the window system.
719 The name of a parameter, as a Lisp symbol,
720 has an `x-frame-parameter' property which is an integer in Lisp
721 that is an index in this table. */
723 struct x_frame_parm_table
726 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
729 static Lisp_Object unwind_create_frame
P_ ((Lisp_Object
));
730 static Lisp_Object unwind_create_tip_frame
P_ ((Lisp_Object
));
731 static void x_change_window_heights
P_ ((Lisp_Object
, int));
732 static void x_disable_image
P_ ((struct frame
*, struct image
*));
733 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
734 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
735 static void x_set_wait_for_wm
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
736 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
737 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
738 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
739 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
740 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
741 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
742 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
743 static void x_set_fringe_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
744 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
745 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
746 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
748 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
749 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
750 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
751 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
753 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
754 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
755 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
756 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
757 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
758 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
759 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
761 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
763 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
768 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
769 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
771 static void init_color_table
P_ ((void));
772 static void free_color_table
P_ ((void));
773 static unsigned long *colors_in_color_table
P_ ((int *n
));
774 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
775 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
779 static struct x_frame_parm_table x_frame_parms
[] =
781 {"auto-raise", x_set_autoraise
},
782 {"auto-lower", x_set_autolower
},
783 {"background-color", x_set_background_color
},
784 {"border-color", x_set_border_color
},
785 {"border-width", x_set_border_width
},
786 {"cursor-color", x_set_cursor_color
},
787 {"cursor-type", x_set_cursor_type
},
788 {"font", x_set_font
},
789 {"foreground-color", x_set_foreground_color
},
790 {"icon-name", x_set_icon_name
},
791 {"icon-type", x_set_icon_type
},
792 {"internal-border-width", x_set_internal_border_width
},
793 {"menu-bar-lines", x_set_menu_bar_lines
},
794 {"mouse-color", x_set_mouse_color
},
795 {"name", x_explicitly_set_name
},
796 {"scroll-bar-width", x_set_scroll_bar_width
},
797 {"title", x_set_title
},
798 {"unsplittable", x_set_unsplittable
},
799 {"vertical-scroll-bars", x_set_vertical_scroll_bars
},
800 {"visibility", x_set_visibility
},
801 {"tool-bar-lines", x_set_tool_bar_lines
},
802 {"scroll-bar-foreground", x_set_scroll_bar_foreground
},
803 {"scroll-bar-background", x_set_scroll_bar_background
},
804 {"screen-gamma", x_set_screen_gamma
},
805 {"line-spacing", x_set_line_spacing
},
806 {"left-fringe", x_set_fringe_width
},
807 {"right-fringe", x_set_fringe_width
},
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 /* Process default font as well, since fringe widths depends on it. */
903 for (p
= 0; p
< i
; p
++)
905 Lisp_Object prop
, val
;
909 if (EQ (prop
, Qforeground_color
)
910 || EQ (prop
, Qbackground_color
)
913 register Lisp_Object param_index
, old_value
;
915 old_value
= get_frame_param (f
, prop
);
917 if (NILP (Fequal (val
, old_value
)))
919 store_frame_param (f
, prop
, val
);
921 param_index
= Fget (prop
, Qx_frame_parameter
);
922 if (NATNUMP (param_index
)
923 && (XFASTINT (param_index
)
924 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
925 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
930 /* Now process them in reverse of specified order. */
931 for (i
--; i
>= 0; i
--)
933 Lisp_Object prop
, val
;
938 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
939 width
= XFASTINT (val
);
940 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
941 height
= XFASTINT (val
);
942 else if (EQ (prop
, Qtop
))
944 else if (EQ (prop
, Qleft
))
946 else if (EQ (prop
, Qicon_top
))
948 else if (EQ (prop
, Qicon_left
))
950 else if (EQ (prop
, Qforeground_color
)
951 || EQ (prop
, Qbackground_color
)
953 /* Processed above. */
957 register Lisp_Object param_index
, old_value
;
959 old_value
= get_frame_param (f
, prop
);
961 store_frame_param (f
, prop
, val
);
963 param_index
= Fget (prop
, Qx_frame_parameter
);
964 if (NATNUMP (param_index
)
965 && (XFASTINT (param_index
)
966 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
967 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
971 /* Don't die if just one of these was set. */
972 if (EQ (left
, Qunbound
))
975 if (f
->output_data
.x
->left_pos
< 0)
976 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
978 XSETINT (left
, f
->output_data
.x
->left_pos
);
980 if (EQ (top
, Qunbound
))
983 if (f
->output_data
.x
->top_pos
< 0)
984 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
986 XSETINT (top
, f
->output_data
.x
->top_pos
);
989 /* If one of the icon positions was not set, preserve or default it. */
990 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
992 icon_left_no_change
= 1;
993 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
994 if (NILP (icon_left
))
995 XSETINT (icon_left
, 0);
997 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
999 icon_top_no_change
= 1;
1000 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
1001 if (NILP (icon_top
))
1002 XSETINT (icon_top
, 0);
1005 /* Don't set these parameters unless they've been explicitly
1006 specified. The window might be mapped or resized while we're in
1007 this function, and we don't want to override that unless the lisp
1008 code has asked for it.
1010 Don't set these parameters unless they actually differ from the
1011 window's current parameters; the window may not actually exist
1016 check_frame_size (f
, &height
, &width
);
1018 XSETFRAME (frame
, f
);
1020 if (width
!= FRAME_WIDTH (f
)
1021 || height
!= FRAME_HEIGHT (f
)
1022 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
1023 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1025 if ((!NILP (left
) || !NILP (top
))
1026 && ! (left_no_change
&& top_no_change
)
1027 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1028 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1033 /* Record the signs. */
1034 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1035 if (EQ (left
, Qminus
))
1036 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1037 else if (INTEGERP (left
))
1039 leftpos
= XINT (left
);
1041 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1043 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1044 && CONSP (XCDR (left
))
1045 && INTEGERP (XCAR (XCDR (left
))))
1047 leftpos
= - XINT (XCAR (XCDR (left
)));
1048 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1050 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1051 && CONSP (XCDR (left
))
1052 && INTEGERP (XCAR (XCDR (left
))))
1054 leftpos
= XINT (XCAR (XCDR (left
)));
1057 if (EQ (top
, Qminus
))
1058 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1059 else if (INTEGERP (top
))
1061 toppos
= XINT (top
);
1063 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1065 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1066 && CONSP (XCDR (top
))
1067 && INTEGERP (XCAR (XCDR (top
))))
1069 toppos
= - XINT (XCAR (XCDR (top
)));
1070 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1072 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1073 && CONSP (XCDR (top
))
1074 && INTEGERP (XCAR (XCDR (top
))))
1076 toppos
= XINT (XCAR (XCDR (top
)));
1080 /* Store the numeric value of the position. */
1081 f
->output_data
.x
->top_pos
= toppos
;
1082 f
->output_data
.x
->left_pos
= leftpos
;
1084 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1086 /* Actually set that position, and convert to absolute. */
1087 x_set_offset (f
, leftpos
, toppos
, -1);
1090 if ((!NILP (icon_left
) || !NILP (icon_top
))
1091 && ! (icon_left_no_change
&& icon_top_no_change
))
1092 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1098 /* Store the screen positions of frame F into XPTR and YPTR.
1099 These are the positions of the containing window manager window,
1100 not Emacs's own window. */
1103 x_real_positions (f
, xptr
, yptr
)
1110 /* This is pretty gross, but seems to be the easiest way out of
1111 the problem that arises when restarting window-managers. */
1113 #ifdef USE_X_TOOLKIT
1114 Window outer
= (f
->output_data
.x
->widget
1115 ? XtWindow (f
->output_data
.x
->widget
)
1116 : FRAME_X_WINDOW (f
));
1118 Window outer
= f
->output_data
.x
->window_desc
;
1120 Window tmp_root_window
;
1121 Window
*tmp_children
;
1122 unsigned int tmp_nchildren
;
1126 int count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1127 Window outer_window
;
1129 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
1130 &f
->output_data
.x
->parent_desc
,
1131 &tmp_children
, &tmp_nchildren
);
1132 XFree ((char *) tmp_children
);
1136 /* Find the position of the outside upper-left corner of
1137 the inner window, with respect to the outer window. */
1138 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
1139 outer_window
= f
->output_data
.x
->parent_desc
;
1141 outer_window
= outer
;
1143 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1145 /* From-window, to-window. */
1147 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1149 /* From-position, to-position. */
1150 0, 0, &win_x
, &win_y
,
1155 /* It is possible for the window returned by the XQueryNotify
1156 to become invalid by the time we call XTranslateCoordinates.
1157 That can happen when you restart some window managers.
1158 If so, we get an error in XTranslateCoordinates.
1159 Detect that and try the whole thing over. */
1160 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1162 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1166 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1173 /* Insert a description of internally-recorded parameters of frame X
1174 into the parameter alist *ALISTPTR that is to be given to the user.
1175 Only parameters that are specific to the X window system
1176 and whose values are not correctly recorded in the frame's
1177 param_alist need to be considered here. */
1180 x_report_frame_params (f
, alistptr
)
1182 Lisp_Object
*alistptr
;
1187 /* Represent negative positions (off the top or left screen edge)
1188 in a way that Fmodify_frame_parameters will understand correctly. */
1189 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1190 if (f
->output_data
.x
->left_pos
>= 0)
1191 store_in_alist (alistptr
, Qleft
, tem
);
1193 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1195 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1196 if (f
->output_data
.x
->top_pos
>= 0)
1197 store_in_alist (alistptr
, Qtop
, tem
);
1199 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1201 store_in_alist (alistptr
, Qborder_width
,
1202 make_number (f
->output_data
.x
->border_width
));
1203 store_in_alist (alistptr
, Qinternal_border_width
,
1204 make_number (f
->output_data
.x
->internal_border_width
));
1205 store_in_alist (alistptr
, Qleft_fringe
,
1206 make_number (f
->output_data
.x
->left_fringe_width
));
1207 store_in_alist (alistptr
, Qright_fringe
,
1208 make_number (f
->output_data
.x
->right_fringe_width
));
1209 store_in_alist (alistptr
, Qscroll_bar_width
,
1210 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
1211 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f
)
1213 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1214 store_in_alist (alistptr
, Qwindow_id
,
1215 build_string (buf
));
1216 #ifdef USE_X_TOOLKIT
1217 /* Tooltip frame may not have this widget. */
1218 if (f
->output_data
.x
->widget
)
1220 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1221 store_in_alist (alistptr
, Qouter_window_id
,
1222 build_string (buf
));
1223 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1224 FRAME_SAMPLE_VISIBILITY (f
);
1225 store_in_alist (alistptr
, Qvisibility
,
1226 (FRAME_VISIBLE_P (f
) ? Qt
1227 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1228 store_in_alist (alistptr
, Qdisplay
,
1229 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1231 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1234 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1235 store_in_alist (alistptr
, Qparent_id
, tem
);
1240 /* Gamma-correct COLOR on frame F. */
1243 gamma_correct (f
, color
)
1249 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1250 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1251 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1256 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1257 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1258 allocate the color. Value is zero if COLOR_NAME is invalid, or
1259 no color could be allocated. */
1262 x_defined_color (f
, color_name
, color
, alloc_p
)
1269 Display
*dpy
= FRAME_X_DISPLAY (f
);
1270 Colormap cmap
= FRAME_X_COLORMAP (f
);
1273 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1274 if (success_p
&& alloc_p
)
1275 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1282 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1283 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1284 Signal an error if color can't be allocated. */
1287 x_decode_color (f
, color_name
, mono_color
)
1289 Lisp_Object color_name
;
1294 CHECK_STRING (color_name
);
1296 #if 0 /* Don't do this. It's wrong when we're not using the default
1297 colormap, it makes freeing difficult, and it's probably not
1298 an important optimization. */
1299 if (strcmp (XSTRING (color_name
)->data
, "black") == 0)
1300 return BLACK_PIX_DEFAULT (f
);
1301 else if (strcmp (XSTRING (color_name
)->data
, "white") == 0)
1302 return WHITE_PIX_DEFAULT (f
);
1305 /* Return MONO_COLOR for monochrome frames. */
1306 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1309 /* x_defined_color is responsible for coping with failures
1310 by looking for a near-miss. */
1311 if (x_defined_color (f
, XSTRING (color_name
)->data
, &cdef
, 1))
1314 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1315 Fcons (color_name
, Qnil
)));
1321 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1322 the previous value of that parameter, NEW_VALUE is the new value. */
1325 x_set_line_spacing (f
, new_value
, old_value
)
1327 Lisp_Object new_value
, old_value
;
1329 if (NILP (new_value
))
1330 f
->extra_line_spacing
= 0;
1331 else if (NATNUMP (new_value
))
1332 f
->extra_line_spacing
= XFASTINT (new_value
);
1334 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1335 Fcons (new_value
, Qnil
)));
1336 if (FRAME_VISIBLE_P (f
))
1341 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1342 the previous value of that parameter, NEW_VALUE is the new value.
1343 See also the comment of wait_for_wm in struct x_output. */
1346 x_set_wait_for_wm (f
, new_value
, old_value
)
1348 Lisp_Object new_value
, old_value
;
1350 f
->output_data
.x
->wait_for_wm
= !NILP (new_value
);
1354 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1355 the previous value of that parameter, NEW_VALUE is the new
1359 x_set_screen_gamma (f
, new_value
, old_value
)
1361 Lisp_Object new_value
, old_value
;
1363 if (NILP (new_value
))
1365 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1366 /* The value 0.4545 is the normal viewing gamma. */
1367 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1369 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1370 Fcons (new_value
, Qnil
)));
1372 clear_face_cache (0);
1376 /* Functions called only from `x_set_frame_param'
1377 to set individual parameters.
1379 If FRAME_X_WINDOW (f) is 0,
1380 the frame is being created and its X-window does not exist yet.
1381 In that case, just record the parameter's new value
1382 in the standard place; do not attempt to change the window. */
1385 x_set_foreground_color (f
, arg
, oldval
)
1387 Lisp_Object arg
, oldval
;
1389 struct x_output
*x
= f
->output_data
.x
;
1390 unsigned long fg
, old_fg
;
1392 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1393 old_fg
= x
->foreground_pixel
;
1394 x
->foreground_pixel
= fg
;
1396 if (FRAME_X_WINDOW (f
) != 0)
1398 Display
*dpy
= FRAME_X_DISPLAY (f
);
1401 XSetForeground (dpy
, x
->normal_gc
, fg
);
1402 XSetBackground (dpy
, x
->reverse_gc
, fg
);
1404 if (x
->cursor_pixel
== old_fg
)
1406 unload_color (f
, x
->cursor_pixel
);
1407 x
->cursor_pixel
= x_copy_color (f
, fg
);
1408 XSetBackground (dpy
, x
->cursor_gc
, x
->cursor_pixel
);
1413 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1415 if (FRAME_VISIBLE_P (f
))
1419 unload_color (f
, old_fg
);
1423 x_set_background_color (f
, arg
, oldval
)
1425 Lisp_Object arg
, oldval
;
1427 struct x_output
*x
= f
->output_data
.x
;
1430 bg
= x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1431 unload_color (f
, x
->background_pixel
);
1432 x
->background_pixel
= bg
;
1434 if (FRAME_X_WINDOW (f
) != 0)
1436 Display
*dpy
= FRAME_X_DISPLAY (f
);
1439 XSetBackground (dpy
, x
->normal_gc
, bg
);
1440 XSetForeground (dpy
, x
->reverse_gc
, bg
);
1441 XSetWindowBackground (dpy
, FRAME_X_WINDOW (f
), bg
);
1442 XSetForeground (dpy
, x
->cursor_gc
, bg
);
1444 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1445 toolkit scroll bars. */
1448 for (bar
= FRAME_SCROLL_BARS (f
);
1450 bar
= XSCROLL_BAR (bar
)->next
)
1452 Window window
= SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
));
1453 XSetWindowBackground (dpy
, window
, bg
);
1456 #endif /* USE_TOOLKIT_SCROLL_BARS */
1459 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1461 if (FRAME_VISIBLE_P (f
))
1467 x_set_mouse_color (f
, arg
, oldval
)
1469 Lisp_Object arg
, oldval
;
1471 struct x_output
*x
= f
->output_data
.x
;
1472 Display
*dpy
= FRAME_X_DISPLAY (f
);
1473 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1474 Cursor hourglass_cursor
, horizontal_drag_cursor
;
1476 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1477 unsigned long mask_color
= x
->background_pixel
;
1479 /* Don't let pointers be invisible. */
1480 if (mask_color
== pixel
)
1482 x_free_colors (f
, &pixel
, 1);
1483 pixel
= x_copy_color (f
, x
->foreground_pixel
);
1486 unload_color (f
, x
->mouse_pixel
);
1487 x
->mouse_pixel
= pixel
;
1491 /* It's not okay to crash if the user selects a screwy cursor. */
1492 count
= x_catch_errors (dpy
);
1494 if (!NILP (Vx_pointer_shape
))
1496 CHECK_NUMBER (Vx_pointer_shape
);
1497 cursor
= XCreateFontCursor (dpy
, XINT (Vx_pointer_shape
));
1500 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1501 x_check_errors (dpy
, "bad text pointer cursor: %s");
1503 if (!NILP (Vx_nontext_pointer_shape
))
1505 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1507 = XCreateFontCursor (dpy
, XINT (Vx_nontext_pointer_shape
));
1510 nontext_cursor
= XCreateFontCursor (dpy
, XC_left_ptr
);
1511 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1513 if (!NILP (Vx_hourglass_pointer_shape
))
1515 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1517 = XCreateFontCursor (dpy
, XINT (Vx_hourglass_pointer_shape
));
1520 hourglass_cursor
= XCreateFontCursor (dpy
, XC_watch
);
1521 x_check_errors (dpy
, "bad hourglass pointer cursor: %s");
1523 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1524 if (!NILP (Vx_mode_pointer_shape
))
1526 CHECK_NUMBER (Vx_mode_pointer_shape
);
1527 mode_cursor
= XCreateFontCursor (dpy
, XINT (Vx_mode_pointer_shape
));
1530 mode_cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1531 x_check_errors (dpy
, "bad modeline pointer cursor: %s");
1533 if (!NILP (Vx_sensitive_text_pointer_shape
))
1535 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1537 = XCreateFontCursor (dpy
, XINT (Vx_sensitive_text_pointer_shape
));
1540 cross_cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
1542 if (!NILP (Vx_window_horizontal_drag_shape
))
1544 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1545 horizontal_drag_cursor
1546 = XCreateFontCursor (dpy
, XINT (Vx_window_horizontal_drag_shape
));
1549 horizontal_drag_cursor
1550 = XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
1552 /* Check and report errors with the above calls. */
1553 x_check_errors (dpy
, "can't set cursor shape: %s");
1554 x_uncatch_errors (dpy
, count
);
1557 XColor fore_color
, back_color
;
1559 fore_color
.pixel
= x
->mouse_pixel
;
1560 x_query_color (f
, &fore_color
);
1561 back_color
.pixel
= mask_color
;
1562 x_query_color (f
, &back_color
);
1564 XRecolorCursor (dpy
, cursor
, &fore_color
, &back_color
);
1565 XRecolorCursor (dpy
, nontext_cursor
, &fore_color
, &back_color
);
1566 XRecolorCursor (dpy
, mode_cursor
, &fore_color
, &back_color
);
1567 XRecolorCursor (dpy
, cross_cursor
, &fore_color
, &back_color
);
1568 XRecolorCursor (dpy
, hourglass_cursor
, &fore_color
, &back_color
);
1569 XRecolorCursor (dpy
, horizontal_drag_cursor
, &fore_color
, &back_color
);
1572 if (FRAME_X_WINDOW (f
) != 0)
1573 XDefineCursor (dpy
, FRAME_X_WINDOW (f
), cursor
);
1575 if (cursor
!= x
->text_cursor
1576 && x
->text_cursor
!= 0)
1577 XFreeCursor (dpy
, x
->text_cursor
);
1578 x
->text_cursor
= cursor
;
1580 if (nontext_cursor
!= x
->nontext_cursor
1581 && x
->nontext_cursor
!= 0)
1582 XFreeCursor (dpy
, x
->nontext_cursor
);
1583 x
->nontext_cursor
= nontext_cursor
;
1585 if (hourglass_cursor
!= x
->hourglass_cursor
1586 && x
->hourglass_cursor
!= 0)
1587 XFreeCursor (dpy
, x
->hourglass_cursor
);
1588 x
->hourglass_cursor
= hourglass_cursor
;
1590 if (mode_cursor
!= x
->modeline_cursor
1591 && x
->modeline_cursor
!= 0)
1592 XFreeCursor (dpy
, f
->output_data
.x
->modeline_cursor
);
1593 x
->modeline_cursor
= mode_cursor
;
1595 if (cross_cursor
!= x
->cross_cursor
1596 && x
->cross_cursor
!= 0)
1597 XFreeCursor (dpy
, x
->cross_cursor
);
1598 x
->cross_cursor
= cross_cursor
;
1600 if (horizontal_drag_cursor
!= x
->horizontal_drag_cursor
1601 && x
->horizontal_drag_cursor
!= 0)
1602 XFreeCursor (dpy
, x
->horizontal_drag_cursor
);
1603 x
->horizontal_drag_cursor
= horizontal_drag_cursor
;
1608 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1612 x_set_cursor_color (f
, arg
, oldval
)
1614 Lisp_Object arg
, oldval
;
1616 unsigned long fore_pixel
, pixel
;
1617 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1618 struct x_output
*x
= f
->output_data
.x
;
1620 if (!NILP (Vx_cursor_fore_pixel
))
1622 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1623 WHITE_PIX_DEFAULT (f
));
1624 fore_pixel_allocated_p
= 1;
1627 fore_pixel
= x
->background_pixel
;
1629 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1630 pixel_allocated_p
= 1;
1632 /* Make sure that the cursor color differs from the background color. */
1633 if (pixel
== x
->background_pixel
)
1635 if (pixel_allocated_p
)
1637 x_free_colors (f
, &pixel
, 1);
1638 pixel_allocated_p
= 0;
1641 pixel
= x
->mouse_pixel
;
1642 if (pixel
== fore_pixel
)
1644 if (fore_pixel_allocated_p
)
1646 x_free_colors (f
, &fore_pixel
, 1);
1647 fore_pixel_allocated_p
= 0;
1649 fore_pixel
= x
->background_pixel
;
1653 unload_color (f
, x
->cursor_foreground_pixel
);
1654 if (!fore_pixel_allocated_p
)
1655 fore_pixel
= x_copy_color (f
, fore_pixel
);
1656 x
->cursor_foreground_pixel
= fore_pixel
;
1658 unload_color (f
, x
->cursor_pixel
);
1659 if (!pixel_allocated_p
)
1660 pixel
= x_copy_color (f
, pixel
);
1661 x
->cursor_pixel
= pixel
;
1663 if (FRAME_X_WINDOW (f
) != 0)
1666 XSetBackground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, x
->cursor_pixel
);
1667 XSetForeground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, fore_pixel
);
1670 if (FRAME_VISIBLE_P (f
))
1672 x_update_cursor (f
, 0);
1673 x_update_cursor (f
, 1);
1677 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1680 /* Set the border-color of frame F to value described by ARG.
1681 ARG can be a string naming a color.
1682 The border-color is used for the border that is drawn by the X server.
1683 Note that this does not fully take effect if done before
1684 F has an x-window; it must be redone when the window is created.
1686 Note: this is done in two routines because of the way X10 works.
1688 Note: under X11, this is normally the province of the window manager,
1689 and so emacs' border colors may be overridden. */
1692 x_set_border_color (f
, arg
, oldval
)
1694 Lisp_Object arg
, oldval
;
1699 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1700 x_set_border_pixel (f
, pix
);
1701 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1704 /* Set the border-color of frame F to pixel value PIX.
1705 Note that this does not fully take effect if done before
1706 F has an x-window. */
1709 x_set_border_pixel (f
, pix
)
1713 unload_color (f
, f
->output_data
.x
->border_pixel
);
1714 f
->output_data
.x
->border_pixel
= pix
;
1716 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1719 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1720 (unsigned long)pix
);
1723 if (FRAME_VISIBLE_P (f
))
1729 /* Value is the internal representation of the specified cursor type
1730 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1731 of the bar cursor. */
1733 enum text_cursor_kinds
1734 x_specified_cursor_type (arg
, width
)
1738 enum text_cursor_kinds type
;
1745 else if (CONSP (arg
)
1746 && EQ (XCAR (arg
), Qbar
)
1747 && INTEGERP (XCDR (arg
))
1748 && XINT (XCDR (arg
)) >= 0)
1751 *width
= XINT (XCDR (arg
));
1753 else if (NILP (arg
))
1756 /* Treat anything unknown as "box cursor".
1757 It was bad to signal an error; people have trouble fixing
1758 .Xdefaults with Emacs, when it has something bad in it. */
1759 type
= FILLED_BOX_CURSOR
;
1765 x_set_cursor_type (f
, arg
, oldval
)
1767 Lisp_Object arg
, oldval
;
1771 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1772 f
->output_data
.x
->cursor_width
= width
;
1774 /* Make sure the cursor gets redrawn. This is overkill, but how
1775 often do people change cursor types? */
1776 update_mode_lines
++;
1780 x_set_icon_type (f
, arg
, oldval
)
1782 Lisp_Object arg
, oldval
;
1788 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1791 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1796 result
= x_text_icon (f
,
1797 (char *) XSTRING ((!NILP (f
->icon_name
)
1801 result
= x_bitmap_icon (f
, arg
);
1806 error ("No icon window available");
1809 XFlush (FRAME_X_DISPLAY (f
));
1813 /* Return non-nil if frame F wants a bitmap icon. */
1821 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1829 x_set_icon_name (f
, arg
, oldval
)
1831 Lisp_Object arg
, oldval
;
1837 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1840 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1845 if (f
->output_data
.x
->icon_bitmap
!= 0)
1850 result
= x_text_icon (f
,
1851 (char *) XSTRING ((!NILP (f
->icon_name
)
1860 error ("No icon window available");
1863 XFlush (FRAME_X_DISPLAY (f
));
1868 x_set_font (f
, arg
, oldval
)
1870 Lisp_Object arg
, oldval
;
1873 Lisp_Object fontset_name
;
1875 int old_fontset
= f
->output_data
.x
->fontset
;
1879 fontset_name
= Fquery_fontset (arg
, Qnil
);
1882 result
= (STRINGP (fontset_name
)
1883 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1884 : x_new_font (f
, XSTRING (arg
)->data
));
1887 if (EQ (result
, Qnil
))
1888 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1889 else if (EQ (result
, Qt
))
1890 error ("The characters of the given font have varying widths");
1891 else if (STRINGP (result
))
1893 if (STRINGP (fontset_name
))
1895 /* Fontset names are built from ASCII font names, so the
1896 names may be equal despite there was a change. */
1897 if (old_fontset
== f
->output_data
.x
->fontset
)
1900 else if (!NILP (Fequal (result
, oldval
)))
1903 store_frame_param (f
, Qfont
, result
);
1904 recompute_basic_faces (f
);
1909 do_pending_window_change (0);
1911 /* Don't call `face-set-after-frame-default' when faces haven't been
1912 initialized yet. This is the case when called from
1913 Fx_create_frame. In that case, the X widget or window doesn't
1914 exist either, and we can end up in x_report_frame_params with a
1915 null widget which gives a segfault. */
1916 if (FRAME_FACE_CACHE (f
))
1918 XSETFRAME (frame
, f
);
1919 call1 (Qface_set_after_frame_default
, frame
);
1924 x_set_fringe_width (f
, new_value
, old_value
)
1926 Lisp_Object new_value
, old_value
;
1928 x_compute_fringe_widths (f
, 1);
1932 x_set_border_width (f
, arg
, oldval
)
1934 Lisp_Object arg
, oldval
;
1938 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1941 if (FRAME_X_WINDOW (f
) != 0)
1942 error ("Cannot change the border width of a window");
1944 f
->output_data
.x
->border_width
= XINT (arg
);
1948 x_set_internal_border_width (f
, arg
, oldval
)
1950 Lisp_Object arg
, oldval
;
1952 int old
= f
->output_data
.x
->internal_border_width
;
1955 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1956 if (f
->output_data
.x
->internal_border_width
< 0)
1957 f
->output_data
.x
->internal_border_width
= 0;
1959 #ifdef USE_X_TOOLKIT
1960 if (f
->output_data
.x
->edit_widget
)
1961 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1964 if (f
->output_data
.x
->internal_border_width
== old
)
1967 if (FRAME_X_WINDOW (f
) != 0)
1969 x_set_window_size (f
, 0, f
->width
, f
->height
);
1970 SET_FRAME_GARBAGED (f
);
1971 do_pending_window_change (0);
1974 SET_FRAME_GARBAGED (f
);
1978 x_set_visibility (f
, value
, oldval
)
1980 Lisp_Object value
, oldval
;
1983 XSETFRAME (frame
, f
);
1986 Fmake_frame_invisible (frame
, Qt
);
1987 else if (EQ (value
, Qicon
))
1988 Ficonify_frame (frame
);
1990 Fmake_frame_visible (frame
);
1994 /* Change window heights in windows rooted in WINDOW by N lines. */
1997 x_change_window_heights (window
, n
)
2001 struct window
*w
= XWINDOW (window
);
2003 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
2004 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
2006 if (INTEGERP (w
->orig_top
))
2007 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
2008 if (INTEGERP (w
->orig_height
))
2009 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
2011 /* Handle just the top child in a vertical split. */
2012 if (!NILP (w
->vchild
))
2013 x_change_window_heights (w
->vchild
, n
);
2015 /* Adjust all children in a horizontal split. */
2016 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
2018 w
= XWINDOW (window
);
2019 x_change_window_heights (window
, n
);
2024 x_set_menu_bar_lines (f
, value
, oldval
)
2026 Lisp_Object value
, oldval
;
2029 #ifndef USE_X_TOOLKIT
2030 int olines
= FRAME_MENU_BAR_LINES (f
);
2033 /* Right now, menu bars don't work properly in minibuf-only frames;
2034 most of the commands try to apply themselves to the minibuffer
2035 frame itself, and get an error because you can't switch buffers
2036 in or split the minibuffer window. */
2037 if (FRAME_MINIBUF_ONLY_P (f
))
2040 if (INTEGERP (value
))
2041 nlines
= XINT (value
);
2045 /* Make sure we redisplay all windows in this frame. */
2046 windows_or_buffers_changed
++;
2048 #ifdef USE_X_TOOLKIT
2049 FRAME_MENU_BAR_LINES (f
) = 0;
2052 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2053 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2054 /* Make sure next redisplay shows the menu bar. */
2055 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2059 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2060 free_frame_menubar (f
);
2061 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2063 f
->output_data
.x
->menubar_widget
= 0;
2065 #else /* not USE_X_TOOLKIT */
2066 FRAME_MENU_BAR_LINES (f
) = nlines
;
2067 x_change_window_heights (f
->root_window
, nlines
- olines
);
2068 #endif /* not USE_X_TOOLKIT */
2073 /* Set the number of lines used for the tool bar of frame F to VALUE.
2074 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2075 is the old number of tool bar lines. This function changes the
2076 height of all windows on frame F to match the new tool bar height.
2077 The frame's height doesn't change. */
2080 x_set_tool_bar_lines (f
, value
, oldval
)
2082 Lisp_Object value
, oldval
;
2084 int delta
, nlines
, root_height
;
2085 Lisp_Object root_window
;
2087 /* Treat tool bars like menu bars. */
2088 if (FRAME_MINIBUF_ONLY_P (f
))
2091 /* Use VALUE only if an integer >= 0. */
2092 if (INTEGERP (value
) && XINT (value
) >= 0)
2093 nlines
= XFASTINT (value
);
2097 /* Make sure we redisplay all windows in this frame. */
2098 ++windows_or_buffers_changed
;
2100 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2102 /* Don't resize the tool-bar to more than we have room for. */
2103 root_window
= FRAME_ROOT_WINDOW (f
);
2104 root_height
= XINT (XWINDOW (root_window
)->height
);
2105 if (root_height
- delta
< 1)
2107 delta
= root_height
- 1;
2108 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2111 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2112 x_change_window_heights (root_window
, delta
);
2115 /* We also have to make sure that the internal border at the top of
2116 the frame, below the menu bar or tool bar, is redrawn when the
2117 tool bar disappears. This is so because the internal border is
2118 below the tool bar if one is displayed, but is below the menu bar
2119 if there isn't a tool bar. The tool bar draws into the area
2120 below the menu bar. */
2121 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2125 clear_current_matrices (f
);
2126 updating_frame
= NULL
;
2129 /* If the tool bar gets smaller, the internal border below it
2130 has to be cleared. It was formerly part of the display
2131 of the larger tool bar, and updating windows won't clear it. */
2134 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2135 int width
= PIXEL_WIDTH (f
);
2136 int y
= nlines
* CANON_Y_UNIT (f
);
2139 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2140 0, y
, width
, height
, False
);
2143 if (WINDOWP (f
->tool_bar_window
))
2144 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2149 /* Set the foreground color for scroll bars on frame F to VALUE.
2150 VALUE should be a string, a color name. If it isn't a string or
2151 isn't a valid color name, do nothing. OLDVAL is the old value of
2152 the frame parameter. */
2155 x_set_scroll_bar_foreground (f
, value
, oldval
)
2157 Lisp_Object value
, oldval
;
2159 unsigned long pixel
;
2161 if (STRINGP (value
))
2162 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2166 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2167 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2169 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2170 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2172 /* Remove all scroll bars because they have wrong colors. */
2173 if (condemn_scroll_bars_hook
)
2174 (*condemn_scroll_bars_hook
) (f
);
2175 if (judge_scroll_bars_hook
)
2176 (*judge_scroll_bars_hook
) (f
);
2178 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2184 /* Set the background color for scroll bars on frame F to VALUE VALUE
2185 should be a string, a color name. If it isn't a string or isn't a
2186 valid color name, do nothing. OLDVAL is the old value of the frame
2190 x_set_scroll_bar_background (f
, value
, oldval
)
2192 Lisp_Object value
, oldval
;
2194 unsigned long pixel
;
2196 if (STRINGP (value
))
2197 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2201 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2202 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2204 #ifdef USE_TOOLKIT_SCROLL_BARS
2205 /* Scrollbar shadow colors. */
2206 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
2208 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
2209 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
2211 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
2213 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
2214 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
2216 #endif /* USE_TOOLKIT_SCROLL_BARS */
2218 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2219 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2221 /* Remove all scroll bars because they have wrong colors. */
2222 if (condemn_scroll_bars_hook
)
2223 (*condemn_scroll_bars_hook
) (f
);
2224 if (judge_scroll_bars_hook
)
2225 (*judge_scroll_bars_hook
) (f
);
2227 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2233 /* Encode Lisp string STRING as a text in a format appropriate for
2234 XICCC (X Inter Client Communication Conventions).
2236 If STRING contains only ASCII characters, do no conversion and
2237 return the string data of STRING. Otherwise, encode the text by
2238 CODING_SYSTEM, and return a newly allocated memory area which
2239 should be freed by `xfree' by a caller.
2241 Store the byte length of resulting text in *TEXT_BYTES.
2243 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2244 which means that the `encoding' of the result can be `STRING'.
2245 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2246 the result should be `COMPOUND_TEXT'. */
2249 x_encode_text (string
, coding_system
, text_bytes
, stringp
)
2250 Lisp_Object string
, coding_system
;
2251 int *text_bytes
, *stringp
;
2253 unsigned char *str
= XSTRING (string
)->data
;
2254 int chars
= XSTRING (string
)->size
;
2255 int bytes
= STRING_BYTES (XSTRING (string
));
2259 struct coding_system coding
;
2261 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2262 if (charset_info
== 0)
2264 /* No multibyte character in OBJ. We need not encode it. */
2265 *text_bytes
= bytes
;
2270 setup_coding_system (coding_system
, &coding
);
2271 coding
.src_multibyte
= 1;
2272 coding
.dst_multibyte
= 0;
2273 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2274 if (coding
.type
== coding_type_iso2022
)
2275 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2276 /* We suppress producing escape sequences for composition. */
2277 coding
.composing
= COMPOSITION_DISABLED
;
2278 bufsize
= encoding_buffer_size (&coding
, bytes
);
2279 buf
= (unsigned char *) xmalloc (bufsize
);
2280 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2281 *text_bytes
= coding
.produced
;
2282 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2287 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2290 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2291 name; if NAME is a string, set F's name to NAME and set
2292 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2294 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2295 suggesting a new name, which lisp code should override; if
2296 F->explicit_name is set, ignore the new name; otherwise, set it. */
2299 x_set_name (f
, name
, explicit)
2304 /* Make sure that requests from lisp code override requests from
2305 Emacs redisplay code. */
2308 /* If we're switching from explicit to implicit, we had better
2309 update the mode lines and thereby update the title. */
2310 if (f
->explicit_name
&& NILP (name
))
2311 update_mode_lines
= 1;
2313 f
->explicit_name
= ! NILP (name
);
2315 else if (f
->explicit_name
)
2318 /* If NAME is nil, set the name to the x_id_name. */
2321 /* Check for no change needed in this very common case
2322 before we do any consing. */
2323 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2324 XSTRING (f
->name
)->data
))
2326 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2329 CHECK_STRING (name
);
2331 /* Don't change the name if it's already NAME. */
2332 if (! NILP (Fstring_equal (name
, f
->name
)))
2337 /* For setting the frame title, the title parameter should override
2338 the name parameter. */
2339 if (! NILP (f
->title
))
2342 if (FRAME_X_WINDOW (f
))
2347 XTextProperty text
, icon
;
2349 Lisp_Object coding_system
;
2351 coding_system
= Vlocale_coding_system
;
2352 if (NILP (coding_system
))
2353 coding_system
= Qcompound_text
;
2354 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2355 text
.encoding
= (stringp
? XA_STRING
2356 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2358 text
.nitems
= bytes
;
2360 if (NILP (f
->icon_name
))
2366 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2368 icon
.encoding
= (stringp
? XA_STRING
2369 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2371 icon
.nitems
= bytes
;
2373 #ifdef USE_X_TOOLKIT
2374 XSetWMName (FRAME_X_DISPLAY (f
),
2375 XtWindow (f
->output_data
.x
->widget
), &text
);
2376 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2378 #else /* not USE_X_TOOLKIT */
2379 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2380 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2381 #endif /* not USE_X_TOOLKIT */
2382 if (!NILP (f
->icon_name
)
2383 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2385 if (text
.value
!= XSTRING (name
)->data
)
2388 #else /* not HAVE_X11R4 */
2389 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2390 XSTRING (name
)->data
);
2391 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2392 XSTRING (name
)->data
);
2393 #endif /* not HAVE_X11R4 */
2398 /* This function should be called when the user's lisp code has
2399 specified a name for the frame; the name will override any set by the
2402 x_explicitly_set_name (f
, arg
, oldval
)
2404 Lisp_Object arg
, oldval
;
2406 x_set_name (f
, arg
, 1);
2409 /* This function should be called by Emacs redisplay code to set the
2410 name; names set this way will never override names set by the user's
2413 x_implicitly_set_name (f
, arg
, oldval
)
2415 Lisp_Object arg
, oldval
;
2417 x_set_name (f
, arg
, 0);
2420 /* Change the title of frame F to NAME.
2421 If NAME is nil, use the frame name as the title.
2423 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2424 name; if NAME is a string, set F's name to NAME and set
2425 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2427 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2428 suggesting a new name, which lisp code should override; if
2429 F->explicit_name is set, ignore the new name; otherwise, set it. */
2432 x_set_title (f
, name
, old_name
)
2434 Lisp_Object name
, old_name
;
2436 /* Don't change the title if it's already NAME. */
2437 if (EQ (name
, f
->title
))
2440 update_mode_lines
= 1;
2447 CHECK_STRING (name
);
2449 if (FRAME_X_WINDOW (f
))
2454 XTextProperty text
, icon
;
2456 Lisp_Object coding_system
;
2458 coding_system
= Vlocale_coding_system
;
2459 if (NILP (coding_system
))
2460 coding_system
= Qcompound_text
;
2461 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2462 text
.encoding
= (stringp
? XA_STRING
2463 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2465 text
.nitems
= bytes
;
2467 if (NILP (f
->icon_name
))
2473 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2475 icon
.encoding
= (stringp
? XA_STRING
2476 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2478 icon
.nitems
= bytes
;
2480 #ifdef USE_X_TOOLKIT
2481 XSetWMName (FRAME_X_DISPLAY (f
),
2482 XtWindow (f
->output_data
.x
->widget
), &text
);
2483 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2485 #else /* not USE_X_TOOLKIT */
2486 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2487 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2488 #endif /* not USE_X_TOOLKIT */
2489 if (!NILP (f
->icon_name
)
2490 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2492 if (text
.value
!= XSTRING (name
)->data
)
2495 #else /* not HAVE_X11R4 */
2496 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2497 XSTRING (name
)->data
);
2498 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2499 XSTRING (name
)->data
);
2500 #endif /* not HAVE_X11R4 */
2506 x_set_autoraise (f
, arg
, oldval
)
2508 Lisp_Object arg
, oldval
;
2510 f
->auto_raise
= !EQ (Qnil
, arg
);
2514 x_set_autolower (f
, arg
, oldval
)
2516 Lisp_Object arg
, oldval
;
2518 f
->auto_lower
= !EQ (Qnil
, arg
);
2522 x_set_unsplittable (f
, arg
, oldval
)
2524 Lisp_Object arg
, oldval
;
2526 f
->no_split
= !NILP (arg
);
2530 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2532 Lisp_Object arg
, oldval
;
2534 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2535 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2536 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2537 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2539 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2541 ? vertical_scroll_bar_none
2543 ? vertical_scroll_bar_right
2544 : vertical_scroll_bar_left
);
2546 /* We set this parameter before creating the X window for the
2547 frame, so we can get the geometry right from the start.
2548 However, if the window hasn't been created yet, we shouldn't
2549 call x_set_window_size. */
2550 if (FRAME_X_WINDOW (f
))
2551 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2552 do_pending_window_change (0);
2557 x_set_scroll_bar_width (f
, arg
, oldval
)
2559 Lisp_Object arg
, oldval
;
2561 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2565 #ifdef USE_TOOLKIT_SCROLL_BARS
2566 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2567 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2568 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2569 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2571 /* Make the actual width at least 14 pixels and a multiple of a
2573 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2575 /* Use all of that space (aside from required margins) for the
2577 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2580 if (FRAME_X_WINDOW (f
))
2581 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2582 do_pending_window_change (0);
2584 else if (INTEGERP (arg
) && XINT (arg
) > 0
2585 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2587 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2588 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2590 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2591 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2592 if (FRAME_X_WINDOW (f
))
2593 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2596 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2597 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2598 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2603 /* Subroutines of creating an X frame. */
2605 /* Make sure that Vx_resource_name is set to a reasonable value.
2606 Fix it up, or set it to `emacs' if it is too hopeless. */
2609 validate_x_resource_name ()
2612 /* Number of valid characters in the resource name. */
2614 /* Number of invalid characters in the resource name. */
2619 if (!STRINGP (Vx_resource_class
))
2620 Vx_resource_class
= build_string (EMACS_CLASS
);
2622 if (STRINGP (Vx_resource_name
))
2624 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2627 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2629 /* Only letters, digits, - and _ are valid in resource names.
2630 Count the valid characters and count the invalid ones. */
2631 for (i
= 0; i
< len
; i
++)
2634 if (! ((c
>= 'a' && c
<= 'z')
2635 || (c
>= 'A' && c
<= 'Z')
2636 || (c
>= '0' && c
<= '9')
2637 || c
== '-' || c
== '_'))
2644 /* Not a string => completely invalid. */
2645 bad_count
= 5, good_count
= 0;
2647 /* If name is valid already, return. */
2651 /* If name is entirely invalid, or nearly so, use `emacs'. */
2653 || (good_count
== 1 && bad_count
> 0))
2655 Vx_resource_name
= build_string ("emacs");
2659 /* Name is partly valid. Copy it and replace the invalid characters
2660 with underscores. */
2662 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2664 for (i
= 0; i
< len
; i
++)
2666 int c
= XSTRING (new)->data
[i
];
2667 if (! ((c
>= 'a' && c
<= 'z')
2668 || (c
>= 'A' && c
<= 'Z')
2669 || (c
>= '0' && c
<= '9')
2670 || c
== '-' || c
== '_'))
2671 XSTRING (new)->data
[i
] = '_';
2676 extern char *x_get_string_resource ();
2678 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2679 doc
: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2680 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2681 class, where INSTANCE is the name under which Emacs was invoked, or
2682 the name specified by the `-name' or `-rn' command-line arguments.
2684 The optional arguments COMPONENT and SUBCLASS add to the key and the
2685 class, respectively. You must specify both of them or neither.
2686 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2687 and the class is `Emacs.CLASS.SUBCLASS'. */)
2688 (attribute
, class, component
, subclass
)
2689 Lisp_Object attribute
, class, component
, subclass
;
2691 register char *value
;
2697 CHECK_STRING (attribute
);
2698 CHECK_STRING (class);
2700 if (!NILP (component
))
2701 CHECK_STRING (component
);
2702 if (!NILP (subclass
))
2703 CHECK_STRING (subclass
);
2704 if (NILP (component
) != NILP (subclass
))
2705 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2707 validate_x_resource_name ();
2709 /* Allocate space for the components, the dots which separate them,
2710 and the final '\0'. Make them big enough for the worst case. */
2711 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2712 + (STRINGP (component
)
2713 ? STRING_BYTES (XSTRING (component
)) : 0)
2714 + STRING_BYTES (XSTRING (attribute
))
2717 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2718 + STRING_BYTES (XSTRING (class))
2719 + (STRINGP (subclass
)
2720 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2723 /* Start with emacs.FRAMENAME for the name (the specific one)
2724 and with `Emacs' for the class key (the general one). */
2725 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2726 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2728 strcat (class_key
, ".");
2729 strcat (class_key
, XSTRING (class)->data
);
2731 if (!NILP (component
))
2733 strcat (class_key
, ".");
2734 strcat (class_key
, XSTRING (subclass
)->data
);
2736 strcat (name_key
, ".");
2737 strcat (name_key
, XSTRING (component
)->data
);
2740 strcat (name_key
, ".");
2741 strcat (name_key
, XSTRING (attribute
)->data
);
2743 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2744 name_key
, class_key
);
2746 if (value
!= (char *) 0)
2747 return build_string (value
);
2752 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2755 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2756 struct x_display_info
*dpyinfo
;
2757 Lisp_Object attribute
, class, component
, subclass
;
2759 register char *value
;
2763 CHECK_STRING (attribute
);
2764 CHECK_STRING (class);
2766 if (!NILP (component
))
2767 CHECK_STRING (component
);
2768 if (!NILP (subclass
))
2769 CHECK_STRING (subclass
);
2770 if (NILP (component
) != NILP (subclass
))
2771 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2773 validate_x_resource_name ();
2775 /* Allocate space for the components, the dots which separate them,
2776 and the final '\0'. Make them big enough for the worst case. */
2777 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2778 + (STRINGP (component
)
2779 ? STRING_BYTES (XSTRING (component
)) : 0)
2780 + STRING_BYTES (XSTRING (attribute
))
2783 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2784 + STRING_BYTES (XSTRING (class))
2785 + (STRINGP (subclass
)
2786 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2789 /* Start with emacs.FRAMENAME for the name (the specific one)
2790 and with `Emacs' for the class key (the general one). */
2791 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2792 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2794 strcat (class_key
, ".");
2795 strcat (class_key
, XSTRING (class)->data
);
2797 if (!NILP (component
))
2799 strcat (class_key
, ".");
2800 strcat (class_key
, XSTRING (subclass
)->data
);
2802 strcat (name_key
, ".");
2803 strcat (name_key
, XSTRING (component
)->data
);
2806 strcat (name_key
, ".");
2807 strcat (name_key
, XSTRING (attribute
)->data
);
2809 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2811 if (value
!= (char *) 0)
2812 return build_string (value
);
2817 /* Used when C code wants a resource value. */
2820 x_get_resource_string (attribute
, class)
2821 char *attribute
, *class;
2825 struct frame
*sf
= SELECTED_FRAME ();
2827 /* Allocate space for the components, the dots which separate them,
2828 and the final '\0'. */
2829 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2830 + strlen (attribute
) + 2);
2831 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2832 + strlen (class) + 2);
2834 sprintf (name_key
, "%s.%s",
2835 XSTRING (Vinvocation_name
)->data
,
2837 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2839 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2840 name_key
, class_key
);
2843 /* Types we might convert a resource string into. */
2853 /* Return the value of parameter PARAM.
2855 First search ALIST, then Vdefault_frame_alist, then the X defaults
2856 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2858 Convert the resource to the type specified by desired_type.
2860 If no default is specified, return Qunbound. If you call
2861 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2862 and don't let it get stored in any Lisp-visible variables! */
2865 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2866 struct x_display_info
*dpyinfo
;
2867 Lisp_Object alist
, param
;
2870 enum resource_types type
;
2872 register Lisp_Object tem
;
2874 tem
= Fassq (param
, alist
);
2876 tem
= Fassq (param
, Vdefault_frame_alist
);
2882 tem
= display_x_get_resource (dpyinfo
,
2883 build_string (attribute
),
2884 build_string (class),
2892 case RES_TYPE_NUMBER
:
2893 return make_number (atoi (XSTRING (tem
)->data
));
2895 case RES_TYPE_FLOAT
:
2896 return make_float (atof (XSTRING (tem
)->data
));
2898 case RES_TYPE_BOOLEAN
:
2899 tem
= Fdowncase (tem
);
2900 if (!strcmp (XSTRING (tem
)->data
, "on")
2901 || !strcmp (XSTRING (tem
)->data
, "true"))
2906 case RES_TYPE_STRING
:
2909 case RES_TYPE_SYMBOL
:
2910 /* As a special case, we map the values `true' and `on'
2911 to Qt, and `false' and `off' to Qnil. */
2914 lower
= Fdowncase (tem
);
2915 if (!strcmp (XSTRING (lower
)->data
, "on")
2916 || !strcmp (XSTRING (lower
)->data
, "true"))
2918 else if (!strcmp (XSTRING (lower
)->data
, "off")
2919 || !strcmp (XSTRING (lower
)->data
, "false"))
2922 return Fintern (tem
, Qnil
);
2935 /* Like x_get_arg, but also record the value in f->param_alist. */
2938 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2940 Lisp_Object alist
, param
;
2943 enum resource_types type
;
2947 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2948 attribute
, class, type
);
2950 store_frame_param (f
, param
, value
);
2955 /* Record in frame F the specified or default value according to ALIST
2956 of the parameter named PROP (a Lisp symbol).
2957 If no value is specified for PROP, look for an X default for XPROP
2958 on the frame named NAME.
2959 If that is not found either, use the value DEFLT. */
2962 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2969 enum resource_types type
;
2973 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2974 if (EQ (tem
, Qunbound
))
2976 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2981 /* Record in frame F the specified or default value according to ALIST
2982 of the parameter named PROP (a Lisp symbol). If no value is
2983 specified for PROP, look for an X default for XPROP on the frame
2984 named NAME. If that is not found either, use the value DEFLT. */
2987 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2996 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2999 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
3000 if (EQ (tem
, Qunbound
))
3002 #ifdef USE_TOOLKIT_SCROLL_BARS
3004 /* See if an X resource for the scroll bar color has been
3006 tem
= display_x_get_resource (dpyinfo
,
3007 build_string (foreground_p
3011 build_string ("verticalScrollBar"),
3015 /* If nothing has been specified, scroll bars will use a
3016 toolkit-dependent default. Because these defaults are
3017 difficult to get at without actually creating a scroll
3018 bar, use nil to indicate that no color has been
3023 #else /* not USE_TOOLKIT_SCROLL_BARS */
3027 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3030 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3036 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3037 doc
: /* Parse an X-style geometry string STRING.
3038 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3039 The properties returned may include `top', `left', `height', and `width'.
3040 The value of `left' or `top' may be an integer,
3041 or a list (+ N) meaning N pixels relative to top/left corner,
3042 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3047 unsigned int width
, height
;
3050 CHECK_STRING (string
);
3052 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
3053 &x
, &y
, &width
, &height
);
3056 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3057 error ("Must specify both x and y position, or neither");
3061 if (geometry
& XValue
)
3063 Lisp_Object element
;
3065 if (x
>= 0 && (geometry
& XNegative
))
3066 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3067 else if (x
< 0 && ! (geometry
& XNegative
))
3068 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3070 element
= Fcons (Qleft
, make_number (x
));
3071 result
= Fcons (element
, result
);
3074 if (geometry
& YValue
)
3076 Lisp_Object element
;
3078 if (y
>= 0 && (geometry
& YNegative
))
3079 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3080 else if (y
< 0 && ! (geometry
& YNegative
))
3081 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3083 element
= Fcons (Qtop
, make_number (y
));
3084 result
= Fcons (element
, result
);
3087 if (geometry
& WidthValue
)
3088 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3089 if (geometry
& HeightValue
)
3090 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3095 /* Calculate the desired size and position of this window,
3096 and return the flags saying which aspects were specified.
3098 This function does not make the coordinates positive. */
3100 #define DEFAULT_ROWS 40
3101 #define DEFAULT_COLS 80
3104 x_figure_window_size (f
, parms
)
3108 register Lisp_Object tem0
, tem1
, tem2
;
3109 long window_prompting
= 0;
3110 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3112 /* Default values if we fall through.
3113 Actually, if that happens we should get
3114 window manager prompting. */
3115 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3116 f
->height
= DEFAULT_ROWS
;
3117 /* Window managers expect that if program-specified
3118 positions are not (0,0), they're intentional, not defaults. */
3119 f
->output_data
.x
->top_pos
= 0;
3120 f
->output_data
.x
->left_pos
= 0;
3122 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3123 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3124 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3125 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3127 if (!EQ (tem0
, Qunbound
))
3129 CHECK_NUMBER (tem0
);
3130 f
->height
= XINT (tem0
);
3132 if (!EQ (tem1
, Qunbound
))
3134 CHECK_NUMBER (tem1
);
3135 SET_FRAME_WIDTH (f
, XINT (tem1
));
3137 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3138 window_prompting
|= USSize
;
3140 window_prompting
|= PSize
;
3143 f
->output_data
.x
->vertical_scroll_bar_extra
3144 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3146 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3148 x_compute_fringe_widths (f
, 0);
3150 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3151 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3153 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3154 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3155 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3156 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3158 if (EQ (tem0
, Qminus
))
3160 f
->output_data
.x
->top_pos
= 0;
3161 window_prompting
|= YNegative
;
3163 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3164 && CONSP (XCDR (tem0
))
3165 && INTEGERP (XCAR (XCDR (tem0
))))
3167 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3168 window_prompting
|= YNegative
;
3170 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3171 && CONSP (XCDR (tem0
))
3172 && INTEGERP (XCAR (XCDR (tem0
))))
3174 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3176 else if (EQ (tem0
, Qunbound
))
3177 f
->output_data
.x
->top_pos
= 0;
3180 CHECK_NUMBER (tem0
);
3181 f
->output_data
.x
->top_pos
= XINT (tem0
);
3182 if (f
->output_data
.x
->top_pos
< 0)
3183 window_prompting
|= YNegative
;
3186 if (EQ (tem1
, Qminus
))
3188 f
->output_data
.x
->left_pos
= 0;
3189 window_prompting
|= XNegative
;
3191 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3192 && CONSP (XCDR (tem1
))
3193 && INTEGERP (XCAR (XCDR (tem1
))))
3195 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3196 window_prompting
|= XNegative
;
3198 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3199 && CONSP (XCDR (tem1
))
3200 && INTEGERP (XCAR (XCDR (tem1
))))
3202 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3204 else if (EQ (tem1
, Qunbound
))
3205 f
->output_data
.x
->left_pos
= 0;
3208 CHECK_NUMBER (tem1
);
3209 f
->output_data
.x
->left_pos
= XINT (tem1
);
3210 if (f
->output_data
.x
->left_pos
< 0)
3211 window_prompting
|= XNegative
;
3214 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3215 window_prompting
|= USPosition
;
3217 window_prompting
|= PPosition
;
3220 return window_prompting
;
3223 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3226 XSetWMProtocols (dpy
, w
, protocols
, count
)
3233 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3234 if (prop
== None
) return False
;
3235 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3236 (unsigned char *) protocols
, count
);
3239 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3241 #ifdef USE_X_TOOLKIT
3243 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3244 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3245 already be present because of the toolkit (Motif adds some of them,
3246 for example, but Xt doesn't). */
3249 hack_wm_protocols (f
, widget
)
3253 Display
*dpy
= XtDisplay (widget
);
3254 Window w
= XtWindow (widget
);
3255 int need_delete
= 1;
3261 Atom type
, *atoms
= 0;
3263 unsigned long nitems
= 0;
3264 unsigned long bytes_after
;
3266 if ((XGetWindowProperty (dpy
, w
,
3267 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3268 (long)0, (long)100, False
, XA_ATOM
,
3269 &type
, &format
, &nitems
, &bytes_after
,
3270 (unsigned char **) &atoms
)
3272 && format
== 32 && type
== XA_ATOM
)
3276 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3278 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3280 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3283 if (atoms
) XFree ((char *) atoms
);
3289 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3291 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3293 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3295 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3296 XA_ATOM
, 32, PropModeAppend
,
3297 (unsigned char *) props
, count
);
3305 /* Support routines for XIC (X Input Context). */
3309 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3310 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3313 /* Supported XIM styles, ordered by preferenc. */
3315 static XIMStyle supported_xim_styles
[] =
3317 XIMPreeditPosition
| XIMStatusArea
,
3318 XIMPreeditPosition
| XIMStatusNothing
,
3319 XIMPreeditPosition
| XIMStatusNone
,
3320 XIMPreeditNothing
| XIMStatusArea
,
3321 XIMPreeditNothing
| XIMStatusNothing
,
3322 XIMPreeditNothing
| XIMStatusNone
,
3323 XIMPreeditNone
| XIMStatusArea
,
3324 XIMPreeditNone
| XIMStatusNothing
,
3325 XIMPreeditNone
| XIMStatusNone
,
3330 /* Create an X fontset on frame F with base font name
3334 xic_create_xfontset (f
, base_fontname
)
3336 char *base_fontname
;
3339 char **missing_list
;
3343 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3344 base_fontname
, &missing_list
,
3345 &missing_count
, &def_string
);
3347 XFreeStringList (missing_list
);
3349 /* No need to free def_string. */
3354 /* Value is the best input style, given user preferences USER (already
3355 checked to be supported by Emacs), and styles supported by the
3356 input method XIM. */
3359 best_xim_style (user
, xim
)
3365 for (i
= 0; i
< user
->count_styles
; ++i
)
3366 for (j
= 0; j
< xim
->count_styles
; ++j
)
3367 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3368 return user
->supported_styles
[i
];
3370 /* Return the default style. */
3371 return XIMPreeditNothing
| XIMStatusNothing
;
3374 /* Create XIC for frame F. */
3376 static XIMStyle xic_style
;
3379 create_frame_xic (f
)
3384 XFontSet xfs
= NULL
;
3389 xim
= FRAME_X_XIM (f
);
3394 XVaNestedList preedit_attr
;
3395 XVaNestedList status_attr
;
3396 char *base_fontname
;
3399 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3400 spot
.x
= 0; spot
.y
= 1;
3401 /* Create X fontset. */
3402 fontset
= FRAME_FONTSET (f
);
3404 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3407 /* Determine the base fontname from the ASCII font name of
3409 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3410 char *p
= ascii_font
;
3413 for (i
= 0; *p
; p
++)
3416 /* As the font name doesn't conform to XLFD, we can't
3417 modify it to get a suitable base fontname for the
3419 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3422 int len
= strlen (ascii_font
) + 1;
3425 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3434 base_fontname
= (char *) alloca (len
);
3435 bzero (base_fontname
, len
);
3436 strcpy (base_fontname
, "-*-*-");
3437 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3438 strcat (base_fontname
, "*-*-*-*-*-*-*");
3441 xfs
= xic_create_xfontset (f
, base_fontname
);
3443 /* Determine XIC style. */
3446 XIMStyles supported_list
;
3447 supported_list
.count_styles
= (sizeof supported_xim_styles
3448 / sizeof supported_xim_styles
[0]);
3449 supported_list
.supported_styles
= supported_xim_styles
;
3450 xic_style
= best_xim_style (&supported_list
,
3451 FRAME_X_XIM_STYLES (f
));
3454 preedit_attr
= XVaCreateNestedList (0,
3457 FRAME_FOREGROUND_PIXEL (f
),
3459 FRAME_BACKGROUND_PIXEL (f
),
3460 (xic_style
& XIMPreeditPosition
3465 status_attr
= XVaCreateNestedList (0,
3471 FRAME_FOREGROUND_PIXEL (f
),
3473 FRAME_BACKGROUND_PIXEL (f
),
3476 xic
= XCreateIC (xim
,
3477 XNInputStyle
, xic_style
,
3478 XNClientWindow
, FRAME_X_WINDOW(f
),
3479 XNFocusWindow
, FRAME_X_WINDOW(f
),
3480 XNStatusAttributes
, status_attr
,
3481 XNPreeditAttributes
, preedit_attr
,
3483 XFree (preedit_attr
);
3484 XFree (status_attr
);
3487 FRAME_XIC (f
) = xic
;
3488 FRAME_XIC_STYLE (f
) = xic_style
;
3489 FRAME_XIC_FONTSET (f
) = xfs
;
3493 /* Destroy XIC and free XIC fontset of frame F, if any. */
3499 if (FRAME_XIC (f
) == NULL
)
3502 XDestroyIC (FRAME_XIC (f
));
3503 if (FRAME_XIC_FONTSET (f
))
3504 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3506 FRAME_XIC (f
) = NULL
;
3507 FRAME_XIC_FONTSET (f
) = NULL
;
3511 /* Place preedit area for XIC of window W's frame to specified
3512 pixel position X/Y. X and Y are relative to window W. */
3515 xic_set_preeditarea (w
, x
, y
)
3519 struct frame
*f
= XFRAME (w
->frame
);
3523 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3524 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3525 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3526 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3531 /* Place status area for XIC in bottom right corner of frame F.. */
3534 xic_set_statusarea (f
)
3537 XIC xic
= FRAME_XIC (f
);
3542 /* Negotiate geometry of status area. If input method has existing
3543 status area, use its current size. */
3544 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3545 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3546 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3549 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3550 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3553 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3555 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3556 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3560 area
.width
= needed
->width
;
3561 area
.height
= needed
->height
;
3562 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3563 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3564 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3567 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3568 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3573 /* Set X fontset for XIC of frame F, using base font name
3574 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3577 xic_set_xfontset (f
, base_fontname
)
3579 char *base_fontname
;
3584 xfs
= xic_create_xfontset (f
, base_fontname
);
3586 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3587 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3588 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3589 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3590 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3593 if (FRAME_XIC_FONTSET (f
))
3594 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3595 FRAME_XIC_FONTSET (f
) = xfs
;
3598 #endif /* HAVE_X_I18N */
3602 #ifdef USE_X_TOOLKIT
3604 /* Create and set up the X widget for frame F. */
3607 x_window (f
, window_prompting
, minibuffer_only
)
3609 long window_prompting
;
3610 int minibuffer_only
;
3612 XClassHint class_hints
;
3613 XSetWindowAttributes attributes
;
3614 unsigned long attribute_mask
;
3615 Widget shell_widget
;
3617 Widget frame_widget
;
3623 /* Use the resource name as the top-level widget name
3624 for looking up resources. Make a non-Lisp copy
3625 for the window manager, so GC relocation won't bother it.
3627 Elsewhere we specify the window name for the window manager. */
3630 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3631 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3632 strcpy (f
->namebuf
, str
);
3636 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3637 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3638 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3639 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3640 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3641 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3642 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3643 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3644 applicationShellWidgetClass
,
3645 FRAME_X_DISPLAY (f
), al
, ac
);
3647 f
->output_data
.x
->widget
= shell_widget
;
3648 /* maybe_set_screen_title_format (shell_widget); */
3650 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3651 (widget_value
*) NULL
,
3652 shell_widget
, False
,
3656 (lw_callback
) NULL
);
3659 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3660 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3661 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3662 XtSetValues (pane_widget
, al
, ac
);
3663 f
->output_data
.x
->column_widget
= pane_widget
;
3665 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3666 the emacs screen when changing menubar. This reduces flickering. */
3669 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3670 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3671 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3672 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3673 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3674 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3675 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3676 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3677 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3680 f
->output_data
.x
->edit_widget
= frame_widget
;
3682 XtManageChild (frame_widget
);
3684 /* Do some needed geometry management. */
3687 char *tem
, shell_position
[32];
3690 int extra_borders
= 0;
3692 = (f
->output_data
.x
->menubar_widget
3693 ? (f
->output_data
.x
->menubar_widget
->core
.height
3694 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3697 #if 0 /* Experimentally, we now get the right results
3698 for -geometry -0-0 without this. 24 Aug 96, rms. */
3699 if (FRAME_EXTERNAL_MENU_BAR (f
))
3702 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3703 menubar_size
+= ibw
;
3707 f
->output_data
.x
->menubar_height
= menubar_size
;
3710 /* Motif seems to need this amount added to the sizes
3711 specified for the shell widget. The Athena/Lucid widgets don't.
3712 Both conclusions reached experimentally. -- rms. */
3713 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3714 &extra_borders
, NULL
);
3718 /* Convert our geometry parameters into a geometry string
3720 Note that we do not specify here whether the position
3721 is a user-specified or program-specified one.
3722 We pass that information later, in x_wm_set_size_hints. */
3724 int left
= f
->output_data
.x
->left_pos
;
3725 int xneg
= window_prompting
& XNegative
;
3726 int top
= f
->output_data
.x
->top_pos
;
3727 int yneg
= window_prompting
& YNegative
;
3733 if (window_prompting
& USPosition
)
3734 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3735 PIXEL_WIDTH (f
) + extra_borders
,
3736 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3737 (xneg
? '-' : '+'), left
,
3738 (yneg
? '-' : '+'), top
);
3740 sprintf (shell_position
, "=%dx%d",
3741 PIXEL_WIDTH (f
) + extra_borders
,
3742 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3745 len
= strlen (shell_position
) + 1;
3746 /* We don't free this because we don't know whether
3747 it is safe to free it while the frame exists.
3748 It isn't worth the trouble of arranging to free it
3749 when the frame is deleted. */
3750 tem
= (char *) xmalloc (len
);
3751 strncpy (tem
, shell_position
, len
);
3752 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3753 XtSetValues (shell_widget
, al
, ac
);
3756 XtManageChild (pane_widget
);
3757 XtRealizeWidget (shell_widget
);
3759 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3761 validate_x_resource_name ();
3763 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3764 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3765 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3768 FRAME_XIC (f
) = NULL
;
3770 create_frame_xic (f
);
3774 f
->output_data
.x
->wm_hints
.input
= True
;
3775 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3776 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3777 &f
->output_data
.x
->wm_hints
);
3779 hack_wm_protocols (f
, shell_widget
);
3782 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3785 /* Do a stupid property change to force the server to generate a
3786 PropertyNotify event so that the event_stream server timestamp will
3787 be initialized to something relevant to the time we created the window.
3789 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3790 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3791 XA_ATOM
, 32, PropModeAppend
,
3792 (unsigned char*) NULL
, 0);
3794 /* Make all the standard events reach the Emacs frame. */
3795 attributes
.event_mask
= STANDARD_EVENT_SET
;
3800 /* XIM server might require some X events. */
3801 unsigned long fevent
= NoEventMask
;
3802 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3803 attributes
.event_mask
|= fevent
;
3805 #endif /* HAVE_X_I18N */
3807 attribute_mask
= CWEventMask
;
3808 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3809 attribute_mask
, &attributes
);
3811 XtMapWidget (frame_widget
);
3813 /* x_set_name normally ignores requests to set the name if the
3814 requested name is the same as the current name. This is the one
3815 place where that assumption isn't correct; f->name is set, but
3816 the X server hasn't been told. */
3819 int explicit = f
->explicit_name
;
3821 f
->explicit_name
= 0;
3824 x_set_name (f
, name
, explicit);
3827 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3828 f
->output_data
.x
->text_cursor
);
3832 /* This is a no-op, except under Motif. Make sure main areas are
3833 set to something reasonable, in case we get an error later. */
3834 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3837 #else /* not USE_X_TOOLKIT */
3839 /* Create and set up the X window for frame F. */
3846 XClassHint class_hints
;
3847 XSetWindowAttributes attributes
;
3848 unsigned long attribute_mask
;
3850 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3851 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3852 attributes
.bit_gravity
= StaticGravity
;
3853 attributes
.backing_store
= NotUseful
;
3854 attributes
.save_under
= True
;
3855 attributes
.event_mask
= STANDARD_EVENT_SET
;
3856 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3857 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3862 = XCreateWindow (FRAME_X_DISPLAY (f
),
3863 f
->output_data
.x
->parent_desc
,
3864 f
->output_data
.x
->left_pos
,
3865 f
->output_data
.x
->top_pos
,
3866 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3867 f
->output_data
.x
->border_width
,
3868 CopyFromParent
, /* depth */
3869 InputOutput
, /* class */
3871 attribute_mask
, &attributes
);
3875 create_frame_xic (f
);
3878 /* XIM server might require some X events. */
3879 unsigned long fevent
= NoEventMask
;
3880 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3881 attributes
.event_mask
|= fevent
;
3882 attribute_mask
= CWEventMask
;
3883 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3884 attribute_mask
, &attributes
);
3887 #endif /* HAVE_X_I18N */
3889 validate_x_resource_name ();
3891 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3892 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3893 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3895 /* The menubar is part of the ordinary display;
3896 it does not count in addition to the height of the window. */
3897 f
->output_data
.x
->menubar_height
= 0;
3899 /* This indicates that we use the "Passive Input" input model.
3900 Unless we do this, we don't get the Focus{In,Out} events that we
3901 need to draw the cursor correctly. Accursed bureaucrats.
3902 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3904 f
->output_data
.x
->wm_hints
.input
= True
;
3905 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3906 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3907 &f
->output_data
.x
->wm_hints
);
3908 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3910 /* Request "save yourself" and "delete window" commands from wm. */
3913 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3914 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3915 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3918 /* x_set_name normally ignores requests to set the name if the
3919 requested name is the same as the current name. This is the one
3920 place where that assumption isn't correct; f->name is set, but
3921 the X server hasn't been told. */
3924 int explicit = f
->explicit_name
;
3926 f
->explicit_name
= 0;
3929 x_set_name (f
, name
, explicit);
3932 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3933 f
->output_data
.x
->text_cursor
);
3937 if (FRAME_X_WINDOW (f
) == 0)
3938 error ("Unable to create window");
3941 #endif /* not USE_X_TOOLKIT */
3943 /* Handle the icon stuff for this window. Perhaps later we might
3944 want an x_set_icon_position which can be called interactively as
3952 Lisp_Object icon_x
, icon_y
;
3953 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3955 /* Set the position of the icon. Note that twm groups all
3956 icons in an icon window. */
3957 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3958 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3959 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3961 CHECK_NUMBER (icon_x
);
3962 CHECK_NUMBER (icon_y
);
3964 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3965 error ("Both left and top icon corners of icon must be specified");
3969 if (! EQ (icon_x
, Qunbound
))
3970 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3972 /* Start up iconic or window? */
3973 x_wm_set_window_state
3974 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3979 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3986 /* Make the GCs needed for this window, setting the
3987 background, border and mouse colors; also create the
3988 mouse cursor and the gray border tile. */
3990 static char cursor_bits
[] =
3992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3993 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3994 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3995 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4002 XGCValues gc_values
;
4006 /* Create the GCs of this frame.
4007 Note that many default values are used. */
4010 gc_values
.font
= f
->output_data
.x
->font
->fid
;
4011 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
4012 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4013 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
4014 f
->output_data
.x
->normal_gc
4015 = XCreateGC (FRAME_X_DISPLAY (f
),
4017 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
4020 /* Reverse video style. */
4021 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4022 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4023 f
->output_data
.x
->reverse_gc
4024 = XCreateGC (FRAME_X_DISPLAY (f
),
4026 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
4029 /* Cursor has cursor-color background, background-color foreground. */
4030 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4031 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
4032 gc_values
.fill_style
= FillOpaqueStippled
;
4034 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4035 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4036 cursor_bits
, 16, 16);
4037 f
->output_data
.x
->cursor_gc
4038 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4039 (GCFont
| GCForeground
| GCBackground
4040 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
4044 f
->output_data
.x
->white_relief
.gc
= 0;
4045 f
->output_data
.x
->black_relief
.gc
= 0;
4047 /* Create the gray border tile used when the pointer is not in
4048 the frame. Since this depends on the frame's pixel values,
4049 this must be done on a per-frame basis. */
4050 f
->output_data
.x
->border_tile
4051 = (XCreatePixmapFromBitmapData
4052 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
4053 gray_bits
, gray_width
, gray_height
,
4054 f
->output_data
.x
->foreground_pixel
,
4055 f
->output_data
.x
->background_pixel
,
4056 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4062 /* Free what was was allocated in x_make_gc. */
4068 Display
*dpy
= FRAME_X_DISPLAY (f
);
4072 if (f
->output_data
.x
->normal_gc
)
4074 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4075 f
->output_data
.x
->normal_gc
= 0;
4078 if (f
->output_data
.x
->reverse_gc
)
4080 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4081 f
->output_data
.x
->reverse_gc
= 0;
4084 if (f
->output_data
.x
->cursor_gc
)
4086 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4087 f
->output_data
.x
->cursor_gc
= 0;
4090 if (f
->output_data
.x
->border_tile
)
4092 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4093 f
->output_data
.x
->border_tile
= 0;
4100 /* Handler for signals raised during x_create_frame and
4101 x_create_top_frame. FRAME is the frame which is partially
4105 unwind_create_frame (frame
)
4108 struct frame
*f
= XFRAME (frame
);
4110 /* If frame is ``official'', nothing to do. */
4111 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4114 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4117 x_free_frame_resources (f
);
4119 /* Check that reference counts are indeed correct. */
4120 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4121 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4129 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4131 doc
: /* Make a new X window, which is called a "frame" in Emacs terms.
4132 Returns an Emacs frame object.
4133 ALIST is an alist of frame parameters.
4134 If the parameters specify that the frame should not have a minibuffer,
4135 and do not specify a specific minibuffer window to use,
4136 then `default-minibuffer-frame' must be a frame whose minibuffer can
4137 be shared by the new frame.
4139 This function is an internal primitive--use `make-frame' instead. */)
4144 Lisp_Object frame
, tem
;
4146 int minibuffer_only
= 0;
4147 long window_prompting
= 0;
4149 int count
= BINDING_STACK_SIZE ();
4150 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4151 Lisp_Object display
;
4152 struct x_display_info
*dpyinfo
= NULL
;
4158 /* Use this general default value to start with
4159 until we know if this frame has a specified name. */
4160 Vx_resource_name
= Vinvocation_name
;
4162 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4163 if (EQ (display
, Qunbound
))
4165 dpyinfo
= check_x_display_info (display
);
4167 kb
= dpyinfo
->kboard
;
4169 kb
= &the_only_kboard
;
4172 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4174 && ! EQ (name
, Qunbound
)
4176 error ("Invalid frame name--not a string or nil");
4179 Vx_resource_name
= name
;
4181 /* See if parent window is specified. */
4182 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4183 if (EQ (parent
, Qunbound
))
4185 if (! NILP (parent
))
4186 CHECK_NUMBER (parent
);
4188 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4189 /* No need to protect DISPLAY because that's not used after passing
4190 it to make_frame_without_minibuffer. */
4192 GCPRO4 (parms
, parent
, name
, frame
);
4193 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4195 if (EQ (tem
, Qnone
) || NILP (tem
))
4196 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4197 else if (EQ (tem
, Qonly
))
4199 f
= make_minibuffer_frame ();
4200 minibuffer_only
= 1;
4202 else if (WINDOWP (tem
))
4203 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4207 XSETFRAME (frame
, f
);
4209 /* Note that X Windows does support scroll bars. */
4210 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4212 f
->output_method
= output_x_window
;
4213 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4214 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4215 f
->output_data
.x
->icon_bitmap
= -1;
4216 f
->output_data
.x
->fontset
= -1;
4217 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4218 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4219 #ifdef USE_TOOLKIT_SCROLL_BARS
4220 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
4221 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
4222 #endif /* USE_TOOLKIT_SCROLL_BARS */
4223 record_unwind_protect (unwind_create_frame
, frame
);
4226 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4228 if (! STRINGP (f
->icon_name
))
4229 f
->icon_name
= Qnil
;
4231 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4233 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4234 dpyinfo_refcount
= dpyinfo
->reference_count
;
4235 #endif /* GLYPH_DEBUG */
4237 FRAME_KBOARD (f
) = kb
;
4240 /* These colors will be set anyway later, but it's important
4241 to get the color reference counts right, so initialize them! */
4244 struct gcpro gcpro1
;
4246 /* Function x_decode_color can signal an error. Make
4247 sure to initialize color slots so that we won't try
4248 to free colors we haven't allocated. */
4249 f
->output_data
.x
->foreground_pixel
= -1;
4250 f
->output_data
.x
->background_pixel
= -1;
4251 f
->output_data
.x
->cursor_pixel
= -1;
4252 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4253 f
->output_data
.x
->border_pixel
= -1;
4254 f
->output_data
.x
->mouse_pixel
= -1;
4256 black
= build_string ("black");
4258 f
->output_data
.x
->foreground_pixel
4259 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4260 f
->output_data
.x
->background_pixel
4261 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4262 f
->output_data
.x
->cursor_pixel
4263 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4264 f
->output_data
.x
->cursor_foreground_pixel
4265 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4266 f
->output_data
.x
->border_pixel
4267 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4268 f
->output_data
.x
->mouse_pixel
4269 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4273 /* Specify the parent under which to make this X window. */
4277 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4278 f
->output_data
.x
->explicit_parent
= 1;
4282 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4283 f
->output_data
.x
->explicit_parent
= 0;
4286 /* Set the name; the functions to which we pass f expect the name to
4288 if (EQ (name
, Qunbound
) || NILP (name
))
4290 f
->name
= build_string (dpyinfo
->x_id_name
);
4291 f
->explicit_name
= 0;
4296 f
->explicit_name
= 1;
4297 /* use the frame's title when getting resources for this frame. */
4298 specbind (Qx_resource_name
, name
);
4301 /* Extract the window parameters from the supplied values
4302 that are needed to determine window geometry. */
4306 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4309 /* First, try whatever font the caller has specified. */
4312 tem
= Fquery_fontset (font
, Qnil
);
4314 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4316 font
= x_new_font (f
, XSTRING (font
)->data
);
4319 /* Try out a font which we hope has bold and italic variations. */
4320 if (!STRINGP (font
))
4321 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4322 if (!STRINGP (font
))
4323 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4324 if (! STRINGP (font
))
4325 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4326 if (! STRINGP (font
))
4327 /* This was formerly the first thing tried, but it finds too many fonts
4328 and takes too long. */
4329 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4330 /* If those didn't work, look for something which will at least work. */
4331 if (! STRINGP (font
))
4332 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4334 if (! STRINGP (font
))
4335 font
= build_string ("fixed");
4337 x_default_parameter (f
, parms
, Qfont
, font
,
4338 "font", "Font", RES_TYPE_STRING
);
4342 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4343 whereby it fails to get any font. */
4344 xlwmenu_default_font
= f
->output_data
.x
->font
;
4347 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4348 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4350 /* This defaults to 1 in order to match xterm. We recognize either
4351 internalBorderWidth or internalBorder (which is what xterm calls
4353 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4357 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4358 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4359 if (! EQ (value
, Qunbound
))
4360 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4363 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4364 "internalBorderWidth", "internalBorderWidth",
4366 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4367 "verticalScrollBars", "ScrollBars",
4370 /* Also do the stuff which must be set before the window exists. */
4371 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4372 "foreground", "Foreground", RES_TYPE_STRING
);
4373 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4374 "background", "Background", RES_TYPE_STRING
);
4375 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4376 "pointerColor", "Foreground", RES_TYPE_STRING
);
4377 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4378 "cursorColor", "Foreground", RES_TYPE_STRING
);
4379 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4380 "borderColor", "BorderColor", RES_TYPE_STRING
);
4381 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4382 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4383 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4384 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4385 x_default_parameter (f
, parms
, Qleft_fringe
, Qnil
,
4386 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4387 x_default_parameter (f
, parms
, Qright_fringe
, Qnil
,
4388 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4390 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4391 "scrollBarForeground",
4392 "ScrollBarForeground", 1);
4393 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4394 "scrollBarBackground",
4395 "ScrollBarBackground", 0);
4397 /* Init faces before x_default_parameter is called for scroll-bar
4398 parameters because that function calls x_set_scroll_bar_width,
4399 which calls change_frame_size, which calls Fset_window_buffer,
4400 which runs hooks, which call Fvertical_motion. At the end, we
4401 end up in init_iterator with a null face cache, which should not
4403 init_frame_faces (f
);
4405 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4406 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4407 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4408 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4409 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4410 "bufferPredicate", "BufferPredicate",
4412 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4413 "title", "Title", RES_TYPE_STRING
);
4414 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4415 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4417 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4419 /* Add the tool-bar height to the initial frame height so that the
4420 user gets a text display area of the size he specified with -g or
4421 via .Xdefaults. Later changes of the tool-bar height don't
4422 change the frame size. This is done so that users can create
4423 tall Emacs frames without having to guess how tall the tool-bar
4425 if (FRAME_TOOL_BAR_LINES (f
))
4427 int margin
, relief
, bar_height
;
4429 relief
= (tool_bar_button_relief
>= 0
4430 ? tool_bar_button_relief
4431 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4433 if (INTEGERP (Vtool_bar_button_margin
)
4434 && XINT (Vtool_bar_button_margin
) > 0)
4435 margin
= XFASTINT (Vtool_bar_button_margin
);
4436 else if (CONSP (Vtool_bar_button_margin
)
4437 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4438 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4439 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4443 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4444 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4447 /* Compute the size of the X window. */
4448 window_prompting
= x_figure_window_size (f
, parms
);
4450 if (window_prompting
& XNegative
)
4452 if (window_prompting
& YNegative
)
4453 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4455 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4459 if (window_prompting
& YNegative
)
4460 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4462 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4465 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4467 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4468 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4470 /* Create the X widget or window. */
4471 #ifdef USE_X_TOOLKIT
4472 x_window (f
, window_prompting
, minibuffer_only
);
4480 /* Now consider the frame official. */
4481 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4482 Vframe_list
= Fcons (frame
, Vframe_list
);
4484 /* We need to do this after creating the X window, so that the
4485 icon-creation functions can say whose icon they're describing. */
4486 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4487 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4489 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4490 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4491 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4492 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4493 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4494 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4495 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4496 "scrollBarWidth", "ScrollBarWidth",
4499 /* Dimensions, especially f->height, must be done via change_frame_size.
4500 Change will not be effected unless different from the current
4506 SET_FRAME_WIDTH (f
, 0);
4507 change_frame_size (f
, height
, width
, 1, 0, 0);
4509 /* Set up faces after all frame parameters are known. This call
4510 also merges in face attributes specified for new frames. If we
4511 don't do this, the `menu' face for instance won't have the right
4512 colors, and the menu bar won't appear in the specified colors for
4514 call1 (Qface_set_after_frame_default
, frame
);
4516 #ifdef USE_X_TOOLKIT
4517 /* Create the menu bar. */
4518 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4520 /* If this signals an error, we haven't set size hints for the
4521 frame and we didn't make it visible. */
4522 initialize_frame_menubar (f
);
4524 /* This is a no-op, except under Motif where it arranges the
4525 main window for the widgets on it. */
4526 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4527 f
->output_data
.x
->menubar_widget
,
4528 f
->output_data
.x
->edit_widget
);
4530 #endif /* USE_X_TOOLKIT */
4532 /* Tell the server what size and position, etc, we want, and how
4533 badly we want them. This should be done after we have the menu
4534 bar so that its size can be taken into account. */
4536 x_wm_set_size_hint (f
, window_prompting
, 0);
4539 /* Make the window appear on the frame and enable display, unless
4540 the caller says not to. However, with explicit parent, Emacs
4541 cannot control visibility, so don't try. */
4542 if (! f
->output_data
.x
->explicit_parent
)
4544 Lisp_Object visibility
;
4546 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4548 if (EQ (visibility
, Qunbound
))
4551 if (EQ (visibility
, Qicon
))
4552 x_iconify_frame (f
);
4553 else if (! NILP (visibility
))
4554 x_make_frame_visible (f
);
4556 /* Must have been Qnil. */
4562 /* Make sure windows on this frame appear in calls to next-window
4563 and similar functions. */
4564 Vwindow_list
= Qnil
;
4566 return unbind_to (count
, frame
);
4570 /* FRAME is used only to get a handle on the X display. We don't pass the
4571 display info directly because we're called from frame.c, which doesn't
4572 know about that structure. */
4575 x_get_focus_frame (frame
)
4576 struct frame
*frame
;
4578 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4580 if (! dpyinfo
->x_focus_frame
)
4583 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4588 /* In certain situations, when the window manager follows a
4589 click-to-focus policy, there seems to be no way around calling
4590 XSetInputFocus to give another frame the input focus .
4592 In an ideal world, XSetInputFocus should generally be avoided so
4593 that applications don't interfere with the window manager's focus
4594 policy. But I think it's okay to use when it's clearly done
4595 following a user-command. */
4597 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4598 doc
: /* Set the input focus to FRAME.
4599 FRAME nil means use the selected frame. */)
4603 struct frame
*f
= check_x_frame (frame
);
4604 Display
*dpy
= FRAME_X_DISPLAY (f
);
4608 count
= x_catch_errors (dpy
);
4609 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4610 RevertToParent
, CurrentTime
);
4611 x_uncatch_errors (dpy
, count
);
4618 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4619 doc
: /* Internal function called by `color-defined-p', which see. */)
4621 Lisp_Object color
, frame
;
4624 FRAME_PTR f
= check_x_frame (frame
);
4626 CHECK_STRING (color
);
4628 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4634 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4635 doc
: /* Internal function called by `color-values', which see. */)
4637 Lisp_Object color
, frame
;
4640 FRAME_PTR f
= check_x_frame (frame
);
4642 CHECK_STRING (color
);
4644 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4648 rgb
[0] = make_number (foo
.red
);
4649 rgb
[1] = make_number (foo
.green
);
4650 rgb
[2] = make_number (foo
.blue
);
4651 return Flist (3, rgb
);
4657 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4658 doc
: /* Internal function called by `display-color-p', which see. */)
4660 Lisp_Object display
;
4662 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4664 if (dpyinfo
->n_planes
<= 2)
4667 switch (dpyinfo
->visual
->class)
4680 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4682 doc
: /* Return t if the X display supports shades of gray.
4683 Note that color displays do support shades of gray.
4684 The optional argument DISPLAY specifies which display to ask about.
4685 DISPLAY should be either a frame or a display name (a string).
4686 If omitted or nil, that stands for the selected frame's display. */)
4688 Lisp_Object display
;
4690 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4692 if (dpyinfo
->n_planes
<= 1)
4695 switch (dpyinfo
->visual
->class)
4710 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4712 doc
: /* Returns the width in pixels of the X display DISPLAY.
4713 The optional argument DISPLAY specifies which display to ask about.
4714 DISPLAY should be either a frame or a display name (a string).
4715 If omitted or nil, that stands for the selected frame's display. */)
4717 Lisp_Object display
;
4719 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4721 return make_number (dpyinfo
->width
);
4724 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4725 Sx_display_pixel_height
, 0, 1, 0,
4726 doc
: /* Returns the height in pixels of the X display DISPLAY.
4727 The optional argument DISPLAY specifies which display to ask about.
4728 DISPLAY should be either a frame or a display name (a string).
4729 If omitted or nil, that stands for the selected frame's display. */)
4731 Lisp_Object display
;
4733 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4735 return make_number (dpyinfo
->height
);
4738 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4740 doc
: /* Returns the number of bitplanes of the X display DISPLAY.
4741 The optional argument DISPLAY specifies which display to ask about.
4742 DISPLAY should be either a frame or a display name (a string).
4743 If omitted or nil, that stands for the selected frame's display. */)
4745 Lisp_Object display
;
4747 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4749 return make_number (dpyinfo
->n_planes
);
4752 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4754 doc
: /* Returns the number of color cells of the X display DISPLAY.
4755 The optional argument DISPLAY specifies which display to ask about.
4756 DISPLAY should be either a frame or a display name (a string).
4757 If omitted or nil, that stands for the selected frame's display. */)
4759 Lisp_Object display
;
4761 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4763 return make_number (DisplayCells (dpyinfo
->display
,
4764 XScreenNumberOfScreen (dpyinfo
->screen
)));
4767 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4768 Sx_server_max_request_size
,
4770 doc
: /* Returns the maximum request size of the X server of display DISPLAY.
4771 The optional argument DISPLAY specifies which display to ask about.
4772 DISPLAY should be either a frame or a display name (a string).
4773 If omitted or nil, that stands for the selected frame's display. */)
4775 Lisp_Object display
;
4777 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4779 return make_number (MAXREQUEST (dpyinfo
->display
));
4782 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4783 doc
: /* Returns the vendor ID string of the X server of display DISPLAY.
4784 The optional argument DISPLAY specifies which display to ask about.
4785 DISPLAY should be either a frame or a display name (a string).
4786 If omitted or nil, that stands for the selected frame's display. */)
4788 Lisp_Object display
;
4790 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4791 char *vendor
= ServerVendor (dpyinfo
->display
);
4793 if (! vendor
) vendor
= "";
4794 return build_string (vendor
);
4797 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4798 doc
: /* Returns the version numbers of the X server of display DISPLAY.
4799 The value is a list of three integers: the major and minor
4800 version numbers of the X Protocol in use, and the vendor-specific release
4801 number. See also the function `x-server-vendor'.
4803 The optional argument DISPLAY specifies which display to ask about.
4804 DISPLAY should be either a frame or a display name (a string).
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
);
4810 Display
*dpy
= dpyinfo
->display
;
4812 return Fcons (make_number (ProtocolVersion (dpy
)),
4813 Fcons (make_number (ProtocolRevision (dpy
)),
4814 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4817 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4818 doc
: /* Return the number of screens on the X server of display DISPLAY.
4819 The optional argument DISPLAY specifies which display to ask about.
4820 DISPLAY should be either a frame or a display name (a string).
4821 If omitted or nil, that stands for the selected frame's display. */)
4823 Lisp_Object display
;
4825 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4827 return make_number (ScreenCount (dpyinfo
->display
));
4830 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4831 doc
: /* Return the height in millimeters of the X display DISPLAY.
4832 The optional argument DISPLAY specifies which display to ask about.
4833 DISPLAY should be either a frame or a display name (a string).
4834 If omitted or nil, that stands for the selected frame's display. */)
4836 Lisp_Object display
;
4838 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4840 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4843 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4844 doc
: /* Return the width in millimeters of the X display DISPLAY.
4845 The optional argument DISPLAY specifies which display to ask about.
4846 DISPLAY should be either a frame or a display name (a string).
4847 If omitted or nil, that stands for the selected frame's display. */)
4849 Lisp_Object display
;
4851 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4853 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4856 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4857 Sx_display_backing_store
, 0, 1, 0,
4858 doc
: /* Returns an indication of whether X display DISPLAY does backing store.
4859 The value may be `always', `when-mapped', or `not-useful'.
4860 The optional argument DISPLAY specifies which display to ask about.
4861 DISPLAY should be either a frame or a display name (a string).
4862 If omitted or nil, that stands for the selected frame's display. */)
4864 Lisp_Object display
;
4866 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4869 switch (DoesBackingStore (dpyinfo
->screen
))
4872 result
= intern ("always");
4876 result
= intern ("when-mapped");
4880 result
= intern ("not-useful");
4884 error ("Strange value for BackingStore parameter of screen");
4891 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4892 Sx_display_visual_class
, 0, 1, 0,
4893 doc
: /* Return the visual class of the X display DISPLAY.
4894 The value is one of the symbols `static-gray', `gray-scale',
4895 `static-color', `pseudo-color', `true-color', or `direct-color'.
4897 The optional argument DISPLAY specifies which display to ask about.
4898 DISPLAY should be either a frame or a display name (a string).
4899 If omitted or nil, that stands for the selected frame's display. */)
4901 Lisp_Object display
;
4903 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4906 switch (dpyinfo
->visual
->class)
4909 result
= intern ("static-gray");
4912 result
= intern ("gray-scale");
4915 result
= intern ("static-color");
4918 result
= intern ("pseudo-color");
4921 result
= intern ("true-color");
4924 result
= intern ("direct-color");
4927 error ("Display has an unknown visual class");
4934 DEFUN ("x-display-save-under", Fx_display_save_under
,
4935 Sx_display_save_under
, 0, 1, 0,
4936 doc
: /* Returns t if the X display DISPLAY supports the save-under feature.
4937 The optional argument DISPLAY specifies which display to ask about.
4938 DISPLAY should be either a frame or a display name (a string).
4939 If omitted or nil, that stands for the selected frame's display. */)
4941 Lisp_Object display
;
4943 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4945 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4953 register struct frame
*f
;
4955 return PIXEL_WIDTH (f
);
4960 register struct frame
*f
;
4962 return PIXEL_HEIGHT (f
);
4967 register struct frame
*f
;
4969 return FONT_WIDTH (f
->output_data
.x
->font
);
4974 register struct frame
*f
;
4976 return f
->output_data
.x
->line_height
;
4981 register struct frame
*f
;
4983 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4988 /************************************************************************
4990 ************************************************************************/
4993 /* Mapping visual names to visuals. */
4995 static struct visual_class
5002 {"StaticGray", StaticGray
},
5003 {"GrayScale", GrayScale
},
5004 {"StaticColor", StaticColor
},
5005 {"PseudoColor", PseudoColor
},
5006 {"TrueColor", TrueColor
},
5007 {"DirectColor", DirectColor
},
5012 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5014 /* Value is the screen number of screen SCR. This is a substitute for
5015 the X function with the same name when that doesn't exist. */
5018 XScreenNumberOfScreen (scr
)
5019 register Screen
*scr
;
5021 Display
*dpy
= scr
->display
;
5024 for (i
= 0; i
< dpy
->nscreens
; ++i
)
5025 if (scr
== dpy
->screens
+ i
)
5031 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5034 /* Select the visual that should be used on display DPYINFO. Set
5035 members of DPYINFO appropriately. Called from x_term_init. */
5038 select_visual (dpyinfo
)
5039 struct x_display_info
*dpyinfo
;
5041 Display
*dpy
= dpyinfo
->display
;
5042 Screen
*screen
= dpyinfo
->screen
;
5045 /* See if a visual is specified. */
5046 value
= display_x_get_resource (dpyinfo
,
5047 build_string ("visualClass"),
5048 build_string ("VisualClass"),
5050 if (STRINGP (value
))
5052 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5053 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5054 depth, a decimal number. NAME is compared with case ignored. */
5055 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
5060 strcpy (s
, XSTRING (value
)->data
);
5061 dash
= index (s
, '-');
5064 dpyinfo
->n_planes
= atoi (dash
+ 1);
5068 /* We won't find a matching visual with depth 0, so that
5069 an error will be printed below. */
5070 dpyinfo
->n_planes
= 0;
5072 /* Determine the visual class. */
5073 for (i
= 0; visual_classes
[i
].name
; ++i
)
5074 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5076 class = visual_classes
[i
].class;
5080 /* Look up a matching visual for the specified class. */
5082 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5083 dpyinfo
->n_planes
, class, &vinfo
))
5084 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
5086 dpyinfo
->visual
= vinfo
.visual
;
5091 XVisualInfo
*vinfo
, vinfo_template
;
5093 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5096 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5098 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5100 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5101 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5102 &vinfo_template
, &n_visuals
);
5104 fatal ("Can't get proper X visual info");
5106 dpyinfo
->n_planes
= vinfo
->depth
;
5107 XFree ((char *) vinfo
);
5112 /* Return the X display structure for the display named NAME.
5113 Open a new connection if necessary. */
5115 struct x_display_info
*
5116 x_display_info_for_name (name
)
5120 struct x_display_info
*dpyinfo
;
5122 CHECK_STRING (name
);
5124 if (! EQ (Vwindow_system
, intern ("x")))
5125 error ("Not using X Windows");
5127 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5129 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5132 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5137 /* Use this general default value to start with. */
5138 Vx_resource_name
= Vinvocation_name
;
5140 validate_x_resource_name ();
5142 dpyinfo
= x_term_init (name
, (char *)0,
5143 (char *) XSTRING (Vx_resource_name
)->data
);
5146 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5149 XSETFASTINT (Vwindow_system_version
, 11);
5155 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5157 doc
: /* Open a connection to an X server.
5158 DISPLAY is the name of the display to connect to.
5159 Optional second arg XRM-STRING is a string of resources in xrdb format.
5160 If the optional third arg MUST-SUCCEED is non-nil,
5161 terminate Emacs if we can't open the connection. */)
5162 (display
, xrm_string
, must_succeed
)
5163 Lisp_Object display
, xrm_string
, must_succeed
;
5165 unsigned char *xrm_option
;
5166 struct x_display_info
*dpyinfo
;
5168 CHECK_STRING (display
);
5169 if (! NILP (xrm_string
))
5170 CHECK_STRING (xrm_string
);
5172 if (! EQ (Vwindow_system
, intern ("x")))
5173 error ("Not using X Windows");
5175 if (! NILP (xrm_string
))
5176 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5178 xrm_option
= (unsigned char *) 0;
5180 validate_x_resource_name ();
5182 /* This is what opens the connection and sets x_current_display.
5183 This also initializes many symbols, such as those used for input. */
5184 dpyinfo
= x_term_init (display
, xrm_option
,
5185 (char *) XSTRING (Vx_resource_name
)->data
);
5189 if (!NILP (must_succeed
))
5190 fatal ("Cannot connect to X server %s.\n\
5191 Check the DISPLAY environment variable or use `-d'.\n\
5192 Also use the `xhost' program to verify that it is set to permit\n\
5193 connections from your machine.\n",
5194 XSTRING (display
)->data
);
5196 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5201 XSETFASTINT (Vwindow_system_version
, 11);
5205 DEFUN ("x-close-connection", Fx_close_connection
,
5206 Sx_close_connection
, 1, 1, 0,
5207 doc
: /* Close the connection to DISPLAY's X server.
5208 For DISPLAY, specify either a frame or a display name (a string).
5209 If DISPLAY is nil, that stands for the selected frame's display. */)
5211 Lisp_Object display
;
5213 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5216 if (dpyinfo
->reference_count
> 0)
5217 error ("Display still has frames on it");
5220 /* Free the fonts in the font table. */
5221 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5222 if (dpyinfo
->font_table
[i
].name
)
5224 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5225 xfree (dpyinfo
->font_table
[i
].full_name
);
5226 xfree (dpyinfo
->font_table
[i
].name
);
5227 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5230 x_destroy_all_bitmaps (dpyinfo
);
5231 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5233 #ifdef USE_X_TOOLKIT
5234 XtCloseDisplay (dpyinfo
->display
);
5236 XCloseDisplay (dpyinfo
->display
);
5239 x_delete_display (dpyinfo
);
5245 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5246 doc
: /* Return the list of display names that Emacs has connections to. */)
5249 Lisp_Object tail
, result
;
5252 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5253 result
= Fcons (XCAR (XCAR (tail
)), result
);
5258 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5259 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5260 If ON is nil, allow buffering of requests.
5261 Turning on synchronization prohibits the Xlib routines from buffering
5262 requests and seriously degrades performance, but makes debugging much
5264 The optional second argument DISPLAY specifies which display to act on.
5265 DISPLAY should be either a frame or a display name (a string).
5266 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5268 Lisp_Object display
, on
;
5270 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5272 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5277 /* Wait for responses to all X commands issued so far for frame F. */
5284 XSync (FRAME_X_DISPLAY (f
), False
);
5289 /***********************************************************************
5291 ***********************************************************************/
5293 /* Value is the number of elements of vector VECTOR. */
5295 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5297 /* List of supported image types. Use define_image_type to add new
5298 types. Use lookup_image_type to find a type for a given symbol. */
5300 static struct image_type
*image_types
;
5302 /* The symbol `image' which is the car of the lists used to represent
5305 extern Lisp_Object Qimage
;
5307 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5313 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5314 extern Lisp_Object QCdata
;
5315 Lisp_Object QCtype
, QCascent
, QCmargin
, QCrelief
;
5316 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5317 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5319 /* Other symbols. */
5321 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5323 /* Time in seconds after which images should be removed from the cache
5324 if not displayed. */
5326 Lisp_Object Vimage_cache_eviction_delay
;
5328 /* Function prototypes. */
5330 static void define_image_type
P_ ((struct image_type
*type
));
5331 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5332 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5333 static void x_laplace
P_ ((struct frame
*, struct image
*));
5334 static void x_emboss
P_ ((struct frame
*, struct image
*));
5335 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5339 /* Define a new image type from TYPE. This adds a copy of TYPE to
5340 image_types and adds the symbol *TYPE->type to Vimage_types. */
5343 define_image_type (type
)
5344 struct image_type
*type
;
5346 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5347 The initialized data segment is read-only. */
5348 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5349 bcopy (type
, p
, sizeof *p
);
5350 p
->next
= image_types
;
5352 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5356 /* Look up image type SYMBOL, and return a pointer to its image_type
5357 structure. Value is null if SYMBOL is not a known image type. */
5359 static INLINE
struct image_type
*
5360 lookup_image_type (symbol
)
5363 struct image_type
*type
;
5365 for (type
= image_types
; type
; type
= type
->next
)
5366 if (EQ (symbol
, *type
->type
))
5373 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5374 valid image specification is a list whose car is the symbol
5375 `image', and whose rest is a property list. The property list must
5376 contain a value for key `:type'. That value must be the name of a
5377 supported image type. The rest of the property list depends on the
5381 valid_image_p (object
)
5386 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5390 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5391 if (EQ (XCAR (tem
), QCtype
))
5394 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5396 struct image_type
*type
;
5397 type
= lookup_image_type (XCAR (tem
));
5399 valid_p
= type
->valid_p (object
);
5410 /* Log error message with format string FORMAT and argument ARG.
5411 Signaling an error, e.g. when an image cannot be loaded, is not a
5412 good idea because this would interrupt redisplay, and the error
5413 message display would lead to another redisplay. This function
5414 therefore simply displays a message. */
5417 image_error (format
, arg1
, arg2
)
5419 Lisp_Object arg1
, arg2
;
5421 add_to_log (format
, arg1
, arg2
);
5426 /***********************************************************************
5427 Image specifications
5428 ***********************************************************************/
5430 enum image_value_type
5432 IMAGE_DONT_CHECK_VALUE_TYPE
,
5434 IMAGE_STRING_OR_NIL_VALUE
,
5436 IMAGE_POSITIVE_INTEGER_VALUE
,
5437 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5438 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5440 IMAGE_INTEGER_VALUE
,
5441 IMAGE_FUNCTION_VALUE
,
5446 /* Structure used when parsing image specifications. */
5448 struct image_keyword
5450 /* Name of keyword. */
5453 /* The type of value allowed. */
5454 enum image_value_type type
;
5456 /* Non-zero means key must be present. */
5459 /* Used to recognize duplicate keywords in a property list. */
5462 /* The value that was found. */
5467 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5469 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5472 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5473 has the format (image KEYWORD VALUE ...). One of the keyword/
5474 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5475 image_keywords structures of size NKEYWORDS describing other
5476 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5479 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5481 struct image_keyword
*keywords
;
5488 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5491 plist
= XCDR (spec
);
5492 while (CONSP (plist
))
5494 Lisp_Object key
, value
;
5496 /* First element of a pair must be a symbol. */
5498 plist
= XCDR (plist
);
5502 /* There must follow a value. */
5505 value
= XCAR (plist
);
5506 plist
= XCDR (plist
);
5508 /* Find key in KEYWORDS. Error if not found. */
5509 for (i
= 0; i
< nkeywords
; ++i
)
5510 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5516 /* Record that we recognized the keyword. If a keywords
5517 was found more than once, it's an error. */
5518 keywords
[i
].value
= value
;
5519 ++keywords
[i
].count
;
5521 if (keywords
[i
].count
> 1)
5524 /* Check type of value against allowed type. */
5525 switch (keywords
[i
].type
)
5527 case IMAGE_STRING_VALUE
:
5528 if (!STRINGP (value
))
5532 case IMAGE_STRING_OR_NIL_VALUE
:
5533 if (!STRINGP (value
) && !NILP (value
))
5537 case IMAGE_SYMBOL_VALUE
:
5538 if (!SYMBOLP (value
))
5542 case IMAGE_POSITIVE_INTEGER_VALUE
:
5543 if (!INTEGERP (value
) || XINT (value
) <= 0)
5547 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5548 if (INTEGERP (value
) && XINT (value
) >= 0)
5551 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5552 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5556 case IMAGE_ASCENT_VALUE
:
5557 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5559 else if (INTEGERP (value
)
5560 && XINT (value
) >= 0
5561 && XINT (value
) <= 100)
5565 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5566 if (!INTEGERP (value
) || XINT (value
) < 0)
5570 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5573 case IMAGE_FUNCTION_VALUE
:
5574 value
= indirect_function (value
);
5576 || COMPILEDP (value
)
5577 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5581 case IMAGE_NUMBER_VALUE
:
5582 if (!INTEGERP (value
) && !FLOATP (value
))
5586 case IMAGE_INTEGER_VALUE
:
5587 if (!INTEGERP (value
))
5591 case IMAGE_BOOL_VALUE
:
5592 if (!NILP (value
) && !EQ (value
, Qt
))
5601 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5605 /* Check that all mandatory fields are present. */
5606 for (i
= 0; i
< nkeywords
; ++i
)
5607 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5610 return NILP (plist
);
5614 /* Return the value of KEY in image specification SPEC. Value is nil
5615 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5616 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5619 image_spec_value (spec
, key
, found
)
5620 Lisp_Object spec
, key
;
5625 xassert (valid_image_p (spec
));
5627 for (tail
= XCDR (spec
);
5628 CONSP (tail
) && CONSP (XCDR (tail
));
5629 tail
= XCDR (XCDR (tail
)))
5631 if (EQ (XCAR (tail
), key
))
5635 return XCAR (XCDR (tail
));
5645 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5646 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5647 PIXELS non-nil means return the size in pixels, otherwise return the
5648 size in canonical character units.
5649 FRAME is the frame on which the image will be displayed. FRAME nil
5650 or omitted means use the selected frame. */)
5651 (spec
, pixels
, frame
)
5652 Lisp_Object spec
, pixels
, frame
;
5657 if (valid_image_p (spec
))
5659 struct frame
*f
= check_x_frame (frame
);
5660 int id
= lookup_image (f
, spec
);
5661 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5662 int width
= img
->width
+ 2 * img
->hmargin
;
5663 int height
= img
->height
+ 2 * img
->vmargin
;
5666 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5667 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5669 size
= Fcons (make_number (width
), make_number (height
));
5672 error ("Invalid image specification");
5678 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5679 doc
: /* Return t if image SPEC has a mask bitmap.
5680 FRAME is the frame on which the image will be displayed. FRAME nil
5681 or omitted means use the selected frame. */)
5683 Lisp_Object spec
, frame
;
5688 if (valid_image_p (spec
))
5690 struct frame
*f
= check_x_frame (frame
);
5691 int id
= lookup_image (f
, spec
);
5692 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5697 error ("Invalid image specification");
5704 /***********************************************************************
5705 Image type independent image structures
5706 ***********************************************************************/
5708 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5709 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5712 /* Allocate and return a new image structure for image specification
5713 SPEC. SPEC has a hash value of HASH. */
5715 static struct image
*
5716 make_image (spec
, hash
)
5720 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5722 xassert (valid_image_p (spec
));
5723 bzero (img
, sizeof *img
);
5724 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5725 xassert (img
->type
!= NULL
);
5727 img
->data
.lisp_val
= Qnil
;
5728 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5734 /* Free image IMG which was used on frame F, including its resources. */
5743 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5745 /* Remove IMG from the hash table of its cache. */
5747 img
->prev
->next
= img
->next
;
5749 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5752 img
->next
->prev
= img
->prev
;
5754 c
->images
[img
->id
] = NULL
;
5756 /* Free resources, then free IMG. */
5757 img
->type
->free (f
, img
);
5763 /* Prepare image IMG for display on frame F. Must be called before
5764 drawing an image. */
5767 prepare_image_for_display (f
, img
)
5773 /* We're about to display IMG, so set its timestamp to `now'. */
5775 img
->timestamp
= EMACS_SECS (t
);
5777 /* If IMG doesn't have a pixmap yet, load it now, using the image
5778 type dependent loader function. */
5779 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5780 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5784 /* Value is the number of pixels for the ascent of image IMG when
5785 drawn in face FACE. */
5788 image_ascent (img
, face
)
5792 int height
= img
->height
+ img
->vmargin
;
5795 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5798 /* This expression is arranged so that if the image can't be
5799 exactly centered, it will be moved slightly up. This is
5800 because a typical font is `top-heavy' (due to the presence
5801 uppercase letters), so the image placement should err towards
5802 being top-heavy too. It also just generally looks better. */
5803 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5805 ascent
= height
/ 2;
5808 ascent
= height
* img
->ascent
/ 100.0;
5814 /* Image background colors. */
5816 static unsigned long
5817 four_corners_best (ximg
, width
, height
)
5819 unsigned long width
, height
;
5821 unsigned long corners
[4], best
;
5824 /* Get the colors at the corners of ximg. */
5825 corners
[0] = XGetPixel (ximg
, 0, 0);
5826 corners
[1] = XGetPixel (ximg
, width
- 1, 0);
5827 corners
[2] = XGetPixel (ximg
, width
- 1, height
- 1);
5828 corners
[3] = XGetPixel (ximg
, 0, height
- 1);
5830 /* Choose the most frequently found color as background. */
5831 for (i
= best_count
= 0; i
< 4; ++i
)
5835 for (j
= n
= 0; j
< 4; ++j
)
5836 if (corners
[i
] == corners
[j
])
5840 best
= corners
[i
], best_count
= n
;
5846 /* Return the `background' field of IMG. If IMG doesn't have one yet,
5847 it is guessed heuristically. If non-zero, XIMG is an existing XImage
5848 object to use for the heuristic. */
5851 image_background (img
, f
, ximg
)
5856 if (! img
->background_valid
)
5857 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5859 int free_ximg
= !ximg
;
5862 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5863 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5865 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
5868 XDestroyImage (ximg
);
5870 img
->background_valid
= 1;
5873 return img
->background
;
5876 /* Return the `background_transparent' field of IMG. If IMG doesn't
5877 have one yet, it is guessed heuristically. If non-zero, MASK is an
5878 existing XImage object to use for the heuristic. */
5881 image_background_transparent (img
, f
, mask
)
5886 if (! img
->background_transparent_valid
)
5887 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5891 int free_mask
= !mask
;
5894 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
5895 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5897 img
->background_transparent
5898 = !four_corners_best (mask
, img
->width
, img
->height
);
5901 XDestroyImage (mask
);
5904 img
->background_transparent
= 0;
5906 img
->background_transparent_valid
= 1;
5909 return img
->background_transparent
;
5913 /***********************************************************************
5914 Helper functions for X image types
5915 ***********************************************************************/
5917 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
5919 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5920 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5922 Lisp_Object color_name
,
5923 unsigned long dflt
));
5926 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5927 free the pixmap if any. MASK_P non-zero means clear the mask
5928 pixmap if any. COLORS_P non-zero means free colors allocated for
5929 the image, if any. */
5932 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
5935 int pixmap_p
, mask_p
, colors_p
;
5937 if (pixmap_p
&& img
->pixmap
)
5939 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5941 img
->background_valid
= 0;
5944 if (mask_p
&& img
->mask
)
5946 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5948 img
->background_transparent_valid
= 0;
5951 if (colors_p
&& img
->ncolors
)
5953 x_free_colors (f
, img
->colors
, img
->ncolors
);
5954 xfree (img
->colors
);
5960 /* Free X resources of image IMG which is used on frame F. */
5963 x_clear_image (f
, img
)
5968 x_clear_image_1 (f
, img
, 1, 1, 1);
5973 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5974 cannot be allocated, use DFLT. Add a newly allocated color to
5975 IMG->colors, so that it can be freed again. Value is the pixel
5978 static unsigned long
5979 x_alloc_image_color (f
, img
, color_name
, dflt
)
5982 Lisp_Object color_name
;
5986 unsigned long result
;
5988 xassert (STRINGP (color_name
));
5990 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
5992 /* This isn't called frequently so we get away with simply
5993 reallocating the color vector to the needed size, here. */
5996 (unsigned long *) xrealloc (img
->colors
,
5997 img
->ncolors
* sizeof *img
->colors
);
5998 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5999 result
= color
.pixel
;
6009 /***********************************************************************
6011 ***********************************************************************/
6013 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
6014 static void postprocess_image
P_ ((struct frame
*, struct image
*));
6017 /* Return a new, initialized image cache that is allocated from the
6018 heap. Call free_image_cache to free an image cache. */
6020 struct image_cache
*
6023 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
6026 bzero (c
, sizeof *c
);
6028 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
6029 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
6030 c
->buckets
= (struct image
**) xmalloc (size
);
6031 bzero (c
->buckets
, size
);
6036 /* Free image cache of frame F. Be aware that X frames share images
6040 free_image_cache (f
)
6043 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6048 /* Cache should not be referenced by any frame when freed. */
6049 xassert (c
->refcount
== 0);
6051 for (i
= 0; i
< c
->used
; ++i
)
6052 free_image (f
, c
->images
[i
]);
6056 FRAME_X_IMAGE_CACHE (f
) = NULL
;
6061 /* Clear image cache of frame F. FORCE_P non-zero means free all
6062 images. FORCE_P zero means clear only images that haven't been
6063 displayed for some time. Should be called from time to time to
6064 reduce the number of loaded images. If image-eviction-seconds is
6065 non-nil, this frees images in the cache which weren't displayed for
6066 at least that many seconds. */
6069 clear_image_cache (f
, force_p
)
6073 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6075 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
6082 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
6084 /* Block input so that we won't be interrupted by a SIGIO
6085 while being in an inconsistent state. */
6088 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
6090 struct image
*img
= c
->images
[i
];
6092 && (force_p
|| img
->timestamp
< old
))
6094 free_image (f
, img
);
6099 /* We may be clearing the image cache because, for example,
6100 Emacs was iconified for a longer period of time. In that
6101 case, current matrices may still contain references to
6102 images freed above. So, clear these matrices. */
6105 Lisp_Object tail
, frame
;
6107 FOR_EACH_FRAME (tail
, frame
)
6109 struct frame
*f
= XFRAME (frame
);
6111 && FRAME_X_IMAGE_CACHE (f
) == c
)
6112 clear_current_matrices (f
);
6115 ++windows_or_buffers_changed
;
6123 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
6125 doc
: /* Clear the image cache of FRAME.
6126 FRAME nil or omitted means use the selected frame.
6127 FRAME t means clear the image caches of all frames. */)
6135 FOR_EACH_FRAME (tail
, frame
)
6136 if (FRAME_X_P (XFRAME (frame
)))
6137 clear_image_cache (XFRAME (frame
), 1);
6140 clear_image_cache (check_x_frame (frame
), 1);
6146 /* Compute masks and transform image IMG on frame F, as specified
6147 by the image's specification, */
6150 postprocess_image (f
, img
)
6154 /* Manipulation of the image's mask. */
6157 Lisp_Object conversion
, spec
;
6162 /* `:heuristic-mask t'
6164 means build a mask heuristically.
6165 `:heuristic-mask (R G B)'
6166 `:mask (heuristic (R G B))'
6167 means build a mask from color (R G B) in the
6170 means remove a mask, if any. */
6172 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6174 x_build_heuristic_mask (f
, img
, mask
);
6179 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6181 if (EQ (mask
, Qheuristic
))
6182 x_build_heuristic_mask (f
, img
, Qt
);
6183 else if (CONSP (mask
)
6184 && EQ (XCAR (mask
), Qheuristic
))
6186 if (CONSP (XCDR (mask
)))
6187 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6189 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6191 else if (NILP (mask
) && found_p
&& img
->mask
)
6193 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6199 /* Should we apply an image transformation algorithm? */
6200 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6201 if (EQ (conversion
, Qdisabled
))
6202 x_disable_image (f
, img
);
6203 else if (EQ (conversion
, Qlaplace
))
6205 else if (EQ (conversion
, Qemboss
))
6207 else if (CONSP (conversion
)
6208 && EQ (XCAR (conversion
), Qedge_detection
))
6211 tem
= XCDR (conversion
);
6213 x_edge_detection (f
, img
,
6214 Fplist_get (tem
, QCmatrix
),
6215 Fplist_get (tem
, QCcolor_adjustment
));
6221 /* Return the id of image with Lisp specification SPEC on frame F.
6222 SPEC must be a valid Lisp image specification (see valid_image_p). */
6225 lookup_image (f
, spec
)
6229 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6233 struct gcpro gcpro1
;
6236 /* F must be a window-system frame, and SPEC must be a valid image
6238 xassert (FRAME_WINDOW_P (f
));
6239 xassert (valid_image_p (spec
));
6243 /* Look up SPEC in the hash table of the image cache. */
6244 hash
= sxhash (spec
, 0);
6245 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6247 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6248 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6251 /* If not found, create a new image and cache it. */
6254 extern Lisp_Object Qpostscript
;
6257 img
= make_image (spec
, hash
);
6258 cache_image (f
, img
);
6259 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6261 /* If we can't load the image, and we don't have a width and
6262 height, use some arbitrary width and height so that we can
6263 draw a rectangle for it. */
6264 if (img
->load_failed_p
)
6268 value
= image_spec_value (spec
, QCwidth
, NULL
);
6269 img
->width
= (INTEGERP (value
)
6270 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6271 value
= image_spec_value (spec
, QCheight
, NULL
);
6272 img
->height
= (INTEGERP (value
)
6273 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6277 /* Handle image type independent image attributes
6278 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6279 `:background COLOR'. */
6280 Lisp_Object ascent
, margin
, relief
, bg
;
6282 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6283 if (INTEGERP (ascent
))
6284 img
->ascent
= XFASTINT (ascent
);
6285 else if (EQ (ascent
, Qcenter
))
6286 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6288 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6289 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6290 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6291 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6292 && INTEGERP (XCDR (margin
)))
6294 if (XINT (XCAR (margin
)) > 0)
6295 img
->hmargin
= XFASTINT (XCAR (margin
));
6296 if (XINT (XCDR (margin
)) > 0)
6297 img
->vmargin
= XFASTINT (XCDR (margin
));
6300 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6301 if (INTEGERP (relief
))
6303 img
->relief
= XINT (relief
);
6304 img
->hmargin
+= abs (img
->relief
);
6305 img
->vmargin
+= abs (img
->relief
);
6308 if (! img
->background_valid
)
6310 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6314 = x_alloc_image_color (f
, img
, bg
,
6315 FRAME_BACKGROUND_PIXEL (f
));
6316 img
->background_valid
= 1;
6320 /* Do image transformations and compute masks, unless we
6321 don't have the image yet. */
6322 if (!EQ (*img
->type
->type
, Qpostscript
))
6323 postprocess_image (f
, img
);
6327 xassert (!interrupt_input_blocked
);
6330 /* We're using IMG, so set its timestamp to `now'. */
6331 EMACS_GET_TIME (now
);
6332 img
->timestamp
= EMACS_SECS (now
);
6336 /* Value is the image id. */
6341 /* Cache image IMG in the image cache of frame F. */
6344 cache_image (f
, img
)
6348 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6351 /* Find a free slot in c->images. */
6352 for (i
= 0; i
< c
->used
; ++i
)
6353 if (c
->images
[i
] == NULL
)
6356 /* If no free slot found, maybe enlarge c->images. */
6357 if (i
== c
->used
&& c
->used
== c
->size
)
6360 c
->images
= (struct image
**) xrealloc (c
->images
,
6361 c
->size
* sizeof *c
->images
);
6364 /* Add IMG to c->images, and assign IMG an id. */
6370 /* Add IMG to the cache's hash table. */
6371 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6372 img
->next
= c
->buckets
[i
];
6374 img
->next
->prev
= img
;
6376 c
->buckets
[i
] = img
;
6380 /* Call FN on every image in the image cache of frame F. Used to mark
6381 Lisp Objects in the image cache. */
6384 forall_images_in_image_cache (f
, fn
)
6386 void (*fn
) P_ ((struct image
*img
));
6388 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6390 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6394 for (i
= 0; i
< c
->used
; ++i
)
6403 /***********************************************************************
6405 ***********************************************************************/
6407 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6408 XImage
**, Pixmap
*));
6409 static void x_destroy_x_image
P_ ((XImage
*));
6410 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6413 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6414 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6415 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6416 via xmalloc. Print error messages via image_error if an error
6417 occurs. Value is non-zero if successful. */
6420 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6422 int width
, height
, depth
;
6426 Display
*display
= FRAME_X_DISPLAY (f
);
6427 Screen
*screen
= FRAME_X_SCREEN (f
);
6428 Window window
= FRAME_X_WINDOW (f
);
6430 xassert (interrupt_input_blocked
);
6433 depth
= DefaultDepthOfScreen (screen
);
6434 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6435 depth
, ZPixmap
, 0, NULL
, width
, height
,
6436 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6439 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6443 /* Allocate image raster. */
6444 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6446 /* Allocate a pixmap of the same size. */
6447 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6448 if (*pixmap
== None
)
6450 x_destroy_x_image (*ximg
);
6452 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6460 /* Destroy XImage XIMG. Free XIMG->data. */
6463 x_destroy_x_image (ximg
)
6466 xassert (interrupt_input_blocked
);
6471 XDestroyImage (ximg
);
6476 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6477 are width and height of both the image and pixmap. */
6480 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6487 xassert (interrupt_input_blocked
);
6488 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6489 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6490 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6495 /***********************************************************************
6497 ***********************************************************************/
6499 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6500 static char *slurp_file
P_ ((char *, int *));
6503 /* Find image file FILE. Look in data-directory, then
6504 x-bitmap-file-path. Value is the full name of the file found, or
6505 nil if not found. */
6508 x_find_image_file (file
)
6511 Lisp_Object file_found
, search_path
;
6512 struct gcpro gcpro1
, gcpro2
;
6516 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6517 GCPRO2 (file_found
, search_path
);
6519 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6520 fd
= openp (search_path
, file
, Qnil
, &file_found
, 0);
6532 /* Read FILE into memory. Value is a pointer to a buffer allocated
6533 with xmalloc holding FILE's contents. Value is null if an error
6534 occurred. *SIZE is set to the size of the file. */
6537 slurp_file (file
, size
)
6545 if (stat (file
, &st
) == 0
6546 && (fp
= fopen (file
, "r")) != NULL
6547 && (buf
= (char *) xmalloc (st
.st_size
),
6548 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6569 /***********************************************************************
6571 ***********************************************************************/
6573 static int xbm_scan
P_ ((char **, char *, char *, int *));
6574 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6575 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6577 static int xbm_image_p
P_ ((Lisp_Object object
));
6578 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6580 static int xbm_file_p
P_ ((Lisp_Object
));
6583 /* Indices of image specification fields in xbm_format, below. */
6585 enum xbm_keyword_index
6603 /* Vector of image_keyword structures describing the format
6604 of valid XBM image specifications. */
6606 static struct image_keyword xbm_format
[XBM_LAST
] =
6608 {":type", IMAGE_SYMBOL_VALUE
, 1},
6609 {":file", IMAGE_STRING_VALUE
, 0},
6610 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6611 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6612 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6613 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6614 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6615 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6616 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6617 {":relief", IMAGE_INTEGER_VALUE
, 0},
6618 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6619 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6620 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6623 /* Structure describing the image type XBM. */
6625 static struct image_type xbm_type
=
6634 /* Tokens returned from xbm_scan. */
6643 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6644 A valid specification is a list starting with the symbol `image'
6645 The rest of the list is a property list which must contain an
6648 If the specification specifies a file to load, it must contain
6649 an entry `:file FILENAME' where FILENAME is a string.
6651 If the specification is for a bitmap loaded from memory it must
6652 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6653 WIDTH and HEIGHT are integers > 0. DATA may be:
6655 1. a string large enough to hold the bitmap data, i.e. it must
6656 have a size >= (WIDTH + 7) / 8 * HEIGHT
6658 2. a bool-vector of size >= WIDTH * HEIGHT
6660 3. a vector of strings or bool-vectors, one for each line of the
6663 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6664 may not be specified in this case because they are defined in the
6667 Both the file and data forms may contain the additional entries
6668 `:background COLOR' and `:foreground COLOR'. If not present,
6669 foreground and background of the frame on which the image is
6670 displayed is used. */
6673 xbm_image_p (object
)
6676 struct image_keyword kw
[XBM_LAST
];
6678 bcopy (xbm_format
, kw
, sizeof kw
);
6679 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6682 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6684 if (kw
[XBM_FILE
].count
)
6686 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6689 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6691 /* In-memory XBM file. */
6692 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6700 /* Entries for `:width', `:height' and `:data' must be present. */
6701 if (!kw
[XBM_WIDTH
].count
6702 || !kw
[XBM_HEIGHT
].count
6703 || !kw
[XBM_DATA
].count
)
6706 data
= kw
[XBM_DATA
].value
;
6707 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6708 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6710 /* Check type of data, and width and height against contents of
6716 /* Number of elements of the vector must be >= height. */
6717 if (XVECTOR (data
)->size
< height
)
6720 /* Each string or bool-vector in data must be large enough
6721 for one line of the image. */
6722 for (i
= 0; i
< height
; ++i
)
6724 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6728 if (XSTRING (elt
)->size
6729 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6732 else if (BOOL_VECTOR_P (elt
))
6734 if (XBOOL_VECTOR (elt
)->size
< width
)
6741 else if (STRINGP (data
))
6743 if (XSTRING (data
)->size
6744 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6747 else if (BOOL_VECTOR_P (data
))
6749 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6760 /* Scan a bitmap file. FP is the stream to read from. Value is
6761 either an enumerator from enum xbm_token, or a character for a
6762 single-character token, or 0 at end of file. If scanning an
6763 identifier, store the lexeme of the identifier in SVAL. If
6764 scanning a number, store its value in *IVAL. */
6767 xbm_scan (s
, end
, sval
, ival
)
6776 /* Skip white space. */
6777 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6782 else if (isdigit (c
))
6784 int value
= 0, digit
;
6786 if (c
== '0' && *s
< end
)
6789 if (c
== 'x' || c
== 'X')
6796 else if (c
>= 'a' && c
<= 'f')
6797 digit
= c
- 'a' + 10;
6798 else if (c
>= 'A' && c
<= 'F')
6799 digit
= c
- 'A' + 10;
6802 value
= 16 * value
+ digit
;
6805 else if (isdigit (c
))
6809 && (c
= *(*s
)++, isdigit (c
)))
6810 value
= 8 * value
+ c
- '0';
6817 && (c
= *(*s
)++, isdigit (c
)))
6818 value
= 10 * value
+ c
- '0';
6826 else if (isalpha (c
) || c
== '_')
6830 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6837 else if (c
== '/' && **s
== '*')
6839 /* C-style comment. */
6841 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6854 /* Replacement for XReadBitmapFileData which isn't available under old
6855 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6856 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6857 the image. Return in *DATA the bitmap data allocated with xmalloc.
6858 Value is non-zero if successful. DATA null means just test if
6859 CONTENTS looks like an in-memory XBM file. */
6862 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
6863 char *contents
, *end
;
6864 int *width
, *height
;
6865 unsigned char **data
;
6868 char buffer
[BUFSIZ
];
6871 int bytes_per_line
, i
, nbytes
;
6877 LA1 = xbm_scan (&s, end, buffer, &value)
6879 #define expect(TOKEN) \
6880 if (LA1 != (TOKEN)) \
6885 #define expect_ident(IDENT) \
6886 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6891 *width
= *height
= -1;
6894 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
6896 /* Parse defines for width, height and hot-spots. */
6900 expect_ident ("define");
6901 expect (XBM_TK_IDENT
);
6903 if (LA1
== XBM_TK_NUMBER
);
6905 char *p
= strrchr (buffer
, '_');
6906 p
= p
? p
+ 1 : buffer
;
6907 if (strcmp (p
, "width") == 0)
6909 else if (strcmp (p
, "height") == 0)
6912 expect (XBM_TK_NUMBER
);
6915 if (*width
< 0 || *height
< 0)
6917 else if (data
== NULL
)
6920 /* Parse bits. Must start with `static'. */
6921 expect_ident ("static");
6922 if (LA1
== XBM_TK_IDENT
)
6924 if (strcmp (buffer
, "unsigned") == 0)
6927 expect_ident ("char");
6929 else if (strcmp (buffer
, "short") == 0)
6933 if (*width
% 16 && *width
% 16 < 9)
6936 else if (strcmp (buffer
, "char") == 0)
6944 expect (XBM_TK_IDENT
);
6950 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6951 nbytes
= bytes_per_line
* *height
;
6952 p
= *data
= (char *) xmalloc (nbytes
);
6956 for (i
= 0; i
< nbytes
; i
+= 2)
6959 expect (XBM_TK_NUMBER
);
6962 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6965 if (LA1
== ',' || LA1
== '}')
6973 for (i
= 0; i
< nbytes
; ++i
)
6976 expect (XBM_TK_NUMBER
);
6980 if (LA1
== ',' || LA1
== '}')
7005 /* Load XBM image IMG which will be displayed on frame F from buffer
7006 CONTENTS. END is the end of the buffer. Value is non-zero if
7010 xbm_load_image (f
, img
, contents
, end
)
7013 char *contents
, *end
;
7016 unsigned char *data
;
7019 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
7022 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7023 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7024 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7027 xassert (img
->width
> 0 && img
->height
> 0);
7029 /* Get foreground and background colors, maybe allocate colors. */
7030 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
7032 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
7033 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7036 background
= x_alloc_image_color (f
, img
, value
, background
);
7037 img
->background
= background
;
7038 img
->background_valid
= 1;
7042 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7045 img
->width
, img
->height
,
7046 foreground
, background
,
7050 if (img
->pixmap
== None
)
7052 x_clear_image (f
, img
);
7053 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
7059 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7065 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7072 return (STRINGP (data
)
7073 && xbm_read_bitmap_data (XSTRING (data
)->data
,
7074 (XSTRING (data
)->data
7075 + STRING_BYTES (XSTRING (data
))),
7080 /* Fill image IMG which is used on frame F with pixmap data. Value is
7081 non-zero if successful. */
7089 Lisp_Object file_name
;
7091 xassert (xbm_image_p (img
->spec
));
7093 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7094 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7095 if (STRINGP (file_name
))
7100 struct gcpro gcpro1
;
7102 file
= x_find_image_file (file_name
);
7104 if (!STRINGP (file
))
7106 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7111 contents
= slurp_file (XSTRING (file
)->data
, &size
);
7112 if (contents
== NULL
)
7114 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7119 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
7124 struct image_keyword fmt
[XBM_LAST
];
7127 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7128 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7131 int in_memory_file_p
= 0;
7133 /* See if data looks like an in-memory XBM file. */
7134 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7135 in_memory_file_p
= xbm_file_p (data
);
7137 /* Parse the image specification. */
7138 bcopy (xbm_format
, fmt
, sizeof fmt
);
7139 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
7142 /* Get specified width, and height. */
7143 if (!in_memory_file_p
)
7145 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
7146 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
7147 xassert (img
->width
> 0 && img
->height
> 0);
7150 /* Get foreground and background colors, maybe allocate colors. */
7151 if (fmt
[XBM_FOREGROUND
].count
7152 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
7153 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
7155 if (fmt
[XBM_BACKGROUND
].count
7156 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
7157 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7160 if (in_memory_file_p
)
7161 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
7162 (XSTRING (data
)->data
7163 + STRING_BYTES (XSTRING (data
))));
7170 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7172 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7173 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7175 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7177 bcopy (XSTRING (line
)->data
, p
, nbytes
);
7179 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7182 else if (STRINGP (data
))
7183 bits
= XSTRING (data
)->data
;
7185 bits
= XBOOL_VECTOR (data
)->data
;
7187 /* Create the pixmap. */
7188 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7190 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7193 img
->width
, img
->height
,
7194 foreground
, background
,
7200 image_error ("Unable to create pixmap for XBM image `%s'",
7202 x_clear_image (f
, img
);
7212 /***********************************************************************
7214 ***********************************************************************/
7218 static int xpm_image_p
P_ ((Lisp_Object object
));
7219 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7220 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7222 #include "X11/xpm.h"
7224 /* The symbol `xpm' identifying XPM-format images. */
7228 /* Indices of image specification fields in xpm_format, below. */
7230 enum xpm_keyword_index
7246 /* Vector of image_keyword structures describing the format
7247 of valid XPM image specifications. */
7249 static struct image_keyword xpm_format
[XPM_LAST
] =
7251 {":type", IMAGE_SYMBOL_VALUE
, 1},
7252 {":file", IMAGE_STRING_VALUE
, 0},
7253 {":data", IMAGE_STRING_VALUE
, 0},
7254 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7255 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7256 {":relief", IMAGE_INTEGER_VALUE
, 0},
7257 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7258 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7259 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7260 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7261 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7264 /* Structure describing the image type XBM. */
7266 static struct image_type xpm_type
=
7276 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7277 functions for allocating image colors. Our own functions handle
7278 color allocation failures more gracefully than the ones on the XPM
7281 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7282 #define ALLOC_XPM_COLORS
7285 #ifdef ALLOC_XPM_COLORS
7287 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7288 static void xpm_free_color_cache
P_ ((void));
7289 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7290 static int xpm_color_bucket
P_ ((char *));
7291 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7294 /* An entry in a hash table used to cache color definitions of named
7295 colors. This cache is necessary to speed up XPM image loading in
7296 case we do color allocations ourselves. Without it, we would need
7297 a call to XParseColor per pixel in the image. */
7299 struct xpm_cached_color
7301 /* Next in collision chain. */
7302 struct xpm_cached_color
*next
;
7304 /* Color definition (RGB and pixel color). */
7311 /* The hash table used for the color cache, and its bucket vector
7314 #define XPM_COLOR_CACHE_BUCKETS 1001
7315 struct xpm_cached_color
**xpm_color_cache
;
7317 /* Initialize the color cache. */
7320 xpm_init_color_cache (f
, attrs
)
7322 XpmAttributes
*attrs
;
7324 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7325 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7326 memset (xpm_color_cache
, 0, nbytes
);
7327 init_color_table ();
7329 if (attrs
->valuemask
& XpmColorSymbols
)
7334 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7335 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7336 attrs
->colorsymbols
[i
].value
, &color
))
7338 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7340 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7346 /* Free the color cache. */
7349 xpm_free_color_cache ()
7351 struct xpm_cached_color
*p
, *next
;
7354 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7355 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7361 xfree (xpm_color_cache
);
7362 xpm_color_cache
= NULL
;
7363 free_color_table ();
7367 /* Return the bucket index for color named COLOR_NAME in the color
7371 xpm_color_bucket (color_name
)
7377 for (s
= color_name
; *s
; ++s
)
7379 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7383 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7384 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7387 static struct xpm_cached_color
*
7388 xpm_cache_color (f
, color_name
, color
, bucket
)
7395 struct xpm_cached_color
*p
;
7398 bucket
= xpm_color_bucket (color_name
);
7400 nbytes
= sizeof *p
+ strlen (color_name
);
7401 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7402 strcpy (p
->name
, color_name
);
7404 p
->next
= xpm_color_cache
[bucket
];
7405 xpm_color_cache
[bucket
] = p
;
7410 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7411 return the cached definition in *COLOR. Otherwise, make a new
7412 entry in the cache and allocate the color. Value is zero if color
7413 allocation failed. */
7416 xpm_lookup_color (f
, color_name
, color
)
7421 struct xpm_cached_color
*p
;
7422 int h
= xpm_color_bucket (color_name
);
7424 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7425 if (strcmp (p
->name
, color_name
) == 0)
7430 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7433 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7435 p
= xpm_cache_color (f
, color_name
, color
, h
);
7442 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7443 CLOSURE is a pointer to the frame on which we allocate the
7444 color. Return in *COLOR the allocated color. Value is non-zero
7448 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7455 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7459 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7460 is a pointer to the frame on which we allocate the color. Value is
7461 non-zero if successful. */
7464 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7474 #endif /* ALLOC_XPM_COLORS */
7477 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7478 for XPM images. Such a list must consist of conses whose car and
7482 xpm_valid_color_symbols_p (color_symbols
)
7483 Lisp_Object color_symbols
;
7485 while (CONSP (color_symbols
))
7487 Lisp_Object sym
= XCAR (color_symbols
);
7489 || !STRINGP (XCAR (sym
))
7490 || !STRINGP (XCDR (sym
)))
7492 color_symbols
= XCDR (color_symbols
);
7495 return NILP (color_symbols
);
7499 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7502 xpm_image_p (object
)
7505 struct image_keyword fmt
[XPM_LAST
];
7506 bcopy (xpm_format
, fmt
, sizeof fmt
);
7507 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7508 /* Either `:file' or `:data' must be present. */
7509 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7510 /* Either no `:color-symbols' or it's a list of conses
7511 whose car and cdr are strings. */
7512 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7513 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7517 /* Load image IMG which will be displayed on frame F. Value is
7518 non-zero if successful. */
7526 XpmAttributes attrs
;
7527 Lisp_Object specified_file
, color_symbols
;
7529 /* Configure the XPM lib. Use the visual of frame F. Allocate
7530 close colors. Return colors allocated. */
7531 bzero (&attrs
, sizeof attrs
);
7532 attrs
.visual
= FRAME_X_VISUAL (f
);
7533 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7534 attrs
.valuemask
|= XpmVisual
;
7535 attrs
.valuemask
|= XpmColormap
;
7537 #ifdef ALLOC_XPM_COLORS
7538 /* Allocate colors with our own functions which handle
7539 failing color allocation more gracefully. */
7540 attrs
.color_closure
= f
;
7541 attrs
.alloc_color
= xpm_alloc_color
;
7542 attrs
.free_colors
= xpm_free_colors
;
7543 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7544 #else /* not ALLOC_XPM_COLORS */
7545 /* Let the XPM lib allocate colors. */
7546 attrs
.valuemask
|= XpmReturnAllocPixels
;
7547 #ifdef XpmAllocCloseColors
7548 attrs
.alloc_close_colors
= 1;
7549 attrs
.valuemask
|= XpmAllocCloseColors
;
7550 #else /* not XpmAllocCloseColors */
7551 attrs
.closeness
= 600;
7552 attrs
.valuemask
|= XpmCloseness
;
7553 #endif /* not XpmAllocCloseColors */
7554 #endif /* ALLOC_XPM_COLORS */
7556 /* If image specification contains symbolic color definitions, add
7557 these to `attrs'. */
7558 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7559 if (CONSP (color_symbols
))
7562 XpmColorSymbol
*xpm_syms
;
7565 attrs
.valuemask
|= XpmColorSymbols
;
7567 /* Count number of symbols. */
7568 attrs
.numsymbols
= 0;
7569 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7572 /* Allocate an XpmColorSymbol array. */
7573 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7574 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7575 bzero (xpm_syms
, size
);
7576 attrs
.colorsymbols
= xpm_syms
;
7578 /* Fill the color symbol array. */
7579 for (tail
= color_symbols
, i
= 0;
7581 ++i
, tail
= XCDR (tail
))
7583 Lisp_Object name
= XCAR (XCAR (tail
));
7584 Lisp_Object color
= XCDR (XCAR (tail
));
7585 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7586 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7587 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7588 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7592 /* Create a pixmap for the image, either from a file, or from a
7593 string buffer containing data in the same format as an XPM file. */
7594 #ifdef ALLOC_XPM_COLORS
7595 xpm_init_color_cache (f
, &attrs
);
7598 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7599 if (STRINGP (specified_file
))
7601 Lisp_Object file
= x_find_image_file (specified_file
);
7602 if (!STRINGP (file
))
7604 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7608 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7609 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7614 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7615 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7616 XSTRING (buffer
)->data
,
7617 &img
->pixmap
, &img
->mask
,
7621 if (rc
== XpmSuccess
)
7623 #ifdef ALLOC_XPM_COLORS
7624 img
->colors
= colors_in_color_table (&img
->ncolors
);
7625 #else /* not ALLOC_XPM_COLORS */
7628 img
->ncolors
= attrs
.nalloc_pixels
;
7629 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7630 * sizeof *img
->colors
);
7631 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7633 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7634 #ifdef DEBUG_X_COLORS
7635 register_color (img
->colors
[i
]);
7638 #endif /* not ALLOC_XPM_COLORS */
7640 img
->width
= attrs
.width
;
7641 img
->height
= attrs
.height
;
7642 xassert (img
->width
> 0 && img
->height
> 0);
7644 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7645 XpmFreeAttributes (&attrs
);
7652 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7655 case XpmFileInvalid
:
7656 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7660 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7663 case XpmColorFailed
:
7664 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7668 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7673 #ifdef ALLOC_XPM_COLORS
7674 xpm_free_color_cache ();
7676 return rc
== XpmSuccess
;
7679 #endif /* HAVE_XPM != 0 */
7682 /***********************************************************************
7684 ***********************************************************************/
7686 /* An entry in the color table mapping an RGB color to a pixel color. */
7691 unsigned long pixel
;
7693 /* Next in color table collision list. */
7694 struct ct_color
*next
;
7697 /* The bucket vector size to use. Must be prime. */
7701 /* Value is a hash of the RGB color given by R, G, and B. */
7703 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7705 /* The color hash table. */
7707 struct ct_color
**ct_table
;
7709 /* Number of entries in the color table. */
7711 int ct_colors_allocated
;
7713 /* Initialize the color table. */
7718 int size
= CT_SIZE
* sizeof (*ct_table
);
7719 ct_table
= (struct ct_color
**) xmalloc (size
);
7720 bzero (ct_table
, size
);
7721 ct_colors_allocated
= 0;
7725 /* Free memory associated with the color table. */
7731 struct ct_color
*p
, *next
;
7733 for (i
= 0; i
< CT_SIZE
; ++i
)
7734 for (p
= ct_table
[i
]; p
; p
= next
)
7745 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7746 entry for that color already is in the color table, return the
7747 pixel color of that entry. Otherwise, allocate a new color for R,
7748 G, B, and make an entry in the color table. */
7750 static unsigned long
7751 lookup_rgb_color (f
, r
, g
, b
)
7755 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7756 int i
= hash
% CT_SIZE
;
7759 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7760 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7773 cmap
= FRAME_X_COLORMAP (f
);
7774 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7778 ++ct_colors_allocated
;
7780 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7784 p
->pixel
= color
.pixel
;
7785 p
->next
= ct_table
[i
];
7789 return FRAME_FOREGROUND_PIXEL (f
);
7796 /* Look up pixel color PIXEL which is used on frame F in the color
7797 table. If not already present, allocate it. Value is PIXEL. */
7799 static unsigned long
7800 lookup_pixel_color (f
, pixel
)
7802 unsigned long pixel
;
7804 int i
= pixel
% CT_SIZE
;
7807 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7808 if (p
->pixel
== pixel
)
7817 cmap
= FRAME_X_COLORMAP (f
);
7818 color
.pixel
= pixel
;
7819 x_query_color (f
, &color
);
7820 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7824 ++ct_colors_allocated
;
7826 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7831 p
->next
= ct_table
[i
];
7835 return FRAME_FOREGROUND_PIXEL (f
);
7842 /* Value is a vector of all pixel colors contained in the color table,
7843 allocated via xmalloc. Set *N to the number of colors. */
7845 static unsigned long *
7846 colors_in_color_table (n
)
7851 unsigned long *colors
;
7853 if (ct_colors_allocated
== 0)
7860 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7862 *n
= ct_colors_allocated
;
7864 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7865 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7866 colors
[j
++] = p
->pixel
;
7874 /***********************************************************************
7876 ***********************************************************************/
7878 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
7879 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
7880 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
7882 /* Non-zero means draw a cross on images having `:conversion
7885 int cross_disabled_images
;
7887 /* Edge detection matrices for different edge-detection
7890 static int emboss_matrix
[9] = {
7892 2, -1, 0, /* y - 1 */
7894 0, 1, -2 /* y + 1 */
7897 static int laplace_matrix
[9] = {
7899 1, 0, 0, /* y - 1 */
7901 0, 0, -1 /* y + 1 */
7904 /* Value is the intensity of the color whose red/green/blue values
7907 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7910 /* On frame F, return an array of XColor structures describing image
7911 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7912 non-zero means also fill the red/green/blue members of the XColor
7913 structures. Value is a pointer to the array of XColors structures,
7914 allocated with xmalloc; it must be freed by the caller. */
7917 x_to_xcolors (f
, img
, rgb_p
)
7926 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
7928 /* Get the X image IMG->pixmap. */
7929 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7930 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7932 /* Fill the `pixel' members of the XColor array. I wished there
7933 were an easy and portable way to circumvent XGetPixel. */
7935 for (y
= 0; y
< img
->height
; ++y
)
7939 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7940 p
->pixel
= XGetPixel (ximg
, x
, y
);
7943 x_query_colors (f
, row
, img
->width
);
7946 XDestroyImage (ximg
);
7951 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7952 RGB members are set. F is the frame on which this all happens.
7953 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7956 x_from_xcolors (f
, img
, colors
)
7966 init_color_table ();
7968 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
7971 for (y
= 0; y
< img
->height
; ++y
)
7972 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7974 unsigned long pixel
;
7975 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
7976 XPutPixel (oimg
, x
, y
, pixel
);
7980 x_clear_image_1 (f
, img
, 1, 0, 1);
7982 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7983 x_destroy_x_image (oimg
);
7984 img
->pixmap
= pixmap
;
7985 img
->colors
= colors_in_color_table (&img
->ncolors
);
7986 free_color_table ();
7990 /* On frame F, perform edge-detection on image IMG.
7992 MATRIX is a nine-element array specifying the transformation
7993 matrix. See emboss_matrix for an example.
7995 COLOR_ADJUST is a color adjustment added to each pixel of the
7999 x_detect_edges (f
, img
, matrix
, color_adjust
)
8002 int matrix
[9], color_adjust
;
8004 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8008 for (i
= sum
= 0; i
< 9; ++i
)
8009 sum
+= abs (matrix
[i
]);
8011 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8013 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
8015 for (y
= 0; y
< img
->height
; ++y
)
8017 p
= COLOR (new, 0, y
);
8018 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8019 p
= COLOR (new, img
->width
- 1, y
);
8020 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8023 for (x
= 1; x
< img
->width
- 1; ++x
)
8025 p
= COLOR (new, x
, 0);
8026 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8027 p
= COLOR (new, x
, img
->height
- 1);
8028 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8031 for (y
= 1; y
< img
->height
- 1; ++y
)
8033 p
= COLOR (new, 1, y
);
8035 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
8037 int r
, g
, b
, y1
, x1
;
8040 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
8041 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
8044 XColor
*t
= COLOR (colors
, x1
, y1
);
8045 r
+= matrix
[i
] * t
->red
;
8046 g
+= matrix
[i
] * t
->green
;
8047 b
+= matrix
[i
] * t
->blue
;
8050 r
= (r
/ sum
+ color_adjust
) & 0xffff;
8051 g
= (g
/ sum
+ color_adjust
) & 0xffff;
8052 b
= (b
/ sum
+ color_adjust
) & 0xffff;
8053 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
8058 x_from_xcolors (f
, img
, new);
8064 /* Perform the pre-defined `emboss' edge-detection on image IMG
8072 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
8076 /* Perform the pre-defined `laplace' edge-detection on image IMG
8084 x_detect_edges (f
, img
, laplace_matrix
, 45000);
8088 /* Perform edge-detection on image IMG on frame F, with specified
8089 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8091 MATRIX must be either
8093 - a list of at least 9 numbers in row-major form
8094 - a vector of at least 9 numbers
8096 COLOR_ADJUST nil means use a default; otherwise it must be a
8100 x_edge_detection (f
, img
, matrix
, color_adjust
)
8103 Lisp_Object matrix
, color_adjust
;
8111 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
8112 ++i
, matrix
= XCDR (matrix
))
8113 trans
[i
] = XFLOATINT (XCAR (matrix
));
8115 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
8117 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
8118 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
8121 if (NILP (color_adjust
))
8122 color_adjust
= make_number (0xffff / 2);
8124 if (i
== 9 && NUMBERP (color_adjust
))
8125 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
8129 /* Transform image IMG on frame F so that it looks disabled. */
8132 x_disable_image (f
, img
)
8136 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8138 if (dpyinfo
->n_planes
>= 2)
8140 /* Color (or grayscale). Convert to gray, and equalize. Just
8141 drawing such images with a stipple can look very odd, so
8142 we're using this method instead. */
8143 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8145 const int h
= 15000;
8146 const int l
= 30000;
8148 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
8152 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
8153 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
8154 p
->red
= p
->green
= p
->blue
= i2
;
8157 x_from_xcolors (f
, img
, colors
);
8160 /* Draw a cross over the disabled image, if we must or if we
8162 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
8164 Display
*dpy
= FRAME_X_DISPLAY (f
);
8167 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
8168 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
8169 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
8170 img
->width
- 1, img
->height
- 1);
8171 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
8177 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
8178 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8179 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8180 img
->width
- 1, img
->height
- 1);
8181 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8189 /* Build a mask for image IMG which is used on frame F. FILE is the
8190 name of an image file, for error messages. HOW determines how to
8191 determine the background color of IMG. If it is a list '(R G B)',
8192 with R, G, and B being integers >= 0, take that as the color of the
8193 background. Otherwise, determine the background color of IMG
8194 heuristically. Value is non-zero if successful. */
8197 x_build_heuristic_mask (f
, img
, how
)
8202 Display
*dpy
= FRAME_X_DISPLAY (f
);
8203 XImage
*ximg
, *mask_img
;
8204 int x
, y
, rc
, use_img_background
;
8205 unsigned long bg
= 0;
8209 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8211 img
->background_transparent_valid
= 0;
8214 /* Create an image and pixmap serving as mask. */
8215 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8216 &mask_img
, &img
->mask
);
8220 /* Get the X image of IMG->pixmap. */
8221 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8224 /* Determine the background color of ximg. If HOW is `(R G B)'
8225 take that as color. Otherwise, use the image's background color. */
8226 use_img_background
= 1;
8232 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
8234 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8238 if (i
== 3 && NILP (how
))
8240 char color_name
[30];
8241 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8242 bg
= x_alloc_image_color (f
, img
, build_string (color_name
), 0);
8243 use_img_background
= 0;
8247 if (use_img_background
)
8248 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
8250 /* Set all bits in mask_img to 1 whose color in ximg is different
8251 from the background color bg. */
8252 for (y
= 0; y
< img
->height
; ++y
)
8253 for (x
= 0; x
< img
->width
; ++x
)
8254 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8256 /* Fill in the background_transparent field while we have the mask handy. */
8257 image_background_transparent (img
, f
, mask_img
);
8259 /* Put mask_img into img->mask. */
8260 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8261 x_destroy_x_image (mask_img
);
8262 XDestroyImage (ximg
);
8269 /***********************************************************************
8270 PBM (mono, gray, color)
8271 ***********************************************************************/
8273 static int pbm_image_p
P_ ((Lisp_Object object
));
8274 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8275 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8277 /* The symbol `pbm' identifying images of this type. */
8281 /* Indices of image specification fields in gs_format, below. */
8283 enum pbm_keyword_index
8299 /* Vector of image_keyword structures describing the format
8300 of valid user-defined image specifications. */
8302 static struct image_keyword pbm_format
[PBM_LAST
] =
8304 {":type", IMAGE_SYMBOL_VALUE
, 1},
8305 {":file", IMAGE_STRING_VALUE
, 0},
8306 {":data", IMAGE_STRING_VALUE
, 0},
8307 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8308 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8309 {":relief", IMAGE_INTEGER_VALUE
, 0},
8310 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8311 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8312 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8313 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8314 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8317 /* Structure describing the image type `pbm'. */
8319 static struct image_type pbm_type
=
8329 /* Return non-zero if OBJECT is a valid PBM image specification. */
8332 pbm_image_p (object
)
8335 struct image_keyword fmt
[PBM_LAST
];
8337 bcopy (pbm_format
, fmt
, sizeof fmt
);
8339 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8342 /* Must specify either :data or :file. */
8343 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8347 /* Scan a decimal number from *S and return it. Advance *S while
8348 reading the number. END is the end of the string. Value is -1 at
8352 pbm_scan_number (s
, end
)
8353 unsigned char **s
, *end
;
8355 int c
= 0, val
= -1;
8359 /* Skip white-space. */
8360 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8365 /* Skip comment to end of line. */
8366 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8369 else if (isdigit (c
))
8371 /* Read decimal number. */
8373 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8374 val
= 10 * val
+ c
- '0';
8385 /* Load PBM image IMG for use on frame F. */
8393 int width
, height
, max_color_idx
= 0;
8395 Lisp_Object file
, specified_file
;
8396 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8397 struct gcpro gcpro1
;
8398 unsigned char *contents
= NULL
;
8399 unsigned char *end
, *p
;
8402 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8406 if (STRINGP (specified_file
))
8408 file
= x_find_image_file (specified_file
);
8409 if (!STRINGP (file
))
8411 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8416 contents
= slurp_file (XSTRING (file
)->data
, &size
);
8417 if (contents
== NULL
)
8419 image_error ("Error reading `%s'", file
, Qnil
);
8425 end
= contents
+ size
;
8430 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8431 p
= XSTRING (data
)->data
;
8432 end
= p
+ STRING_BYTES (XSTRING (data
));
8435 /* Check magic number. */
8436 if (end
- p
< 2 || *p
++ != 'P')
8438 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8448 raw_p
= 0, type
= PBM_MONO
;
8452 raw_p
= 0, type
= PBM_GRAY
;
8456 raw_p
= 0, type
= PBM_COLOR
;
8460 raw_p
= 1, type
= PBM_MONO
;
8464 raw_p
= 1, type
= PBM_GRAY
;
8468 raw_p
= 1, type
= PBM_COLOR
;
8472 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8476 /* Read width, height, maximum color-component. Characters
8477 starting with `#' up to the end of a line are ignored. */
8478 width
= pbm_scan_number (&p
, end
);
8479 height
= pbm_scan_number (&p
, end
);
8481 if (type
!= PBM_MONO
)
8483 max_color_idx
= pbm_scan_number (&p
, end
);
8484 if (raw_p
&& max_color_idx
> 255)
8485 max_color_idx
= 255;
8490 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8493 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8494 &ximg
, &img
->pixmap
))
8497 /* Initialize the color hash table. */
8498 init_color_table ();
8500 if (type
== PBM_MONO
)
8503 struct image_keyword fmt
[PBM_LAST
];
8504 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8505 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8507 /* Parse the image specification. */
8508 bcopy (pbm_format
, fmt
, sizeof fmt
);
8509 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8511 /* Get foreground and background colors, maybe allocate colors. */
8512 if (fmt
[PBM_FOREGROUND
].count
8513 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8514 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8515 if (fmt
[PBM_BACKGROUND
].count
8516 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8518 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8519 img
->background
= bg
;
8520 img
->background_valid
= 1;
8523 for (y
= 0; y
< height
; ++y
)
8524 for (x
= 0; x
< width
; ++x
)
8534 g
= pbm_scan_number (&p
, end
);
8536 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8541 for (y
= 0; y
< height
; ++y
)
8542 for (x
= 0; x
< width
; ++x
)
8546 if (type
== PBM_GRAY
)
8547 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8556 r
= pbm_scan_number (&p
, end
);
8557 g
= pbm_scan_number (&p
, end
);
8558 b
= pbm_scan_number (&p
, end
);
8561 if (r
< 0 || g
< 0 || b
< 0)
8565 XDestroyImage (ximg
);
8566 image_error ("Invalid pixel value in image `%s'",
8571 /* RGB values are now in the range 0..max_color_idx.
8572 Scale this to the range 0..0xffff supported by X. */
8573 r
= (double) r
* 65535 / max_color_idx
;
8574 g
= (double) g
* 65535 / max_color_idx
;
8575 b
= (double) b
* 65535 / max_color_idx
;
8576 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8580 /* Store in IMG->colors the colors allocated for the image, and
8581 free the color table. */
8582 img
->colors
= colors_in_color_table (&img
->ncolors
);
8583 free_color_table ();
8585 /* Maybe fill in the background field while we have ximg handy. */
8586 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8587 IMAGE_BACKGROUND (img
, f
, ximg
);
8589 /* Put the image into a pixmap. */
8590 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8591 x_destroy_x_image (ximg
);
8594 img
->height
= height
;
8603 /***********************************************************************
8605 ***********************************************************************/
8611 /* Function prototypes. */
8613 static int png_image_p
P_ ((Lisp_Object object
));
8614 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8616 /* The symbol `png' identifying images of this type. */
8620 /* Indices of image specification fields in png_format, below. */
8622 enum png_keyword_index
8637 /* Vector of image_keyword structures describing the format
8638 of valid user-defined image specifications. */
8640 static struct image_keyword png_format
[PNG_LAST
] =
8642 {":type", IMAGE_SYMBOL_VALUE
, 1},
8643 {":data", IMAGE_STRING_VALUE
, 0},
8644 {":file", IMAGE_STRING_VALUE
, 0},
8645 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8646 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8647 {":relief", IMAGE_INTEGER_VALUE
, 0},
8648 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8649 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8650 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8651 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8654 /* Structure describing the image type `png'. */
8656 static struct image_type png_type
=
8666 /* Return non-zero if OBJECT is a valid PNG image specification. */
8669 png_image_p (object
)
8672 struct image_keyword fmt
[PNG_LAST
];
8673 bcopy (png_format
, fmt
, sizeof fmt
);
8675 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8678 /* Must specify either the :data or :file keyword. */
8679 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8683 /* Error and warning handlers installed when the PNG library
8687 my_png_error (png_ptr
, msg
)
8688 png_struct
*png_ptr
;
8691 xassert (png_ptr
!= NULL
);
8692 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8693 longjmp (png_ptr
->jmpbuf
, 1);
8698 my_png_warning (png_ptr
, msg
)
8699 png_struct
*png_ptr
;
8702 xassert (png_ptr
!= NULL
);
8703 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8706 /* Memory source for PNG decoding. */
8708 struct png_memory_storage
8710 unsigned char *bytes
; /* The data */
8711 size_t len
; /* How big is it? */
8712 int index
; /* Where are we? */
8716 /* Function set as reader function when reading PNG image from memory.
8717 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8718 bytes from the input to DATA. */
8721 png_read_from_memory (png_ptr
, data
, length
)
8722 png_structp png_ptr
;
8726 struct png_memory_storage
*tbr
8727 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8729 if (length
> tbr
->len
- tbr
->index
)
8730 png_error (png_ptr
, "Read error");
8732 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8733 tbr
->index
= tbr
->index
+ length
;
8736 /* Load PNG image IMG for use on frame F. Value is non-zero if
8744 Lisp_Object file
, specified_file
;
8745 Lisp_Object specified_data
;
8747 XImage
*ximg
, *mask_img
= NULL
;
8748 struct gcpro gcpro1
;
8749 png_struct
*png_ptr
= NULL
;
8750 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8751 FILE *volatile fp
= NULL
;
8753 png_byte
* volatile pixels
= NULL
;
8754 png_byte
** volatile rows
= NULL
;
8755 png_uint_32 width
, height
;
8756 int bit_depth
, color_type
, interlace_type
;
8758 png_uint_32 row_bytes
;
8761 double screen_gamma
, image_gamma
;
8763 struct png_memory_storage tbr
; /* Data to be read */
8765 /* Find out what file to load. */
8766 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8767 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8771 if (NILP (specified_data
))
8773 file
= x_find_image_file (specified_file
);
8774 if (!STRINGP (file
))
8776 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8781 /* Open the image file. */
8782 fp
= fopen (XSTRING (file
)->data
, "rb");
8785 image_error ("Cannot open image file `%s'", file
, Qnil
);
8791 /* Check PNG signature. */
8792 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8793 || !png_check_sig (sig
, sizeof sig
))
8795 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8803 /* Read from memory. */
8804 tbr
.bytes
= XSTRING (specified_data
)->data
;
8805 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8808 /* Check PNG signature. */
8809 if (tbr
.len
< sizeof sig
8810 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8812 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8817 /* Need to skip past the signature. */
8818 tbr
.bytes
+= sizeof (sig
);
8821 /* Initialize read and info structs for PNG lib. */
8822 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8823 my_png_error
, my_png_warning
);
8826 if (fp
) fclose (fp
);
8831 info_ptr
= png_create_info_struct (png_ptr
);
8834 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8835 if (fp
) fclose (fp
);
8840 end_info
= png_create_info_struct (png_ptr
);
8843 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8844 if (fp
) fclose (fp
);
8849 /* Set error jump-back. We come back here when the PNG library
8850 detects an error. */
8851 if (setjmp (png_ptr
->jmpbuf
))
8855 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8858 if (fp
) fclose (fp
);
8863 /* Read image info. */
8864 if (!NILP (specified_data
))
8865 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
8867 png_init_io (png_ptr
, fp
);
8869 png_set_sig_bytes (png_ptr
, sizeof sig
);
8870 png_read_info (png_ptr
, info_ptr
);
8871 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8872 &interlace_type
, NULL
, NULL
);
8874 /* If image contains simply transparency data, we prefer to
8875 construct a clipping mask. */
8876 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8881 /* This function is easier to write if we only have to handle
8882 one data format: RGB or RGBA with 8 bits per channel. Let's
8883 transform other formats into that format. */
8885 /* Strip more than 8 bits per channel. */
8886 if (bit_depth
== 16)
8887 png_set_strip_16 (png_ptr
);
8889 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8891 png_set_expand (png_ptr
);
8893 /* Convert grayscale images to RGB. */
8894 if (color_type
== PNG_COLOR_TYPE_GRAY
8895 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
8896 png_set_gray_to_rgb (png_ptr
);
8898 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8899 gamma_str
= getenv ("SCREEN_GAMMA");
8900 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
8902 /* Tell the PNG lib to handle gamma correction for us. */
8904 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8905 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
8906 /* There is a special chunk in the image specifying the gamma. */
8907 png_set_sRGB (png_ptr
, info_ptr
, intent
);
8910 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
8911 /* Image contains gamma information. */
8912 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
8914 /* Use a default of 0.5 for the image gamma. */
8915 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
8917 /* Handle alpha channel by combining the image with a background
8918 color. Do this only if a real alpha channel is supplied. For
8919 simple transparency, we prefer a clipping mask. */
8922 png_color_16
*image_bg
;
8923 Lisp_Object specified_bg
8924 = image_spec_value (img
->spec
, QCbackground
, NULL
);
8926 if (STRINGP (specified_bg
))
8927 /* The user specified `:background', use that. */
8930 if (x_defined_color (f
, XSTRING (specified_bg
)->data
, &color
, 0))
8932 png_color_16 user_bg
;
8934 bzero (&user_bg
, sizeof user_bg
);
8935 user_bg
.red
= color
.red
;
8936 user_bg
.green
= color
.green
;
8937 user_bg
.blue
= color
.blue
;
8939 png_set_background (png_ptr
, &user_bg
,
8940 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8943 else if (png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
8944 /* Image contains a background color with which to
8945 combine the image. */
8946 png_set_background (png_ptr
, image_bg
,
8947 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
8950 /* Image does not contain a background color with which
8951 to combine the image data via an alpha channel. Use
8952 the frame's background instead. */
8955 png_color_16 frame_background
;
8957 cmap
= FRAME_X_COLORMAP (f
);
8958 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8959 x_query_color (f
, &color
);
8961 bzero (&frame_background
, sizeof frame_background
);
8962 frame_background
.red
= color
.red
;
8963 frame_background
.green
= color
.green
;
8964 frame_background
.blue
= color
.blue
;
8966 png_set_background (png_ptr
, &frame_background
,
8967 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8971 /* Update info structure. */
8972 png_read_update_info (png_ptr
, info_ptr
);
8974 /* Get number of channels. Valid values are 1 for grayscale images
8975 and images with a palette, 2 for grayscale images with transparency
8976 information (alpha channel), 3 for RGB images, and 4 for RGB
8977 images with alpha channel, i.e. RGBA. If conversions above were
8978 sufficient we should only have 3 or 4 channels here. */
8979 channels
= png_get_channels (png_ptr
, info_ptr
);
8980 xassert (channels
== 3 || channels
== 4);
8982 /* Number of bytes needed for one row of the image. */
8983 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
8985 /* Allocate memory for the image. */
8986 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
8987 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
8988 for (i
= 0; i
< height
; ++i
)
8989 rows
[i
] = pixels
+ i
* row_bytes
;
8991 /* Read the entire image. */
8992 png_read_image (png_ptr
, rows
);
8993 png_read_end (png_ptr
, info_ptr
);
9000 /* Create the X image and pixmap. */
9001 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
9005 /* Create an image and pixmap serving as mask if the PNG image
9006 contains an alpha channel. */
9009 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
9010 &mask_img
, &img
->mask
))
9012 x_destroy_x_image (ximg
);
9013 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
9018 /* Fill the X image and mask from PNG data. */
9019 init_color_table ();
9021 for (y
= 0; y
< height
; ++y
)
9023 png_byte
*p
= rows
[y
];
9025 for (x
= 0; x
< width
; ++x
)
9032 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
9034 /* An alpha channel, aka mask channel, associates variable
9035 transparency with an image. Where other image formats
9036 support binary transparency---fully transparent or fully
9037 opaque---PNG allows up to 254 levels of partial transparency.
9038 The PNG library implements partial transparency by combining
9039 the image with a specified background color.
9041 I'm not sure how to handle this here nicely: because the
9042 background on which the image is displayed may change, for
9043 real alpha channel support, it would be necessary to create
9044 a new image for each possible background.
9046 What I'm doing now is that a mask is created if we have
9047 boolean transparency information. Otherwise I'm using
9048 the frame's background color to combine the image with. */
9053 XPutPixel (mask_img
, x
, y
, *p
> 0);
9059 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9060 /* Set IMG's background color from the PNG image, unless the user
9064 if (png_get_bKGD (png_ptr
, info_ptr
, &bg
))
9066 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
9067 img
->background_valid
= 1;
9071 /* Remember colors allocated for this image. */
9072 img
->colors
= colors_in_color_table (&img
->ncolors
);
9073 free_color_table ();
9076 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9081 img
->height
= height
;
9083 /* Maybe fill in the background field while we have ximg handy. */
9084 IMAGE_BACKGROUND (img
, f
, ximg
);
9086 /* Put the image into the pixmap, then free the X image and its buffer. */
9087 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9088 x_destroy_x_image (ximg
);
9090 /* Same for the mask. */
9093 /* Fill in the background_transparent field while we have the mask
9095 image_background_transparent (img
, f
, mask_img
);
9097 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
9098 x_destroy_x_image (mask_img
);
9105 #endif /* HAVE_PNG != 0 */
9109 /***********************************************************************
9111 ***********************************************************************/
9115 /* Work around a warning about HAVE_STDLIB_H being redefined in
9117 #ifdef HAVE_STDLIB_H
9118 #define HAVE_STDLIB_H_1
9119 #undef HAVE_STDLIB_H
9120 #endif /* HAVE_STLIB_H */
9122 #include <jpeglib.h>
9126 #ifdef HAVE_STLIB_H_1
9127 #define HAVE_STDLIB_H 1
9130 static int jpeg_image_p
P_ ((Lisp_Object object
));
9131 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
9133 /* The symbol `jpeg' identifying images of this type. */
9137 /* Indices of image specification fields in gs_format, below. */
9139 enum jpeg_keyword_index
9148 JPEG_HEURISTIC_MASK
,
9154 /* Vector of image_keyword structures describing the format
9155 of valid user-defined image specifications. */
9157 static struct image_keyword jpeg_format
[JPEG_LAST
] =
9159 {":type", IMAGE_SYMBOL_VALUE
, 1},
9160 {":data", IMAGE_STRING_VALUE
, 0},
9161 {":file", IMAGE_STRING_VALUE
, 0},
9162 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9163 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9164 {":relief", IMAGE_INTEGER_VALUE
, 0},
9165 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9166 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9167 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9168 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9171 /* Structure describing the image type `jpeg'. */
9173 static struct image_type jpeg_type
=
9183 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9186 jpeg_image_p (object
)
9189 struct image_keyword fmt
[JPEG_LAST
];
9191 bcopy (jpeg_format
, fmt
, sizeof fmt
);
9193 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
9196 /* Must specify either the :data or :file keyword. */
9197 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9201 struct my_jpeg_error_mgr
9203 struct jpeg_error_mgr pub
;
9204 jmp_buf setjmp_buffer
;
9209 my_error_exit (cinfo
)
9212 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9213 longjmp (mgr
->setjmp_buffer
, 1);
9217 /* Init source method for JPEG data source manager. Called by
9218 jpeg_read_header() before any data is actually read. See
9219 libjpeg.doc from the JPEG lib distribution. */
9222 our_init_source (cinfo
)
9223 j_decompress_ptr cinfo
;
9228 /* Fill input buffer method for JPEG data source manager. Called
9229 whenever more data is needed. We read the whole image in one step,
9230 so this only adds a fake end of input marker at the end. */
9233 our_fill_input_buffer (cinfo
)
9234 j_decompress_ptr cinfo
;
9236 /* Insert a fake EOI marker. */
9237 struct jpeg_source_mgr
*src
= cinfo
->src
;
9238 static JOCTET buffer
[2];
9240 buffer
[0] = (JOCTET
) 0xFF;
9241 buffer
[1] = (JOCTET
) JPEG_EOI
;
9243 src
->next_input_byte
= buffer
;
9244 src
->bytes_in_buffer
= 2;
9249 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9250 is the JPEG data source manager. */
9253 our_skip_input_data (cinfo
, num_bytes
)
9254 j_decompress_ptr cinfo
;
9257 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9261 if (num_bytes
> src
->bytes_in_buffer
)
9262 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9264 src
->bytes_in_buffer
-= num_bytes
;
9265 src
->next_input_byte
+= num_bytes
;
9270 /* Method to terminate data source. Called by
9271 jpeg_finish_decompress() after all data has been processed. */
9274 our_term_source (cinfo
)
9275 j_decompress_ptr cinfo
;
9280 /* Set up the JPEG lib for reading an image from DATA which contains
9281 LEN bytes. CINFO is the decompression info structure created for
9282 reading the image. */
9285 jpeg_memory_src (cinfo
, data
, len
)
9286 j_decompress_ptr cinfo
;
9290 struct jpeg_source_mgr
*src
;
9292 if (cinfo
->src
== NULL
)
9294 /* First time for this JPEG object? */
9295 cinfo
->src
= (struct jpeg_source_mgr
*)
9296 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9297 sizeof (struct jpeg_source_mgr
));
9298 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9299 src
->next_input_byte
= data
;
9302 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9303 src
->init_source
= our_init_source
;
9304 src
->fill_input_buffer
= our_fill_input_buffer
;
9305 src
->skip_input_data
= our_skip_input_data
;
9306 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9307 src
->term_source
= our_term_source
;
9308 src
->bytes_in_buffer
= len
;
9309 src
->next_input_byte
= data
;
9313 /* Load image IMG for use on frame F. Patterned after example.c
9314 from the JPEG lib. */
9321 struct jpeg_decompress_struct cinfo
;
9322 struct my_jpeg_error_mgr mgr
;
9323 Lisp_Object file
, specified_file
;
9324 Lisp_Object specified_data
;
9325 FILE * volatile fp
= NULL
;
9327 int row_stride
, x
, y
;
9328 XImage
*ximg
= NULL
;
9330 unsigned long *colors
;
9332 struct gcpro gcpro1
;
9334 /* Open the JPEG file. */
9335 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9336 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9340 if (NILP (specified_data
))
9342 file
= x_find_image_file (specified_file
);
9343 if (!STRINGP (file
))
9345 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9350 fp
= fopen (XSTRING (file
)->data
, "r");
9353 image_error ("Cannot open `%s'", file
, Qnil
);
9359 /* Customize libjpeg's error handling to call my_error_exit when an
9360 error is detected. This function will perform a longjmp. */
9361 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9362 mgr
.pub
.error_exit
= my_error_exit
;
9364 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9368 /* Called from my_error_exit. Display a JPEG error. */
9369 char buffer
[JMSG_LENGTH_MAX
];
9370 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9371 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9372 build_string (buffer
));
9375 /* Close the input file and destroy the JPEG object. */
9377 fclose ((FILE *) fp
);
9378 jpeg_destroy_decompress (&cinfo
);
9380 /* If we already have an XImage, free that. */
9381 x_destroy_x_image (ximg
);
9383 /* Free pixmap and colors. */
9384 x_clear_image (f
, img
);
9390 /* Create the JPEG decompression object. Let it read from fp.
9391 Read the JPEG image header. */
9392 jpeg_create_decompress (&cinfo
);
9394 if (NILP (specified_data
))
9395 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9397 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
9398 STRING_BYTES (XSTRING (specified_data
)));
9400 jpeg_read_header (&cinfo
, TRUE
);
9402 /* Customize decompression so that color quantization will be used.
9403 Start decompression. */
9404 cinfo
.quantize_colors
= TRUE
;
9405 jpeg_start_decompress (&cinfo
);
9406 width
= img
->width
= cinfo
.output_width
;
9407 height
= img
->height
= cinfo
.output_height
;
9409 /* Create X image and pixmap. */
9410 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9411 longjmp (mgr
.setjmp_buffer
, 2);
9413 /* Allocate colors. When color quantization is used,
9414 cinfo.actual_number_of_colors has been set with the number of
9415 colors generated, and cinfo.colormap is a two-dimensional array
9416 of color indices in the range 0..cinfo.actual_number_of_colors.
9417 No more than 255 colors will be generated. */
9421 if (cinfo
.out_color_components
> 2)
9422 ir
= 0, ig
= 1, ib
= 2;
9423 else if (cinfo
.out_color_components
> 1)
9424 ir
= 0, ig
= 1, ib
= 0;
9426 ir
= 0, ig
= 0, ib
= 0;
9428 /* Use the color table mechanism because it handles colors that
9429 cannot be allocated nicely. Such colors will be replaced with
9430 a default color, and we don't have to care about which colors
9431 can be freed safely, and which can't. */
9432 init_color_table ();
9433 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9436 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9438 /* Multiply RGB values with 255 because X expects RGB values
9439 in the range 0..0xffff. */
9440 int r
= cinfo
.colormap
[ir
][i
] << 8;
9441 int g
= cinfo
.colormap
[ig
][i
] << 8;
9442 int b
= cinfo
.colormap
[ib
][i
] << 8;
9443 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9446 /* Remember those colors actually allocated. */
9447 img
->colors
= colors_in_color_table (&img
->ncolors
);
9448 free_color_table ();
9452 row_stride
= width
* cinfo
.output_components
;
9453 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9455 for (y
= 0; y
< height
; ++y
)
9457 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9458 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9459 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9463 jpeg_finish_decompress (&cinfo
);
9464 jpeg_destroy_decompress (&cinfo
);
9466 fclose ((FILE *) fp
);
9468 /* Maybe fill in the background field while we have ximg handy. */
9469 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9470 IMAGE_BACKGROUND (img
, f
, ximg
);
9472 /* Put the image into the pixmap. */
9473 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9474 x_destroy_x_image (ximg
);
9479 #endif /* HAVE_JPEG */
9483 /***********************************************************************
9485 ***********************************************************************/
9491 static int tiff_image_p
P_ ((Lisp_Object object
));
9492 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9494 /* The symbol `tiff' identifying images of this type. */
9498 /* Indices of image specification fields in tiff_format, below. */
9500 enum tiff_keyword_index
9509 TIFF_HEURISTIC_MASK
,
9515 /* Vector of image_keyword structures describing the format
9516 of valid user-defined image specifications. */
9518 static struct image_keyword tiff_format
[TIFF_LAST
] =
9520 {":type", IMAGE_SYMBOL_VALUE
, 1},
9521 {":data", IMAGE_STRING_VALUE
, 0},
9522 {":file", IMAGE_STRING_VALUE
, 0},
9523 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9524 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9525 {":relief", IMAGE_INTEGER_VALUE
, 0},
9526 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9527 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9528 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9529 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9532 /* Structure describing the image type `tiff'. */
9534 static struct image_type tiff_type
=
9544 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9547 tiff_image_p (object
)
9550 struct image_keyword fmt
[TIFF_LAST
];
9551 bcopy (tiff_format
, fmt
, sizeof fmt
);
9553 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9556 /* Must specify either the :data or :file keyword. */
9557 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9561 /* Reading from a memory buffer for TIFF images Based on the PNG
9562 memory source, but we have to provide a lot of extra functions.
9565 We really only need to implement read and seek, but I am not
9566 convinced that the TIFF library is smart enough not to destroy
9567 itself if we only hand it the function pointers we need to
9572 unsigned char *bytes
;
9580 tiff_read_from_memory (data
, buf
, size
)
9585 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9587 if (size
> src
->len
- src
->index
)
9589 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9596 tiff_write_from_memory (data
, buf
, size
)
9606 tiff_seek_in_memory (data
, off
, whence
)
9611 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9616 case SEEK_SET
: /* Go from beginning of source. */
9620 case SEEK_END
: /* Go from end of source. */
9621 idx
= src
->len
+ off
;
9624 case SEEK_CUR
: /* Go from current position. */
9625 idx
= src
->index
+ off
;
9628 default: /* Invalid `whence'. */
9632 if (idx
> src
->len
|| idx
< 0)
9641 tiff_close_memory (data
)
9650 tiff_mmap_memory (data
, pbase
, psize
)
9655 /* It is already _IN_ memory. */
9661 tiff_unmap_memory (data
, base
, size
)
9666 /* We don't need to do this. */
9671 tiff_size_of_memory (data
)
9674 return ((tiff_memory_source
*) data
)->len
;
9679 tiff_error_handler (title
, format
, ap
)
9680 const char *title
, *format
;
9686 len
= sprintf (buf
, "TIFF error: %s ", title
);
9687 vsprintf (buf
+ len
, format
, ap
);
9688 add_to_log (buf
, Qnil
, Qnil
);
9693 tiff_warning_handler (title
, format
, ap
)
9694 const char *title
, *format
;
9700 len
= sprintf (buf
, "TIFF warning: %s ", title
);
9701 vsprintf (buf
+ len
, format
, ap
);
9702 add_to_log (buf
, Qnil
, Qnil
);
9706 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9714 Lisp_Object file
, specified_file
;
9715 Lisp_Object specified_data
;
9717 int width
, height
, x
, y
;
9721 struct gcpro gcpro1
;
9722 tiff_memory_source memsrc
;
9724 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9725 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9729 TIFFSetErrorHandler (tiff_error_handler
);
9730 TIFFSetWarningHandler (tiff_warning_handler
);
9732 if (NILP (specified_data
))
9734 /* Read from a file */
9735 file
= x_find_image_file (specified_file
);
9736 if (!STRINGP (file
))
9738 image_error ("Cannot find image file `%s'", file
, Qnil
);
9743 /* Try to open the image file. */
9744 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9747 image_error ("Cannot open `%s'", file
, Qnil
);
9754 /* Memory source! */
9755 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9756 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9759 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9760 (TIFFReadWriteProc
) tiff_read_from_memory
,
9761 (TIFFReadWriteProc
) tiff_write_from_memory
,
9762 tiff_seek_in_memory
,
9764 tiff_size_of_memory
,
9770 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9776 /* Get width and height of the image, and allocate a raster buffer
9777 of width x height 32-bit values. */
9778 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9779 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9780 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9782 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9786 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9792 /* Create the X image and pixmap. */
9793 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9800 /* Initialize the color table. */
9801 init_color_table ();
9803 /* Process the pixel raster. Origin is in the lower-left corner. */
9804 for (y
= 0; y
< height
; ++y
)
9806 uint32
*row
= buf
+ y
* width
;
9808 for (x
= 0; x
< width
; ++x
)
9810 uint32 abgr
= row
[x
];
9811 int r
= TIFFGetR (abgr
) << 8;
9812 int g
= TIFFGetG (abgr
) << 8;
9813 int b
= TIFFGetB (abgr
) << 8;
9814 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9818 /* Remember the colors allocated for the image. Free the color table. */
9819 img
->colors
= colors_in_color_table (&img
->ncolors
);
9820 free_color_table ();
9823 img
->height
= height
;
9825 /* Maybe fill in the background field while we have ximg handy. */
9826 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9827 IMAGE_BACKGROUND (img
, f
, ximg
);
9829 /* Put the image into the pixmap, then free the X image and its buffer. */
9830 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9831 x_destroy_x_image (ximg
);
9838 #endif /* HAVE_TIFF != 0 */
9842 /***********************************************************************
9844 ***********************************************************************/
9848 #include <gif_lib.h>
9850 static int gif_image_p
P_ ((Lisp_Object object
));
9851 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9853 /* The symbol `gif' identifying images of this type. */
9857 /* Indices of image specification fields in gif_format, below. */
9859 enum gif_keyword_index
9875 /* Vector of image_keyword structures describing the format
9876 of valid user-defined image specifications. */
9878 static struct image_keyword gif_format
[GIF_LAST
] =
9880 {":type", IMAGE_SYMBOL_VALUE
, 1},
9881 {":data", IMAGE_STRING_VALUE
, 0},
9882 {":file", IMAGE_STRING_VALUE
, 0},
9883 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9884 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9885 {":relief", IMAGE_INTEGER_VALUE
, 0},
9886 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9887 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9888 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9889 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
9890 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9893 /* Structure describing the image type `gif'. */
9895 static struct image_type gif_type
=
9905 /* Return non-zero if OBJECT is a valid GIF image specification. */
9908 gif_image_p (object
)
9911 struct image_keyword fmt
[GIF_LAST
];
9912 bcopy (gif_format
, fmt
, sizeof fmt
);
9914 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
9917 /* Must specify either the :data or :file keyword. */
9918 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
9922 /* Reading a GIF image from memory
9923 Based on the PNG memory stuff to a certain extent. */
9927 unsigned char *bytes
;
9934 /* Make the current memory source available to gif_read_from_memory.
9935 It's done this way because not all versions of libungif support
9936 a UserData field in the GifFileType structure. */
9937 static gif_memory_source
*current_gif_memory_src
;
9940 gif_read_from_memory (file
, buf
, len
)
9945 gif_memory_source
*src
= current_gif_memory_src
;
9947 if (len
> src
->len
- src
->index
)
9950 bcopy (src
->bytes
+ src
->index
, buf
, len
);
9956 /* Load GIF image IMG for use on frame F. Value is non-zero if
9964 Lisp_Object file
, specified_file
;
9965 Lisp_Object specified_data
;
9966 int rc
, width
, height
, x
, y
, i
;
9968 ColorMapObject
*gif_color_map
;
9969 unsigned long pixel_colors
[256];
9971 struct gcpro gcpro1
;
9973 int ino
, image_left
, image_top
, image_width
, image_height
;
9974 gif_memory_source memsrc
;
9975 unsigned char *raster
;
9977 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9978 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9982 if (NILP (specified_data
))
9984 file
= x_find_image_file (specified_file
);
9985 if (!STRINGP (file
))
9987 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9992 /* Open the GIF file. */
9993 gif
= DGifOpenFileName (XSTRING (file
)->data
);
9996 image_error ("Cannot open `%s'", file
, Qnil
);
10003 /* Read from memory! */
10004 current_gif_memory_src
= &memsrc
;
10005 memsrc
.bytes
= XSTRING (specified_data
)->data
;
10006 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
10009 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
10012 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
10018 /* Read entire contents. */
10019 rc
= DGifSlurp (gif
);
10020 if (rc
== GIF_ERROR
)
10022 image_error ("Error reading `%s'", img
->spec
, Qnil
);
10023 DGifCloseFile (gif
);
10028 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
10029 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
10030 if (ino
>= gif
->ImageCount
)
10032 image_error ("Invalid image number `%s' in image `%s'",
10034 DGifCloseFile (gif
);
10039 width
= img
->width
= gif
->SWidth
;
10040 height
= img
->height
= gif
->SHeight
;
10042 /* Create the X image and pixmap. */
10043 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
10045 DGifCloseFile (gif
);
10050 /* Allocate colors. */
10051 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
10052 if (!gif_color_map
)
10053 gif_color_map
= gif
->SColorMap
;
10054 init_color_table ();
10055 bzero (pixel_colors
, sizeof pixel_colors
);
10057 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
10059 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
10060 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
10061 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
10062 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
10065 img
->colors
= colors_in_color_table (&img
->ncolors
);
10066 free_color_table ();
10068 /* Clear the part of the screen image that are not covered by
10069 the image from the GIF file. Full animated GIF support
10070 requires more than can be done here (see the gif89 spec,
10071 disposal methods). Let's simply assume that the part
10072 not covered by a sub-image is in the frame's background color. */
10073 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
10074 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
10075 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
10076 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
10078 for (y
= 0; y
< image_top
; ++y
)
10079 for (x
= 0; x
< width
; ++x
)
10080 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10082 for (y
= image_top
+ image_height
; y
< height
; ++y
)
10083 for (x
= 0; x
< width
; ++x
)
10084 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10086 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
10088 for (x
= 0; x
< image_left
; ++x
)
10089 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10090 for (x
= image_left
+ image_width
; x
< width
; ++x
)
10091 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10094 /* Read the GIF image into the X image. We use a local variable
10095 `raster' here because RasterBits below is a char *, and invites
10096 problems with bytes >= 0x80. */
10097 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
10099 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
10101 static int interlace_start
[] = {0, 4, 2, 1};
10102 static int interlace_increment
[] = {8, 8, 4, 2};
10104 int row
= interlace_start
[0];
10108 for (y
= 0; y
< image_height
; y
++)
10110 if (row
>= image_height
)
10112 row
= interlace_start
[++pass
];
10113 while (row
>= image_height
)
10114 row
= interlace_start
[++pass
];
10117 for (x
= 0; x
< image_width
; x
++)
10119 int i
= raster
[(y
* image_width
) + x
];
10120 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
10124 row
+= interlace_increment
[pass
];
10129 for (y
= 0; y
< image_height
; ++y
)
10130 for (x
= 0; x
< image_width
; ++x
)
10132 int i
= raster
[y
* image_width
+ x
];
10133 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
10137 DGifCloseFile (gif
);
10139 /* Maybe fill in the background field while we have ximg handy. */
10140 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
10141 IMAGE_BACKGROUND (img
, f
, ximg
);
10143 /* Put the image into the pixmap, then free the X image and its buffer. */
10144 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10145 x_destroy_x_image (ximg
);
10151 #endif /* HAVE_GIF != 0 */
10155 /***********************************************************************
10157 ***********************************************************************/
10159 static int gs_image_p
P_ ((Lisp_Object object
));
10160 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
10161 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
10163 /* The symbol `postscript' identifying images of this type. */
10165 Lisp_Object Qpostscript
;
10167 /* Keyword symbols. */
10169 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
10171 /* Indices of image specification fields in gs_format, below. */
10173 enum gs_keyword_index
10191 /* Vector of image_keyword structures describing the format
10192 of valid user-defined image specifications. */
10194 static struct image_keyword gs_format
[GS_LAST
] =
10196 {":type", IMAGE_SYMBOL_VALUE
, 1},
10197 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10198 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10199 {":file", IMAGE_STRING_VALUE
, 1},
10200 {":loader", IMAGE_FUNCTION_VALUE
, 0},
10201 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
10202 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10203 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10204 {":relief", IMAGE_INTEGER_VALUE
, 0},
10205 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10206 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10207 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10208 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10211 /* Structure describing the image type `ghostscript'. */
10213 static struct image_type gs_type
=
10223 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10226 gs_clear_image (f
, img
)
10230 /* IMG->data.ptr_val may contain a recorded colormap. */
10231 xfree (img
->data
.ptr_val
);
10232 x_clear_image (f
, img
);
10236 /* Return non-zero if OBJECT is a valid Ghostscript image
10240 gs_image_p (object
)
10241 Lisp_Object object
;
10243 struct image_keyword fmt
[GS_LAST
];
10247 bcopy (gs_format
, fmt
, sizeof fmt
);
10249 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10252 /* Bounding box must be a list or vector containing 4 integers. */
10253 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10256 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10257 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10262 else if (VECTORP (tem
))
10264 if (XVECTOR (tem
)->size
!= 4)
10266 for (i
= 0; i
< 4; ++i
)
10267 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10277 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10286 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10287 struct gcpro gcpro1
, gcpro2
;
10289 double in_width
, in_height
;
10290 Lisp_Object pixel_colors
= Qnil
;
10292 /* Compute pixel size of pixmap needed from the given size in the
10293 image specification. Sizes in the specification are in pt. 1 pt
10294 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10296 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10297 in_width
= XFASTINT (pt_width
) / 72.0;
10298 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10299 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10300 in_height
= XFASTINT (pt_height
) / 72.0;
10301 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10303 /* Create the pixmap. */
10304 xassert (img
->pixmap
== None
);
10305 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10306 img
->width
, img
->height
,
10307 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10311 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10315 /* Call the loader to fill the pixmap. It returns a process object
10316 if successful. We do not record_unwind_protect here because
10317 other places in redisplay like calling window scroll functions
10318 don't either. Let the Lisp loader use `unwind-protect' instead. */
10319 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10321 sprintf (buffer
, "%lu %lu",
10322 (unsigned long) FRAME_X_WINDOW (f
),
10323 (unsigned long) img
->pixmap
);
10324 window_and_pixmap_id
= build_string (buffer
);
10326 sprintf (buffer
, "%lu %lu",
10327 FRAME_FOREGROUND_PIXEL (f
),
10328 FRAME_BACKGROUND_PIXEL (f
));
10329 pixel_colors
= build_string (buffer
);
10331 XSETFRAME (frame
, f
);
10332 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10334 loader
= intern ("gs-load-image");
10336 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10337 make_number (img
->width
),
10338 make_number (img
->height
),
10339 window_and_pixmap_id
,
10342 return PROCESSP (img
->data
.lisp_val
);
10346 /* Kill the Ghostscript process that was started to fill PIXMAP on
10347 frame F. Called from XTread_socket when receiving an event
10348 telling Emacs that Ghostscript has finished drawing. */
10351 x_kill_gs_process (pixmap
, f
)
10355 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10359 /* Find the image containing PIXMAP. */
10360 for (i
= 0; i
< c
->used
; ++i
)
10361 if (c
->images
[i
]->pixmap
== pixmap
)
10364 /* Should someone in between have cleared the image cache, for
10365 instance, give up. */
10369 /* Kill the GS process. We should have found PIXMAP in the image
10370 cache and its image should contain a process object. */
10371 img
= c
->images
[i
];
10372 xassert (PROCESSP (img
->data
.lisp_val
));
10373 Fkill_process (img
->data
.lisp_val
, Qnil
);
10374 img
->data
.lisp_val
= Qnil
;
10376 /* On displays with a mutable colormap, figure out the colors
10377 allocated for the image by looking at the pixels of an XImage for
10379 class = FRAME_X_VISUAL (f
)->class;
10380 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10386 /* Try to get an XImage for img->pixmep. */
10387 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10388 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10393 /* Initialize the color table. */
10394 init_color_table ();
10396 /* For each pixel of the image, look its color up in the
10397 color table. After having done so, the color table will
10398 contain an entry for each color used by the image. */
10399 for (y
= 0; y
< img
->height
; ++y
)
10400 for (x
= 0; x
< img
->width
; ++x
)
10402 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10403 lookup_pixel_color (f
, pixel
);
10406 /* Record colors in the image. Free color table and XImage. */
10407 img
->colors
= colors_in_color_table (&img
->ncolors
);
10408 free_color_table ();
10409 XDestroyImage (ximg
);
10411 #if 0 /* This doesn't seem to be the case. If we free the colors
10412 here, we get a BadAccess later in x_clear_image when
10413 freeing the colors. */
10414 /* We have allocated colors once, but Ghostscript has also
10415 allocated colors on behalf of us. So, to get the
10416 reference counts right, free them once. */
10418 x_free_colors (f
, img
->colors
, img
->ncolors
);
10422 image_error ("Cannot get X image of `%s'; colors will not be freed",
10428 /* Now that we have the pixmap, compute mask and transform the
10429 image if requested. */
10431 postprocess_image (f
, img
);
10437 /***********************************************************************
10439 ***********************************************************************/
10441 DEFUN ("x-change-window-property", Fx_change_window_property
,
10442 Sx_change_window_property
, 2, 3, 0,
10443 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
10444 PROP and VALUE must be strings. FRAME nil or omitted means use the
10445 selected frame. Value is VALUE. */)
10446 (prop
, value
, frame
)
10447 Lisp_Object frame
, prop
, value
;
10449 struct frame
*f
= check_x_frame (frame
);
10452 CHECK_STRING (prop
);
10453 CHECK_STRING (value
);
10456 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10457 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10458 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10459 XSTRING (value
)->data
, XSTRING (value
)->size
);
10461 /* Make sure the property is set when we return. */
10462 XFlush (FRAME_X_DISPLAY (f
));
10469 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10470 Sx_delete_window_property
, 1, 2, 0,
10471 doc
: /* Remove window property PROP from X window of FRAME.
10472 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10474 Lisp_Object prop
, frame
;
10476 struct frame
*f
= check_x_frame (frame
);
10479 CHECK_STRING (prop
);
10481 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10482 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10484 /* Make sure the property is removed when we return. */
10485 XFlush (FRAME_X_DISPLAY (f
));
10492 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10494 doc
: /* Value is the value of window property PROP on FRAME.
10495 If FRAME is nil or omitted, use the selected frame. Value is nil
10496 if FRAME hasn't a property with name PROP or if PROP has no string
10499 Lisp_Object prop
, frame
;
10501 struct frame
*f
= check_x_frame (frame
);
10504 Lisp_Object prop_value
= Qnil
;
10505 char *tmp_data
= NULL
;
10508 unsigned long actual_size
, bytes_remaining
;
10510 CHECK_STRING (prop
);
10512 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10513 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10514 prop_atom
, 0, 0, False
, XA_STRING
,
10515 &actual_type
, &actual_format
, &actual_size
,
10516 &bytes_remaining
, (unsigned char **) &tmp_data
);
10519 int size
= bytes_remaining
;
10524 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10525 prop_atom
, 0, bytes_remaining
,
10527 &actual_type
, &actual_format
,
10528 &actual_size
, &bytes_remaining
,
10529 (unsigned char **) &tmp_data
);
10530 if (rc
== Success
&& tmp_data
)
10531 prop_value
= make_string (tmp_data
, size
);
10542 /***********************************************************************
10544 ***********************************************************************/
10546 /* If non-null, an asynchronous timer that, when it expires, displays
10547 an hourglass cursor on all frames. */
10549 static struct atimer
*hourglass_atimer
;
10551 /* Non-zero means an hourglass cursor is currently shown. */
10553 static int hourglass_shown_p
;
10555 /* Number of seconds to wait before displaying an hourglass cursor. */
10557 static Lisp_Object Vhourglass_delay
;
10559 /* Default number of seconds to wait before displaying an hourglass
10562 #define DEFAULT_HOURGLASS_DELAY 1
10564 /* Function prototypes. */
10566 static void show_hourglass
P_ ((struct atimer
*));
10567 static void hide_hourglass
P_ ((void));
10570 /* Cancel a currently active hourglass timer, and start a new one. */
10576 int secs
, usecs
= 0;
10578 cancel_hourglass ();
10580 if (INTEGERP (Vhourglass_delay
)
10581 && XINT (Vhourglass_delay
) > 0)
10582 secs
= XFASTINT (Vhourglass_delay
);
10583 else if (FLOATP (Vhourglass_delay
)
10584 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10587 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10588 secs
= XFASTINT (tem
);
10589 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10592 secs
= DEFAULT_HOURGLASS_DELAY
;
10594 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10595 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10596 show_hourglass
, NULL
);
10600 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10604 cancel_hourglass ()
10606 if (hourglass_atimer
)
10608 cancel_atimer (hourglass_atimer
);
10609 hourglass_atimer
= NULL
;
10612 if (hourglass_shown_p
)
10617 /* Timer function of hourglass_atimer. TIMER is equal to
10620 Display an hourglass pointer on all frames by mapping the frames'
10621 hourglass_window. Set the hourglass_p flag in the frames'
10622 output_data.x structure to indicate that an hourglass cursor is
10623 shown on the frames. */
10626 show_hourglass (timer
)
10627 struct atimer
*timer
;
10629 /* The timer implementation will cancel this timer automatically
10630 after this function has run. Set hourglass_atimer to null
10631 so that we know the timer doesn't have to be canceled. */
10632 hourglass_atimer
= NULL
;
10634 if (!hourglass_shown_p
)
10636 Lisp_Object rest
, frame
;
10640 FOR_EACH_FRAME (rest
, frame
)
10642 struct frame
*f
= XFRAME (frame
);
10644 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10646 Display
*dpy
= FRAME_X_DISPLAY (f
);
10648 #ifdef USE_X_TOOLKIT
10649 if (f
->output_data
.x
->widget
)
10651 if (FRAME_OUTER_WINDOW (f
))
10654 f
->output_data
.x
->hourglass_p
= 1;
10656 if (!f
->output_data
.x
->hourglass_window
)
10658 unsigned long mask
= CWCursor
;
10659 XSetWindowAttributes attrs
;
10661 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10663 f
->output_data
.x
->hourglass_window
10664 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10665 0, 0, 32000, 32000, 0, 0,
10671 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10677 hourglass_shown_p
= 1;
10683 /* Hide the hourglass pointer on all frames, if it is currently
10689 if (hourglass_shown_p
)
10691 Lisp_Object rest
, frame
;
10694 FOR_EACH_FRAME (rest
, frame
)
10696 struct frame
*f
= XFRAME (frame
);
10699 /* Watch out for newly created frames. */
10700 && f
->output_data
.x
->hourglass_window
)
10702 XUnmapWindow (FRAME_X_DISPLAY (f
),
10703 f
->output_data
.x
->hourglass_window
);
10704 /* Sync here because XTread_socket looks at the
10705 hourglass_p flag that is reset to zero below. */
10706 XSync (FRAME_X_DISPLAY (f
), False
);
10707 f
->output_data
.x
->hourglass_p
= 0;
10711 hourglass_shown_p
= 0;
10718 /***********************************************************************
10720 ***********************************************************************/
10722 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10723 Lisp_Object
, Lisp_Object
));
10724 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10725 Lisp_Object
, int, int, int *, int *));
10727 /* The frame of a currently visible tooltip. */
10729 Lisp_Object tip_frame
;
10731 /* If non-nil, a timer started that hides the last tooltip when it
10734 Lisp_Object tip_timer
;
10737 /* If non-nil, a vector of 3 elements containing the last args
10738 with which x-show-tip was called. See there. */
10740 Lisp_Object last_show_tip_args
;
10742 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10744 Lisp_Object Vx_max_tooltip_size
;
10748 unwind_create_tip_frame (frame
)
10751 Lisp_Object deleted
;
10753 deleted
= unwind_create_frame (frame
);
10754 if (EQ (deleted
, Qt
))
10764 /* Create a frame for a tooltip on the display described by DPYINFO.
10765 PARMS is a list of frame parameters. TEXT is the string to
10766 display in the tip frame. Value is the frame.
10768 Note that functions called here, esp. x_default_parameter can
10769 signal errors, for instance when a specified color name is
10770 undefined. We have to make sure that we're in a consistent state
10771 when this happens. */
10774 x_create_tip_frame (dpyinfo
, parms
, text
)
10775 struct x_display_info
*dpyinfo
;
10776 Lisp_Object parms
, text
;
10779 Lisp_Object frame
, tem
;
10781 long window_prompting
= 0;
10783 int count
= BINDING_STACK_SIZE ();
10784 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10786 int face_change_count_before
= face_change_count
;
10787 Lisp_Object buffer
;
10788 struct buffer
*old_buffer
;
10792 /* Use this general default value to start with until we know if
10793 this frame has a specified name. */
10794 Vx_resource_name
= Vinvocation_name
;
10796 #ifdef MULTI_KBOARD
10797 kb
= dpyinfo
->kboard
;
10799 kb
= &the_only_kboard
;
10802 /* Get the name of the frame to use for resource lookup. */
10803 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10804 if (!STRINGP (name
)
10805 && !EQ (name
, Qunbound
)
10807 error ("Invalid frame name--not a string or nil");
10808 Vx_resource_name
= name
;
10811 GCPRO3 (parms
, name
, frame
);
10812 f
= make_frame (1);
10813 XSETFRAME (frame
, f
);
10815 buffer
= Fget_buffer_create (build_string (" *tip*"));
10816 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10817 old_buffer
= current_buffer
;
10818 set_buffer_internal_1 (XBUFFER (buffer
));
10819 current_buffer
->truncate_lines
= Qnil
;
10821 Finsert (1, &text
);
10822 set_buffer_internal_1 (old_buffer
);
10824 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10825 record_unwind_protect (unwind_create_tip_frame
, frame
);
10827 /* By setting the output method, we're essentially saying that
10828 the frame is live, as per FRAME_LIVE_P. If we get a signal
10829 from this point on, x_destroy_window might screw up reference
10831 f
->output_method
= output_x_window
;
10832 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10833 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10834 f
->output_data
.x
->icon_bitmap
= -1;
10835 f
->output_data
.x
->fontset
= -1;
10836 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10837 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10838 #ifdef USE_TOOLKIT_SCROLL_BARS
10839 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
10840 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
10841 #endif /* USE_TOOLKIT_SCROLL_BARS */
10842 f
->icon_name
= Qnil
;
10843 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10845 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
10846 dpyinfo_refcount
= dpyinfo
->reference_count
;
10847 #endif /* GLYPH_DEBUG */
10848 #ifdef MULTI_KBOARD
10849 FRAME_KBOARD (f
) = kb
;
10851 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10852 f
->output_data
.x
->explicit_parent
= 0;
10854 /* These colors will be set anyway later, but it's important
10855 to get the color reference counts right, so initialize them! */
10858 struct gcpro gcpro1
;
10860 black
= build_string ("black");
10862 f
->output_data
.x
->foreground_pixel
10863 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10864 f
->output_data
.x
->background_pixel
10865 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10866 f
->output_data
.x
->cursor_pixel
10867 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10868 f
->output_data
.x
->cursor_foreground_pixel
10869 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10870 f
->output_data
.x
->border_pixel
10871 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10872 f
->output_data
.x
->mouse_pixel
10873 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10877 /* Set the name; the functions to which we pass f expect the name to
10879 if (EQ (name
, Qunbound
) || NILP (name
))
10881 f
->name
= build_string (dpyinfo
->x_id_name
);
10882 f
->explicit_name
= 0;
10887 f
->explicit_name
= 1;
10888 /* use the frame's title when getting resources for this frame. */
10889 specbind (Qx_resource_name
, name
);
10892 /* Extract the window parameters from the supplied values that are
10893 needed to determine window geometry. */
10897 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
10900 /* First, try whatever font the caller has specified. */
10901 if (STRINGP (font
))
10903 tem
= Fquery_fontset (font
, Qnil
);
10905 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
10907 font
= x_new_font (f
, XSTRING (font
)->data
);
10910 /* Try out a font which we hope has bold and italic variations. */
10911 if (!STRINGP (font
))
10912 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10913 if (!STRINGP (font
))
10914 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10915 if (! STRINGP (font
))
10916 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10917 if (! STRINGP (font
))
10918 /* This was formerly the first thing tried, but it finds too many fonts
10919 and takes too long. */
10920 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10921 /* If those didn't work, look for something which will at least work. */
10922 if (! STRINGP (font
))
10923 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10925 if (! STRINGP (font
))
10926 font
= build_string ("fixed");
10928 x_default_parameter (f
, parms
, Qfont
, font
,
10929 "font", "Font", RES_TYPE_STRING
);
10932 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
10933 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
10935 /* This defaults to 2 in order to match xterm. We recognize either
10936 internalBorderWidth or internalBorder (which is what xterm calls
10938 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10942 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
10943 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
10944 if (! EQ (value
, Qunbound
))
10945 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
10949 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
10950 "internalBorderWidth", "internalBorderWidth",
10953 /* Also do the stuff which must be set before the window exists. */
10954 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
10955 "foreground", "Foreground", RES_TYPE_STRING
);
10956 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
10957 "background", "Background", RES_TYPE_STRING
);
10958 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
10959 "pointerColor", "Foreground", RES_TYPE_STRING
);
10960 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
10961 "cursorColor", "Foreground", RES_TYPE_STRING
);
10962 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
10963 "borderColor", "BorderColor", RES_TYPE_STRING
);
10965 /* Init faces before x_default_parameter is called for scroll-bar
10966 parameters because that function calls x_set_scroll_bar_width,
10967 which calls change_frame_size, which calls Fset_window_buffer,
10968 which runs hooks, which call Fvertical_motion. At the end, we
10969 end up in init_iterator with a null face cache, which should not
10971 init_frame_faces (f
);
10973 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10974 window_prompting
= x_figure_window_size (f
, parms
);
10976 if (window_prompting
& XNegative
)
10978 if (window_prompting
& YNegative
)
10979 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
10981 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
10985 if (window_prompting
& YNegative
)
10986 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
10988 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10991 f
->output_data
.x
->size_hint_flags
= window_prompting
;
10993 XSetWindowAttributes attrs
;
10994 unsigned long mask
;
10997 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
10998 if (DoesSaveUnders (dpyinfo
->screen
))
10999 mask
|= CWSaveUnder
;
11001 /* Window managers look at the override-redirect flag to determine
11002 whether or net to give windows a decoration (Xlib spec, chapter
11004 attrs
.override_redirect
= True
;
11005 attrs
.save_under
= True
;
11006 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
11007 /* Arrange for getting MapNotify and UnmapNotify events. */
11008 attrs
.event_mask
= StructureNotifyMask
;
11010 = FRAME_X_WINDOW (f
)
11011 = XCreateWindow (FRAME_X_DISPLAY (f
),
11012 FRAME_X_DISPLAY_INFO (f
)->root_window
,
11013 /* x, y, width, height */
11017 CopyFromParent
, InputOutput
, CopyFromParent
,
11024 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
11025 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11026 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
11027 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11028 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
11029 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
11031 /* Dimensions, especially f->height, must be done via change_frame_size.
11032 Change will not be effected unless different from the current
11035 height
= f
->height
;
11037 SET_FRAME_WIDTH (f
, 0);
11038 change_frame_size (f
, height
, width
, 1, 0, 0);
11040 /* Set up faces after all frame parameters are known. This call
11041 also merges in face attributes specified for new frames.
11043 Frame parameters may be changed if .Xdefaults contains
11044 specifications for the default font. For example, if there is an
11045 `Emacs.default.attributeBackground: pink', the `background-color'
11046 attribute of the frame get's set, which let's the internal border
11047 of the tooltip frame appear in pink. Prevent this. */
11049 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
11051 /* Set tip_frame here, so that */
11053 call1 (Qface_set_after_frame_default
, frame
);
11055 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
11056 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
11064 /* It is now ok to make the frame official even if we get an error
11065 below. And the frame needs to be on Vframe_list or making it
11066 visible won't work. */
11067 Vframe_list
= Fcons (frame
, Vframe_list
);
11069 /* Now that the frame is official, it counts as a reference to
11071 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
11073 /* Setting attributes of faces of the tooltip frame from resources
11074 and similar will increment face_change_count, which leads to the
11075 clearing of all current matrices. Since this isn't necessary
11076 here, avoid it by resetting face_change_count to the value it
11077 had before we created the tip frame. */
11078 face_change_count
= face_change_count_before
;
11080 /* Discard the unwind_protect. */
11081 return unbind_to (count
, frame
);
11085 /* Compute where to display tip frame F. PARMS is the list of frame
11086 parameters for F. DX and DY are specified offsets from the current
11087 location of the mouse. WIDTH and HEIGHT are the width and height
11088 of the tooltip. Return coordinates relative to the root window of
11089 the display in *ROOT_X, and *ROOT_Y. */
11092 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
11094 Lisp_Object parms
, dx
, dy
;
11096 int *root_x
, *root_y
;
11098 Lisp_Object left
, top
;
11100 Window root
, child
;
11103 /* User-specified position? */
11104 left
= Fcdr (Fassq (Qleft
, parms
));
11105 top
= Fcdr (Fassq (Qtop
, parms
));
11107 /* Move the tooltip window where the mouse pointer is. Resize and
11109 if (!INTEGERP (left
) || !INTEGERP (top
))
11112 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
11113 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
11117 if (INTEGERP (top
))
11118 *root_y
= XINT (top
);
11119 else if (*root_y
+ XINT (dy
) - height
< 0)
11120 *root_y
-= XINT (dy
);
11124 *root_y
+= XINT (dy
);
11127 if (INTEGERP (left
))
11128 *root_x
= XINT (left
);
11129 else if (*root_x
+ XINT (dx
) + width
<= FRAME_X_DISPLAY_INFO (f
)->width
)
11130 /* It fits to the right of the pointer. */
11131 *root_x
+= XINT (dx
);
11132 else if (width
+ XINT (dx
) <= *root_x
)
11133 /* It fits to the left of the pointer. */
11134 *root_x
-= width
+ XINT (dx
);
11136 /* Put it left-justified on the screen--it ought to fit that way. */
11141 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
11142 doc
: /* Show STRING in a "tooltip" window on frame FRAME.
11143 A tooltip window is a small X window displaying a string.
11145 FRAME nil or omitted means use the selected frame.
11147 PARMS is an optional list of frame parameters which can be used to
11148 change the tooltip's appearance.
11150 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11151 means use the default timeout of 5 seconds.
11153 If the list of frame parameters PARAMS contains a `left' parameters,
11154 the tooltip is displayed at that x-position. Otherwise it is
11155 displayed at the mouse position, with offset DX added (default is 5 if
11156 DX isn't specified). Likewise for the y-position; if a `top' frame
11157 parameter is specified, it determines the y-position of the tooltip
11158 window, otherwise it is displayed at the mouse position, with offset
11159 DY added (default is -10).
11161 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11162 Text larger than the specified size is clipped. */)
11163 (string
, frame
, parms
, timeout
, dx
, dy
)
11164 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
11168 int root_x
, root_y
;
11169 struct buffer
*old_buffer
;
11170 struct text_pos pos
;
11171 int i
, width
, height
;
11172 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
11173 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
11174 int count
= BINDING_STACK_SIZE ();
11176 specbind (Qinhibit_redisplay
, Qt
);
11178 GCPRO4 (string
, parms
, frame
, timeout
);
11180 CHECK_STRING (string
);
11181 f
= check_x_frame (frame
);
11182 if (NILP (timeout
))
11183 timeout
= make_number (5);
11185 CHECK_NATNUM (timeout
);
11188 dx
= make_number (5);
11193 dy
= make_number (-10);
11197 if (NILP (last_show_tip_args
))
11198 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
11200 if (!NILP (tip_frame
))
11202 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
11203 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
11204 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
11206 if (EQ (frame
, last_frame
)
11207 && !NILP (Fequal (last_string
, string
))
11208 && !NILP (Fequal (last_parms
, parms
)))
11210 struct frame
*f
= XFRAME (tip_frame
);
11212 /* Only DX and DY have changed. */
11213 if (!NILP (tip_timer
))
11215 Lisp_Object timer
= tip_timer
;
11217 call1 (Qcancel_timer
, timer
);
11221 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
11222 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
11223 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11230 /* Hide a previous tip, if any. */
11233 ASET (last_show_tip_args
, 0, string
);
11234 ASET (last_show_tip_args
, 1, frame
);
11235 ASET (last_show_tip_args
, 2, parms
);
11237 /* Add default values to frame parameters. */
11238 if (NILP (Fassq (Qname
, parms
)))
11239 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
11240 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11241 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
11242 if (NILP (Fassq (Qborder_width
, parms
)))
11243 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
11244 if (NILP (Fassq (Qborder_color
, parms
)))
11245 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
11246 if (NILP (Fassq (Qbackground_color
, parms
)))
11247 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
11250 /* Create a frame for the tooltip, and record it in the global
11251 variable tip_frame. */
11252 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
11253 f
= XFRAME (frame
);
11255 /* Set up the frame's root window. */
11256 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
11257 w
->left
= w
->top
= make_number (0);
11259 if (CONSP (Vx_max_tooltip_size
)
11260 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11261 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11262 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11263 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11265 w
->width
= XCAR (Vx_max_tooltip_size
);
11266 w
->height
= XCDR (Vx_max_tooltip_size
);
11270 w
->width
= make_number (80);
11271 w
->height
= make_number (40);
11274 f
->window_width
= XINT (w
->width
);
11276 w
->pseudo_window_p
= 1;
11278 /* Display the tooltip text in a temporary buffer. */
11279 old_buffer
= current_buffer
;
11280 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11281 current_buffer
->truncate_lines
= Qnil
;
11282 clear_glyph_matrix (w
->desired_matrix
);
11283 clear_glyph_matrix (w
->current_matrix
);
11284 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11285 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11287 /* Compute width and height of the tooltip. */
11288 width
= height
= 0;
11289 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11291 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11292 struct glyph
*last
;
11295 /* Stop at the first empty row at the end. */
11296 if (!row
->enabled_p
|| !row
->displays_text_p
)
11299 /* Let the row go over the full width of the frame. */
11300 row
->full_width_p
= 1;
11302 /* There's a glyph at the end of rows that is used to place
11303 the cursor there. Don't include the width of this glyph. */
11304 if (row
->used
[TEXT_AREA
])
11306 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11307 row_width
= row
->pixel_width
- last
->pixel_width
;
11310 row_width
= row
->pixel_width
;
11312 height
+= row
->height
;
11313 width
= max (width
, row_width
);
11316 /* Add the frame's internal border to the width and height the X
11317 window should have. */
11318 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11319 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11321 /* Move the tooltip window where the mouse pointer is. Resize and
11323 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11326 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11327 root_x
, root_y
, width
, height
);
11328 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11331 /* Draw into the window. */
11332 w
->must_be_updated_p
= 1;
11333 update_single_window (w
, 1);
11335 /* Restore original current buffer. */
11336 set_buffer_internal_1 (old_buffer
);
11337 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11340 /* Let the tip disappear after timeout seconds. */
11341 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11342 intern ("x-hide-tip"));
11345 return unbind_to (count
, Qnil
);
11349 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11350 doc
: /* Hide the current tooltip window, if there is any.
11351 Value is t if tooltip was open, nil otherwise. */)
11355 Lisp_Object deleted
, frame
, timer
;
11356 struct gcpro gcpro1
, gcpro2
;
11358 /* Return quickly if nothing to do. */
11359 if (NILP (tip_timer
) && NILP (tip_frame
))
11364 GCPRO2 (frame
, timer
);
11365 tip_frame
= tip_timer
= deleted
= Qnil
;
11367 count
= BINDING_STACK_SIZE ();
11368 specbind (Qinhibit_redisplay
, Qt
);
11369 specbind (Qinhibit_quit
, Qt
);
11372 call1 (Qcancel_timer
, timer
);
11374 if (FRAMEP (frame
))
11376 Fdelete_frame (frame
, Qnil
);
11380 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11381 redisplay procedure is not called when a tip frame over menu
11382 items is unmapped. Redisplay the menu manually... */
11384 struct frame
*f
= SELECTED_FRAME ();
11385 Widget w
= f
->output_data
.x
->menubar_widget
;
11386 extern void xlwmenu_redisplay
P_ ((Widget
));
11388 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11392 xlwmenu_redisplay (w
);
11396 #endif /* USE_LUCID */
11400 return unbind_to (count
, deleted
);
11405 /***********************************************************************
11406 File selection dialog
11407 ***********************************************************************/
11411 /* Callback for "OK" and "Cancel" on file selection dialog. */
11414 file_dialog_cb (widget
, client_data
, call_data
)
11416 XtPointer call_data
, client_data
;
11418 int *result
= (int *) client_data
;
11419 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11420 *result
= cb
->reason
;
11424 /* Callback for unmapping a file selection dialog. This is used to
11425 capture the case where a dialog is closed via a window manager's
11426 closer button, for example. Using a XmNdestroyCallback didn't work
11430 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11432 XtPointer call_data
, client_data
;
11434 int *result
= (int *) client_data
;
11435 *result
= XmCR_CANCEL
;
11439 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11440 doc
: /* Read file name, prompting with PROMPT in directory DIR.
11441 Use a file selection dialog.
11442 Select DEFAULT-FILENAME in the dialog's file selection box, if
11443 specified. Don't let the user enter a file name in the file
11444 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11445 (prompt
, dir
, default_filename
, mustmatch
)
11446 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11449 struct frame
*f
= SELECTED_FRAME ();
11450 Lisp_Object file
= Qnil
;
11451 Widget dialog
, text
, list
, help
;
11454 extern XtAppContext Xt_app_con
;
11455 XmString dir_xmstring
, pattern_xmstring
;
11456 int count
= specpdl_ptr
- specpdl
;
11457 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11459 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11460 CHECK_STRING (prompt
);
11461 CHECK_STRING (dir
);
11463 /* Prevent redisplay. */
11464 specbind (Qinhibit_redisplay
, Qt
);
11468 /* Create the dialog with PROMPT as title, using DIR as initial
11469 directory and using "*" as pattern. */
11470 dir
= Fexpand_file_name (dir
, Qnil
);
11471 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
11472 pattern_xmstring
= XmStringCreateLocalized ("*");
11474 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
11475 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11476 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11477 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11478 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11479 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11481 XmStringFree (dir_xmstring
);
11482 XmStringFree (pattern_xmstring
);
11484 /* Add callbacks for OK and Cancel. */
11485 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11486 (XtPointer
) &result
);
11487 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11488 (XtPointer
) &result
);
11489 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11490 (XtPointer
) &result
);
11492 /* Disable the help button since we can't display help. */
11493 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11494 XtSetSensitive (help
, False
);
11496 /* Mark OK button as default. */
11497 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11498 XmNshowAsDefault
, True
, NULL
);
11500 /* If MUSTMATCH is non-nil, disable the file entry field of the
11501 dialog, so that the user must select a file from the files list
11502 box. We can't remove it because we wouldn't have a way to get at
11503 the result file name, then. */
11504 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11505 if (!NILP (mustmatch
))
11508 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11509 XtSetSensitive (text
, False
);
11510 XtSetSensitive (label
, False
);
11513 /* Manage the dialog, so that list boxes get filled. */
11514 XtManageChild (dialog
);
11516 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11517 must include the path for this to work. */
11518 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11519 if (STRINGP (default_filename
))
11521 XmString default_xmstring
;
11525 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
11527 if (!XmListItemExists (list
, default_xmstring
))
11529 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11530 XmListAddItem (list
, default_xmstring
, 0);
11534 item_pos
= XmListItemPos (list
, default_xmstring
);
11535 XmStringFree (default_xmstring
);
11537 /* Select the item and scroll it into view. */
11538 XmListSelectPos (list
, item_pos
, True
);
11539 XmListSetPos (list
, item_pos
);
11542 /* Process events until the user presses Cancel or OK. Block
11543 and unblock input here so that we get a chance of processing
11547 while (result
== 0)
11550 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11555 /* Get the result. */
11556 if (result
== XmCR_OK
)
11561 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11562 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11563 XmStringFree (text
);
11564 file
= build_string (data
);
11571 XtUnmanageChild (dialog
);
11572 XtDestroyWidget (dialog
);
11576 /* Make "Cancel" equivalent to C-g. */
11578 Fsignal (Qquit
, Qnil
);
11580 return unbind_to (count
, file
);
11583 #endif /* USE_MOTIF */
11587 /***********************************************************************
11589 ***********************************************************************/
11591 #ifdef HAVE_XKBGETKEYBOARD
11592 #include <X11/XKBlib.h>
11593 #include <X11/keysym.h>
11596 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11597 Sx_backspace_delete_keys_p
, 0, 1, 0,
11598 doc
: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11599 FRAME nil means use the selected frame.
11600 Value is t if we know that both keys are present, and are mapped to the
11601 usual X keysyms. */)
11605 #ifdef HAVE_XKBGETKEYBOARD
11607 struct frame
*f
= check_x_frame (frame
);
11608 Display
*dpy
= FRAME_X_DISPLAY (f
);
11609 Lisp_Object have_keys
;
11610 int major
, minor
, op
, event
, error
;
11614 /* Check library version in case we're dynamically linked. */
11615 major
= XkbMajorVersion
;
11616 minor
= XkbMinorVersion
;
11617 if (!XkbLibraryVersion (&major
, &minor
))
11623 /* Check that the server supports XKB. */
11624 major
= XkbMajorVersion
;
11625 minor
= XkbMinorVersion
;
11626 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11633 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11636 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11638 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11640 for (i
= kb
->min_key_code
;
11641 (i
< kb
->max_key_code
11642 && (delete_keycode
== 0 || backspace_keycode
== 0));
11645 /* The XKB symbolic key names can be seen most easily in
11646 the PS file generated by `xkbprint -label name
11648 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11649 delete_keycode
= i
;
11650 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11651 backspace_keycode
= i
;
11654 XkbFreeNames (kb
, 0, True
);
11657 XkbFreeClientMap (kb
, 0, True
);
11660 && backspace_keycode
11661 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11662 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11667 #else /* not HAVE_XKBGETKEYBOARD */
11669 #endif /* not HAVE_XKBGETKEYBOARD */
11674 /***********************************************************************
11676 ***********************************************************************/
11681 /* This is zero if not using X windows. */
11684 /* The section below is built by the lisp expression at the top of the file,
11685 just above where these variables are declared. */
11686 /*&&& init symbols here &&&*/
11687 Qauto_raise
= intern ("auto-raise");
11688 staticpro (&Qauto_raise
);
11689 Qauto_lower
= intern ("auto-lower");
11690 staticpro (&Qauto_lower
);
11691 Qbar
= intern ("bar");
11693 Qborder_color
= intern ("border-color");
11694 staticpro (&Qborder_color
);
11695 Qborder_width
= intern ("border-width");
11696 staticpro (&Qborder_width
);
11697 Qbox
= intern ("box");
11699 Qcursor_color
= intern ("cursor-color");
11700 staticpro (&Qcursor_color
);
11701 Qcursor_type
= intern ("cursor-type");
11702 staticpro (&Qcursor_type
);
11703 Qgeometry
= intern ("geometry");
11704 staticpro (&Qgeometry
);
11705 Qicon_left
= intern ("icon-left");
11706 staticpro (&Qicon_left
);
11707 Qicon_top
= intern ("icon-top");
11708 staticpro (&Qicon_top
);
11709 Qicon_type
= intern ("icon-type");
11710 staticpro (&Qicon_type
);
11711 Qicon_name
= intern ("icon-name");
11712 staticpro (&Qicon_name
);
11713 Qinternal_border_width
= intern ("internal-border-width");
11714 staticpro (&Qinternal_border_width
);
11715 Qleft
= intern ("left");
11716 staticpro (&Qleft
);
11717 Qright
= intern ("right");
11718 staticpro (&Qright
);
11719 Qmouse_color
= intern ("mouse-color");
11720 staticpro (&Qmouse_color
);
11721 Qnone
= intern ("none");
11722 staticpro (&Qnone
);
11723 Qparent_id
= intern ("parent-id");
11724 staticpro (&Qparent_id
);
11725 Qscroll_bar_width
= intern ("scroll-bar-width");
11726 staticpro (&Qscroll_bar_width
);
11727 Qsuppress_icon
= intern ("suppress-icon");
11728 staticpro (&Qsuppress_icon
);
11729 Qundefined_color
= intern ("undefined-color");
11730 staticpro (&Qundefined_color
);
11731 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11732 staticpro (&Qvertical_scroll_bars
);
11733 Qvisibility
= intern ("visibility");
11734 staticpro (&Qvisibility
);
11735 Qwindow_id
= intern ("window-id");
11736 staticpro (&Qwindow_id
);
11737 Qouter_window_id
= intern ("outer-window-id");
11738 staticpro (&Qouter_window_id
);
11739 Qx_frame_parameter
= intern ("x-frame-parameter");
11740 staticpro (&Qx_frame_parameter
);
11741 Qx_resource_name
= intern ("x-resource-name");
11742 staticpro (&Qx_resource_name
);
11743 Quser_position
= intern ("user-position");
11744 staticpro (&Quser_position
);
11745 Quser_size
= intern ("user-size");
11746 staticpro (&Quser_size
);
11747 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11748 staticpro (&Qscroll_bar_foreground
);
11749 Qscroll_bar_background
= intern ("scroll-bar-background");
11750 staticpro (&Qscroll_bar_background
);
11751 Qscreen_gamma
= intern ("screen-gamma");
11752 staticpro (&Qscreen_gamma
);
11753 Qline_spacing
= intern ("line-spacing");
11754 staticpro (&Qline_spacing
);
11755 Qcenter
= intern ("center");
11756 staticpro (&Qcenter
);
11757 Qcompound_text
= intern ("compound-text");
11758 staticpro (&Qcompound_text
);
11759 Qcancel_timer
= intern ("cancel-timer");
11760 staticpro (&Qcancel_timer
);
11761 Qwait_for_wm
= intern ("wait-for-wm");
11762 staticpro (&Qwait_for_wm
);
11763 /* This is the end of symbol initialization. */
11765 /* Text property `display' should be nonsticky by default. */
11766 Vtext_property_default_nonsticky
11767 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11770 Qlaplace
= intern ("laplace");
11771 staticpro (&Qlaplace
);
11772 Qemboss
= intern ("emboss");
11773 staticpro (&Qemboss
);
11774 Qedge_detection
= intern ("edge-detection");
11775 staticpro (&Qedge_detection
);
11776 Qheuristic
= intern ("heuristic");
11777 staticpro (&Qheuristic
);
11778 QCmatrix
= intern (":matrix");
11779 staticpro (&QCmatrix
);
11780 QCcolor_adjustment
= intern (":color-adjustment");
11781 staticpro (&QCcolor_adjustment
);
11782 QCmask
= intern (":mask");
11783 staticpro (&QCmask
);
11785 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11786 staticpro (&Qface_set_after_frame_default
);
11788 Fput (Qundefined_color
, Qerror_conditions
,
11789 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11790 Fput (Qundefined_color
, Qerror_message
,
11791 build_string ("Undefined color"));
11793 init_x_parm_symbols ();
11795 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11796 doc
: /* Non-nil means always draw a cross over disabled images.
11797 Disabled images are those having an `:conversion disabled' property.
11798 A cross is always drawn on black & white displays. */);
11799 cross_disabled_images
= 0;
11801 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11802 doc
: /* List of directories to search for bitmap files for X. */);
11803 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11805 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11806 doc
: /* The shape of the pointer when over text.
11807 Changing the value does not affect existing frames
11808 unless you set the mouse color. */);
11809 Vx_pointer_shape
= Qnil
;
11811 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11812 doc
: /* The name Emacs uses to look up X resources.
11813 `x-get-resource' uses this as the first component of the instance name
11814 when requesting resource values.
11815 Emacs initially sets `x-resource-name' to the name under which Emacs
11816 was invoked, or to the value specified with the `-name' or `-rn'
11817 switches, if present.
11819 It may be useful to bind this variable locally around a call
11820 to `x-get-resource'. See also the variable `x-resource-class'. */);
11821 Vx_resource_name
= Qnil
;
11823 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11824 doc
: /* The class Emacs uses to look up X resources.
11825 `x-get-resource' uses this as the first component of the instance class
11826 when requesting resource values.
11828 Emacs initially sets `x-resource-class' to "Emacs".
11830 Setting this variable permanently is not a reasonable thing to do,
11831 but binding this variable locally around a call to `x-get-resource'
11832 is a reasonable practice. See also the variable `x-resource-name'. */);
11833 Vx_resource_class
= build_string (EMACS_CLASS
);
11835 #if 0 /* This doesn't really do anything. */
11836 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11837 doc
: /* The shape of the pointer when not over text.
11838 This variable takes effect when you create a new frame
11839 or when you set the mouse color. */);
11841 Vx_nontext_pointer_shape
= Qnil
;
11843 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
11844 doc
: /* The shape of the pointer when Emacs is busy.
11845 This variable takes effect when you create a new frame
11846 or when you set the mouse color. */);
11847 Vx_hourglass_pointer_shape
= Qnil
;
11849 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
11850 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
11851 display_hourglass_p
= 1;
11853 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
11854 doc
: /* *Seconds to wait before displaying an hourglass pointer.
11855 Value must be an integer or float. */);
11856 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
11858 #if 0 /* This doesn't really do anything. */
11859 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
11860 doc
: /* The shape of the pointer when over the mode line.
11861 This variable takes effect when you create a new frame
11862 or when you set the mouse color. */);
11864 Vx_mode_pointer_shape
= Qnil
;
11866 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11867 &Vx_sensitive_text_pointer_shape
,
11868 doc
: /* The shape of the pointer when over mouse-sensitive text.
11869 This variable takes effect when you create a new frame
11870 or when you set the mouse color. */);
11871 Vx_sensitive_text_pointer_shape
= Qnil
;
11873 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11874 &Vx_window_horizontal_drag_shape
,
11875 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
11876 This variable takes effect when you create a new frame
11877 or when you set the mouse color. */);
11878 Vx_window_horizontal_drag_shape
= Qnil
;
11880 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
11881 doc
: /* A string indicating the foreground color of the cursor box. */);
11882 Vx_cursor_fore_pixel
= Qnil
;
11884 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
11885 doc
: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
11886 Text larger than this is clipped. */);
11887 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
11889 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
11890 doc
: /* Non-nil if no X window manager is in use.
11891 Emacs doesn't try to figure this out; this is always nil
11892 unless you set it to something else. */);
11893 /* We don't have any way to find this out, so set it to nil
11894 and maybe the user would like to set it to t. */
11895 Vx_no_window_manager
= Qnil
;
11897 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11898 &Vx_pixel_size_width_font_regexp
,
11899 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
11901 Since Emacs gets width of a font matching with this regexp from
11902 PIXEL_SIZE field of the name, font finding mechanism gets faster for
11903 such a font. This is especially effective for such large fonts as
11904 Chinese, Japanese, and Korean. */);
11905 Vx_pixel_size_width_font_regexp
= Qnil
;
11907 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
11908 doc
: /* Time after which cached images are removed from the cache.
11909 When an image has not been displayed this many seconds, remove it
11910 from the image cache. Value must be an integer or nil with nil
11911 meaning don't clear the cache. */);
11912 Vimage_cache_eviction_delay
= make_number (30 * 60);
11914 #ifdef USE_X_TOOLKIT
11915 Fprovide (intern ("x-toolkit"), Qnil
);
11917 Fprovide (intern ("motif"), Qnil
);
11919 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
11920 doc
: /* Version info for LessTif/Motif. */);
11921 Vmotif_version_string
= build_string (XmVERSION_STRING
);
11922 #endif /* USE_MOTIF */
11923 #endif /* USE_X_TOOLKIT */
11925 defsubr (&Sx_get_resource
);
11927 /* X window properties. */
11928 defsubr (&Sx_change_window_property
);
11929 defsubr (&Sx_delete_window_property
);
11930 defsubr (&Sx_window_property
);
11932 defsubr (&Sxw_display_color_p
);
11933 defsubr (&Sx_display_grayscale_p
);
11934 defsubr (&Sxw_color_defined_p
);
11935 defsubr (&Sxw_color_values
);
11936 defsubr (&Sx_server_max_request_size
);
11937 defsubr (&Sx_server_vendor
);
11938 defsubr (&Sx_server_version
);
11939 defsubr (&Sx_display_pixel_width
);
11940 defsubr (&Sx_display_pixel_height
);
11941 defsubr (&Sx_display_mm_width
);
11942 defsubr (&Sx_display_mm_height
);
11943 defsubr (&Sx_display_screens
);
11944 defsubr (&Sx_display_planes
);
11945 defsubr (&Sx_display_color_cells
);
11946 defsubr (&Sx_display_visual_class
);
11947 defsubr (&Sx_display_backing_store
);
11948 defsubr (&Sx_display_save_under
);
11949 defsubr (&Sx_parse_geometry
);
11950 defsubr (&Sx_create_frame
);
11951 defsubr (&Sx_open_connection
);
11952 defsubr (&Sx_close_connection
);
11953 defsubr (&Sx_display_list
);
11954 defsubr (&Sx_synchronize
);
11955 defsubr (&Sx_focus_frame
);
11956 defsubr (&Sx_backspace_delete_keys_p
);
11958 /* Setting callback functions for fontset handler. */
11959 get_font_info_func
= x_get_font_info
;
11961 #if 0 /* This function pointer doesn't seem to be used anywhere.
11962 And the pointer assigned has the wrong type, anyway. */
11963 list_fonts_func
= x_list_fonts
;
11966 load_font_func
= x_load_font
;
11967 find_ccl_program_func
= x_find_ccl_program
;
11968 query_font_func
= x_query_font
;
11969 set_frame_fontset_func
= x_set_font
;
11970 check_window_system_func
= check_x
;
11973 Qxbm
= intern ("xbm");
11975 QCtype
= intern (":type");
11976 staticpro (&QCtype
);
11977 QCconversion
= intern (":conversion");
11978 staticpro (&QCconversion
);
11979 QCheuristic_mask
= intern (":heuristic-mask");
11980 staticpro (&QCheuristic_mask
);
11981 QCcolor_symbols
= intern (":color-symbols");
11982 staticpro (&QCcolor_symbols
);
11983 QCascent
= intern (":ascent");
11984 staticpro (&QCascent
);
11985 QCmargin
= intern (":margin");
11986 staticpro (&QCmargin
);
11987 QCrelief
= intern (":relief");
11988 staticpro (&QCrelief
);
11989 Qpostscript
= intern ("postscript");
11990 staticpro (&Qpostscript
);
11991 QCloader
= intern (":loader");
11992 staticpro (&QCloader
);
11993 QCbounding_box
= intern (":bounding-box");
11994 staticpro (&QCbounding_box
);
11995 QCpt_width
= intern (":pt-width");
11996 staticpro (&QCpt_width
);
11997 QCpt_height
= intern (":pt-height");
11998 staticpro (&QCpt_height
);
11999 QCindex
= intern (":index");
12000 staticpro (&QCindex
);
12001 Qpbm
= intern ("pbm");
12005 Qxpm
= intern ("xpm");
12010 Qjpeg
= intern ("jpeg");
12011 staticpro (&Qjpeg
);
12015 Qtiff
= intern ("tiff");
12016 staticpro (&Qtiff
);
12020 Qgif
= intern ("gif");
12025 Qpng
= intern ("png");
12029 defsubr (&Sclear_image_cache
);
12030 defsubr (&Simage_size
);
12031 defsubr (&Simage_mask_p
);
12033 hourglass_atimer
= NULL
;
12034 hourglass_shown_p
= 0;
12036 defsubr (&Sx_show_tip
);
12037 defsubr (&Sx_hide_tip
);
12039 staticpro (&tip_timer
);
12041 staticpro (&tip_frame
);
12043 last_show_tip_args
= Qnil
;
12044 staticpro (&last_show_tip_args
);
12047 defsubr (&Sx_file_dialog
);
12055 image_types
= NULL
;
12056 Vimage_types
= Qnil
;
12058 define_image_type (&xbm_type
);
12059 define_image_type (&gs_type
);
12060 define_image_type (&pbm_type
);
12063 define_image_type (&xpm_type
);
12067 define_image_type (&jpeg_type
);
12071 define_image_type (&tiff_type
);
12075 define_image_type (&gif_type
);
12079 define_image_type (&png_type
);
12083 #endif /* HAVE_X_WINDOWS */