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
;
188 Lisp_Object Qborder_color
;
189 Lisp_Object Qborder_width
;
190 extern Lisp_Object Qbox
;
191 Lisp_Object Qcursor_color
;
192 Lisp_Object Qcursor_type
;
193 Lisp_Object Qgeometry
;
194 Lisp_Object Qicon_left
;
195 Lisp_Object Qicon_top
;
196 Lisp_Object Qicon_type
;
197 Lisp_Object Qicon_name
;
198 Lisp_Object Qinternal_border_width
;
201 Lisp_Object Qmouse_color
;
203 Lisp_Object Qouter_window_id
;
204 Lisp_Object Qparent_id
;
205 Lisp_Object Qscroll_bar_width
;
206 Lisp_Object Qsuppress_icon
;
207 extern Lisp_Object Qtop
;
208 Lisp_Object Qundefined_color
;
209 Lisp_Object Qvertical_scroll_bars
;
210 Lisp_Object Qvisibility
;
211 Lisp_Object Qwindow_id
;
212 Lisp_Object Qx_frame_parameter
;
213 Lisp_Object Qx_resource_name
;
214 Lisp_Object Quser_position
;
215 Lisp_Object Quser_size
;
216 extern Lisp_Object Qdisplay
;
217 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
218 Lisp_Object Qscreen_gamma
, Qline_spacing
, Qcenter
;
219 Lisp_Object Qcompound_text
, Qcancel_timer
;
220 Lisp_Object Qwait_for_wm
;
221 Lisp_Object Qfullscreen
;
222 Lisp_Object Qfullwidth
;
223 Lisp_Object Qfullheight
;
224 Lisp_Object Qfullboth
;
226 /* The below are defined in frame.c. */
228 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
229 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
230 extern Lisp_Object Qtool_bar_lines
;
232 extern Lisp_Object Vwindow_system_version
;
234 Lisp_Object Qface_set_after_frame_default
;
237 int image_cache_refcount
, dpyinfo_refcount
;
242 /* Error if we are not connected to X. */
248 error ("X windows are not in use or not initialized");
251 /* Nonzero if we can use mouse menus.
252 You should not call this unless HAVE_MENUS is defined. */
260 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
261 and checking validity for X. */
264 check_x_frame (frame
)
270 frame
= selected_frame
;
271 CHECK_LIVE_FRAME (frame
);
274 error ("Non-X frame used");
278 /* Let the user specify an X display with a frame.
279 nil stands for the selected frame--or, if that is not an X frame,
280 the first X display on the list. */
282 static struct x_display_info
*
283 check_x_display_info (frame
)
286 struct x_display_info
*dpyinfo
= NULL
;
290 struct frame
*sf
= XFRAME (selected_frame
);
292 if (FRAME_X_P (sf
) && FRAME_LIVE_P (sf
))
293 dpyinfo
= FRAME_X_DISPLAY_INFO (sf
);
294 else if (x_display_list
!= 0)
295 dpyinfo
= x_display_list
;
297 error ("X windows are not in use or not initialized");
299 else if (STRINGP (frame
))
300 dpyinfo
= x_display_info_for_name (frame
);
303 FRAME_PTR f
= check_x_frame (frame
);
304 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
311 /* Return the Emacs frame-object corresponding to an X window.
312 It could be the frame's main window or an icon window. */
314 /* This function can be called during GC, so use GC_xxx type test macros. */
317 x_window_to_frame (dpyinfo
, wdesc
)
318 struct x_display_info
*dpyinfo
;
321 Lisp_Object tail
, frame
;
324 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
327 if (!GC_FRAMEP (frame
))
330 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
332 if (f
->output_data
.x
->hourglass_window
== wdesc
)
335 if ((f
->output_data
.x
->edit_widget
336 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
337 /* A tooltip frame? */
338 || (!f
->output_data
.x
->edit_widget
339 && FRAME_X_WINDOW (f
) == wdesc
)
340 || f
->output_data
.x
->icon_desc
== wdesc
)
342 #else /* not USE_X_TOOLKIT */
343 if (FRAME_X_WINDOW (f
) == wdesc
344 || f
->output_data
.x
->icon_desc
== wdesc
)
346 #endif /* not USE_X_TOOLKIT */
352 /* Like x_window_to_frame but also compares the window with the widget's
356 x_any_window_to_frame (dpyinfo
, wdesc
)
357 struct x_display_info
*dpyinfo
;
360 Lisp_Object tail
, frame
;
361 struct frame
*f
, *found
;
365 for (tail
= Vframe_list
; GC_CONSP (tail
) && !found
; tail
= XCDR (tail
))
368 if (!GC_FRAMEP (frame
))
372 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
374 /* This frame matches if the window is any of its widgets. */
375 x
= f
->output_data
.x
;
376 if (x
->hourglass_window
== wdesc
)
380 if (wdesc
== XtWindow (x
->widget
)
381 || wdesc
== XtWindow (x
->column_widget
)
382 || wdesc
== XtWindow (x
->edit_widget
))
384 /* Match if the window is this frame's menubar. */
385 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
388 else if (FRAME_X_WINDOW (f
) == wdesc
)
389 /* A tooltip frame. */
397 /* Likewise, but exclude the menu bar widget. */
400 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
401 struct x_display_info
*dpyinfo
;
404 Lisp_Object tail
, frame
;
408 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
411 if (!GC_FRAMEP (frame
))
414 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
416 x
= f
->output_data
.x
;
417 /* This frame matches if the window is any of its widgets. */
418 if (x
->hourglass_window
== wdesc
)
422 if (wdesc
== XtWindow (x
->widget
)
423 || wdesc
== XtWindow (x
->column_widget
)
424 || wdesc
== XtWindow (x
->edit_widget
))
427 else if (FRAME_X_WINDOW (f
) == wdesc
)
428 /* A tooltip frame. */
434 /* Likewise, but consider only the menu bar widget. */
437 x_menubar_window_to_frame (dpyinfo
, wdesc
)
438 struct x_display_info
*dpyinfo
;
441 Lisp_Object tail
, frame
;
445 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
448 if (!GC_FRAMEP (frame
))
451 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
453 x
= f
->output_data
.x
;
454 /* Match if the window is this frame's menubar. */
455 if (x
->menubar_widget
456 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
462 /* Return the frame whose principal (outermost) window is WDESC.
463 If WDESC is some other (smaller) window, we return 0. */
466 x_top_window_to_frame (dpyinfo
, wdesc
)
467 struct x_display_info
*dpyinfo
;
470 Lisp_Object tail
, frame
;
474 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
477 if (!GC_FRAMEP (frame
))
480 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
482 x
= f
->output_data
.x
;
486 /* This frame matches if the window is its topmost widget. */
487 if (wdesc
== XtWindow (x
->widget
))
489 #if 0 /* I don't know why it did this,
490 but it seems logically wrong,
491 and it causes trouble for MapNotify events. */
492 /* Match if the window is this frame's menubar. */
493 if (x
->menubar_widget
494 && wdesc
== XtWindow (x
->menubar_widget
))
498 else if (FRAME_X_WINDOW (f
) == wdesc
)
504 #endif /* USE_X_TOOLKIT */
508 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
509 id, which is just an int that this section returns. Bitmaps are
510 reference counted so they can be shared among frames.
512 Bitmap indices are guaranteed to be > 0, so a negative number can
513 be used to indicate no bitmap.
515 If you use x_create_bitmap_from_data, then you must keep track of
516 the bitmaps yourself. That is, creating a bitmap from the same
517 data more than once will not be caught. */
520 /* Functions to access the contents of a bitmap, given an id. */
523 x_bitmap_height (f
, id
)
527 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
531 x_bitmap_width (f
, id
)
535 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
539 x_bitmap_pixmap (f
, id
)
543 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
547 /* Allocate a new bitmap record. Returns index of new record. */
550 x_allocate_bitmap_record (f
)
553 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
556 if (dpyinfo
->bitmaps
== NULL
)
558 dpyinfo
->bitmaps_size
= 10;
560 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
561 dpyinfo
->bitmaps_last
= 1;
565 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
566 return ++dpyinfo
->bitmaps_last
;
568 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
569 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
572 dpyinfo
->bitmaps_size
*= 2;
574 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
575 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
576 return ++dpyinfo
->bitmaps_last
;
579 /* Add one reference to the reference count of the bitmap with id ID. */
582 x_reference_bitmap (f
, id
)
586 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
589 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
592 x_create_bitmap_from_data (f
, bits
, width
, height
)
595 unsigned int width
, height
;
597 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
601 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
602 bits
, width
, height
);
607 id
= x_allocate_bitmap_record (f
);
608 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
609 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
610 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
611 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
612 dpyinfo
->bitmaps
[id
- 1].height
= height
;
613 dpyinfo
->bitmaps
[id
- 1].width
= width
;
618 /* Create bitmap from file FILE for frame F. */
621 x_create_bitmap_from_file (f
, file
)
625 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
626 unsigned int width
, height
;
628 int xhot
, yhot
, result
, id
;
633 /* Look for an existing bitmap with the same name. */
634 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
636 if (dpyinfo
->bitmaps
[id
].refcount
637 && dpyinfo
->bitmaps
[id
].file
638 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
640 ++dpyinfo
->bitmaps
[id
].refcount
;
645 /* Search bitmap-file-path for the file, if appropriate. */
646 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
651 filename
= (char *) SDATA (found
);
653 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
654 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
655 if (result
!= BitmapSuccess
)
658 id
= x_allocate_bitmap_record (f
);
659 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
660 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
661 dpyinfo
->bitmaps
[id
- 1].file
662 = (char *) xmalloc (SBYTES (file
) + 1);
663 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
664 dpyinfo
->bitmaps
[id
- 1].height
= height
;
665 dpyinfo
->bitmaps
[id
- 1].width
= width
;
666 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
671 /* Remove reference to bitmap with id number ID. */
674 x_destroy_bitmap (f
, id
)
678 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
682 --dpyinfo
->bitmaps
[id
- 1].refcount
;
683 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
686 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
687 if (dpyinfo
->bitmaps
[id
- 1].file
)
689 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
690 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
697 /* Free all the bitmaps for the display specified by DPYINFO. */
700 x_destroy_all_bitmaps (dpyinfo
)
701 struct x_display_info
*dpyinfo
;
704 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
705 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
707 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
708 if (dpyinfo
->bitmaps
[i
].file
)
709 xfree (dpyinfo
->bitmaps
[i
].file
);
711 dpyinfo
->bitmaps_last
= 0;
714 /* Connect the frame-parameter names for X frames
715 to the ways of passing the parameter values to the window system.
717 The name of a parameter, as a Lisp symbol,
718 has an `x-frame-parameter' property which is an integer in Lisp
719 that is an index in this table. */
721 struct x_frame_parm_table
724 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
727 static Lisp_Object unwind_create_frame
P_ ((Lisp_Object
));
728 static Lisp_Object unwind_create_tip_frame
P_ ((Lisp_Object
));
729 static void x_change_window_heights
P_ ((Lisp_Object
, int));
730 static void x_disable_image
P_ ((struct frame
*, struct image
*));
731 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
732 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
733 static void x_set_wait_for_wm
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
734 static void x_set_fullscreen
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
735 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
736 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
737 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
738 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
739 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
740 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
741 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
742 static void x_set_fringe_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
743 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
744 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
745 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
747 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
748 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
749 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
750 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
752 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
753 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
754 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
755 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
756 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
757 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
758 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
760 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
762 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
767 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
768 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
770 static void init_color_table
P_ ((void));
771 static void free_color_table
P_ ((void));
772 static unsigned long *colors_in_color_table
P_ ((int *n
));
773 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
774 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
778 static struct x_frame_parm_table x_frame_parms
[] =
780 {"auto-raise", x_set_autoraise
},
781 {"auto-lower", x_set_autolower
},
782 {"background-color", x_set_background_color
},
783 {"border-color", x_set_border_color
},
784 {"border-width", x_set_border_width
},
785 {"cursor-color", x_set_cursor_color
},
786 {"cursor-type", x_set_cursor_type
},
787 {"font", x_set_font
},
788 {"foreground-color", x_set_foreground_color
},
789 {"icon-name", x_set_icon_name
},
790 {"icon-type", x_set_icon_type
},
791 {"internal-border-width", x_set_internal_border_width
},
792 {"menu-bar-lines", x_set_menu_bar_lines
},
793 {"mouse-color", x_set_mouse_color
},
794 {"name", x_explicitly_set_name
},
795 {"scroll-bar-width", x_set_scroll_bar_width
},
796 {"title", x_set_title
},
797 {"unsplittable", x_set_unsplittable
},
798 {"vertical-scroll-bars", x_set_vertical_scroll_bars
},
799 {"visibility", x_set_visibility
},
800 {"tool-bar-lines", x_set_tool_bar_lines
},
801 {"scroll-bar-foreground", x_set_scroll_bar_foreground
},
802 {"scroll-bar-background", x_set_scroll_bar_background
},
803 {"screen-gamma", x_set_screen_gamma
},
804 {"line-spacing", x_set_line_spacing
},
805 {"left-fringe", x_set_fringe_width
},
806 {"right-fringe", x_set_fringe_width
},
807 {"wait-for-wm", x_set_wait_for_wm
},
808 {"fullscreen", x_set_fullscreen
},
812 /* Attach the `x-frame-parameter' properties to
813 the Lisp symbol names of parameters relevant to X. */
816 init_x_parm_symbols ()
820 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
821 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
826 /* Really try to move where we want to be in case of fullscreen. Some WMs
827 moves the window where we tell them. Some (mwm, twm) moves the outer
828 window manager window there instead.
829 Try to compensate for those WM here. */
831 x_fullscreen_move (f
, new_top
, new_left
)
836 if (new_top
!= f
->output_data
.x
->top_pos
837 || new_left
!= f
->output_data
.x
->left_pos
)
839 int move_x
= new_left
+ f
->output_data
.x
->x_pixels_outer_diff
;
840 int move_y
= new_top
+ f
->output_data
.x
->y_pixels_outer_diff
;
842 f
->output_data
.x
->want_fullscreen
|= FULLSCREEN_MOVE_WAIT
;
843 x_set_offset (f
, move_x
, move_y
, 1);
847 /* Change the parameters of frame F as specified by ALIST.
848 If a parameter is not specially recognized, do nothing special;
849 otherwise call the `x_set_...' function for that parameter.
850 Except for certain geometry properties, always call store_frame_param
851 to store the new value in the parameter alist. */
854 x_set_frame_parameters (f
, alist
)
860 /* If both of these parameters are present, it's more efficient to
861 set them both at once. So we wait until we've looked at the
862 entire list before we set them. */
866 Lisp_Object left
, top
;
868 /* Same with these. */
869 Lisp_Object icon_left
, icon_top
;
871 /* Record in these vectors all the parms specified. */
875 int left_no_change
= 0, top_no_change
= 0;
876 int icon_left_no_change
= 0, icon_top_no_change
= 0;
877 int fullscreen_is_being_set
= 0;
879 struct gcpro gcpro1
, gcpro2
;
882 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
885 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
886 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
888 /* Extract parm names and values into those vectors. */
891 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
896 parms
[i
] = Fcar (elt
);
897 values
[i
] = Fcdr (elt
);
900 /* TAIL and ALIST are not used again below here. */
903 GCPRO2 (*parms
, *values
);
907 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
908 because their values appear in VALUES and strings are not valid. */
909 top
= left
= Qunbound
;
910 icon_left
= icon_top
= Qunbound
;
912 /* Provide default values for HEIGHT and WIDTH. */
913 if (FRAME_NEW_WIDTH (f
))
914 width
= FRAME_NEW_WIDTH (f
);
916 width
= FRAME_WIDTH (f
);
918 if (FRAME_NEW_HEIGHT (f
))
919 height
= FRAME_NEW_HEIGHT (f
);
921 height
= FRAME_HEIGHT (f
);
923 /* Process foreground_color and background_color before anything else.
924 They are independent of other properties, but other properties (e.g.,
925 cursor_color) are dependent upon them. */
926 /* Process default font as well, since fringe widths depends on it. */
927 /* Also, process fullscreen, width and height depend upon that */
928 for (p
= 0; p
< i
; p
++)
930 Lisp_Object prop
, val
;
934 if (EQ (prop
, Qforeground_color
)
935 || EQ (prop
, Qbackground_color
)
937 || EQ (prop
, Qfullscreen
))
939 register Lisp_Object param_index
, old_value
;
941 old_value
= get_frame_param (f
, prop
);
942 fullscreen_is_being_set
|= EQ (prop
, Qfullscreen
);
944 if (NILP (Fequal (val
, old_value
)))
946 store_frame_param (f
, prop
, val
);
948 param_index
= Fget (prop
, Qx_frame_parameter
);
949 if (NATNUMP (param_index
)
950 && (XFASTINT (param_index
)
951 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
952 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
957 /* Now process them in reverse of specified order. */
958 for (i
--; i
>= 0; i
--)
960 Lisp_Object prop
, val
;
965 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
966 width
= XFASTINT (val
);
967 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
968 height
= XFASTINT (val
);
969 else if (EQ (prop
, Qtop
))
971 else if (EQ (prop
, Qleft
))
973 else if (EQ (prop
, Qicon_top
))
975 else if (EQ (prop
, Qicon_left
))
977 else if (EQ (prop
, Qforeground_color
)
978 || EQ (prop
, Qbackground_color
)
980 || EQ (prop
, Qfullscreen
))
981 /* Processed above. */
985 register Lisp_Object param_index
, old_value
;
987 old_value
= get_frame_param (f
, prop
);
989 store_frame_param (f
, prop
, val
);
991 param_index
= Fget (prop
, Qx_frame_parameter
);
992 if (NATNUMP (param_index
)
993 && (XFASTINT (param_index
)
994 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
995 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
999 /* Don't die if just one of these was set. */
1000 if (EQ (left
, Qunbound
))
1003 if (f
->output_data
.x
->left_pos
< 0)
1004 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
1006 XSETINT (left
, f
->output_data
.x
->left_pos
);
1008 if (EQ (top
, Qunbound
))
1011 if (f
->output_data
.x
->top_pos
< 0)
1012 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
1014 XSETINT (top
, f
->output_data
.x
->top_pos
);
1017 /* If one of the icon positions was not set, preserve or default it. */
1018 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
1020 icon_left_no_change
= 1;
1021 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
1022 if (NILP (icon_left
))
1023 XSETINT (icon_left
, 0);
1025 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
1027 icon_top_no_change
= 1;
1028 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
1029 if (NILP (icon_top
))
1030 XSETINT (icon_top
, 0);
1033 if (FRAME_VISIBLE_P (f
) && fullscreen_is_being_set
)
1035 /* If the frame is visible already and the fullscreen parameter is
1036 being set, it is too late to set WM manager hints to specify
1038 Here we first get the width, height and position that applies to
1039 fullscreen. We then move the frame to the appropriate
1040 position. Resize of the frame is taken care of in the code after
1041 this if-statement. */
1042 int new_left
, new_top
;
1044 x_fullscreen_adjust (f
, &width
, &height
, &new_top
, &new_left
);
1045 x_fullscreen_move (f
, new_top
, new_left
);
1048 /* Don't set these parameters unless they've been explicitly
1049 specified. The window might be mapped or resized while we're in
1050 this function, and we don't want to override that unless the lisp
1051 code has asked for it.
1053 Don't set these parameters unless they actually differ from the
1054 window's current parameters; the window may not actually exist
1059 check_frame_size (f
, &height
, &width
);
1061 XSETFRAME (frame
, f
);
1063 if (width
!= FRAME_WIDTH (f
)
1064 || height
!= FRAME_HEIGHT (f
)
1065 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
1066 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1068 if ((!NILP (left
) || !NILP (top
))
1069 && ! (left_no_change
&& top_no_change
)
1070 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1071 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1076 /* Record the signs. */
1077 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1078 if (EQ (left
, Qminus
))
1079 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1080 else if (INTEGERP (left
))
1082 leftpos
= XINT (left
);
1084 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1086 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1087 && CONSP (XCDR (left
))
1088 && INTEGERP (XCAR (XCDR (left
))))
1090 leftpos
= - XINT (XCAR (XCDR (left
)));
1091 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1093 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1094 && CONSP (XCDR (left
))
1095 && INTEGERP (XCAR (XCDR (left
))))
1097 leftpos
= XINT (XCAR (XCDR (left
)));
1100 if (EQ (top
, Qminus
))
1101 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1102 else if (INTEGERP (top
))
1104 toppos
= XINT (top
);
1106 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1108 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1109 && CONSP (XCDR (top
))
1110 && INTEGERP (XCAR (XCDR (top
))))
1112 toppos
= - XINT (XCAR (XCDR (top
)));
1113 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1115 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1116 && CONSP (XCDR (top
))
1117 && INTEGERP (XCAR (XCDR (top
))))
1119 toppos
= XINT (XCAR (XCDR (top
)));
1123 /* Store the numeric value of the position. */
1124 f
->output_data
.x
->top_pos
= toppos
;
1125 f
->output_data
.x
->left_pos
= leftpos
;
1127 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1129 /* Actually set that position, and convert to absolute. */
1130 x_set_offset (f
, leftpos
, toppos
, -1);
1133 if ((!NILP (icon_left
) || !NILP (icon_top
))
1134 && ! (icon_left_no_change
&& icon_top_no_change
))
1135 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1141 /* Store the screen positions of frame F into XPTR and YPTR.
1142 These are the positions of the containing window manager window,
1143 not Emacs's own window. */
1146 x_real_positions (f
, xptr
, yptr
)
1150 int win_x
, win_y
, outer_x
, outer_y
;
1151 int real_x
= 0, real_y
= 0;
1153 Window win
= f
->output_data
.x
->parent_desc
;
1159 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1161 if (win
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1162 win
= FRAME_OUTER_WINDOW (f
);
1164 /* This loop traverses up the containment tree until we hit the root
1165 window. Window managers may intersect many windows between our window
1166 and the root window. The window we find just before the root window
1167 should be the outer WM window. */
1170 Window wm_window
, rootw
;
1171 Window
*tmp_children
;
1172 unsigned int tmp_nchildren
;
1175 success
= XQueryTree (FRAME_X_DISPLAY (f
), win
, &rootw
,
1176 &wm_window
, &tmp_children
, &tmp_nchildren
);
1178 had_errors
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1180 /* Don't free tmp_children if XQueryTree failed. */
1184 XFree ((char *) tmp_children
);
1186 if (wm_window
== rootw
|| had_errors
)
1195 Window child
, rootw
;
1197 /* Get the real coordinates for the WM window upper left corner */
1198 XGetGeometry (FRAME_X_DISPLAY (f
), win
,
1199 &rootw
, &real_x
, &real_y
, &ign
, &ign
, &ign
, &ign
);
1201 /* Translate real coordinates to coordinates relative to our
1202 window. For our window, the upper left corner is 0, 0.
1203 Since the upper left corner of the WM window is outside
1204 our window, win_x and win_y will be negative:
1206 ------------------ ---> x
1208 | ----------------- v y
1211 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1213 /* From-window, to-window. */
1214 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1217 /* From-position, to-position. */
1218 real_x
, real_y
, &win_x
, &win_y
,
1223 if (FRAME_X_WINDOW (f
) == FRAME_OUTER_WINDOW (f
))
1230 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1232 /* From-window, to-window. */
1233 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1234 FRAME_OUTER_WINDOW (f
),
1236 /* From-position, to-position. */
1237 real_x
, real_y
, &outer_x
, &outer_y
,
1243 had_errors
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1246 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1250 if (had_errors
) return;
1252 f
->output_data
.x
->x_pixels_diff
= -win_x
;
1253 f
->output_data
.x
->y_pixels_diff
= -win_y
;
1254 f
->output_data
.x
->x_pixels_outer_diff
= -outer_x
;
1255 f
->output_data
.x
->y_pixels_outer_diff
= -outer_y
;
1261 /* Insert a description of internally-recorded parameters of frame X
1262 into the parameter alist *ALISTPTR that is to be given to the user.
1263 Only parameters that are specific to the X window system
1264 and whose values are not correctly recorded in the frame's
1265 param_alist need to be considered here. */
1268 x_report_frame_params (f
, alistptr
)
1270 Lisp_Object
*alistptr
;
1275 /* Represent negative positions (off the top or left screen edge)
1276 in a way that Fmodify_frame_parameters will understand correctly. */
1277 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1278 if (f
->output_data
.x
->left_pos
>= 0)
1279 store_in_alist (alistptr
, Qleft
, tem
);
1281 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1283 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1284 if (f
->output_data
.x
->top_pos
>= 0)
1285 store_in_alist (alistptr
, Qtop
, tem
);
1287 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1289 store_in_alist (alistptr
, Qborder_width
,
1290 make_number (f
->output_data
.x
->border_width
));
1291 store_in_alist (alistptr
, Qinternal_border_width
,
1292 make_number (f
->output_data
.x
->internal_border_width
));
1293 store_in_alist (alistptr
, Qleft_fringe
,
1294 make_number (f
->output_data
.x
->left_fringe_width
));
1295 store_in_alist (alistptr
, Qright_fringe
,
1296 make_number (f
->output_data
.x
->right_fringe_width
));
1297 store_in_alist (alistptr
, Qscroll_bar_width
,
1298 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
1300 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
1301 ? make_number (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
1302 /* nil means "use default width"
1303 for non-toolkit scroll bar.
1304 ruler-mode.el depends on this. */
1306 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1307 store_in_alist (alistptr
, Qwindow_id
,
1308 build_string (buf
));
1309 #ifdef USE_X_TOOLKIT
1310 /* Tooltip frame may not have this widget. */
1311 if (f
->output_data
.x
->widget
)
1313 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1314 store_in_alist (alistptr
, Qouter_window_id
,
1315 build_string (buf
));
1316 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1317 FRAME_SAMPLE_VISIBILITY (f
);
1318 store_in_alist (alistptr
, Qvisibility
,
1319 (FRAME_VISIBLE_P (f
) ? Qt
1320 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1321 store_in_alist (alistptr
, Qdisplay
,
1322 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1324 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1327 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1328 store_in_alist (alistptr
, Qparent_id
, tem
);
1333 /* Gamma-correct COLOR on frame F. */
1336 gamma_correct (f
, color
)
1342 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1343 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1344 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1349 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1350 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1351 allocate the color. Value is zero if COLOR_NAME is invalid, or
1352 no color could be allocated. */
1355 x_defined_color (f
, color_name
, color
, alloc_p
)
1362 Display
*dpy
= FRAME_X_DISPLAY (f
);
1363 Colormap cmap
= FRAME_X_COLORMAP (f
);
1366 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1367 if (success_p
&& alloc_p
)
1368 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1375 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1376 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1377 Signal an error if color can't be allocated. */
1380 x_decode_color (f
, color_name
, mono_color
)
1382 Lisp_Object color_name
;
1387 CHECK_STRING (color_name
);
1389 #if 0 /* Don't do this. It's wrong when we're not using the default
1390 colormap, it makes freeing difficult, and it's probably not
1391 an important optimization. */
1392 if (strcmp (SDATA (color_name
), "black") == 0)
1393 return BLACK_PIX_DEFAULT (f
);
1394 else if (strcmp (SDATA (color_name
), "white") == 0)
1395 return WHITE_PIX_DEFAULT (f
);
1398 /* Return MONO_COLOR for monochrome frames. */
1399 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1402 /* x_defined_color is responsible for coping with failures
1403 by looking for a near-miss. */
1404 if (x_defined_color (f
, SDATA (color_name
), &cdef
, 1))
1407 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1408 Fcons (color_name
, Qnil
)));
1414 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1415 the previous value of that parameter, NEW_VALUE is the new value. */
1418 x_set_line_spacing (f
, new_value
, old_value
)
1420 Lisp_Object new_value
, old_value
;
1422 if (NILP (new_value
))
1423 f
->extra_line_spacing
= 0;
1424 else if (NATNUMP (new_value
))
1425 f
->extra_line_spacing
= XFASTINT (new_value
);
1427 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1428 Fcons (new_value
, Qnil
)));
1429 if (FRAME_VISIBLE_P (f
))
1434 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1435 the previous value of that parameter, NEW_VALUE is the new value.
1436 See also the comment of wait_for_wm in struct x_output. */
1439 x_set_wait_for_wm (f
, new_value
, old_value
)
1441 Lisp_Object new_value
, old_value
;
1443 f
->output_data
.x
->wait_for_wm
= !NILP (new_value
);
1447 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
1448 the previous value of that parameter, NEW_VALUE is the new value. */
1451 x_set_fullscreen (f
, new_value
, old_value
)
1453 Lisp_Object new_value
, old_value
;
1455 if (NILP (new_value
))
1456 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_NONE
;
1457 else if (EQ (new_value
, Qfullboth
))
1458 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_BOTH
;
1459 else if (EQ (new_value
, Qfullwidth
))
1460 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_WIDTH
;
1461 else if (EQ (new_value
, Qfullheight
))
1462 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_HEIGHT
;
1466 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1467 the previous value of that parameter, NEW_VALUE is the new
1471 x_set_screen_gamma (f
, new_value
, old_value
)
1473 Lisp_Object new_value
, old_value
;
1475 if (NILP (new_value
))
1477 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1478 /* The value 0.4545 is the normal viewing gamma. */
1479 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1481 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1482 Fcons (new_value
, Qnil
)));
1484 clear_face_cache (0);
1488 /* Functions called only from `x_set_frame_param'
1489 to set individual parameters.
1491 If FRAME_X_WINDOW (f) is 0,
1492 the frame is being created and its X-window does not exist yet.
1493 In that case, just record the parameter's new value
1494 in the standard place; do not attempt to change the window. */
1497 x_set_foreground_color (f
, arg
, oldval
)
1499 Lisp_Object arg
, oldval
;
1501 struct x_output
*x
= f
->output_data
.x
;
1502 unsigned long fg
, old_fg
;
1504 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1505 old_fg
= x
->foreground_pixel
;
1506 x
->foreground_pixel
= fg
;
1508 if (FRAME_X_WINDOW (f
) != 0)
1510 Display
*dpy
= FRAME_X_DISPLAY (f
);
1513 XSetForeground (dpy
, x
->normal_gc
, fg
);
1514 XSetBackground (dpy
, x
->reverse_gc
, fg
);
1516 if (x
->cursor_pixel
== old_fg
)
1518 unload_color (f
, x
->cursor_pixel
);
1519 x
->cursor_pixel
= x_copy_color (f
, fg
);
1520 XSetBackground (dpy
, x
->cursor_gc
, x
->cursor_pixel
);
1525 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1527 if (FRAME_VISIBLE_P (f
))
1531 unload_color (f
, old_fg
);
1535 x_set_background_color (f
, arg
, oldval
)
1537 Lisp_Object arg
, oldval
;
1539 struct x_output
*x
= f
->output_data
.x
;
1542 bg
= x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1543 unload_color (f
, x
->background_pixel
);
1544 x
->background_pixel
= bg
;
1546 if (FRAME_X_WINDOW (f
) != 0)
1548 Display
*dpy
= FRAME_X_DISPLAY (f
);
1551 XSetBackground (dpy
, x
->normal_gc
, bg
);
1552 XSetForeground (dpy
, x
->reverse_gc
, bg
);
1553 XSetWindowBackground (dpy
, FRAME_X_WINDOW (f
), bg
);
1554 XSetForeground (dpy
, x
->cursor_gc
, bg
);
1556 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1557 toolkit scroll bars. */
1560 for (bar
= FRAME_SCROLL_BARS (f
);
1562 bar
= XSCROLL_BAR (bar
)->next
)
1564 Window window
= SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
));
1565 XSetWindowBackground (dpy
, window
, bg
);
1568 #endif /* USE_TOOLKIT_SCROLL_BARS */
1571 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1573 if (FRAME_VISIBLE_P (f
))
1579 x_set_mouse_color (f
, arg
, oldval
)
1581 Lisp_Object arg
, oldval
;
1583 struct x_output
*x
= f
->output_data
.x
;
1584 Display
*dpy
= FRAME_X_DISPLAY (f
);
1585 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1586 Cursor hourglass_cursor
, horizontal_drag_cursor
;
1588 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1589 unsigned long mask_color
= x
->background_pixel
;
1591 /* Don't let pointers be invisible. */
1592 if (mask_color
== pixel
)
1594 x_free_colors (f
, &pixel
, 1);
1595 pixel
= x_copy_color (f
, x
->foreground_pixel
);
1598 unload_color (f
, x
->mouse_pixel
);
1599 x
->mouse_pixel
= pixel
;
1603 /* It's not okay to crash if the user selects a screwy cursor. */
1604 count
= x_catch_errors (dpy
);
1606 if (!NILP (Vx_pointer_shape
))
1608 CHECK_NUMBER (Vx_pointer_shape
);
1609 cursor
= XCreateFontCursor (dpy
, XINT (Vx_pointer_shape
));
1612 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1613 x_check_errors (dpy
, "bad text pointer cursor: %s");
1615 if (!NILP (Vx_nontext_pointer_shape
))
1617 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1619 = XCreateFontCursor (dpy
, XINT (Vx_nontext_pointer_shape
));
1622 nontext_cursor
= XCreateFontCursor (dpy
, XC_left_ptr
);
1623 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1625 if (!NILP (Vx_hourglass_pointer_shape
))
1627 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1629 = XCreateFontCursor (dpy
, XINT (Vx_hourglass_pointer_shape
));
1632 hourglass_cursor
= XCreateFontCursor (dpy
, XC_watch
);
1633 x_check_errors (dpy
, "bad hourglass pointer cursor: %s");
1635 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1636 if (!NILP (Vx_mode_pointer_shape
))
1638 CHECK_NUMBER (Vx_mode_pointer_shape
);
1639 mode_cursor
= XCreateFontCursor (dpy
, XINT (Vx_mode_pointer_shape
));
1642 mode_cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1643 x_check_errors (dpy
, "bad modeline pointer cursor: %s");
1645 if (!NILP (Vx_sensitive_text_pointer_shape
))
1647 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1649 = XCreateFontCursor (dpy
, XINT (Vx_sensitive_text_pointer_shape
));
1652 cross_cursor
= XCreateFontCursor (dpy
, XC_hand2
);
1654 if (!NILP (Vx_window_horizontal_drag_shape
))
1656 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1657 horizontal_drag_cursor
1658 = XCreateFontCursor (dpy
, XINT (Vx_window_horizontal_drag_shape
));
1661 horizontal_drag_cursor
1662 = XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
1664 /* Check and report errors with the above calls. */
1665 x_check_errors (dpy
, "can't set cursor shape: %s");
1666 x_uncatch_errors (dpy
, count
);
1669 XColor fore_color
, back_color
;
1671 fore_color
.pixel
= x
->mouse_pixel
;
1672 x_query_color (f
, &fore_color
);
1673 back_color
.pixel
= mask_color
;
1674 x_query_color (f
, &back_color
);
1676 XRecolorCursor (dpy
, cursor
, &fore_color
, &back_color
);
1677 XRecolorCursor (dpy
, nontext_cursor
, &fore_color
, &back_color
);
1678 XRecolorCursor (dpy
, mode_cursor
, &fore_color
, &back_color
);
1679 XRecolorCursor (dpy
, cross_cursor
, &fore_color
, &back_color
);
1680 XRecolorCursor (dpy
, hourglass_cursor
, &fore_color
, &back_color
);
1681 XRecolorCursor (dpy
, horizontal_drag_cursor
, &fore_color
, &back_color
);
1684 if (FRAME_X_WINDOW (f
) != 0)
1685 XDefineCursor (dpy
, FRAME_X_WINDOW (f
), cursor
);
1687 if (cursor
!= x
->text_cursor
1688 && x
->text_cursor
!= 0)
1689 XFreeCursor (dpy
, x
->text_cursor
);
1690 x
->text_cursor
= cursor
;
1692 if (nontext_cursor
!= x
->nontext_cursor
1693 && x
->nontext_cursor
!= 0)
1694 XFreeCursor (dpy
, x
->nontext_cursor
);
1695 x
->nontext_cursor
= nontext_cursor
;
1697 if (hourglass_cursor
!= x
->hourglass_cursor
1698 && x
->hourglass_cursor
!= 0)
1699 XFreeCursor (dpy
, x
->hourglass_cursor
);
1700 x
->hourglass_cursor
= hourglass_cursor
;
1702 if (mode_cursor
!= x
->modeline_cursor
1703 && x
->modeline_cursor
!= 0)
1704 XFreeCursor (dpy
, f
->output_data
.x
->modeline_cursor
);
1705 x
->modeline_cursor
= mode_cursor
;
1707 if (cross_cursor
!= x
->cross_cursor
1708 && x
->cross_cursor
!= 0)
1709 XFreeCursor (dpy
, x
->cross_cursor
);
1710 x
->cross_cursor
= cross_cursor
;
1712 if (horizontal_drag_cursor
!= x
->horizontal_drag_cursor
1713 && x
->horizontal_drag_cursor
!= 0)
1714 XFreeCursor (dpy
, x
->horizontal_drag_cursor
);
1715 x
->horizontal_drag_cursor
= horizontal_drag_cursor
;
1720 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1724 x_set_cursor_color (f
, arg
, oldval
)
1726 Lisp_Object arg
, oldval
;
1728 unsigned long fore_pixel
, pixel
;
1729 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1730 struct x_output
*x
= f
->output_data
.x
;
1732 if (!NILP (Vx_cursor_fore_pixel
))
1734 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1735 WHITE_PIX_DEFAULT (f
));
1736 fore_pixel_allocated_p
= 1;
1739 fore_pixel
= x
->background_pixel
;
1741 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1742 pixel_allocated_p
= 1;
1744 /* Make sure that the cursor color differs from the background color. */
1745 if (pixel
== x
->background_pixel
)
1747 if (pixel_allocated_p
)
1749 x_free_colors (f
, &pixel
, 1);
1750 pixel_allocated_p
= 0;
1753 pixel
= x
->mouse_pixel
;
1754 if (pixel
== fore_pixel
)
1756 if (fore_pixel_allocated_p
)
1758 x_free_colors (f
, &fore_pixel
, 1);
1759 fore_pixel_allocated_p
= 0;
1761 fore_pixel
= x
->background_pixel
;
1765 unload_color (f
, x
->cursor_foreground_pixel
);
1766 if (!fore_pixel_allocated_p
)
1767 fore_pixel
= x_copy_color (f
, fore_pixel
);
1768 x
->cursor_foreground_pixel
= fore_pixel
;
1770 unload_color (f
, x
->cursor_pixel
);
1771 if (!pixel_allocated_p
)
1772 pixel
= x_copy_color (f
, pixel
);
1773 x
->cursor_pixel
= pixel
;
1775 if (FRAME_X_WINDOW (f
) != 0)
1778 XSetBackground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, x
->cursor_pixel
);
1779 XSetForeground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, fore_pixel
);
1782 if (FRAME_VISIBLE_P (f
))
1784 x_update_cursor (f
, 0);
1785 x_update_cursor (f
, 1);
1789 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1792 /* Set the border-color of frame F to value described by ARG.
1793 ARG can be a string naming a color.
1794 The border-color is used for the border that is drawn by the X server.
1795 Note that this does not fully take effect if done before
1796 F has an x-window; it must be redone when the window is created.
1798 Note: this is done in two routines because of the way X10 works.
1800 Note: under X11, this is normally the province of the window manager,
1801 and so emacs' border colors may be overridden. */
1804 x_set_border_color (f
, arg
, oldval
)
1806 Lisp_Object arg
, oldval
;
1811 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1812 x_set_border_pixel (f
, pix
);
1813 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1816 /* Set the border-color of frame F to pixel value PIX.
1817 Note that this does not fully take effect if done before
1818 F has an x-window. */
1821 x_set_border_pixel (f
, pix
)
1825 unload_color (f
, f
->output_data
.x
->border_pixel
);
1826 f
->output_data
.x
->border_pixel
= pix
;
1828 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1831 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1832 (unsigned long)pix
);
1835 if (FRAME_VISIBLE_P (f
))
1843 x_set_cursor_type (f
, arg
, oldval
)
1845 Lisp_Object arg
, oldval
;
1847 set_frame_cursor_types (f
, arg
);
1849 /* Make sure the cursor gets redrawn. */
1850 cursor_type_changed
= 1;
1854 x_set_icon_type (f
, arg
, oldval
)
1856 Lisp_Object arg
, oldval
;
1862 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1865 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1870 result
= x_text_icon (f
,
1871 (char *) SDATA ((!NILP (f
->icon_name
)
1875 result
= x_bitmap_icon (f
, arg
);
1880 error ("No icon window available");
1883 XFlush (FRAME_X_DISPLAY (f
));
1887 /* Return non-nil if frame F wants a bitmap icon. */
1895 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1903 x_set_icon_name (f
, arg
, oldval
)
1905 Lisp_Object arg
, oldval
;
1911 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1914 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1919 if (f
->output_data
.x
->icon_bitmap
!= 0)
1924 result
= x_text_icon (f
,
1925 (char *) SDATA ((!NILP (f
->icon_name
)
1934 error ("No icon window available");
1937 XFlush (FRAME_X_DISPLAY (f
));
1942 x_set_font (f
, arg
, oldval
)
1944 Lisp_Object arg
, oldval
;
1947 Lisp_Object fontset_name
;
1949 int old_fontset
= f
->output_data
.x
->fontset
;
1953 fontset_name
= Fquery_fontset (arg
, Qnil
);
1956 result
= (STRINGP (fontset_name
)
1957 ? x_new_fontset (f
, SDATA (fontset_name
))
1958 : x_new_font (f
, SDATA (arg
)));
1961 if (EQ (result
, Qnil
))
1962 error ("Font `%s' is not defined", SDATA (arg
));
1963 else if (EQ (result
, Qt
))
1964 error ("The characters of the given font have varying widths");
1965 else if (STRINGP (result
))
1967 if (STRINGP (fontset_name
))
1969 /* Fontset names are built from ASCII font names, so the
1970 names may be equal despite there was a change. */
1971 if (old_fontset
== f
->output_data
.x
->fontset
)
1974 else if (!NILP (Fequal (result
, oldval
)))
1977 store_frame_param (f
, Qfont
, result
);
1978 recompute_basic_faces (f
);
1983 do_pending_window_change (0);
1985 /* Don't call `face-set-after-frame-default' when faces haven't been
1986 initialized yet. This is the case when called from
1987 Fx_create_frame. In that case, the X widget or window doesn't
1988 exist either, and we can end up in x_report_frame_params with a
1989 null widget which gives a segfault. */
1990 if (FRAME_FACE_CACHE (f
))
1992 XSETFRAME (frame
, f
);
1993 call1 (Qface_set_after_frame_default
, frame
);
1998 x_set_fringe_width (f
, new_value
, old_value
)
2000 Lisp_Object new_value
, old_value
;
2002 x_compute_fringe_widths (f
, 1);
2006 x_set_border_width (f
, arg
, oldval
)
2008 Lisp_Object arg
, oldval
;
2012 if (XINT (arg
) == f
->output_data
.x
->border_width
)
2015 if (FRAME_X_WINDOW (f
) != 0)
2016 error ("Cannot change the border width of a window");
2018 f
->output_data
.x
->border_width
= XINT (arg
);
2022 x_set_internal_border_width (f
, arg
, oldval
)
2024 Lisp_Object arg
, oldval
;
2026 int old
= f
->output_data
.x
->internal_border_width
;
2029 f
->output_data
.x
->internal_border_width
= XINT (arg
);
2030 if (f
->output_data
.x
->internal_border_width
< 0)
2031 f
->output_data
.x
->internal_border_width
= 0;
2033 #ifdef USE_X_TOOLKIT
2034 if (f
->output_data
.x
->edit_widget
)
2035 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
2038 if (f
->output_data
.x
->internal_border_width
== old
)
2041 if (FRAME_X_WINDOW (f
) != 0)
2043 x_set_window_size (f
, 0, f
->width
, f
->height
);
2044 SET_FRAME_GARBAGED (f
);
2045 do_pending_window_change (0);
2048 SET_FRAME_GARBAGED (f
);
2052 x_set_visibility (f
, value
, oldval
)
2054 Lisp_Object value
, oldval
;
2057 XSETFRAME (frame
, f
);
2060 Fmake_frame_invisible (frame
, Qt
);
2061 else if (EQ (value
, Qicon
))
2062 Ficonify_frame (frame
);
2064 Fmake_frame_visible (frame
);
2068 /* Change window heights in windows rooted in WINDOW by N lines. */
2071 x_change_window_heights (window
, n
)
2075 struct window
*w
= XWINDOW (window
);
2077 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
2078 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
2080 if (INTEGERP (w
->orig_top
))
2081 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
2082 if (INTEGERP (w
->orig_height
))
2083 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
2085 /* Handle just the top child in a vertical split. */
2086 if (!NILP (w
->vchild
))
2087 x_change_window_heights (w
->vchild
, n
);
2089 /* Adjust all children in a horizontal split. */
2090 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
2092 w
= XWINDOW (window
);
2093 x_change_window_heights (window
, n
);
2098 x_set_menu_bar_lines (f
, value
, oldval
)
2100 Lisp_Object value
, oldval
;
2103 #ifndef USE_X_TOOLKIT
2104 int olines
= FRAME_MENU_BAR_LINES (f
);
2107 /* Right now, menu bars don't work properly in minibuf-only frames;
2108 most of the commands try to apply themselves to the minibuffer
2109 frame itself, and get an error because you can't switch buffers
2110 in or split the minibuffer window. */
2111 if (FRAME_MINIBUF_ONLY_P (f
))
2114 if (INTEGERP (value
))
2115 nlines
= XINT (value
);
2119 /* Make sure we redisplay all windows in this frame. */
2120 windows_or_buffers_changed
++;
2122 #ifdef USE_X_TOOLKIT
2123 FRAME_MENU_BAR_LINES (f
) = 0;
2126 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2127 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2128 /* Make sure next redisplay shows the menu bar. */
2129 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2133 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2134 free_frame_menubar (f
);
2135 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2137 f
->output_data
.x
->menubar_widget
= 0;
2139 #else /* not USE_X_TOOLKIT */
2140 FRAME_MENU_BAR_LINES (f
) = nlines
;
2141 x_change_window_heights (f
->root_window
, nlines
- olines
);
2142 #endif /* not USE_X_TOOLKIT */
2147 /* Set the number of lines used for the tool bar of frame F to VALUE.
2148 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2149 is the old number of tool bar lines. This function changes the
2150 height of all windows on frame F to match the new tool bar height.
2151 The frame's height doesn't change. */
2154 x_set_tool_bar_lines (f
, value
, oldval
)
2156 Lisp_Object value
, oldval
;
2158 int delta
, nlines
, root_height
;
2159 Lisp_Object root_window
;
2161 /* Treat tool bars like menu bars. */
2162 if (FRAME_MINIBUF_ONLY_P (f
))
2165 /* Use VALUE only if an integer >= 0. */
2166 if (INTEGERP (value
) && XINT (value
) >= 0)
2167 nlines
= XFASTINT (value
);
2171 /* Make sure we redisplay all windows in this frame. */
2172 ++windows_or_buffers_changed
;
2174 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2176 /* Don't resize the tool-bar to more than we have room for. */
2177 root_window
= FRAME_ROOT_WINDOW (f
);
2178 root_height
= XINT (XWINDOW (root_window
)->height
);
2179 if (root_height
- delta
< 1)
2181 delta
= root_height
- 1;
2182 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2185 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2186 x_change_window_heights (root_window
, delta
);
2189 /* We also have to make sure that the internal border at the top of
2190 the frame, below the menu bar or tool bar, is redrawn when the
2191 tool bar disappears. This is so because the internal border is
2192 below the tool bar if one is displayed, but is below the menu bar
2193 if there isn't a tool bar. The tool bar draws into the area
2194 below the menu bar. */
2195 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2199 clear_current_matrices (f
);
2200 updating_frame
= NULL
;
2203 /* If the tool bar gets smaller, the internal border below it
2204 has to be cleared. It was formerly part of the display
2205 of the larger tool bar, and updating windows won't clear it. */
2208 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2209 int width
= PIXEL_WIDTH (f
);
2210 int y
= nlines
* CANON_Y_UNIT (f
);
2213 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2214 0, y
, width
, height
, False
);
2217 if (WINDOWP (f
->tool_bar_window
))
2218 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2223 /* Set the foreground color for scroll bars on frame F to VALUE.
2224 VALUE should be a string, a color name. If it isn't a string or
2225 isn't a valid color name, do nothing. OLDVAL is the old value of
2226 the frame parameter. */
2229 x_set_scroll_bar_foreground (f
, value
, oldval
)
2231 Lisp_Object value
, oldval
;
2233 unsigned long pixel
;
2235 if (STRINGP (value
))
2236 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2240 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2241 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2243 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2244 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2246 /* Remove all scroll bars because they have wrong colors. */
2247 if (condemn_scroll_bars_hook
)
2248 (*condemn_scroll_bars_hook
) (f
);
2249 if (judge_scroll_bars_hook
)
2250 (*judge_scroll_bars_hook
) (f
);
2252 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2258 /* Set the background color for scroll bars on frame F to VALUE VALUE
2259 should be a string, a color name. If it isn't a string or isn't a
2260 valid color name, do nothing. OLDVAL is the old value of the frame
2264 x_set_scroll_bar_background (f
, value
, oldval
)
2266 Lisp_Object value
, oldval
;
2268 unsigned long pixel
;
2270 if (STRINGP (value
))
2271 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2275 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2276 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2278 #ifdef USE_TOOLKIT_SCROLL_BARS
2279 /* Scrollbar shadow colors. */
2280 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
2282 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
2283 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
2285 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
2287 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
2288 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
2290 #endif /* USE_TOOLKIT_SCROLL_BARS */
2292 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2293 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2295 /* Remove all scroll bars because they have wrong colors. */
2296 if (condemn_scroll_bars_hook
)
2297 (*condemn_scroll_bars_hook
) (f
);
2298 if (judge_scroll_bars_hook
)
2299 (*judge_scroll_bars_hook
) (f
);
2301 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2307 /* Encode Lisp string STRING as a text in a format appropriate for
2308 XICCC (X Inter Client Communication Conventions).
2310 If STRING contains only ASCII characters, do no conversion and
2311 return the string data of STRING. Otherwise, encode the text by
2312 CODING_SYSTEM, and return a newly allocated memory area which
2313 should be freed by `xfree' by a caller.
2315 SELECTIONP non-zero means the string is being encoded for an X
2316 selection, so it is safe to run pre-write conversions (which
2319 Store the byte length of resulting text in *TEXT_BYTES.
2321 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2322 which means that the `encoding' of the result can be `STRING'.
2323 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2324 the result should be `COMPOUND_TEXT'. */
2327 x_encode_text (string
, coding_system
, selectionp
, text_bytes
, stringp
)
2328 Lisp_Object string
, coding_system
;
2329 int *text_bytes
, *stringp
;
2332 unsigned char *str
= SDATA (string
);
2333 int chars
= SCHARS (string
);
2334 int bytes
= SBYTES (string
);
2338 struct coding_system coding
;
2339 extern Lisp_Object Qcompound_text_with_extensions
;
2341 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2342 if (charset_info
== 0)
2344 /* No multibyte character in OBJ. We need not encode it. */
2345 *text_bytes
= bytes
;
2350 setup_coding_system (coding_system
, &coding
);
2352 && SYMBOLP (coding
.pre_write_conversion
)
2353 && !NILP (Ffboundp (coding
.pre_write_conversion
)))
2355 string
= run_pre_post_conversion_on_str (string
, &coding
, 1);
2356 str
= SDATA (string
);
2357 chars
= SCHARS (string
);
2358 bytes
= SBYTES (string
);
2360 coding
.src_multibyte
= 1;
2361 coding
.dst_multibyte
= 0;
2362 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2363 if (coding
.type
== coding_type_iso2022
)
2364 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2365 /* We suppress producing escape sequences for composition. */
2366 coding
.composing
= COMPOSITION_DISABLED
;
2367 bufsize
= encoding_buffer_size (&coding
, bytes
);
2368 buf
= (unsigned char *) xmalloc (bufsize
);
2369 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2370 *text_bytes
= coding
.produced
;
2371 *stringp
= (charset_info
== 1
2372 || (!EQ (coding_system
, Qcompound_text
)
2373 && !EQ (coding_system
, Qcompound_text_with_extensions
)));
2378 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2381 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2382 name; if NAME is a string, set F's name to NAME and set
2383 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2385 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2386 suggesting a new name, which lisp code should override; if
2387 F->explicit_name is set, ignore the new name; otherwise, set it. */
2390 x_set_name (f
, name
, explicit)
2395 /* Make sure that requests from lisp code override requests from
2396 Emacs redisplay code. */
2399 /* If we're switching from explicit to implicit, we had better
2400 update the mode lines and thereby update the title. */
2401 if (f
->explicit_name
&& NILP (name
))
2402 update_mode_lines
= 1;
2404 f
->explicit_name
= ! NILP (name
);
2406 else if (f
->explicit_name
)
2409 /* If NAME is nil, set the name to the x_id_name. */
2412 /* Check for no change needed in this very common case
2413 before we do any consing. */
2414 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2417 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2420 CHECK_STRING (name
);
2422 /* Don't change the name if it's already NAME. */
2423 if (! NILP (Fstring_equal (name
, f
->name
)))
2428 /* For setting the frame title, the title parameter should override
2429 the name parameter. */
2430 if (! NILP (f
->title
))
2433 if (FRAME_X_WINDOW (f
))
2438 XTextProperty text
, icon
;
2440 Lisp_Object coding_system
;
2442 coding_system
= Vlocale_coding_system
;
2443 if (NILP (coding_system
))
2444 coding_system
= Qcompound_text
;
2445 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2446 text
.encoding
= (stringp
? XA_STRING
2447 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2449 text
.nitems
= bytes
;
2451 if (NILP (f
->icon_name
))
2457 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2459 icon
.encoding
= (stringp
? XA_STRING
2460 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2462 icon
.nitems
= bytes
;
2464 #ifdef USE_X_TOOLKIT
2465 XSetWMName (FRAME_X_DISPLAY (f
),
2466 XtWindow (f
->output_data
.x
->widget
), &text
);
2467 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2469 #else /* not USE_X_TOOLKIT */
2470 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2471 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2472 #endif /* not USE_X_TOOLKIT */
2473 if (!NILP (f
->icon_name
)
2474 && icon
.value
!= SDATA (f
->icon_name
))
2476 if (text
.value
!= SDATA (name
))
2479 #else /* not HAVE_X11R4 */
2480 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2482 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2484 #endif /* not HAVE_X11R4 */
2489 /* This function should be called when the user's lisp code has
2490 specified a name for the frame; the name will override any set by the
2493 x_explicitly_set_name (f
, arg
, oldval
)
2495 Lisp_Object arg
, oldval
;
2497 x_set_name (f
, arg
, 1);
2500 /* This function should be called by Emacs redisplay code to set the
2501 name; names set this way will never override names set by the user's
2504 x_implicitly_set_name (f
, arg
, oldval
)
2506 Lisp_Object arg
, oldval
;
2508 x_set_name (f
, arg
, 0);
2511 /* Change the title of frame F to NAME.
2512 If NAME is nil, use the frame name as the title.
2514 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2515 name; if NAME is a string, set F's name to NAME and set
2516 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2518 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2519 suggesting a new name, which lisp code should override; if
2520 F->explicit_name is set, ignore the new name; otherwise, set it. */
2523 x_set_title (f
, name
, old_name
)
2525 Lisp_Object name
, old_name
;
2527 /* Don't change the title if it's already NAME. */
2528 if (EQ (name
, f
->title
))
2531 update_mode_lines
= 1;
2538 CHECK_STRING (name
);
2540 if (FRAME_X_WINDOW (f
))
2545 XTextProperty text
, icon
;
2547 Lisp_Object coding_system
;
2549 coding_system
= Vlocale_coding_system
;
2550 if (NILP (coding_system
))
2551 coding_system
= Qcompound_text
;
2552 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2553 text
.encoding
= (stringp
? XA_STRING
2554 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2556 text
.nitems
= bytes
;
2558 if (NILP (f
->icon_name
))
2564 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2566 icon
.encoding
= (stringp
? XA_STRING
2567 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2569 icon
.nitems
= bytes
;
2571 #ifdef USE_X_TOOLKIT
2572 XSetWMName (FRAME_X_DISPLAY (f
),
2573 XtWindow (f
->output_data
.x
->widget
), &text
);
2574 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2576 #else /* not USE_X_TOOLKIT */
2577 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2578 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2579 #endif /* not USE_X_TOOLKIT */
2580 if (!NILP (f
->icon_name
)
2581 && icon
.value
!= SDATA (f
->icon_name
))
2583 if (text
.value
!= SDATA (name
))
2586 #else /* not HAVE_X11R4 */
2587 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2589 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2591 #endif /* not HAVE_X11R4 */
2597 x_set_autoraise (f
, arg
, oldval
)
2599 Lisp_Object arg
, oldval
;
2601 f
->auto_raise
= !EQ (Qnil
, arg
);
2605 x_set_autolower (f
, arg
, oldval
)
2607 Lisp_Object arg
, oldval
;
2609 f
->auto_lower
= !EQ (Qnil
, arg
);
2613 x_set_unsplittable (f
, arg
, oldval
)
2615 Lisp_Object arg
, oldval
;
2617 f
->no_split
= !NILP (arg
);
2621 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2623 Lisp_Object arg
, oldval
;
2625 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2626 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2627 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2628 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2630 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2632 ? vertical_scroll_bar_none
2634 ? vertical_scroll_bar_right
2635 : vertical_scroll_bar_left
);
2637 /* We set this parameter before creating the X window for the
2638 frame, so we can get the geometry right from the start.
2639 However, if the window hasn't been created yet, we shouldn't
2640 call x_set_window_size. */
2641 if (FRAME_X_WINDOW (f
))
2642 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2643 do_pending_window_change (0);
2648 x_set_scroll_bar_width (f
, arg
, oldval
)
2650 Lisp_Object arg
, oldval
;
2652 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2656 #ifdef USE_TOOLKIT_SCROLL_BARS
2657 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2658 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2659 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2660 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2662 /* Make the actual width at least 14 pixels and a multiple of a
2664 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2666 /* Use all of that space (aside from required margins) for the
2668 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2671 if (FRAME_X_WINDOW (f
))
2672 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2673 do_pending_window_change (0);
2675 else if (INTEGERP (arg
) && XINT (arg
) > 0
2676 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2678 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2679 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2681 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2682 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2683 if (FRAME_X_WINDOW (f
))
2684 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2687 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2688 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2689 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2694 /* Subroutines of creating an X frame. */
2696 /* Make sure that Vx_resource_name is set to a reasonable value.
2697 Fix it up, or set it to `emacs' if it is too hopeless. */
2700 validate_x_resource_name ()
2703 /* Number of valid characters in the resource name. */
2705 /* Number of invalid characters in the resource name. */
2710 if (!STRINGP (Vx_resource_class
))
2711 Vx_resource_class
= build_string (EMACS_CLASS
);
2713 if (STRINGP (Vx_resource_name
))
2715 unsigned char *p
= SDATA (Vx_resource_name
);
2718 len
= SBYTES (Vx_resource_name
);
2720 /* Only letters, digits, - and _ are valid in resource names.
2721 Count the valid characters and count the invalid ones. */
2722 for (i
= 0; i
< len
; i
++)
2725 if (! ((c
>= 'a' && c
<= 'z')
2726 || (c
>= 'A' && c
<= 'Z')
2727 || (c
>= '0' && c
<= '9')
2728 || c
== '-' || c
== '_'))
2735 /* Not a string => completely invalid. */
2736 bad_count
= 5, good_count
= 0;
2738 /* If name is valid already, return. */
2742 /* If name is entirely invalid, or nearly so, use `emacs'. */
2744 || (good_count
== 1 && bad_count
> 0))
2746 Vx_resource_name
= build_string ("emacs");
2750 /* Name is partly valid. Copy it and replace the invalid characters
2751 with underscores. */
2753 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2755 for (i
= 0; i
< len
; i
++)
2757 int c
= SREF (new, i
);
2758 if (! ((c
>= 'a' && c
<= 'z')
2759 || (c
>= 'A' && c
<= 'Z')
2760 || (c
>= '0' && c
<= '9')
2761 || c
== '-' || c
== '_'))
2767 extern char *x_get_string_resource ();
2769 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2770 doc
: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2771 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2772 class, where INSTANCE is the name under which Emacs was invoked, or
2773 the name specified by the `-name' or `-rn' command-line arguments.
2775 The optional arguments COMPONENT and SUBCLASS add to the key and the
2776 class, respectively. You must specify both of them or neither.
2777 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2778 and the class is `Emacs.CLASS.SUBCLASS'. */)
2779 (attribute
, class, component
, subclass
)
2780 Lisp_Object attribute
, class, component
, subclass
;
2782 register char *value
;
2788 CHECK_STRING (attribute
);
2789 CHECK_STRING (class);
2791 if (!NILP (component
))
2792 CHECK_STRING (component
);
2793 if (!NILP (subclass
))
2794 CHECK_STRING (subclass
);
2795 if (NILP (component
) != NILP (subclass
))
2796 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2798 validate_x_resource_name ();
2800 /* Allocate space for the components, the dots which separate them,
2801 and the final '\0'. Make them big enough for the worst case. */
2802 name_key
= (char *) alloca (SBYTES (Vx_resource_name
)
2803 + (STRINGP (component
)
2804 ? SBYTES (component
) : 0)
2805 + SBYTES (attribute
)
2808 class_key
= (char *) alloca (SBYTES (Vx_resource_class
)
2810 + (STRINGP (subclass
)
2811 ? SBYTES (subclass
) : 0)
2814 /* Start with emacs.FRAMENAME for the name (the specific one)
2815 and with `Emacs' for the class key (the general one). */
2816 strcpy (name_key
, SDATA (Vx_resource_name
));
2817 strcpy (class_key
, SDATA (Vx_resource_class
));
2819 strcat (class_key
, ".");
2820 strcat (class_key
, SDATA (class));
2822 if (!NILP (component
))
2824 strcat (class_key
, ".");
2825 strcat (class_key
, SDATA (subclass
));
2827 strcat (name_key
, ".");
2828 strcat (name_key
, SDATA (component
));
2831 strcat (name_key
, ".");
2832 strcat (name_key
, SDATA (attribute
));
2834 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2835 name_key
, class_key
);
2837 if (value
!= (char *) 0)
2838 return build_string (value
);
2843 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2846 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2847 struct x_display_info
*dpyinfo
;
2848 Lisp_Object attribute
, class, component
, subclass
;
2850 register char *value
;
2854 CHECK_STRING (attribute
);
2855 CHECK_STRING (class);
2857 if (!NILP (component
))
2858 CHECK_STRING (component
);
2859 if (!NILP (subclass
))
2860 CHECK_STRING (subclass
);
2861 if (NILP (component
) != NILP (subclass
))
2862 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2864 validate_x_resource_name ();
2866 /* Allocate space for the components, the dots which separate them,
2867 and the final '\0'. Make them big enough for the worst case. */
2868 name_key
= (char *) alloca (SBYTES (Vx_resource_name
)
2869 + (STRINGP (component
)
2870 ? SBYTES (component
) : 0)
2871 + SBYTES (attribute
)
2874 class_key
= (char *) alloca (SBYTES (Vx_resource_class
)
2876 + (STRINGP (subclass
)
2877 ? SBYTES (subclass
) : 0)
2880 /* Start with emacs.FRAMENAME for the name (the specific one)
2881 and with `Emacs' for the class key (the general one). */
2882 strcpy (name_key
, SDATA (Vx_resource_name
));
2883 strcpy (class_key
, SDATA (Vx_resource_class
));
2885 strcat (class_key
, ".");
2886 strcat (class_key
, SDATA (class));
2888 if (!NILP (component
))
2890 strcat (class_key
, ".");
2891 strcat (class_key
, SDATA (subclass
));
2893 strcat (name_key
, ".");
2894 strcat (name_key
, SDATA (component
));
2897 strcat (name_key
, ".");
2898 strcat (name_key
, SDATA (attribute
));
2900 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2902 if (value
!= (char *) 0)
2903 return build_string (value
);
2908 /* Used when C code wants a resource value. */
2911 x_get_resource_string (attribute
, class)
2912 char *attribute
, *class;
2916 struct frame
*sf
= SELECTED_FRAME ();
2918 /* Allocate space for the components, the dots which separate them,
2919 and the final '\0'. */
2920 name_key
= (char *) alloca (SBYTES (Vinvocation_name
)
2921 + strlen (attribute
) + 2);
2922 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2923 + strlen (class) + 2);
2925 sprintf (name_key
, "%s.%s",
2926 SDATA (Vinvocation_name
),
2928 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2930 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2931 name_key
, class_key
);
2934 /* Types we might convert a resource string into. */
2944 /* Return the value of parameter PARAM.
2946 First search ALIST, then Vdefault_frame_alist, then the X defaults
2947 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2949 Convert the resource to the type specified by desired_type.
2951 If no default is specified, return Qunbound. If you call
2952 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2953 and don't let it get stored in any Lisp-visible variables! */
2956 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2957 struct x_display_info
*dpyinfo
;
2958 Lisp_Object alist
, param
;
2961 enum resource_types type
;
2963 register Lisp_Object tem
;
2965 tem
= Fassq (param
, alist
);
2967 tem
= Fassq (param
, Vdefault_frame_alist
);
2973 tem
= display_x_get_resource (dpyinfo
,
2974 build_string (attribute
),
2975 build_string (class),
2983 case RES_TYPE_NUMBER
:
2984 return make_number (atoi (SDATA (tem
)));
2986 case RES_TYPE_FLOAT
:
2987 return make_float (atof (SDATA (tem
)));
2989 case RES_TYPE_BOOLEAN
:
2990 tem
= Fdowncase (tem
);
2991 if (!strcmp (SDATA (tem
), "on")
2992 || !strcmp (SDATA (tem
), "true"))
2997 case RES_TYPE_STRING
:
3000 case RES_TYPE_SYMBOL
:
3001 /* As a special case, we map the values `true' and `on'
3002 to Qt, and `false' and `off' to Qnil. */
3005 lower
= Fdowncase (tem
);
3006 if (!strcmp (SDATA (lower
), "on")
3007 || !strcmp (SDATA (lower
), "true"))
3009 else if (!strcmp (SDATA (lower
), "off")
3010 || !strcmp (SDATA (lower
), "false"))
3013 return Fintern (tem
, Qnil
);
3026 /* Like x_get_arg, but also record the value in f->param_alist. */
3029 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
3031 Lisp_Object alist
, param
;
3034 enum resource_types type
;
3038 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
3039 attribute
, class, type
);
3041 store_frame_param (f
, param
, value
);
3046 /* Record in frame F the specified or default value according to ALIST
3047 of the parameter named PROP (a Lisp symbol).
3048 If no value is specified for PROP, look for an X default for XPROP
3049 on the frame named NAME.
3050 If that is not found either, use the value DEFLT. */
3053 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
3060 enum resource_types type
;
3064 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
3065 if (EQ (tem
, Qunbound
))
3067 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3072 /* Record in frame F the specified or default value according to ALIST
3073 of the parameter named PROP (a Lisp symbol). If no value is
3074 specified for PROP, look for an X default for XPROP on the frame
3075 named NAME. If that is not found either, use the value DEFLT. */
3078 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
3087 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3090 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
3091 if (EQ (tem
, Qunbound
))
3093 #ifdef USE_TOOLKIT_SCROLL_BARS
3095 /* See if an X resource for the scroll bar color has been
3097 tem
= display_x_get_resource (dpyinfo
,
3098 build_string (foreground_p
3102 build_string ("verticalScrollBar"),
3106 /* If nothing has been specified, scroll bars will use a
3107 toolkit-dependent default. Because these defaults are
3108 difficult to get at without actually creating a scroll
3109 bar, use nil to indicate that no color has been
3114 #else /* not USE_TOOLKIT_SCROLL_BARS */
3118 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3121 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3127 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3128 doc
: /* Parse an X-style geometry string STRING.
3129 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3130 The properties returned may include `top', `left', `height', and `width'.
3131 The value of `left' or `top' may be an integer,
3132 or a list (+ N) meaning N pixels relative to top/left corner,
3133 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3138 unsigned int width
, height
;
3141 CHECK_STRING (string
);
3143 geometry
= XParseGeometry ((char *) SDATA (string
),
3144 &x
, &y
, &width
, &height
);
3147 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3148 error ("Must specify both x and y position, or neither");
3152 if (geometry
& XValue
)
3154 Lisp_Object element
;
3156 if (x
>= 0 && (geometry
& XNegative
))
3157 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3158 else if (x
< 0 && ! (geometry
& XNegative
))
3159 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3161 element
= Fcons (Qleft
, make_number (x
));
3162 result
= Fcons (element
, result
);
3165 if (geometry
& YValue
)
3167 Lisp_Object element
;
3169 if (y
>= 0 && (geometry
& YNegative
))
3170 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3171 else if (y
< 0 && ! (geometry
& YNegative
))
3172 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3174 element
= Fcons (Qtop
, make_number (y
));
3175 result
= Fcons (element
, result
);
3178 if (geometry
& WidthValue
)
3179 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3180 if (geometry
& HeightValue
)
3181 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3186 /* Calculate the desired size and position of this window,
3187 and return the flags saying which aspects were specified.
3189 This function does not make the coordinates positive. */
3191 #define DEFAULT_ROWS 40
3192 #define DEFAULT_COLS 80
3195 x_figure_window_size (f
, parms
)
3199 register Lisp_Object tem0
, tem1
, tem2
;
3200 long window_prompting
= 0;
3201 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3203 /* Default values if we fall through.
3204 Actually, if that happens we should get
3205 window manager prompting. */
3206 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3207 f
->height
= DEFAULT_ROWS
;
3208 /* Window managers expect that if program-specified
3209 positions are not (0,0), they're intentional, not defaults. */
3210 f
->output_data
.x
->top_pos
= 0;
3211 f
->output_data
.x
->left_pos
= 0;
3213 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3214 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3215 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3216 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3218 if (!EQ (tem0
, Qunbound
))
3220 CHECK_NUMBER (tem0
);
3221 f
->height
= XINT (tem0
);
3223 if (!EQ (tem1
, Qunbound
))
3225 CHECK_NUMBER (tem1
);
3226 SET_FRAME_WIDTH (f
, XINT (tem1
));
3228 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3229 window_prompting
|= USSize
;
3231 window_prompting
|= PSize
;
3234 f
->output_data
.x
->vertical_scroll_bar_extra
3235 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3237 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3239 x_compute_fringe_widths (f
, 0);
3241 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3242 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3244 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3245 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3246 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3247 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3249 if (EQ (tem0
, Qminus
))
3251 f
->output_data
.x
->top_pos
= 0;
3252 window_prompting
|= YNegative
;
3254 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3255 && CONSP (XCDR (tem0
))
3256 && INTEGERP (XCAR (XCDR (tem0
))))
3258 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3259 window_prompting
|= YNegative
;
3261 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3262 && CONSP (XCDR (tem0
))
3263 && INTEGERP (XCAR (XCDR (tem0
))))
3265 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3267 else if (EQ (tem0
, Qunbound
))
3268 f
->output_data
.x
->top_pos
= 0;
3271 CHECK_NUMBER (tem0
);
3272 f
->output_data
.x
->top_pos
= XINT (tem0
);
3273 if (f
->output_data
.x
->top_pos
< 0)
3274 window_prompting
|= YNegative
;
3277 if (EQ (tem1
, Qminus
))
3279 f
->output_data
.x
->left_pos
= 0;
3280 window_prompting
|= XNegative
;
3282 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3283 && CONSP (XCDR (tem1
))
3284 && INTEGERP (XCAR (XCDR (tem1
))))
3286 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3287 window_prompting
|= XNegative
;
3289 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3290 && CONSP (XCDR (tem1
))
3291 && INTEGERP (XCAR (XCDR (tem1
))))
3293 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3295 else if (EQ (tem1
, Qunbound
))
3296 f
->output_data
.x
->left_pos
= 0;
3299 CHECK_NUMBER (tem1
);
3300 f
->output_data
.x
->left_pos
= XINT (tem1
);
3301 if (f
->output_data
.x
->left_pos
< 0)
3302 window_prompting
|= XNegative
;
3305 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3306 window_prompting
|= USPosition
;
3308 window_prompting
|= PPosition
;
3311 if (f
->output_data
.x
->want_fullscreen
!= FULLSCREEN_NONE
)
3316 /* It takes both for some WM:s to place it where we want */
3317 window_prompting
= USPosition
| PPosition
;
3318 x_fullscreen_adjust (f
, &width
, &height
, &top
, &left
);
3321 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3322 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3323 f
->output_data
.x
->left_pos
= left
;
3324 f
->output_data
.x
->top_pos
= top
;
3327 return window_prompting
;
3330 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3333 XSetWMProtocols (dpy
, w
, protocols
, count
)
3340 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3341 if (prop
== None
) return False
;
3342 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3343 (unsigned char *) protocols
, count
);
3346 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3348 #ifdef USE_X_TOOLKIT
3350 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3351 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3352 already be present because of the toolkit (Motif adds some of them,
3353 for example, but Xt doesn't). */
3356 hack_wm_protocols (f
, widget
)
3360 Display
*dpy
= XtDisplay (widget
);
3361 Window w
= XtWindow (widget
);
3362 int need_delete
= 1;
3368 Atom type
, *atoms
= 0;
3370 unsigned long nitems
= 0;
3371 unsigned long bytes_after
;
3373 if ((XGetWindowProperty (dpy
, w
,
3374 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3375 (long)0, (long)100, False
, XA_ATOM
,
3376 &type
, &format
, &nitems
, &bytes_after
,
3377 (unsigned char **) &atoms
)
3379 && format
== 32 && type
== XA_ATOM
)
3383 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3385 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3387 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3390 if (atoms
) XFree ((char *) atoms
);
3396 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3398 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3400 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3402 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3403 XA_ATOM
, 32, PropModeAppend
,
3404 (unsigned char *) props
, count
);
3412 /* Support routines for XIC (X Input Context). */
3416 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3417 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3420 /* Supported XIM styles, ordered by preferenc. */
3422 static XIMStyle supported_xim_styles
[] =
3424 XIMPreeditPosition
| XIMStatusArea
,
3425 XIMPreeditPosition
| XIMStatusNothing
,
3426 XIMPreeditPosition
| XIMStatusNone
,
3427 XIMPreeditNothing
| XIMStatusArea
,
3428 XIMPreeditNothing
| XIMStatusNothing
,
3429 XIMPreeditNothing
| XIMStatusNone
,
3430 XIMPreeditNone
| XIMStatusArea
,
3431 XIMPreeditNone
| XIMStatusNothing
,
3432 XIMPreeditNone
| XIMStatusNone
,
3437 /* Create an X fontset on frame F with base font name
3441 xic_create_xfontset (f
, base_fontname
)
3443 char *base_fontname
;
3446 char **missing_list
;
3450 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3451 base_fontname
, &missing_list
,
3452 &missing_count
, &def_string
);
3454 XFreeStringList (missing_list
);
3456 /* No need to free def_string. */
3461 /* Value is the best input style, given user preferences USER (already
3462 checked to be supported by Emacs), and styles supported by the
3463 input method XIM. */
3466 best_xim_style (user
, xim
)
3472 for (i
= 0; i
< user
->count_styles
; ++i
)
3473 for (j
= 0; j
< xim
->count_styles
; ++j
)
3474 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3475 return user
->supported_styles
[i
];
3477 /* Return the default style. */
3478 return XIMPreeditNothing
| XIMStatusNothing
;
3481 /* Create XIC for frame F. */
3483 static XIMStyle xic_style
;
3486 create_frame_xic (f
)
3491 XFontSet xfs
= NULL
;
3496 xim
= FRAME_X_XIM (f
);
3501 XVaNestedList preedit_attr
;
3502 XVaNestedList status_attr
;
3503 char *base_fontname
;
3506 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3507 spot
.x
= 0; spot
.y
= 1;
3508 /* Create X fontset. */
3509 fontset
= FRAME_FONTSET (f
);
3511 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3514 /* Determine the base fontname from the ASCII font name of
3516 char *ascii_font
= (char *) SDATA (fontset_ascii (fontset
));
3517 char *p
= ascii_font
;
3520 for (i
= 0; *p
; p
++)
3523 /* As the font name doesn't conform to XLFD, we can't
3524 modify it to get a suitable base fontname for the
3526 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3529 int len
= strlen (ascii_font
) + 1;
3532 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3541 base_fontname
= (char *) alloca (len
);
3542 bzero (base_fontname
, len
);
3543 strcpy (base_fontname
, "-*-*-");
3544 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3545 strcat (base_fontname
, "*-*-*-*-*-*-*");
3548 xfs
= xic_create_xfontset (f
, base_fontname
);
3550 /* Determine XIC style. */
3553 XIMStyles supported_list
;
3554 supported_list
.count_styles
= (sizeof supported_xim_styles
3555 / sizeof supported_xim_styles
[0]);
3556 supported_list
.supported_styles
= supported_xim_styles
;
3557 xic_style
= best_xim_style (&supported_list
,
3558 FRAME_X_XIM_STYLES (f
));
3561 preedit_attr
= XVaCreateNestedList (0,
3564 FRAME_FOREGROUND_PIXEL (f
),
3566 FRAME_BACKGROUND_PIXEL (f
),
3567 (xic_style
& XIMPreeditPosition
3572 status_attr
= XVaCreateNestedList (0,
3578 FRAME_FOREGROUND_PIXEL (f
),
3580 FRAME_BACKGROUND_PIXEL (f
),
3583 xic
= XCreateIC (xim
,
3584 XNInputStyle
, xic_style
,
3585 XNClientWindow
, FRAME_X_WINDOW(f
),
3586 XNFocusWindow
, FRAME_X_WINDOW(f
),
3587 XNStatusAttributes
, status_attr
,
3588 XNPreeditAttributes
, preedit_attr
,
3590 XFree (preedit_attr
);
3591 XFree (status_attr
);
3594 FRAME_XIC (f
) = xic
;
3595 FRAME_XIC_STYLE (f
) = xic_style
;
3596 FRAME_XIC_FONTSET (f
) = xfs
;
3600 /* Destroy XIC and free XIC fontset of frame F, if any. */
3606 if (FRAME_XIC (f
) == NULL
)
3609 XDestroyIC (FRAME_XIC (f
));
3610 if (FRAME_XIC_FONTSET (f
))
3611 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3613 FRAME_XIC (f
) = NULL
;
3614 FRAME_XIC_FONTSET (f
) = NULL
;
3618 /* Place preedit area for XIC of window W's frame to specified
3619 pixel position X/Y. X and Y are relative to window W. */
3622 xic_set_preeditarea (w
, x
, y
)
3626 struct frame
*f
= XFRAME (w
->frame
);
3630 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3631 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3632 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3633 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3638 /* Place status area for XIC in bottom right corner of frame F.. */
3641 xic_set_statusarea (f
)
3644 XIC xic
= FRAME_XIC (f
);
3649 /* Negotiate geometry of status area. If input method has existing
3650 status area, use its current size. */
3651 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3652 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3653 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3656 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3657 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3660 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3662 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3663 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3667 area
.width
= needed
->width
;
3668 area
.height
= needed
->height
;
3669 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3670 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3671 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3674 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3675 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3680 /* Set X fontset for XIC of frame F, using base font name
3681 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3684 xic_set_xfontset (f
, base_fontname
)
3686 char *base_fontname
;
3691 xfs
= xic_create_xfontset (f
, base_fontname
);
3693 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3694 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3695 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3696 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3697 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3700 if (FRAME_XIC_FONTSET (f
))
3701 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3702 FRAME_XIC_FONTSET (f
) = xfs
;
3705 #endif /* HAVE_X_I18N */
3709 #ifdef USE_X_TOOLKIT
3711 /* Create and set up the X widget for frame F. */
3714 x_window (f
, window_prompting
, minibuffer_only
)
3716 long window_prompting
;
3717 int minibuffer_only
;
3719 XClassHint class_hints
;
3720 XSetWindowAttributes attributes
;
3721 unsigned long attribute_mask
;
3722 Widget shell_widget
;
3724 Widget frame_widget
;
3730 /* Use the resource name as the top-level widget name
3731 for looking up resources. Make a non-Lisp copy
3732 for the window manager, so GC relocation won't bother it.
3734 Elsewhere we specify the window name for the window manager. */
3737 char *str
= (char *) SDATA (Vx_resource_name
);
3738 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3739 strcpy (f
->namebuf
, str
);
3743 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3744 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3745 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3746 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3747 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3748 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3749 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3750 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3751 applicationShellWidgetClass
,
3752 FRAME_X_DISPLAY (f
), al
, ac
);
3754 f
->output_data
.x
->widget
= shell_widget
;
3755 /* maybe_set_screen_title_format (shell_widget); */
3757 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3758 (widget_value
*) NULL
,
3759 shell_widget
, False
,
3763 (lw_callback
) NULL
);
3766 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3767 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3768 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3769 XtSetValues (pane_widget
, al
, ac
);
3770 f
->output_data
.x
->column_widget
= pane_widget
;
3772 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3773 the emacs screen when changing menubar. This reduces flickering. */
3776 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3777 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3778 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3779 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3780 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3781 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3782 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3783 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3784 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3787 f
->output_data
.x
->edit_widget
= frame_widget
;
3789 XtManageChild (frame_widget
);
3791 /* Do some needed geometry management. */
3794 char *tem
, shell_position
[32];
3797 int extra_borders
= 0;
3799 = (f
->output_data
.x
->menubar_widget
3800 ? (f
->output_data
.x
->menubar_widget
->core
.height
3801 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3804 #if 0 /* Experimentally, we now get the right results
3805 for -geometry -0-0 without this. 24 Aug 96, rms. */
3806 if (FRAME_EXTERNAL_MENU_BAR (f
))
3809 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3810 menubar_size
+= ibw
;
3814 f
->output_data
.x
->menubar_height
= menubar_size
;
3817 /* Motif seems to need this amount added to the sizes
3818 specified for the shell widget. The Athena/Lucid widgets don't.
3819 Both conclusions reached experimentally. -- rms. */
3820 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3821 &extra_borders
, NULL
);
3825 /* Convert our geometry parameters into a geometry string
3827 Note that we do not specify here whether the position
3828 is a user-specified or program-specified one.
3829 We pass that information later, in x_wm_set_size_hints. */
3831 int left
= f
->output_data
.x
->left_pos
;
3832 int xneg
= window_prompting
& XNegative
;
3833 int top
= f
->output_data
.x
->top_pos
;
3834 int yneg
= window_prompting
& YNegative
;
3840 if (window_prompting
& USPosition
)
3841 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3842 PIXEL_WIDTH (f
) + extra_borders
,
3843 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3844 (xneg
? '-' : '+'), left
,
3845 (yneg
? '-' : '+'), top
);
3847 sprintf (shell_position
, "=%dx%d",
3848 PIXEL_WIDTH (f
) + extra_borders
,
3849 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3852 len
= strlen (shell_position
) + 1;
3853 /* We don't free this because we don't know whether
3854 it is safe to free it while the frame exists.
3855 It isn't worth the trouble of arranging to free it
3856 when the frame is deleted. */
3857 tem
= (char *) xmalloc (len
);
3858 strncpy (tem
, shell_position
, len
);
3859 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3860 XtSetValues (shell_widget
, al
, ac
);
3863 XtManageChild (pane_widget
);
3864 XtRealizeWidget (shell_widget
);
3866 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3868 validate_x_resource_name ();
3870 class_hints
.res_name
= (char *) SDATA (Vx_resource_name
);
3871 class_hints
.res_class
= (char *) SDATA (Vx_resource_class
);
3872 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3875 FRAME_XIC (f
) = NULL
;
3877 create_frame_xic (f
);
3881 f
->output_data
.x
->wm_hints
.input
= True
;
3882 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3883 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3884 &f
->output_data
.x
->wm_hints
);
3886 hack_wm_protocols (f
, shell_widget
);
3889 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3892 /* Do a stupid property change to force the server to generate a
3893 PropertyNotify event so that the event_stream server timestamp will
3894 be initialized to something relevant to the time we created the window.
3896 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3897 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3898 XA_ATOM
, 32, PropModeAppend
,
3899 (unsigned char*) NULL
, 0);
3901 /* Make all the standard events reach the Emacs frame. */
3902 attributes
.event_mask
= STANDARD_EVENT_SET
;
3907 /* XIM server might require some X events. */
3908 unsigned long fevent
= NoEventMask
;
3909 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3910 attributes
.event_mask
|= fevent
;
3912 #endif /* HAVE_X_I18N */
3914 attribute_mask
= CWEventMask
;
3915 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3916 attribute_mask
, &attributes
);
3918 XtMapWidget (frame_widget
);
3920 /* x_set_name normally ignores requests to set the name if the
3921 requested name is the same as the current name. This is the one
3922 place where that assumption isn't correct; f->name is set, but
3923 the X server hasn't been told. */
3926 int explicit = f
->explicit_name
;
3928 f
->explicit_name
= 0;
3931 x_set_name (f
, name
, explicit);
3934 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3935 f
->output_data
.x
->text_cursor
);
3939 /* This is a no-op, except under Motif. Make sure main areas are
3940 set to something reasonable, in case we get an error later. */
3941 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3944 #else /* not USE_X_TOOLKIT */
3946 /* Create and set up the X window for frame F. */
3953 XClassHint class_hints
;
3954 XSetWindowAttributes attributes
;
3955 unsigned long attribute_mask
;
3957 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3958 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3959 attributes
.bit_gravity
= StaticGravity
;
3960 attributes
.backing_store
= NotUseful
;
3961 attributes
.save_under
= True
;
3962 attributes
.event_mask
= STANDARD_EVENT_SET
;
3963 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3964 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3969 = XCreateWindow (FRAME_X_DISPLAY (f
),
3970 f
->output_data
.x
->parent_desc
,
3971 f
->output_data
.x
->left_pos
,
3972 f
->output_data
.x
->top_pos
,
3973 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3974 f
->output_data
.x
->border_width
,
3975 CopyFromParent
, /* depth */
3976 InputOutput
, /* class */
3978 attribute_mask
, &attributes
);
3982 create_frame_xic (f
);
3985 /* XIM server might require some X events. */
3986 unsigned long fevent
= NoEventMask
;
3987 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3988 attributes
.event_mask
|= fevent
;
3989 attribute_mask
= CWEventMask
;
3990 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3991 attribute_mask
, &attributes
);
3994 #endif /* HAVE_X_I18N */
3996 validate_x_resource_name ();
3998 class_hints
.res_name
= (char *) SDATA (Vx_resource_name
);
3999 class_hints
.res_class
= (char *) SDATA (Vx_resource_class
);
4000 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
4002 /* The menubar is part of the ordinary display;
4003 it does not count in addition to the height of the window. */
4004 f
->output_data
.x
->menubar_height
= 0;
4006 /* This indicates that we use the "Passive Input" input model.
4007 Unless we do this, we don't get the Focus{In,Out} events that we
4008 need to draw the cursor correctly. Accursed bureaucrats.
4009 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
4011 f
->output_data
.x
->wm_hints
.input
= True
;
4012 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
4013 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4014 &f
->output_data
.x
->wm_hints
);
4015 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
4017 /* Request "save yourself" and "delete window" commands from wm. */
4020 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
4021 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
4022 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
4025 /* x_set_name normally ignores requests to set the name if the
4026 requested name is the same as the current name. This is the one
4027 place where that assumption isn't correct; f->name is set, but
4028 the X server hasn't been told. */
4031 int explicit = f
->explicit_name
;
4033 f
->explicit_name
= 0;
4036 x_set_name (f
, name
, explicit);
4039 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4040 f
->output_data
.x
->text_cursor
);
4044 if (FRAME_X_WINDOW (f
) == 0)
4045 error ("Unable to create window");
4048 #endif /* not USE_X_TOOLKIT */
4050 /* Handle the icon stuff for this window. Perhaps later we might
4051 want an x_set_icon_position which can be called interactively as
4059 Lisp_Object icon_x
, icon_y
;
4060 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4062 /* Set the position of the icon. Note that twm groups all
4063 icons in an icon window. */
4064 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4065 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4066 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4068 CHECK_NUMBER (icon_x
);
4069 CHECK_NUMBER (icon_y
);
4071 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4072 error ("Both left and top icon corners of icon must be specified");
4076 if (! EQ (icon_x
, Qunbound
))
4077 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4079 /* Start up iconic or window? */
4080 x_wm_set_window_state
4081 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
4086 x_text_icon (f
, (char *) SDATA ((!NILP (f
->icon_name
)
4093 /* Make the GCs needed for this window, setting the
4094 background, border and mouse colors; also create the
4095 mouse cursor and the gray border tile. */
4097 static char cursor_bits
[] =
4099 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4109 XGCValues gc_values
;
4113 /* Create the GCs of this frame.
4114 Note that many default values are used. */
4117 gc_values
.font
= f
->output_data
.x
->font
->fid
;
4118 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
4119 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4120 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
4121 f
->output_data
.x
->normal_gc
4122 = XCreateGC (FRAME_X_DISPLAY (f
),
4124 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
4127 /* Reverse video style. */
4128 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4129 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4130 f
->output_data
.x
->reverse_gc
4131 = XCreateGC (FRAME_X_DISPLAY (f
),
4133 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
4136 /* Cursor has cursor-color background, background-color foreground. */
4137 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4138 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
4139 gc_values
.fill_style
= FillOpaqueStippled
;
4141 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4142 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4143 cursor_bits
, 16, 16);
4144 f
->output_data
.x
->cursor_gc
4145 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4146 (GCFont
| GCForeground
| GCBackground
4147 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
4151 f
->output_data
.x
->white_relief
.gc
= 0;
4152 f
->output_data
.x
->black_relief
.gc
= 0;
4154 /* Create the gray border tile used when the pointer is not in
4155 the frame. Since this depends on the frame's pixel values,
4156 this must be done on a per-frame basis. */
4157 f
->output_data
.x
->border_tile
4158 = (XCreatePixmapFromBitmapData
4159 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
4160 gray_bits
, gray_width
, gray_height
,
4161 f
->output_data
.x
->foreground_pixel
,
4162 f
->output_data
.x
->background_pixel
,
4163 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4169 /* Free what was was allocated in x_make_gc. */
4175 Display
*dpy
= FRAME_X_DISPLAY (f
);
4179 if (f
->output_data
.x
->normal_gc
)
4181 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4182 f
->output_data
.x
->normal_gc
= 0;
4185 if (f
->output_data
.x
->reverse_gc
)
4187 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4188 f
->output_data
.x
->reverse_gc
= 0;
4191 if (f
->output_data
.x
->cursor_gc
)
4193 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4194 f
->output_data
.x
->cursor_gc
= 0;
4197 if (f
->output_data
.x
->border_tile
)
4199 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4200 f
->output_data
.x
->border_tile
= 0;
4207 /* Handler for signals raised during x_create_frame and
4208 x_create_top_frame. FRAME is the frame which is partially
4212 unwind_create_frame (frame
)
4215 struct frame
*f
= XFRAME (frame
);
4217 /* If frame is ``official'', nothing to do. */
4218 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4221 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4224 x_free_frame_resources (f
);
4226 /* Check that reference counts are indeed correct. */
4227 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4228 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4236 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4238 doc
: /* Make a new X window, which is called a "frame" in Emacs terms.
4239 Returns an Emacs frame object.
4240 ALIST is an alist of frame parameters.
4241 If the parameters specify that the frame should not have a minibuffer,
4242 and do not specify a specific minibuffer window to use,
4243 then `default-minibuffer-frame' must be a frame whose minibuffer can
4244 be shared by the new frame.
4246 This function is an internal primitive--use `make-frame' instead. */)
4251 Lisp_Object frame
, tem
;
4253 int minibuffer_only
= 0;
4254 long window_prompting
= 0;
4256 int count
= SPECPDL_INDEX ();
4257 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4258 Lisp_Object display
;
4259 struct x_display_info
*dpyinfo
= NULL
;
4265 /* Use this general default value to start with
4266 until we know if this frame has a specified name. */
4267 Vx_resource_name
= Vinvocation_name
;
4269 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4270 if (EQ (display
, Qunbound
))
4272 dpyinfo
= check_x_display_info (display
);
4274 kb
= dpyinfo
->kboard
;
4276 kb
= &the_only_kboard
;
4279 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4281 && ! EQ (name
, Qunbound
)
4283 error ("Invalid frame name--not a string or nil");
4286 Vx_resource_name
= name
;
4288 /* See if parent window is specified. */
4289 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4290 if (EQ (parent
, Qunbound
))
4292 if (! NILP (parent
))
4293 CHECK_NUMBER (parent
);
4295 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4296 /* No need to protect DISPLAY because that's not used after passing
4297 it to make_frame_without_minibuffer. */
4299 GCPRO4 (parms
, parent
, name
, frame
);
4300 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4302 if (EQ (tem
, Qnone
) || NILP (tem
))
4303 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4304 else if (EQ (tem
, Qonly
))
4306 f
= make_minibuffer_frame ();
4307 minibuffer_only
= 1;
4309 else if (WINDOWP (tem
))
4310 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4314 XSETFRAME (frame
, f
);
4316 /* Note that X Windows does support scroll bars. */
4317 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4319 f
->output_method
= output_x_window
;
4320 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4321 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4322 f
->output_data
.x
->icon_bitmap
= -1;
4323 f
->output_data
.x
->fontset
= -1;
4324 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4325 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4326 #ifdef USE_TOOLKIT_SCROLL_BARS
4327 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
4328 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
4329 #endif /* USE_TOOLKIT_SCROLL_BARS */
4330 record_unwind_protect (unwind_create_frame
, frame
);
4333 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4335 if (! STRINGP (f
->icon_name
))
4336 f
->icon_name
= Qnil
;
4338 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4340 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4341 dpyinfo_refcount
= dpyinfo
->reference_count
;
4342 #endif /* GLYPH_DEBUG */
4344 FRAME_KBOARD (f
) = kb
;
4347 /* These colors will be set anyway later, but it's important
4348 to get the color reference counts right, so initialize them! */
4351 struct gcpro gcpro1
;
4353 /* Function x_decode_color can signal an error. Make
4354 sure to initialize color slots so that we won't try
4355 to free colors we haven't allocated. */
4356 f
->output_data
.x
->foreground_pixel
= -1;
4357 f
->output_data
.x
->background_pixel
= -1;
4358 f
->output_data
.x
->cursor_pixel
= -1;
4359 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4360 f
->output_data
.x
->border_pixel
= -1;
4361 f
->output_data
.x
->mouse_pixel
= -1;
4363 black
= build_string ("black");
4365 f
->output_data
.x
->foreground_pixel
4366 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4367 f
->output_data
.x
->background_pixel
4368 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4369 f
->output_data
.x
->cursor_pixel
4370 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4371 f
->output_data
.x
->cursor_foreground_pixel
4372 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4373 f
->output_data
.x
->border_pixel
4374 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4375 f
->output_data
.x
->mouse_pixel
4376 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4380 /* Specify the parent under which to make this X window. */
4384 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4385 f
->output_data
.x
->explicit_parent
= 1;
4389 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4390 f
->output_data
.x
->explicit_parent
= 0;
4393 /* Set the name; the functions to which we pass f expect the name to
4395 if (EQ (name
, Qunbound
) || NILP (name
))
4397 f
->name
= build_string (dpyinfo
->x_id_name
);
4398 f
->explicit_name
= 0;
4403 f
->explicit_name
= 1;
4404 /* use the frame's title when getting resources for this frame. */
4405 specbind (Qx_resource_name
, name
);
4408 /* Extract the window parameters from the supplied values
4409 that are needed to determine window geometry. */
4413 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4416 /* First, try whatever font the caller has specified. */
4419 tem
= Fquery_fontset (font
, Qnil
);
4421 font
= x_new_fontset (f
, SDATA (tem
));
4423 font
= x_new_font (f
, SDATA (font
));
4426 /* Try out a font which we hope has bold and italic variations. */
4427 if (!STRINGP (font
))
4428 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4429 if (!STRINGP (font
))
4430 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4431 if (! STRINGP (font
))
4432 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4433 if (! STRINGP (font
))
4434 /* This was formerly the first thing tried, but it finds too many fonts
4435 and takes too long. */
4436 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4437 /* If those didn't work, look for something which will at least work. */
4438 if (! STRINGP (font
))
4439 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4441 if (! STRINGP (font
))
4442 font
= build_string ("fixed");
4444 x_default_parameter (f
, parms
, Qfont
, font
,
4445 "font", "Font", RES_TYPE_STRING
);
4449 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4450 whereby it fails to get any font. */
4451 xlwmenu_default_font
= f
->output_data
.x
->font
;
4454 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4455 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4457 /* This defaults to 1 in order to match xterm. We recognize either
4458 internalBorderWidth or internalBorder (which is what xterm calls
4460 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4464 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4465 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4466 if (! EQ (value
, Qunbound
))
4467 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4470 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4471 "internalBorderWidth", "internalBorderWidth",
4473 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4474 "verticalScrollBars", "ScrollBars",
4477 /* Also do the stuff which must be set before the window exists. */
4478 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4479 "foreground", "Foreground", RES_TYPE_STRING
);
4480 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4481 "background", "Background", RES_TYPE_STRING
);
4482 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4483 "pointerColor", "Foreground", RES_TYPE_STRING
);
4484 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4485 "cursorColor", "Foreground", RES_TYPE_STRING
);
4486 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4487 "borderColor", "BorderColor", RES_TYPE_STRING
);
4488 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4489 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4490 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4491 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4492 x_default_parameter (f
, parms
, Qleft_fringe
, Qnil
,
4493 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4494 x_default_parameter (f
, parms
, Qright_fringe
, Qnil
,
4495 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4497 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4498 "scrollBarForeground",
4499 "ScrollBarForeground", 1);
4500 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4501 "scrollBarBackground",
4502 "ScrollBarBackground", 0);
4504 /* Init faces before x_default_parameter is called for scroll-bar
4505 parameters because that function calls x_set_scroll_bar_width,
4506 which calls change_frame_size, which calls Fset_window_buffer,
4507 which runs hooks, which call Fvertical_motion. At the end, we
4508 end up in init_iterator with a null face cache, which should not
4510 init_frame_faces (f
);
4512 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4513 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4514 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4515 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4516 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4517 "bufferPredicate", "BufferPredicate",
4519 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4520 "title", "Title", RES_TYPE_STRING
);
4521 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4522 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4523 x_default_parameter (f
, parms
, Qfullscreen
, Qnil
,
4524 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4526 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4528 /* Add the tool-bar height to the initial frame height so that the
4529 user gets a text display area of the size he specified with -g or
4530 via .Xdefaults. Later changes of the tool-bar height don't
4531 change the frame size. This is done so that users can create
4532 tall Emacs frames without having to guess how tall the tool-bar
4534 if (FRAME_TOOL_BAR_LINES (f
))
4536 int margin
, relief
, bar_height
;
4538 relief
= (tool_bar_button_relief
>= 0
4539 ? tool_bar_button_relief
4540 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4542 if (INTEGERP (Vtool_bar_button_margin
)
4543 && XINT (Vtool_bar_button_margin
) > 0)
4544 margin
= XFASTINT (Vtool_bar_button_margin
);
4545 else if (CONSP (Vtool_bar_button_margin
)
4546 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4547 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4548 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4552 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4553 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4556 /* Compute the size of the X window. */
4557 window_prompting
= x_figure_window_size (f
, parms
);
4559 if (window_prompting
& XNegative
)
4561 if (window_prompting
& YNegative
)
4562 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4564 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4568 if (window_prompting
& YNegative
)
4569 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4571 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4574 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4576 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4577 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4579 /* Create the X widget or window. */
4580 #ifdef USE_X_TOOLKIT
4581 x_window (f
, window_prompting
, minibuffer_only
);
4589 /* Now consider the frame official. */
4590 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4591 Vframe_list
= Fcons (frame
, Vframe_list
);
4593 /* We need to do this after creating the X window, so that the
4594 icon-creation functions can say whose icon they're describing. */
4595 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4596 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4598 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4599 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4600 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4601 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4602 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4603 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4604 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4605 "scrollBarWidth", "ScrollBarWidth",
4608 /* Dimensions, especially f->height, must be done via change_frame_size.
4609 Change will not be effected unless different from the current
4615 SET_FRAME_WIDTH (f
, 0);
4616 change_frame_size (f
, height
, width
, 1, 0, 0);
4618 /* Set up faces after all frame parameters are known. This call
4619 also merges in face attributes specified for new frames. If we
4620 don't do this, the `menu' face for instance won't have the right
4621 colors, and the menu bar won't appear in the specified colors for
4623 call1 (Qface_set_after_frame_default
, frame
);
4625 #ifdef USE_X_TOOLKIT
4626 /* Create the menu bar. */
4627 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4629 /* If this signals an error, we haven't set size hints for the
4630 frame and we didn't make it visible. */
4631 initialize_frame_menubar (f
);
4633 /* This is a no-op, except under Motif where it arranges the
4634 main window for the widgets on it. */
4635 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4636 f
->output_data
.x
->menubar_widget
,
4637 f
->output_data
.x
->edit_widget
);
4639 #endif /* USE_X_TOOLKIT */
4641 /* Tell the server what size and position, etc, we want, and how
4642 badly we want them. This should be done after we have the menu
4643 bar so that its size can be taken into account. */
4645 x_wm_set_size_hint (f
, window_prompting
, 0);
4648 /* Make the window appear on the frame and enable display, unless
4649 the caller says not to. However, with explicit parent, Emacs
4650 cannot control visibility, so don't try. */
4651 if (! f
->output_data
.x
->explicit_parent
)
4653 Lisp_Object visibility
;
4655 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4657 if (EQ (visibility
, Qunbound
))
4660 if (EQ (visibility
, Qicon
))
4661 x_iconify_frame (f
);
4662 else if (! NILP (visibility
))
4663 x_make_frame_visible (f
);
4665 /* Must have been Qnil. */
4671 /* Make sure windows on this frame appear in calls to next-window
4672 and similar functions. */
4673 Vwindow_list
= Qnil
;
4675 return unbind_to (count
, frame
);
4679 /* FRAME is used only to get a handle on the X display. We don't pass the
4680 display info directly because we're called from frame.c, which doesn't
4681 know about that structure. */
4684 x_get_focus_frame (frame
)
4685 struct frame
*frame
;
4687 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4689 if (! dpyinfo
->x_focus_frame
)
4692 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4697 /* In certain situations, when the window manager follows a
4698 click-to-focus policy, there seems to be no way around calling
4699 XSetInputFocus to give another frame the input focus .
4701 In an ideal world, XSetInputFocus should generally be avoided so
4702 that applications don't interfere with the window manager's focus
4703 policy. But I think it's okay to use when it's clearly done
4704 following a user-command. */
4706 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4707 doc
: /* Set the input focus to FRAME.
4708 FRAME nil means use the selected frame. */)
4712 struct frame
*f
= check_x_frame (frame
);
4713 Display
*dpy
= FRAME_X_DISPLAY (f
);
4717 count
= x_catch_errors (dpy
);
4718 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4719 RevertToParent
, CurrentTime
);
4720 x_uncatch_errors (dpy
, count
);
4727 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4728 doc
: /* Internal function called by `color-defined-p', which see. */)
4730 Lisp_Object color
, frame
;
4733 FRAME_PTR f
= check_x_frame (frame
);
4735 CHECK_STRING (color
);
4737 if (x_defined_color (f
, SDATA (color
), &foo
, 0))
4743 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4744 doc
: /* Internal function called by `color-values', which see. */)
4746 Lisp_Object color
, frame
;
4749 FRAME_PTR f
= check_x_frame (frame
);
4751 CHECK_STRING (color
);
4753 if (x_defined_color (f
, SDATA (color
), &foo
, 0))
4757 rgb
[0] = make_number (foo
.red
);
4758 rgb
[1] = make_number (foo
.green
);
4759 rgb
[2] = make_number (foo
.blue
);
4760 return Flist (3, rgb
);
4766 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4767 doc
: /* Internal function called by `display-color-p', which see. */)
4769 Lisp_Object display
;
4771 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4773 if (dpyinfo
->n_planes
<= 2)
4776 switch (dpyinfo
->visual
->class)
4789 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4791 doc
: /* Return t if the X display supports shades of gray.
4792 Note that color displays do support shades of gray.
4793 The optional argument DISPLAY specifies which display to ask about.
4794 DISPLAY should be either a frame or a display name (a string).
4795 If omitted or nil, that stands for the selected frame's display. */)
4797 Lisp_Object display
;
4799 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4801 if (dpyinfo
->n_planes
<= 1)
4804 switch (dpyinfo
->visual
->class)
4819 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4821 doc
: /* Returns the width in pixels of the X display DISPLAY.
4822 The optional argument DISPLAY specifies which display to ask about.
4823 DISPLAY should be either a frame or a display name (a string).
4824 If omitted or nil, that stands for the selected frame's display. */)
4826 Lisp_Object display
;
4828 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4830 return make_number (dpyinfo
->width
);
4833 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4834 Sx_display_pixel_height
, 0, 1, 0,
4835 doc
: /* Returns the height in pixels of the X display DISPLAY.
4836 The optional argument DISPLAY specifies which display to ask about.
4837 DISPLAY should be either a frame or a display name (a string).
4838 If omitted or nil, that stands for the selected frame's display. */)
4840 Lisp_Object display
;
4842 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4844 return make_number (dpyinfo
->height
);
4847 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4849 doc
: /* Returns the number of bitplanes of the X display DISPLAY.
4850 The optional argument DISPLAY specifies which display to ask about.
4851 DISPLAY should be either a frame or a display name (a string).
4852 If omitted or nil, that stands for the selected frame's display. */)
4854 Lisp_Object display
;
4856 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4858 return make_number (dpyinfo
->n_planes
);
4861 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4863 doc
: /* Returns the number of color cells of the X display DISPLAY.
4864 The optional argument DISPLAY specifies which display to ask about.
4865 DISPLAY should be either a frame or a display name (a string).
4866 If omitted or nil, that stands for the selected frame's display. */)
4868 Lisp_Object display
;
4870 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4872 return make_number (DisplayCells (dpyinfo
->display
,
4873 XScreenNumberOfScreen (dpyinfo
->screen
)));
4876 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4877 Sx_server_max_request_size
,
4879 doc
: /* Returns the maximum request size of the X server of display DISPLAY.
4880 The optional argument DISPLAY specifies which display to ask about.
4881 DISPLAY should be either a frame or a display name (a string).
4882 If omitted or nil, that stands for the selected frame's display. */)
4884 Lisp_Object display
;
4886 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4888 return make_number (MAXREQUEST (dpyinfo
->display
));
4891 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4892 doc
: /* Returns the vendor ID string of the X server of display DISPLAY.
4893 The optional argument DISPLAY specifies which display to ask about.
4894 DISPLAY should be either a frame or a display name (a string).
4895 If omitted or nil, that stands for the selected frame's display. */)
4897 Lisp_Object display
;
4899 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4900 char *vendor
= ServerVendor (dpyinfo
->display
);
4902 if (! vendor
) vendor
= "";
4903 return build_string (vendor
);
4906 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4907 doc
: /* Returns the version numbers of the X server of display DISPLAY.
4908 The value is a list of three integers: the major and minor
4909 version numbers of the X Protocol in use, and the vendor-specific release
4910 number. See also the function `x-server-vendor'.
4912 The optional argument DISPLAY specifies which display to ask about.
4913 DISPLAY should be either a frame or a display name (a string).
4914 If omitted or nil, that stands for the selected frame's display. */)
4916 Lisp_Object display
;
4918 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4919 Display
*dpy
= dpyinfo
->display
;
4921 return Fcons (make_number (ProtocolVersion (dpy
)),
4922 Fcons (make_number (ProtocolRevision (dpy
)),
4923 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4926 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4927 doc
: /* Return the number of screens on the X server of display DISPLAY.
4928 The optional argument DISPLAY specifies which display to ask about.
4929 DISPLAY should be either a frame or a display name (a string).
4930 If omitted or nil, that stands for the selected frame's display. */)
4932 Lisp_Object display
;
4934 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4936 return make_number (ScreenCount (dpyinfo
->display
));
4939 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4940 doc
: /* Return the height in millimeters of the X display DISPLAY.
4941 The optional argument DISPLAY specifies which display to ask about.
4942 DISPLAY should be either a frame or a display name (a string).
4943 If omitted or nil, that stands for the selected frame's display. */)
4945 Lisp_Object display
;
4947 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4949 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4952 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4953 doc
: /* Return the width in millimeters of the X display DISPLAY.
4954 The optional argument DISPLAY specifies which display to ask about.
4955 DISPLAY should be either a frame or a display name (a string).
4956 If omitted or nil, that stands for the selected frame's display. */)
4958 Lisp_Object display
;
4960 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4962 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4965 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4966 Sx_display_backing_store
, 0, 1, 0,
4967 doc
: /* Returns an indication of whether X display DISPLAY does backing store.
4968 The value may be `always', `when-mapped', or `not-useful'.
4969 The optional argument DISPLAY specifies which display to ask about.
4970 DISPLAY should be either a frame or a display name (a string).
4971 If omitted or nil, that stands for the selected frame's display. */)
4973 Lisp_Object display
;
4975 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4978 switch (DoesBackingStore (dpyinfo
->screen
))
4981 result
= intern ("always");
4985 result
= intern ("when-mapped");
4989 result
= intern ("not-useful");
4993 error ("Strange value for BackingStore parameter of screen");
5000 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
5001 Sx_display_visual_class
, 0, 1, 0,
5002 doc
: /* Return the visual class of the X display DISPLAY.
5003 The value is one of the symbols `static-gray', `gray-scale',
5004 `static-color', `pseudo-color', `true-color', or `direct-color'.
5006 The optional argument DISPLAY specifies which display to ask about.
5007 DISPLAY should be either a frame or a display name (a string).
5008 If omitted or nil, that stands for the selected frame's display. */)
5010 Lisp_Object display
;
5012 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5015 switch (dpyinfo
->visual
->class)
5018 result
= intern ("static-gray");
5021 result
= intern ("gray-scale");
5024 result
= intern ("static-color");
5027 result
= intern ("pseudo-color");
5030 result
= intern ("true-color");
5033 result
= intern ("direct-color");
5036 error ("Display has an unknown visual class");
5043 DEFUN ("x-display-save-under", Fx_display_save_under
,
5044 Sx_display_save_under
, 0, 1, 0,
5045 doc
: /* Returns t if the X display DISPLAY supports the save-under feature.
5046 The optional argument DISPLAY specifies which display to ask about.
5047 DISPLAY should be either a frame or a display name (a string).
5048 If omitted or nil, that stands for the selected frame's display. */)
5050 Lisp_Object display
;
5052 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5054 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
5062 register struct frame
*f
;
5064 return PIXEL_WIDTH (f
);
5069 register struct frame
*f
;
5071 return PIXEL_HEIGHT (f
);
5076 register struct frame
*f
;
5078 return FONT_WIDTH (f
->output_data
.x
->font
);
5083 register struct frame
*f
;
5085 return f
->output_data
.x
->line_height
;
5090 register struct frame
*f
;
5092 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
5097 /************************************************************************
5099 ************************************************************************/
5102 /* Mapping visual names to visuals. */
5104 static struct visual_class
5111 {"StaticGray", StaticGray
},
5112 {"GrayScale", GrayScale
},
5113 {"StaticColor", StaticColor
},
5114 {"PseudoColor", PseudoColor
},
5115 {"TrueColor", TrueColor
},
5116 {"DirectColor", DirectColor
},
5121 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5123 /* Value is the screen number of screen SCR. This is a substitute for
5124 the X function with the same name when that doesn't exist. */
5127 XScreenNumberOfScreen (scr
)
5128 register Screen
*scr
;
5130 Display
*dpy
= scr
->display
;
5133 for (i
= 0; i
< dpy
->nscreens
; ++i
)
5134 if (scr
== dpy
->screens
+ i
)
5140 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5143 /* Select the visual that should be used on display DPYINFO. Set
5144 members of DPYINFO appropriately. Called from x_term_init. */
5147 select_visual (dpyinfo
)
5148 struct x_display_info
*dpyinfo
;
5150 Display
*dpy
= dpyinfo
->display
;
5151 Screen
*screen
= dpyinfo
->screen
;
5154 /* See if a visual is specified. */
5155 value
= display_x_get_resource (dpyinfo
,
5156 build_string ("visualClass"),
5157 build_string ("VisualClass"),
5159 if (STRINGP (value
))
5161 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5162 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5163 depth, a decimal number. NAME is compared with case ignored. */
5164 char *s
= (char *) alloca (SBYTES (value
) + 1);
5169 strcpy (s
, SDATA (value
));
5170 dash
= index (s
, '-');
5173 dpyinfo
->n_planes
= atoi (dash
+ 1);
5177 /* We won't find a matching visual with depth 0, so that
5178 an error will be printed below. */
5179 dpyinfo
->n_planes
= 0;
5181 /* Determine the visual class. */
5182 for (i
= 0; visual_classes
[i
].name
; ++i
)
5183 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5185 class = visual_classes
[i
].class;
5189 /* Look up a matching visual for the specified class. */
5191 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5192 dpyinfo
->n_planes
, class, &vinfo
))
5193 fatal ("Invalid visual specification `%s'", SDATA (value
));
5195 dpyinfo
->visual
= vinfo
.visual
;
5200 XVisualInfo
*vinfo
, vinfo_template
;
5202 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5205 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5207 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5209 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5210 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5211 &vinfo_template
, &n_visuals
);
5213 fatal ("Can't get proper X visual info");
5215 dpyinfo
->n_planes
= vinfo
->depth
;
5216 XFree ((char *) vinfo
);
5221 /* Return the X display structure for the display named NAME.
5222 Open a new connection if necessary. */
5224 struct x_display_info
*
5225 x_display_info_for_name (name
)
5229 struct x_display_info
*dpyinfo
;
5231 CHECK_STRING (name
);
5233 if (! EQ (Vwindow_system
, intern ("x")))
5234 error ("Not using X Windows");
5236 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5238 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5241 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5246 /* Use this general default value to start with. */
5247 Vx_resource_name
= Vinvocation_name
;
5249 validate_x_resource_name ();
5251 dpyinfo
= x_term_init (name
, (char *)0,
5252 (char *) SDATA (Vx_resource_name
));
5255 error ("Cannot connect to X server %s", SDATA (name
));
5258 XSETFASTINT (Vwindow_system_version
, 11);
5264 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5266 doc
: /* Open a connection to an X server.
5267 DISPLAY is the name of the display to connect to.
5268 Optional second arg XRM-STRING is a string of resources in xrdb format.
5269 If the optional third arg MUST-SUCCEED is non-nil,
5270 terminate Emacs if we can't open the connection. */)
5271 (display
, xrm_string
, must_succeed
)
5272 Lisp_Object display
, xrm_string
, must_succeed
;
5274 unsigned char *xrm_option
;
5275 struct x_display_info
*dpyinfo
;
5277 CHECK_STRING (display
);
5278 if (! NILP (xrm_string
))
5279 CHECK_STRING (xrm_string
);
5281 if (! EQ (Vwindow_system
, intern ("x")))
5282 error ("Not using X Windows");
5284 if (! NILP (xrm_string
))
5285 xrm_option
= (unsigned char *) SDATA (xrm_string
);
5287 xrm_option
= (unsigned char *) 0;
5289 validate_x_resource_name ();
5291 /* This is what opens the connection and sets x_current_display.
5292 This also initializes many symbols, such as those used for input. */
5293 dpyinfo
= x_term_init (display
, xrm_option
,
5294 (char *) SDATA (Vx_resource_name
));
5298 if (!NILP (must_succeed
))
5299 fatal ("Cannot connect to X server %s.\n\
5300 Check the DISPLAY environment variable or use `-d'.\n\
5301 Also use the `xauth' program to verify that you have the proper\n\
5302 authorization information needed to connect the X server.\n\
5303 An insecure way to solve the problem may be to use `xhost'.\n",
5306 error ("Cannot connect to X server %s", SDATA (display
));
5311 XSETFASTINT (Vwindow_system_version
, 11);
5315 DEFUN ("x-close-connection", Fx_close_connection
,
5316 Sx_close_connection
, 1, 1, 0,
5317 doc
: /* Close the connection to DISPLAY's X server.
5318 For DISPLAY, specify either a frame or a display name (a string).
5319 If DISPLAY is nil, that stands for the selected frame's display. */)
5321 Lisp_Object display
;
5323 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5326 if (dpyinfo
->reference_count
> 0)
5327 error ("Display still has frames on it");
5330 /* Free the fonts in the font table. */
5331 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5332 if (dpyinfo
->font_table
[i
].name
)
5334 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5335 xfree (dpyinfo
->font_table
[i
].full_name
);
5336 xfree (dpyinfo
->font_table
[i
].name
);
5337 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5340 x_destroy_all_bitmaps (dpyinfo
);
5341 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5343 #ifdef USE_X_TOOLKIT
5344 XtCloseDisplay (dpyinfo
->display
);
5346 XCloseDisplay (dpyinfo
->display
);
5349 x_delete_display (dpyinfo
);
5355 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5356 doc
: /* Return the list of display names that Emacs has connections to. */)
5359 Lisp_Object tail
, result
;
5362 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5363 result
= Fcons (XCAR (XCAR (tail
)), result
);
5368 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5369 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5370 If ON is nil, allow buffering of requests.
5371 Turning on synchronization prohibits the Xlib routines from buffering
5372 requests and seriously degrades performance, but makes debugging much
5374 The optional second argument DISPLAY specifies which display to act on.
5375 DISPLAY should be either a frame or a display name (a string).
5376 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5378 Lisp_Object display
, on
;
5380 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5382 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5387 /* Wait for responses to all X commands issued so far for frame F. */
5394 XSync (FRAME_X_DISPLAY (f
), False
);
5399 /***********************************************************************
5401 ***********************************************************************/
5403 /* Value is the number of elements of vector VECTOR. */
5405 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5407 /* List of supported image types. Use define_image_type to add new
5408 types. Use lookup_image_type to find a type for a given symbol. */
5410 static struct image_type
*image_types
;
5412 /* The symbol `image' which is the car of the lists used to represent
5415 extern Lisp_Object Qimage
;
5417 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5423 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5424 extern Lisp_Object QCdata
, QCtype
;
5425 Lisp_Object QCascent
, QCmargin
, QCrelief
;
5426 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5427 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5429 /* Other symbols. */
5431 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5433 /* Time in seconds after which images should be removed from the cache
5434 if not displayed. */
5436 Lisp_Object Vimage_cache_eviction_delay
;
5438 /* Function prototypes. */
5440 static void define_image_type
P_ ((struct image_type
*type
));
5441 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5442 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5443 static void x_laplace
P_ ((struct frame
*, struct image
*));
5444 static void x_emboss
P_ ((struct frame
*, struct image
*));
5445 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5449 /* Define a new image type from TYPE. This adds a copy of TYPE to
5450 image_types and adds the symbol *TYPE->type to Vimage_types. */
5453 define_image_type (type
)
5454 struct image_type
*type
;
5456 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5457 The initialized data segment is read-only. */
5458 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5459 bcopy (type
, p
, sizeof *p
);
5460 p
->next
= image_types
;
5462 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5466 /* Look up image type SYMBOL, and return a pointer to its image_type
5467 structure. Value is null if SYMBOL is not a known image type. */
5469 static INLINE
struct image_type
*
5470 lookup_image_type (symbol
)
5473 struct image_type
*type
;
5475 for (type
= image_types
; type
; type
= type
->next
)
5476 if (EQ (symbol
, *type
->type
))
5483 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5484 valid image specification is a list whose car is the symbol
5485 `image', and whose rest is a property list. The property list must
5486 contain a value for key `:type'. That value must be the name of a
5487 supported image type. The rest of the property list depends on the
5491 valid_image_p (object
)
5496 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5500 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5501 if (EQ (XCAR (tem
), QCtype
))
5504 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5506 struct image_type
*type
;
5507 type
= lookup_image_type (XCAR (tem
));
5509 valid_p
= type
->valid_p (object
);
5520 /* Log error message with format string FORMAT and argument ARG.
5521 Signaling an error, e.g. when an image cannot be loaded, is not a
5522 good idea because this would interrupt redisplay, and the error
5523 message display would lead to another redisplay. This function
5524 therefore simply displays a message. */
5527 image_error (format
, arg1
, arg2
)
5529 Lisp_Object arg1
, arg2
;
5531 add_to_log (format
, arg1
, arg2
);
5536 /***********************************************************************
5537 Image specifications
5538 ***********************************************************************/
5540 enum image_value_type
5542 IMAGE_DONT_CHECK_VALUE_TYPE
,
5544 IMAGE_STRING_OR_NIL_VALUE
,
5546 IMAGE_POSITIVE_INTEGER_VALUE
,
5547 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5548 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5550 IMAGE_INTEGER_VALUE
,
5551 IMAGE_FUNCTION_VALUE
,
5556 /* Structure used when parsing image specifications. */
5558 struct image_keyword
5560 /* Name of keyword. */
5563 /* The type of value allowed. */
5564 enum image_value_type type
;
5566 /* Non-zero means key must be present. */
5569 /* Used to recognize duplicate keywords in a property list. */
5572 /* The value that was found. */
5577 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5579 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5582 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5583 has the format (image KEYWORD VALUE ...). One of the keyword/
5584 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5585 image_keywords structures of size NKEYWORDS describing other
5586 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5589 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5591 struct image_keyword
*keywords
;
5598 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5601 plist
= XCDR (spec
);
5602 while (CONSP (plist
))
5604 Lisp_Object key
, value
;
5606 /* First element of a pair must be a symbol. */
5608 plist
= XCDR (plist
);
5612 /* There must follow a value. */
5615 value
= XCAR (plist
);
5616 plist
= XCDR (plist
);
5618 /* Find key in KEYWORDS. Error if not found. */
5619 for (i
= 0; i
< nkeywords
; ++i
)
5620 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
5626 /* Record that we recognized the keyword. If a keywords
5627 was found more than once, it's an error. */
5628 keywords
[i
].value
= value
;
5629 ++keywords
[i
].count
;
5631 if (keywords
[i
].count
> 1)
5634 /* Check type of value against allowed type. */
5635 switch (keywords
[i
].type
)
5637 case IMAGE_STRING_VALUE
:
5638 if (!STRINGP (value
))
5642 case IMAGE_STRING_OR_NIL_VALUE
:
5643 if (!STRINGP (value
) && !NILP (value
))
5647 case IMAGE_SYMBOL_VALUE
:
5648 if (!SYMBOLP (value
))
5652 case IMAGE_POSITIVE_INTEGER_VALUE
:
5653 if (!INTEGERP (value
) || XINT (value
) <= 0)
5657 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5658 if (INTEGERP (value
) && XINT (value
) >= 0)
5661 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5662 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5666 case IMAGE_ASCENT_VALUE
:
5667 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5669 else if (INTEGERP (value
)
5670 && XINT (value
) >= 0
5671 && XINT (value
) <= 100)
5675 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5676 if (!INTEGERP (value
) || XINT (value
) < 0)
5680 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5683 case IMAGE_FUNCTION_VALUE
:
5684 value
= indirect_function (value
);
5686 || COMPILEDP (value
)
5687 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5691 case IMAGE_NUMBER_VALUE
:
5692 if (!INTEGERP (value
) && !FLOATP (value
))
5696 case IMAGE_INTEGER_VALUE
:
5697 if (!INTEGERP (value
))
5701 case IMAGE_BOOL_VALUE
:
5702 if (!NILP (value
) && !EQ (value
, Qt
))
5711 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5715 /* Check that all mandatory fields are present. */
5716 for (i
= 0; i
< nkeywords
; ++i
)
5717 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5720 return NILP (plist
);
5724 /* Return the value of KEY in image specification SPEC. Value is nil
5725 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5726 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5729 image_spec_value (spec
, key
, found
)
5730 Lisp_Object spec
, key
;
5735 xassert (valid_image_p (spec
));
5737 for (tail
= XCDR (spec
);
5738 CONSP (tail
) && CONSP (XCDR (tail
));
5739 tail
= XCDR (XCDR (tail
)))
5741 if (EQ (XCAR (tail
), key
))
5745 return XCAR (XCDR (tail
));
5755 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5756 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5757 PIXELS non-nil means return the size in pixels, otherwise return the
5758 size in canonical character units.
5759 FRAME is the frame on which the image will be displayed. FRAME nil
5760 or omitted means use the selected frame. */)
5761 (spec
, pixels
, frame
)
5762 Lisp_Object spec
, pixels
, frame
;
5767 if (valid_image_p (spec
))
5769 struct frame
*f
= check_x_frame (frame
);
5770 int id
= lookup_image (f
, spec
);
5771 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5772 int width
= img
->width
+ 2 * img
->hmargin
;
5773 int height
= img
->height
+ 2 * img
->vmargin
;
5776 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5777 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5779 size
= Fcons (make_number (width
), make_number (height
));
5782 error ("Invalid image specification");
5788 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5789 doc
: /* Return t if image SPEC has a mask bitmap.
5790 FRAME is the frame on which the image will be displayed. FRAME nil
5791 or omitted means use the selected frame. */)
5793 Lisp_Object spec
, frame
;
5798 if (valid_image_p (spec
))
5800 struct frame
*f
= check_x_frame (frame
);
5801 int id
= lookup_image (f
, spec
);
5802 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5807 error ("Invalid image specification");
5814 /***********************************************************************
5815 Image type independent image structures
5816 ***********************************************************************/
5818 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5819 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5822 /* Allocate and return a new image structure for image specification
5823 SPEC. SPEC has a hash value of HASH. */
5825 static struct image
*
5826 make_image (spec
, hash
)
5830 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5832 xassert (valid_image_p (spec
));
5833 bzero (img
, sizeof *img
);
5834 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5835 xassert (img
->type
!= NULL
);
5837 img
->data
.lisp_val
= Qnil
;
5838 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5844 /* Free image IMG which was used on frame F, including its resources. */
5853 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5855 /* Remove IMG from the hash table of its cache. */
5857 img
->prev
->next
= img
->next
;
5859 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5862 img
->next
->prev
= img
->prev
;
5864 c
->images
[img
->id
] = NULL
;
5866 /* Free resources, then free IMG. */
5867 img
->type
->free (f
, img
);
5873 /* Prepare image IMG for display on frame F. Must be called before
5874 drawing an image. */
5877 prepare_image_for_display (f
, img
)
5883 /* We're about to display IMG, so set its timestamp to `now'. */
5885 img
->timestamp
= EMACS_SECS (t
);
5887 /* If IMG doesn't have a pixmap yet, load it now, using the image
5888 type dependent loader function. */
5889 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5890 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5894 /* Value is the number of pixels for the ascent of image IMG when
5895 drawn in face FACE. */
5898 image_ascent (img
, face
)
5902 int height
= img
->height
+ img
->vmargin
;
5905 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5908 /* This expression is arranged so that if the image can't be
5909 exactly centered, it will be moved slightly up. This is
5910 because a typical font is `top-heavy' (due to the presence
5911 uppercase letters), so the image placement should err towards
5912 being top-heavy too. It also just generally looks better. */
5913 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5915 ascent
= height
/ 2;
5918 ascent
= height
* img
->ascent
/ 100.0;
5924 /* Image background colors. */
5926 static unsigned long
5927 four_corners_best (ximg
, width
, height
)
5929 unsigned long width
, height
;
5931 unsigned long corners
[4], best
;
5934 /* Get the colors at the corners of ximg. */
5935 corners
[0] = XGetPixel (ximg
, 0, 0);
5936 corners
[1] = XGetPixel (ximg
, width
- 1, 0);
5937 corners
[2] = XGetPixel (ximg
, width
- 1, height
- 1);
5938 corners
[3] = XGetPixel (ximg
, 0, height
- 1);
5940 /* Choose the most frequently found color as background. */
5941 for (i
= best_count
= 0; i
< 4; ++i
)
5945 for (j
= n
= 0; j
< 4; ++j
)
5946 if (corners
[i
] == corners
[j
])
5950 best
= corners
[i
], best_count
= n
;
5956 /* Return the `background' field of IMG. If IMG doesn't have one yet,
5957 it is guessed heuristically. If non-zero, XIMG is an existing XImage
5958 object to use for the heuristic. */
5961 image_background (img
, f
, ximg
)
5966 if (! img
->background_valid
)
5967 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5969 int free_ximg
= !ximg
;
5972 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5973 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5975 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
5978 XDestroyImage (ximg
);
5980 img
->background_valid
= 1;
5983 return img
->background
;
5986 /* Return the `background_transparent' field of IMG. If IMG doesn't
5987 have one yet, it is guessed heuristically. If non-zero, MASK is an
5988 existing XImage object to use for the heuristic. */
5991 image_background_transparent (img
, f
, mask
)
5996 if (! img
->background_transparent_valid
)
5997 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6001 int free_mask
= !mask
;
6004 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
6005 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6007 img
->background_transparent
6008 = !four_corners_best (mask
, img
->width
, img
->height
);
6011 XDestroyImage (mask
);
6014 img
->background_transparent
= 0;
6016 img
->background_transparent_valid
= 1;
6019 return img
->background_transparent
;
6023 /***********************************************************************
6024 Helper functions for X image types
6025 ***********************************************************************/
6027 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
6029 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
6030 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
6032 Lisp_Object color_name
,
6033 unsigned long dflt
));
6036 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6037 free the pixmap if any. MASK_P non-zero means clear the mask
6038 pixmap if any. COLORS_P non-zero means free colors allocated for
6039 the image, if any. */
6042 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
6045 int pixmap_p
, mask_p
, colors_p
;
6047 if (pixmap_p
&& img
->pixmap
)
6049 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6051 img
->background_valid
= 0;
6054 if (mask_p
&& img
->mask
)
6056 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6058 img
->background_transparent_valid
= 0;
6061 if (colors_p
&& img
->ncolors
)
6063 x_free_colors (f
, img
->colors
, img
->ncolors
);
6064 xfree (img
->colors
);
6070 /* Free X resources of image IMG which is used on frame F. */
6073 x_clear_image (f
, img
)
6078 x_clear_image_1 (f
, img
, 1, 1, 1);
6083 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6084 cannot be allocated, use DFLT. Add a newly allocated color to
6085 IMG->colors, so that it can be freed again. Value is the pixel
6088 static unsigned long
6089 x_alloc_image_color (f
, img
, color_name
, dflt
)
6092 Lisp_Object color_name
;
6096 unsigned long result
;
6098 xassert (STRINGP (color_name
));
6100 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
6102 /* This isn't called frequently so we get away with simply
6103 reallocating the color vector to the needed size, here. */
6106 (unsigned long *) xrealloc (img
->colors
,
6107 img
->ncolors
* sizeof *img
->colors
);
6108 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
6109 result
= color
.pixel
;
6119 /***********************************************************************
6121 ***********************************************************************/
6123 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
6124 static void postprocess_image
P_ ((struct frame
*, struct image
*));
6127 /* Return a new, initialized image cache that is allocated from the
6128 heap. Call free_image_cache to free an image cache. */
6130 struct image_cache
*
6133 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
6136 bzero (c
, sizeof *c
);
6138 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
6139 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
6140 c
->buckets
= (struct image
**) xmalloc (size
);
6141 bzero (c
->buckets
, size
);
6146 /* Free image cache of frame F. Be aware that X frames share images
6150 free_image_cache (f
)
6153 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6158 /* Cache should not be referenced by any frame when freed. */
6159 xassert (c
->refcount
== 0);
6161 for (i
= 0; i
< c
->used
; ++i
)
6162 free_image (f
, c
->images
[i
]);
6166 FRAME_X_IMAGE_CACHE (f
) = NULL
;
6171 /* Clear image cache of frame F. FORCE_P non-zero means free all
6172 images. FORCE_P zero means clear only images that haven't been
6173 displayed for some time. Should be called from time to time to
6174 reduce the number of loaded images. If image-eviction-seconds is
6175 non-nil, this frees images in the cache which weren't displayed for
6176 at least that many seconds. */
6179 clear_image_cache (f
, force_p
)
6183 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6185 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
6192 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
6194 /* Block input so that we won't be interrupted by a SIGIO
6195 while being in an inconsistent state. */
6198 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
6200 struct image
*img
= c
->images
[i
];
6202 && (force_p
|| img
->timestamp
< old
))
6204 free_image (f
, img
);
6209 /* We may be clearing the image cache because, for example,
6210 Emacs was iconified for a longer period of time. In that
6211 case, current matrices may still contain references to
6212 images freed above. So, clear these matrices. */
6215 Lisp_Object tail
, frame
;
6217 FOR_EACH_FRAME (tail
, frame
)
6219 struct frame
*f
= XFRAME (frame
);
6221 && FRAME_X_IMAGE_CACHE (f
) == c
)
6222 clear_current_matrices (f
);
6225 ++windows_or_buffers_changed
;
6233 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
6235 doc
: /* Clear the image cache of FRAME.
6236 FRAME nil or omitted means use the selected frame.
6237 FRAME t means clear the image caches of all frames. */)
6245 FOR_EACH_FRAME (tail
, frame
)
6246 if (FRAME_X_P (XFRAME (frame
)))
6247 clear_image_cache (XFRAME (frame
), 1);
6250 clear_image_cache (check_x_frame (frame
), 1);
6256 /* Compute masks and transform image IMG on frame F, as specified
6257 by the image's specification, */
6260 postprocess_image (f
, img
)
6264 /* Manipulation of the image's mask. */
6267 Lisp_Object conversion
, spec
;
6272 /* `:heuristic-mask t'
6274 means build a mask heuristically.
6275 `:heuristic-mask (R G B)'
6276 `:mask (heuristic (R G B))'
6277 means build a mask from color (R G B) in the
6280 means remove a mask, if any. */
6282 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6284 x_build_heuristic_mask (f
, img
, mask
);
6289 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6291 if (EQ (mask
, Qheuristic
))
6292 x_build_heuristic_mask (f
, img
, Qt
);
6293 else if (CONSP (mask
)
6294 && EQ (XCAR (mask
), Qheuristic
))
6296 if (CONSP (XCDR (mask
)))
6297 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6299 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6301 else if (NILP (mask
) && found_p
&& img
->mask
)
6303 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6309 /* Should we apply an image transformation algorithm? */
6310 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6311 if (EQ (conversion
, Qdisabled
))
6312 x_disable_image (f
, img
);
6313 else if (EQ (conversion
, Qlaplace
))
6315 else if (EQ (conversion
, Qemboss
))
6317 else if (CONSP (conversion
)
6318 && EQ (XCAR (conversion
), Qedge_detection
))
6321 tem
= XCDR (conversion
);
6323 x_edge_detection (f
, img
,
6324 Fplist_get (tem
, QCmatrix
),
6325 Fplist_get (tem
, QCcolor_adjustment
));
6331 /* Return the id of image with Lisp specification SPEC on frame F.
6332 SPEC must be a valid Lisp image specification (see valid_image_p). */
6335 lookup_image (f
, spec
)
6339 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6343 struct gcpro gcpro1
;
6346 /* F must be a window-system frame, and SPEC must be a valid image
6348 xassert (FRAME_WINDOW_P (f
));
6349 xassert (valid_image_p (spec
));
6353 /* Look up SPEC in the hash table of the image cache. */
6354 hash
= sxhash (spec
, 0);
6355 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6357 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6358 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6361 /* If not found, create a new image and cache it. */
6364 extern Lisp_Object Qpostscript
;
6367 img
= make_image (spec
, hash
);
6368 cache_image (f
, img
);
6369 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6371 /* If we can't load the image, and we don't have a width and
6372 height, use some arbitrary width and height so that we can
6373 draw a rectangle for it. */
6374 if (img
->load_failed_p
)
6378 value
= image_spec_value (spec
, QCwidth
, NULL
);
6379 img
->width
= (INTEGERP (value
)
6380 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6381 value
= image_spec_value (spec
, QCheight
, NULL
);
6382 img
->height
= (INTEGERP (value
)
6383 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6387 /* Handle image type independent image attributes
6388 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6389 `:background COLOR'. */
6390 Lisp_Object ascent
, margin
, relief
, bg
;
6392 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6393 if (INTEGERP (ascent
))
6394 img
->ascent
= XFASTINT (ascent
);
6395 else if (EQ (ascent
, Qcenter
))
6396 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6398 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6399 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6400 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6401 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6402 && INTEGERP (XCDR (margin
)))
6404 if (XINT (XCAR (margin
)) > 0)
6405 img
->hmargin
= XFASTINT (XCAR (margin
));
6406 if (XINT (XCDR (margin
)) > 0)
6407 img
->vmargin
= XFASTINT (XCDR (margin
));
6410 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6411 if (INTEGERP (relief
))
6413 img
->relief
= XINT (relief
);
6414 img
->hmargin
+= abs (img
->relief
);
6415 img
->vmargin
+= abs (img
->relief
);
6418 if (! img
->background_valid
)
6420 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6424 = x_alloc_image_color (f
, img
, bg
,
6425 FRAME_BACKGROUND_PIXEL (f
));
6426 img
->background_valid
= 1;
6430 /* Do image transformations and compute masks, unless we
6431 don't have the image yet. */
6432 if (!EQ (*img
->type
->type
, Qpostscript
))
6433 postprocess_image (f
, img
);
6437 xassert (!interrupt_input_blocked
);
6440 /* We're using IMG, so set its timestamp to `now'. */
6441 EMACS_GET_TIME (now
);
6442 img
->timestamp
= EMACS_SECS (now
);
6446 /* Value is the image id. */
6451 /* Cache image IMG in the image cache of frame F. */
6454 cache_image (f
, img
)
6458 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6461 /* Find a free slot in c->images. */
6462 for (i
= 0; i
< c
->used
; ++i
)
6463 if (c
->images
[i
] == NULL
)
6466 /* If no free slot found, maybe enlarge c->images. */
6467 if (i
== c
->used
&& c
->used
== c
->size
)
6470 c
->images
= (struct image
**) xrealloc (c
->images
,
6471 c
->size
* sizeof *c
->images
);
6474 /* Add IMG to c->images, and assign IMG an id. */
6480 /* Add IMG to the cache's hash table. */
6481 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6482 img
->next
= c
->buckets
[i
];
6484 img
->next
->prev
= img
;
6486 c
->buckets
[i
] = img
;
6490 /* Call FN on every image in the image cache of frame F. Used to mark
6491 Lisp Objects in the image cache. */
6494 forall_images_in_image_cache (f
, fn
)
6496 void (*fn
) P_ ((struct image
*img
));
6498 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6500 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6504 for (i
= 0; i
< c
->used
; ++i
)
6513 /***********************************************************************
6515 ***********************************************************************/
6517 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6518 XImage
**, Pixmap
*));
6519 static void x_destroy_x_image
P_ ((XImage
*));
6520 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6523 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6524 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6525 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6526 via xmalloc. Print error messages via image_error if an error
6527 occurs. Value is non-zero if successful. */
6530 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6532 int width
, height
, depth
;
6536 Display
*display
= FRAME_X_DISPLAY (f
);
6537 Screen
*screen
= FRAME_X_SCREEN (f
);
6538 Window window
= FRAME_X_WINDOW (f
);
6540 xassert (interrupt_input_blocked
);
6543 depth
= DefaultDepthOfScreen (screen
);
6544 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6545 depth
, ZPixmap
, 0, NULL
, width
, height
,
6546 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6549 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6553 /* Allocate image raster. */
6554 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6556 /* Allocate a pixmap of the same size. */
6557 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6558 if (*pixmap
== None
)
6560 x_destroy_x_image (*ximg
);
6562 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6570 /* Destroy XImage XIMG. Free XIMG->data. */
6573 x_destroy_x_image (ximg
)
6576 xassert (interrupt_input_blocked
);
6581 XDestroyImage (ximg
);
6586 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6587 are width and height of both the image and pixmap. */
6590 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6597 xassert (interrupt_input_blocked
);
6598 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6599 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6600 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6605 /***********************************************************************
6607 ***********************************************************************/
6609 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6610 static char *slurp_file
P_ ((char *, int *));
6613 /* Find image file FILE. Look in data-directory, then
6614 x-bitmap-file-path. Value is the full name of the file found, or
6615 nil if not found. */
6618 x_find_image_file (file
)
6621 Lisp_Object file_found
, search_path
;
6622 struct gcpro gcpro1
, gcpro2
;
6626 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6627 GCPRO2 (file_found
, search_path
);
6629 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6630 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
6642 /* Read FILE into memory. Value is a pointer to a buffer allocated
6643 with xmalloc holding FILE's contents. Value is null if an error
6644 occurred. *SIZE is set to the size of the file. */
6647 slurp_file (file
, size
)
6655 if (stat (file
, &st
) == 0
6656 && (fp
= fopen (file
, "r")) != NULL
6657 && (buf
= (char *) xmalloc (st
.st_size
),
6658 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6679 /***********************************************************************
6681 ***********************************************************************/
6683 static int xbm_scan
P_ ((char **, char *, char *, int *));
6684 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6685 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6687 static int xbm_image_p
P_ ((Lisp_Object object
));
6688 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6690 static int xbm_file_p
P_ ((Lisp_Object
));
6693 /* Indices of image specification fields in xbm_format, below. */
6695 enum xbm_keyword_index
6713 /* Vector of image_keyword structures describing the format
6714 of valid XBM image specifications. */
6716 static struct image_keyword xbm_format
[XBM_LAST
] =
6718 {":type", IMAGE_SYMBOL_VALUE
, 1},
6719 {":file", IMAGE_STRING_VALUE
, 0},
6720 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6721 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6722 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6723 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6724 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6725 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6726 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6727 {":relief", IMAGE_INTEGER_VALUE
, 0},
6728 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6729 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6730 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6733 /* Structure describing the image type XBM. */
6735 static struct image_type xbm_type
=
6744 /* Tokens returned from xbm_scan. */
6753 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6754 A valid specification is a list starting with the symbol `image'
6755 The rest of the list is a property list which must contain an
6758 If the specification specifies a file to load, it must contain
6759 an entry `:file FILENAME' where FILENAME is a string.
6761 If the specification is for a bitmap loaded from memory it must
6762 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6763 WIDTH and HEIGHT are integers > 0. DATA may be:
6765 1. a string large enough to hold the bitmap data, i.e. it must
6766 have a size >= (WIDTH + 7) / 8 * HEIGHT
6768 2. a bool-vector of size >= WIDTH * HEIGHT
6770 3. a vector of strings or bool-vectors, one for each line of the
6773 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6774 may not be specified in this case because they are defined in the
6777 Both the file and data forms may contain the additional entries
6778 `:background COLOR' and `:foreground COLOR'. If not present,
6779 foreground and background of the frame on which the image is
6780 displayed is used. */
6783 xbm_image_p (object
)
6786 struct image_keyword kw
[XBM_LAST
];
6788 bcopy (xbm_format
, kw
, sizeof kw
);
6789 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6792 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6794 if (kw
[XBM_FILE
].count
)
6796 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6799 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6801 /* In-memory XBM file. */
6802 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6810 /* Entries for `:width', `:height' and `:data' must be present. */
6811 if (!kw
[XBM_WIDTH
].count
6812 || !kw
[XBM_HEIGHT
].count
6813 || !kw
[XBM_DATA
].count
)
6816 data
= kw
[XBM_DATA
].value
;
6817 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6818 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6820 /* Check type of data, and width and height against contents of
6826 /* Number of elements of the vector must be >= height. */
6827 if (XVECTOR (data
)->size
< height
)
6830 /* Each string or bool-vector in data must be large enough
6831 for one line of the image. */
6832 for (i
= 0; i
< height
; ++i
)
6834 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6839 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6842 else if (BOOL_VECTOR_P (elt
))
6844 if (XBOOL_VECTOR (elt
)->size
< width
)
6851 else if (STRINGP (data
))
6854 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6857 else if (BOOL_VECTOR_P (data
))
6859 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6870 /* Scan a bitmap file. FP is the stream to read from. Value is
6871 either an enumerator from enum xbm_token, or a character for a
6872 single-character token, or 0 at end of file. If scanning an
6873 identifier, store the lexeme of the identifier in SVAL. If
6874 scanning a number, store its value in *IVAL. */
6877 xbm_scan (s
, end
, sval
, ival
)
6886 /* Skip white space. */
6887 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6892 else if (isdigit (c
))
6894 int value
= 0, digit
;
6896 if (c
== '0' && *s
< end
)
6899 if (c
== 'x' || c
== 'X')
6906 else if (c
>= 'a' && c
<= 'f')
6907 digit
= c
- 'a' + 10;
6908 else if (c
>= 'A' && c
<= 'F')
6909 digit
= c
- 'A' + 10;
6912 value
= 16 * value
+ digit
;
6915 else if (isdigit (c
))
6919 && (c
= *(*s
)++, isdigit (c
)))
6920 value
= 8 * value
+ c
- '0';
6927 && (c
= *(*s
)++, isdigit (c
)))
6928 value
= 10 * value
+ c
- '0';
6936 else if (isalpha (c
) || c
== '_')
6940 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6947 else if (c
== '/' && **s
== '*')
6949 /* C-style comment. */
6951 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6964 /* Replacement for XReadBitmapFileData which isn't available under old
6965 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6966 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6967 the image. Return in *DATA the bitmap data allocated with xmalloc.
6968 Value is non-zero if successful. DATA null means just test if
6969 CONTENTS looks like an in-memory XBM file. */
6972 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
6973 char *contents
, *end
;
6974 int *width
, *height
;
6975 unsigned char **data
;
6978 char buffer
[BUFSIZ
];
6981 int bytes_per_line
, i
, nbytes
;
6987 LA1 = xbm_scan (&s, end, buffer, &value)
6989 #define expect(TOKEN) \
6990 if (LA1 != (TOKEN)) \
6995 #define expect_ident(IDENT) \
6996 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
7001 *width
= *height
= -1;
7004 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
7006 /* Parse defines for width, height and hot-spots. */
7010 expect_ident ("define");
7011 expect (XBM_TK_IDENT
);
7013 if (LA1
== XBM_TK_NUMBER
);
7015 char *p
= strrchr (buffer
, '_');
7016 p
= p
? p
+ 1 : buffer
;
7017 if (strcmp (p
, "width") == 0)
7019 else if (strcmp (p
, "height") == 0)
7022 expect (XBM_TK_NUMBER
);
7025 if (*width
< 0 || *height
< 0)
7027 else if (data
== NULL
)
7030 /* Parse bits. Must start with `static'. */
7031 expect_ident ("static");
7032 if (LA1
== XBM_TK_IDENT
)
7034 if (strcmp (buffer
, "unsigned") == 0)
7037 expect_ident ("char");
7039 else if (strcmp (buffer
, "short") == 0)
7043 if (*width
% 16 && *width
% 16 < 9)
7046 else if (strcmp (buffer
, "char") == 0)
7054 expect (XBM_TK_IDENT
);
7060 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
7061 nbytes
= bytes_per_line
* *height
;
7062 p
= *data
= (char *) xmalloc (nbytes
);
7066 for (i
= 0; i
< nbytes
; i
+= 2)
7069 expect (XBM_TK_NUMBER
);
7072 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
7075 if (LA1
== ',' || LA1
== '}')
7083 for (i
= 0; i
< nbytes
; ++i
)
7086 expect (XBM_TK_NUMBER
);
7090 if (LA1
== ',' || LA1
== '}')
7115 /* Load XBM image IMG which will be displayed on frame F from buffer
7116 CONTENTS. END is the end of the buffer. Value is non-zero if
7120 xbm_load_image (f
, img
, contents
, end
)
7123 char *contents
, *end
;
7126 unsigned char *data
;
7129 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
7132 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7133 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7134 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7137 xassert (img
->width
> 0 && img
->height
> 0);
7139 /* Get foreground and background colors, maybe allocate colors. */
7140 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
7142 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
7143 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7146 background
= x_alloc_image_color (f
, img
, value
, background
);
7147 img
->background
= background
;
7148 img
->background_valid
= 1;
7152 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7155 img
->width
, img
->height
,
7156 foreground
, background
,
7160 if (img
->pixmap
== None
)
7162 x_clear_image (f
, img
);
7163 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
7169 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7175 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7182 return (STRINGP (data
)
7183 && xbm_read_bitmap_data (SDATA (data
),
7190 /* Fill image IMG which is used on frame F with pixmap data. Value is
7191 non-zero if successful. */
7199 Lisp_Object file_name
;
7201 xassert (xbm_image_p (img
->spec
));
7203 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7204 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7205 if (STRINGP (file_name
))
7210 struct gcpro gcpro1
;
7212 file
= x_find_image_file (file_name
);
7214 if (!STRINGP (file
))
7216 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7221 contents
= slurp_file (SDATA (file
), &size
);
7222 if (contents
== NULL
)
7224 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7229 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
7234 struct image_keyword fmt
[XBM_LAST
];
7237 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7238 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7241 int in_memory_file_p
= 0;
7243 /* See if data looks like an in-memory XBM file. */
7244 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7245 in_memory_file_p
= xbm_file_p (data
);
7247 /* Parse the image specification. */
7248 bcopy (xbm_format
, fmt
, sizeof fmt
);
7249 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
7252 /* Get specified width, and height. */
7253 if (!in_memory_file_p
)
7255 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
7256 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
7257 xassert (img
->width
> 0 && img
->height
> 0);
7260 /* Get foreground and background colors, maybe allocate colors. */
7261 if (fmt
[XBM_FOREGROUND
].count
7262 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
7263 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
7265 if (fmt
[XBM_BACKGROUND
].count
7266 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
7267 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7270 if (in_memory_file_p
)
7271 success_p
= xbm_load_image (f
, img
, SDATA (data
),
7280 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7282 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7283 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7285 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7287 bcopy (SDATA (line
), p
, nbytes
);
7289 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7292 else if (STRINGP (data
))
7293 bits
= SDATA (data
);
7295 bits
= XBOOL_VECTOR (data
)->data
;
7297 /* Create the pixmap. */
7298 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7300 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7303 img
->width
, img
->height
,
7304 foreground
, background
,
7310 image_error ("Unable to create pixmap for XBM image `%s'",
7312 x_clear_image (f
, img
);
7322 /***********************************************************************
7324 ***********************************************************************/
7328 static int xpm_image_p
P_ ((Lisp_Object object
));
7329 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7330 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7332 #include "X11/xpm.h"
7334 /* The symbol `xpm' identifying XPM-format images. */
7338 /* Indices of image specification fields in xpm_format, below. */
7340 enum xpm_keyword_index
7356 /* Vector of image_keyword structures describing the format
7357 of valid XPM image specifications. */
7359 static struct image_keyword xpm_format
[XPM_LAST
] =
7361 {":type", IMAGE_SYMBOL_VALUE
, 1},
7362 {":file", IMAGE_STRING_VALUE
, 0},
7363 {":data", IMAGE_STRING_VALUE
, 0},
7364 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7365 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7366 {":relief", IMAGE_INTEGER_VALUE
, 0},
7367 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7368 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7369 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7370 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7371 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7374 /* Structure describing the image type XBM. */
7376 static struct image_type xpm_type
=
7386 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7387 functions for allocating image colors. Our own functions handle
7388 color allocation failures more gracefully than the ones on the XPM
7391 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7392 #define ALLOC_XPM_COLORS
7395 #ifdef ALLOC_XPM_COLORS
7397 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7398 static void xpm_free_color_cache
P_ ((void));
7399 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7400 static int xpm_color_bucket
P_ ((char *));
7401 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7404 /* An entry in a hash table used to cache color definitions of named
7405 colors. This cache is necessary to speed up XPM image loading in
7406 case we do color allocations ourselves. Without it, we would need
7407 a call to XParseColor per pixel in the image. */
7409 struct xpm_cached_color
7411 /* Next in collision chain. */
7412 struct xpm_cached_color
*next
;
7414 /* Color definition (RGB and pixel color). */
7421 /* The hash table used for the color cache, and its bucket vector
7424 #define XPM_COLOR_CACHE_BUCKETS 1001
7425 struct xpm_cached_color
**xpm_color_cache
;
7427 /* Initialize the color cache. */
7430 xpm_init_color_cache (f
, attrs
)
7432 XpmAttributes
*attrs
;
7434 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7435 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7436 memset (xpm_color_cache
, 0, nbytes
);
7437 init_color_table ();
7439 if (attrs
->valuemask
& XpmColorSymbols
)
7444 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7445 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7446 attrs
->colorsymbols
[i
].value
, &color
))
7448 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7450 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7456 /* Free the color cache. */
7459 xpm_free_color_cache ()
7461 struct xpm_cached_color
*p
, *next
;
7464 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7465 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7471 xfree (xpm_color_cache
);
7472 xpm_color_cache
= NULL
;
7473 free_color_table ();
7477 /* Return the bucket index for color named COLOR_NAME in the color
7481 xpm_color_bucket (color_name
)
7487 for (s
= color_name
; *s
; ++s
)
7489 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7493 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7494 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7497 static struct xpm_cached_color
*
7498 xpm_cache_color (f
, color_name
, color
, bucket
)
7505 struct xpm_cached_color
*p
;
7508 bucket
= xpm_color_bucket (color_name
);
7510 nbytes
= sizeof *p
+ strlen (color_name
);
7511 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7512 strcpy (p
->name
, color_name
);
7514 p
->next
= xpm_color_cache
[bucket
];
7515 xpm_color_cache
[bucket
] = p
;
7520 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7521 return the cached definition in *COLOR. Otherwise, make a new
7522 entry in the cache and allocate the color. Value is zero if color
7523 allocation failed. */
7526 xpm_lookup_color (f
, color_name
, color
)
7531 struct xpm_cached_color
*p
;
7532 int h
= xpm_color_bucket (color_name
);
7534 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7535 if (strcmp (p
->name
, color_name
) == 0)
7540 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7543 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7545 p
= xpm_cache_color (f
, color_name
, color
, h
);
7552 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7553 CLOSURE is a pointer to the frame on which we allocate the
7554 color. Return in *COLOR the allocated color. Value is non-zero
7558 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7565 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7569 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7570 is a pointer to the frame on which we allocate the color. Value is
7571 non-zero if successful. */
7574 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7584 #endif /* ALLOC_XPM_COLORS */
7587 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7588 for XPM images. Such a list must consist of conses whose car and
7592 xpm_valid_color_symbols_p (color_symbols
)
7593 Lisp_Object color_symbols
;
7595 while (CONSP (color_symbols
))
7597 Lisp_Object sym
= XCAR (color_symbols
);
7599 || !STRINGP (XCAR (sym
))
7600 || !STRINGP (XCDR (sym
)))
7602 color_symbols
= XCDR (color_symbols
);
7605 return NILP (color_symbols
);
7609 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7612 xpm_image_p (object
)
7615 struct image_keyword fmt
[XPM_LAST
];
7616 bcopy (xpm_format
, fmt
, sizeof fmt
);
7617 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7618 /* Either `:file' or `:data' must be present. */
7619 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7620 /* Either no `:color-symbols' or it's a list of conses
7621 whose car and cdr are strings. */
7622 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7623 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7627 /* Load image IMG which will be displayed on frame F. Value is
7628 non-zero if successful. */
7636 XpmAttributes attrs
;
7637 Lisp_Object specified_file
, color_symbols
;
7639 /* Configure the XPM lib. Use the visual of frame F. Allocate
7640 close colors. Return colors allocated. */
7641 bzero (&attrs
, sizeof attrs
);
7642 attrs
.visual
= FRAME_X_VISUAL (f
);
7643 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7644 attrs
.valuemask
|= XpmVisual
;
7645 attrs
.valuemask
|= XpmColormap
;
7647 #ifdef ALLOC_XPM_COLORS
7648 /* Allocate colors with our own functions which handle
7649 failing color allocation more gracefully. */
7650 attrs
.color_closure
= f
;
7651 attrs
.alloc_color
= xpm_alloc_color
;
7652 attrs
.free_colors
= xpm_free_colors
;
7653 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7654 #else /* not ALLOC_XPM_COLORS */
7655 /* Let the XPM lib allocate colors. */
7656 attrs
.valuemask
|= XpmReturnAllocPixels
;
7657 #ifdef XpmAllocCloseColors
7658 attrs
.alloc_close_colors
= 1;
7659 attrs
.valuemask
|= XpmAllocCloseColors
;
7660 #else /* not XpmAllocCloseColors */
7661 attrs
.closeness
= 600;
7662 attrs
.valuemask
|= XpmCloseness
;
7663 #endif /* not XpmAllocCloseColors */
7664 #endif /* ALLOC_XPM_COLORS */
7666 /* If image specification contains symbolic color definitions, add
7667 these to `attrs'. */
7668 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7669 if (CONSP (color_symbols
))
7672 XpmColorSymbol
*xpm_syms
;
7675 attrs
.valuemask
|= XpmColorSymbols
;
7677 /* Count number of symbols. */
7678 attrs
.numsymbols
= 0;
7679 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7682 /* Allocate an XpmColorSymbol array. */
7683 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7684 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7685 bzero (xpm_syms
, size
);
7686 attrs
.colorsymbols
= xpm_syms
;
7688 /* Fill the color symbol array. */
7689 for (tail
= color_symbols
, i
= 0;
7691 ++i
, tail
= XCDR (tail
))
7693 Lisp_Object name
= XCAR (XCAR (tail
));
7694 Lisp_Object color
= XCDR (XCAR (tail
));
7695 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
7696 strcpy (xpm_syms
[i
].name
, SDATA (name
));
7697 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
7698 strcpy (xpm_syms
[i
].value
, SDATA (color
));
7702 /* Create a pixmap for the image, either from a file, or from a
7703 string buffer containing data in the same format as an XPM file. */
7704 #ifdef ALLOC_XPM_COLORS
7705 xpm_init_color_cache (f
, &attrs
);
7708 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7709 if (STRINGP (specified_file
))
7711 Lisp_Object file
= x_find_image_file (specified_file
);
7712 if (!STRINGP (file
))
7714 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7718 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7719 SDATA (file
), &img
->pixmap
, &img
->mask
,
7724 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7725 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7727 &img
->pixmap
, &img
->mask
,
7731 if (rc
== XpmSuccess
)
7733 #ifdef ALLOC_XPM_COLORS
7734 img
->colors
= colors_in_color_table (&img
->ncolors
);
7735 #else /* not ALLOC_XPM_COLORS */
7738 img
->ncolors
= attrs
.nalloc_pixels
;
7739 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7740 * sizeof *img
->colors
);
7741 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7743 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7744 #ifdef DEBUG_X_COLORS
7745 register_color (img
->colors
[i
]);
7748 #endif /* not ALLOC_XPM_COLORS */
7750 img
->width
= attrs
.width
;
7751 img
->height
= attrs
.height
;
7752 xassert (img
->width
> 0 && img
->height
> 0);
7754 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7755 XpmFreeAttributes (&attrs
);
7762 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7765 case XpmFileInvalid
:
7766 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7770 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7773 case XpmColorFailed
:
7774 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7778 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7783 #ifdef ALLOC_XPM_COLORS
7784 xpm_free_color_cache ();
7786 return rc
== XpmSuccess
;
7789 #endif /* HAVE_XPM != 0 */
7792 /***********************************************************************
7794 ***********************************************************************/
7796 /* An entry in the color table mapping an RGB color to a pixel color. */
7801 unsigned long pixel
;
7803 /* Next in color table collision list. */
7804 struct ct_color
*next
;
7807 /* The bucket vector size to use. Must be prime. */
7811 /* Value is a hash of the RGB color given by R, G, and B. */
7813 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7815 /* The color hash table. */
7817 struct ct_color
**ct_table
;
7819 /* Number of entries in the color table. */
7821 int ct_colors_allocated
;
7823 /* Initialize the color table. */
7828 int size
= CT_SIZE
* sizeof (*ct_table
);
7829 ct_table
= (struct ct_color
**) xmalloc (size
);
7830 bzero (ct_table
, size
);
7831 ct_colors_allocated
= 0;
7835 /* Free memory associated with the color table. */
7841 struct ct_color
*p
, *next
;
7843 for (i
= 0; i
< CT_SIZE
; ++i
)
7844 for (p
= ct_table
[i
]; p
; p
= next
)
7855 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7856 entry for that color already is in the color table, return the
7857 pixel color of that entry. Otherwise, allocate a new color for R,
7858 G, B, and make an entry in the color table. */
7860 static unsigned long
7861 lookup_rgb_color (f
, r
, g
, b
)
7865 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7866 int i
= hash
% CT_SIZE
;
7869 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7870 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7883 cmap
= FRAME_X_COLORMAP (f
);
7884 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7888 ++ct_colors_allocated
;
7890 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7894 p
->pixel
= color
.pixel
;
7895 p
->next
= ct_table
[i
];
7899 return FRAME_FOREGROUND_PIXEL (f
);
7906 /* Look up pixel color PIXEL which is used on frame F in the color
7907 table. If not already present, allocate it. Value is PIXEL. */
7909 static unsigned long
7910 lookup_pixel_color (f
, pixel
)
7912 unsigned long pixel
;
7914 int i
= pixel
% CT_SIZE
;
7917 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7918 if (p
->pixel
== pixel
)
7927 cmap
= FRAME_X_COLORMAP (f
);
7928 color
.pixel
= pixel
;
7929 x_query_color (f
, &color
);
7930 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7934 ++ct_colors_allocated
;
7936 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7941 p
->next
= ct_table
[i
];
7945 return FRAME_FOREGROUND_PIXEL (f
);
7952 /* Value is a vector of all pixel colors contained in the color table,
7953 allocated via xmalloc. Set *N to the number of colors. */
7955 static unsigned long *
7956 colors_in_color_table (n
)
7961 unsigned long *colors
;
7963 if (ct_colors_allocated
== 0)
7970 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7972 *n
= ct_colors_allocated
;
7974 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7975 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7976 colors
[j
++] = p
->pixel
;
7984 /***********************************************************************
7986 ***********************************************************************/
7988 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
7989 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
7990 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
7992 /* Non-zero means draw a cross on images having `:conversion
7995 int cross_disabled_images
;
7997 /* Edge detection matrices for different edge-detection
8000 static int emboss_matrix
[9] = {
8002 2, -1, 0, /* y - 1 */
8004 0, 1, -2 /* y + 1 */
8007 static int laplace_matrix
[9] = {
8009 1, 0, 0, /* y - 1 */
8011 0, 0, -1 /* y + 1 */
8014 /* Value is the intensity of the color whose red/green/blue values
8017 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8020 /* On frame F, return an array of XColor structures describing image
8021 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8022 non-zero means also fill the red/green/blue members of the XColor
8023 structures. Value is a pointer to the array of XColors structures,
8024 allocated with xmalloc; it must be freed by the caller. */
8027 x_to_xcolors (f
, img
, rgb_p
)
8036 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
8038 /* Get the X image IMG->pixmap. */
8039 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8040 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8042 /* Fill the `pixel' members of the XColor array. I wished there
8043 were an easy and portable way to circumvent XGetPixel. */
8045 for (y
= 0; y
< img
->height
; ++y
)
8049 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8050 p
->pixel
= XGetPixel (ximg
, x
, y
);
8053 x_query_colors (f
, row
, img
->width
);
8056 XDestroyImage (ximg
);
8061 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8062 RGB members are set. F is the frame on which this all happens.
8063 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8066 x_from_xcolors (f
, img
, colors
)
8076 init_color_table ();
8078 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
8081 for (y
= 0; y
< img
->height
; ++y
)
8082 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8084 unsigned long pixel
;
8085 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
8086 XPutPixel (oimg
, x
, y
, pixel
);
8090 x_clear_image_1 (f
, img
, 1, 0, 1);
8092 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
8093 x_destroy_x_image (oimg
);
8094 img
->pixmap
= pixmap
;
8095 img
->colors
= colors_in_color_table (&img
->ncolors
);
8096 free_color_table ();
8100 /* On frame F, perform edge-detection on image IMG.
8102 MATRIX is a nine-element array specifying the transformation
8103 matrix. See emboss_matrix for an example.
8105 COLOR_ADJUST is a color adjustment added to each pixel of the
8109 x_detect_edges (f
, img
, matrix
, color_adjust
)
8112 int matrix
[9], color_adjust
;
8114 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8118 for (i
= sum
= 0; i
< 9; ++i
)
8119 sum
+= abs (matrix
[i
]);
8121 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8123 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
8125 for (y
= 0; y
< img
->height
; ++y
)
8127 p
= COLOR (new, 0, y
);
8128 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8129 p
= COLOR (new, img
->width
- 1, y
);
8130 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8133 for (x
= 1; x
< img
->width
- 1; ++x
)
8135 p
= COLOR (new, x
, 0);
8136 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8137 p
= COLOR (new, x
, img
->height
- 1);
8138 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8141 for (y
= 1; y
< img
->height
- 1; ++y
)
8143 p
= COLOR (new, 1, y
);
8145 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
8147 int r
, g
, b
, y1
, x1
;
8150 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
8151 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
8154 XColor
*t
= COLOR (colors
, x1
, y1
);
8155 r
+= matrix
[i
] * t
->red
;
8156 g
+= matrix
[i
] * t
->green
;
8157 b
+= matrix
[i
] * t
->blue
;
8160 r
= (r
/ sum
+ color_adjust
) & 0xffff;
8161 g
= (g
/ sum
+ color_adjust
) & 0xffff;
8162 b
= (b
/ sum
+ color_adjust
) & 0xffff;
8163 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
8168 x_from_xcolors (f
, img
, new);
8174 /* Perform the pre-defined `emboss' edge-detection on image IMG
8182 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
8186 /* Perform the pre-defined `laplace' edge-detection on image IMG
8194 x_detect_edges (f
, img
, laplace_matrix
, 45000);
8198 /* Perform edge-detection on image IMG on frame F, with specified
8199 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8201 MATRIX must be either
8203 - a list of at least 9 numbers in row-major form
8204 - a vector of at least 9 numbers
8206 COLOR_ADJUST nil means use a default; otherwise it must be a
8210 x_edge_detection (f
, img
, matrix
, color_adjust
)
8213 Lisp_Object matrix
, color_adjust
;
8221 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
8222 ++i
, matrix
= XCDR (matrix
))
8223 trans
[i
] = XFLOATINT (XCAR (matrix
));
8225 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
8227 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
8228 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
8231 if (NILP (color_adjust
))
8232 color_adjust
= make_number (0xffff / 2);
8234 if (i
== 9 && NUMBERP (color_adjust
))
8235 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
8239 /* Transform image IMG on frame F so that it looks disabled. */
8242 x_disable_image (f
, img
)
8246 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8248 if (dpyinfo
->n_planes
>= 2)
8250 /* Color (or grayscale). Convert to gray, and equalize. Just
8251 drawing such images with a stipple can look very odd, so
8252 we're using this method instead. */
8253 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8255 const int h
= 15000;
8256 const int l
= 30000;
8258 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
8262 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
8263 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
8264 p
->red
= p
->green
= p
->blue
= i2
;
8267 x_from_xcolors (f
, img
, colors
);
8270 /* Draw a cross over the disabled image, if we must or if we
8272 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
8274 Display
*dpy
= FRAME_X_DISPLAY (f
);
8277 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
8278 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
8279 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
8280 img
->width
- 1, img
->height
- 1);
8281 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
8287 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
8288 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8289 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8290 img
->width
- 1, img
->height
- 1);
8291 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8299 /* Build a mask for image IMG which is used on frame F. FILE is the
8300 name of an image file, for error messages. HOW determines how to
8301 determine the background color of IMG. If it is a list '(R G B)',
8302 with R, G, and B being integers >= 0, take that as the color of the
8303 background. Otherwise, determine the background color of IMG
8304 heuristically. Value is non-zero if successful. */
8307 x_build_heuristic_mask (f
, img
, how
)
8312 Display
*dpy
= FRAME_X_DISPLAY (f
);
8313 XImage
*ximg
, *mask_img
;
8314 int x
, y
, rc
, use_img_background
;
8315 unsigned long bg
= 0;
8319 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8321 img
->background_transparent_valid
= 0;
8324 /* Create an image and pixmap serving as mask. */
8325 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8326 &mask_img
, &img
->mask
);
8330 /* Get the X image of IMG->pixmap. */
8331 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8334 /* Determine the background color of ximg. If HOW is `(R G B)'
8335 take that as color. Otherwise, use the image's background color. */
8336 use_img_background
= 1;
8342 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
8344 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8348 if (i
== 3 && NILP (how
))
8350 char color_name
[30];
8351 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8352 bg
= x_alloc_image_color (f
, img
, build_string (color_name
), 0);
8353 use_img_background
= 0;
8357 if (use_img_background
)
8358 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
8360 /* Set all bits in mask_img to 1 whose color in ximg is different
8361 from the background color bg. */
8362 for (y
= 0; y
< img
->height
; ++y
)
8363 for (x
= 0; x
< img
->width
; ++x
)
8364 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8366 /* Fill in the background_transparent field while we have the mask handy. */
8367 image_background_transparent (img
, f
, mask_img
);
8369 /* Put mask_img into img->mask. */
8370 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8371 x_destroy_x_image (mask_img
);
8372 XDestroyImage (ximg
);
8379 /***********************************************************************
8380 PBM (mono, gray, color)
8381 ***********************************************************************/
8383 static int pbm_image_p
P_ ((Lisp_Object object
));
8384 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8385 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8387 /* The symbol `pbm' identifying images of this type. */
8391 /* Indices of image specification fields in gs_format, below. */
8393 enum pbm_keyword_index
8409 /* Vector of image_keyword structures describing the format
8410 of valid user-defined image specifications. */
8412 static struct image_keyword pbm_format
[PBM_LAST
] =
8414 {":type", IMAGE_SYMBOL_VALUE
, 1},
8415 {":file", IMAGE_STRING_VALUE
, 0},
8416 {":data", IMAGE_STRING_VALUE
, 0},
8417 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8418 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8419 {":relief", IMAGE_INTEGER_VALUE
, 0},
8420 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8421 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8422 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8423 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8424 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8427 /* Structure describing the image type `pbm'. */
8429 static struct image_type pbm_type
=
8439 /* Return non-zero if OBJECT is a valid PBM image specification. */
8442 pbm_image_p (object
)
8445 struct image_keyword fmt
[PBM_LAST
];
8447 bcopy (pbm_format
, fmt
, sizeof fmt
);
8449 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8452 /* Must specify either :data or :file. */
8453 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8457 /* Scan a decimal number from *S and return it. Advance *S while
8458 reading the number. END is the end of the string. Value is -1 at
8462 pbm_scan_number (s
, end
)
8463 unsigned char **s
, *end
;
8465 int c
= 0, val
= -1;
8469 /* Skip white-space. */
8470 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8475 /* Skip comment to end of line. */
8476 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8479 else if (isdigit (c
))
8481 /* Read decimal number. */
8483 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8484 val
= 10 * val
+ c
- '0';
8495 /* Load PBM image IMG for use on frame F. */
8503 int width
, height
, max_color_idx
= 0;
8505 Lisp_Object file
, specified_file
;
8506 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8507 struct gcpro gcpro1
;
8508 unsigned char *contents
= NULL
;
8509 unsigned char *end
, *p
;
8512 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8516 if (STRINGP (specified_file
))
8518 file
= x_find_image_file (specified_file
);
8519 if (!STRINGP (file
))
8521 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8526 contents
= slurp_file (SDATA (file
), &size
);
8527 if (contents
== NULL
)
8529 image_error ("Error reading `%s'", file
, Qnil
);
8535 end
= contents
+ size
;
8540 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8542 end
= p
+ SBYTES (data
);
8545 /* Check magic number. */
8546 if (end
- p
< 2 || *p
++ != 'P')
8548 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8558 raw_p
= 0, type
= PBM_MONO
;
8562 raw_p
= 0, type
= PBM_GRAY
;
8566 raw_p
= 0, type
= PBM_COLOR
;
8570 raw_p
= 1, type
= PBM_MONO
;
8574 raw_p
= 1, type
= PBM_GRAY
;
8578 raw_p
= 1, type
= PBM_COLOR
;
8582 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8586 /* Read width, height, maximum color-component. Characters
8587 starting with `#' up to the end of a line are ignored. */
8588 width
= pbm_scan_number (&p
, end
);
8589 height
= pbm_scan_number (&p
, end
);
8591 if (type
!= PBM_MONO
)
8593 max_color_idx
= pbm_scan_number (&p
, end
);
8594 if (raw_p
&& max_color_idx
> 255)
8595 max_color_idx
= 255;
8600 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8603 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8604 &ximg
, &img
->pixmap
))
8607 /* Initialize the color hash table. */
8608 init_color_table ();
8610 if (type
== PBM_MONO
)
8613 struct image_keyword fmt
[PBM_LAST
];
8614 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8615 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8617 /* Parse the image specification. */
8618 bcopy (pbm_format
, fmt
, sizeof fmt
);
8619 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8621 /* Get foreground and background colors, maybe allocate colors. */
8622 if (fmt
[PBM_FOREGROUND
].count
8623 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8624 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8625 if (fmt
[PBM_BACKGROUND
].count
8626 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8628 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8629 img
->background
= bg
;
8630 img
->background_valid
= 1;
8633 for (y
= 0; y
< height
; ++y
)
8634 for (x
= 0; x
< width
; ++x
)
8644 g
= pbm_scan_number (&p
, end
);
8646 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8651 for (y
= 0; y
< height
; ++y
)
8652 for (x
= 0; x
< width
; ++x
)
8656 if (type
== PBM_GRAY
)
8657 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8666 r
= pbm_scan_number (&p
, end
);
8667 g
= pbm_scan_number (&p
, end
);
8668 b
= pbm_scan_number (&p
, end
);
8671 if (r
< 0 || g
< 0 || b
< 0)
8675 XDestroyImage (ximg
);
8676 image_error ("Invalid pixel value in image `%s'",
8681 /* RGB values are now in the range 0..max_color_idx.
8682 Scale this to the range 0..0xffff supported by X. */
8683 r
= (double) r
* 65535 / max_color_idx
;
8684 g
= (double) g
* 65535 / max_color_idx
;
8685 b
= (double) b
* 65535 / max_color_idx
;
8686 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8690 /* Store in IMG->colors the colors allocated for the image, and
8691 free the color table. */
8692 img
->colors
= colors_in_color_table (&img
->ncolors
);
8693 free_color_table ();
8695 /* Maybe fill in the background field while we have ximg handy. */
8696 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8697 IMAGE_BACKGROUND (img
, f
, ximg
);
8699 /* Put the image into a pixmap. */
8700 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8701 x_destroy_x_image (ximg
);
8704 img
->height
= height
;
8713 /***********************************************************************
8715 ***********************************************************************/
8721 /* Function prototypes. */
8723 static int png_image_p
P_ ((Lisp_Object object
));
8724 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8726 /* The symbol `png' identifying images of this type. */
8730 /* Indices of image specification fields in png_format, below. */
8732 enum png_keyword_index
8747 /* Vector of image_keyword structures describing the format
8748 of valid user-defined image specifications. */
8750 static struct image_keyword png_format
[PNG_LAST
] =
8752 {":type", IMAGE_SYMBOL_VALUE
, 1},
8753 {":data", IMAGE_STRING_VALUE
, 0},
8754 {":file", IMAGE_STRING_VALUE
, 0},
8755 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8756 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8757 {":relief", IMAGE_INTEGER_VALUE
, 0},
8758 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8759 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8760 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8761 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8764 /* Structure describing the image type `png'. */
8766 static struct image_type png_type
=
8776 /* Return non-zero if OBJECT is a valid PNG image specification. */
8779 png_image_p (object
)
8782 struct image_keyword fmt
[PNG_LAST
];
8783 bcopy (png_format
, fmt
, sizeof fmt
);
8785 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8788 /* Must specify either the :data or :file keyword. */
8789 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8793 /* Error and warning handlers installed when the PNG library
8797 my_png_error (png_ptr
, msg
)
8798 png_struct
*png_ptr
;
8801 xassert (png_ptr
!= NULL
);
8802 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8803 longjmp (png_ptr
->jmpbuf
, 1);
8808 my_png_warning (png_ptr
, msg
)
8809 png_struct
*png_ptr
;
8812 xassert (png_ptr
!= NULL
);
8813 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8816 /* Memory source for PNG decoding. */
8818 struct png_memory_storage
8820 unsigned char *bytes
; /* The data */
8821 size_t len
; /* How big is it? */
8822 int index
; /* Where are we? */
8826 /* Function set as reader function when reading PNG image from memory.
8827 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8828 bytes from the input to DATA. */
8831 png_read_from_memory (png_ptr
, data
, length
)
8832 png_structp png_ptr
;
8836 struct png_memory_storage
*tbr
8837 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8839 if (length
> tbr
->len
- tbr
->index
)
8840 png_error (png_ptr
, "Read error");
8842 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8843 tbr
->index
= tbr
->index
+ length
;
8846 /* Load PNG image IMG for use on frame F. Value is non-zero if
8854 Lisp_Object file
, specified_file
;
8855 Lisp_Object specified_data
;
8857 XImage
*ximg
, *mask_img
= NULL
;
8858 struct gcpro gcpro1
;
8859 png_struct
*png_ptr
= NULL
;
8860 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8861 FILE *volatile fp
= NULL
;
8863 png_byte
* volatile pixels
= NULL
;
8864 png_byte
** volatile rows
= NULL
;
8865 png_uint_32 width
, height
;
8866 int bit_depth
, color_type
, interlace_type
;
8868 png_uint_32 row_bytes
;
8870 double screen_gamma
, image_gamma
;
8872 struct png_memory_storage tbr
; /* Data to be read */
8874 /* Find out what file to load. */
8875 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8876 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8880 if (NILP (specified_data
))
8882 file
= x_find_image_file (specified_file
);
8883 if (!STRINGP (file
))
8885 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8890 /* Open the image file. */
8891 fp
= fopen (SDATA (file
), "rb");
8894 image_error ("Cannot open image file `%s'", file
, Qnil
);
8900 /* Check PNG signature. */
8901 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8902 || !png_check_sig (sig
, sizeof sig
))
8904 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8912 /* Read from memory. */
8913 tbr
.bytes
= SDATA (specified_data
);
8914 tbr
.len
= SBYTES (specified_data
);
8917 /* Check PNG signature. */
8918 if (tbr
.len
< sizeof sig
8919 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8921 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8926 /* Need to skip past the signature. */
8927 tbr
.bytes
+= sizeof (sig
);
8930 /* Initialize read and info structs for PNG lib. */
8931 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8932 my_png_error
, my_png_warning
);
8935 if (fp
) fclose (fp
);
8940 info_ptr
= png_create_info_struct (png_ptr
);
8943 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8944 if (fp
) fclose (fp
);
8949 end_info
= png_create_info_struct (png_ptr
);
8952 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8953 if (fp
) fclose (fp
);
8958 /* Set error jump-back. We come back here when the PNG library
8959 detects an error. */
8960 if (setjmp (png_ptr
->jmpbuf
))
8964 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8967 if (fp
) fclose (fp
);
8972 /* Read image info. */
8973 if (!NILP (specified_data
))
8974 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
8976 png_init_io (png_ptr
, fp
);
8978 png_set_sig_bytes (png_ptr
, sizeof sig
);
8979 png_read_info (png_ptr
, info_ptr
);
8980 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8981 &interlace_type
, NULL
, NULL
);
8983 /* If image contains simply transparency data, we prefer to
8984 construct a clipping mask. */
8985 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8990 /* This function is easier to write if we only have to handle
8991 one data format: RGB or RGBA with 8 bits per channel. Let's
8992 transform other formats into that format. */
8994 /* Strip more than 8 bits per channel. */
8995 if (bit_depth
== 16)
8996 png_set_strip_16 (png_ptr
);
8998 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
9000 png_set_expand (png_ptr
);
9002 /* Convert grayscale images to RGB. */
9003 if (color_type
== PNG_COLOR_TYPE_GRAY
9004 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
9005 png_set_gray_to_rgb (png_ptr
);
9007 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
9009 /* Tell the PNG lib to handle gamma correction for us. */
9011 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9012 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
9013 /* The libpng documentation says this is right in this case. */
9014 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9017 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
9018 /* Image contains gamma information. */
9019 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
9021 /* Use the standard default for the image gamma. */
9022 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9024 /* Handle alpha channel by combining the image with a background
9025 color. Do this only if a real alpha channel is supplied. For
9026 simple transparency, we prefer a clipping mask. */
9029 png_color_16
*image_bg
;
9030 Lisp_Object specified_bg
9031 = image_spec_value (img
->spec
, QCbackground
, NULL
);
9033 if (STRINGP (specified_bg
))
9034 /* The user specified `:background', use that. */
9037 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
9039 png_color_16 user_bg
;
9041 bzero (&user_bg
, sizeof user_bg
);
9042 user_bg
.red
= color
.red
;
9043 user_bg
.green
= color
.green
;
9044 user_bg
.blue
= color
.blue
;
9046 png_set_background (png_ptr
, &user_bg
,
9047 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9050 else if (png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
9051 /* Image contains a background color with which to
9052 combine the image. */
9053 png_set_background (png_ptr
, image_bg
,
9054 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
9057 /* Image does not contain a background color with which
9058 to combine the image data via an alpha channel. Use
9059 the frame's background instead. */
9062 png_color_16 frame_background
;
9064 cmap
= FRAME_X_COLORMAP (f
);
9065 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
9066 x_query_color (f
, &color
);
9068 bzero (&frame_background
, sizeof frame_background
);
9069 frame_background
.red
= color
.red
;
9070 frame_background
.green
= color
.green
;
9071 frame_background
.blue
= color
.blue
;
9073 png_set_background (png_ptr
, &frame_background
,
9074 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9078 /* Update info structure. */
9079 png_read_update_info (png_ptr
, info_ptr
);
9081 /* Get number of channels. Valid values are 1 for grayscale images
9082 and images with a palette, 2 for grayscale images with transparency
9083 information (alpha channel), 3 for RGB images, and 4 for RGB
9084 images with alpha channel, i.e. RGBA. If conversions above were
9085 sufficient we should only have 3 or 4 channels here. */
9086 channels
= png_get_channels (png_ptr
, info_ptr
);
9087 xassert (channels
== 3 || channels
== 4);
9089 /* Number of bytes needed for one row of the image. */
9090 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
9092 /* Allocate memory for the image. */
9093 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
9094 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
9095 for (i
= 0; i
< height
; ++i
)
9096 rows
[i
] = pixels
+ i
* row_bytes
;
9098 /* Read the entire image. */
9099 png_read_image (png_ptr
, rows
);
9100 png_read_end (png_ptr
, info_ptr
);
9107 /* Create the X image and pixmap. */
9108 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
9112 /* Create an image and pixmap serving as mask if the PNG image
9113 contains an alpha channel. */
9116 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
9117 &mask_img
, &img
->mask
))
9119 x_destroy_x_image (ximg
);
9120 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
9125 /* Fill the X image and mask from PNG data. */
9126 init_color_table ();
9128 for (y
= 0; y
< height
; ++y
)
9130 png_byte
*p
= rows
[y
];
9132 for (x
= 0; x
< width
; ++x
)
9139 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
9141 /* An alpha channel, aka mask channel, associates variable
9142 transparency with an image. Where other image formats
9143 support binary transparency---fully transparent or fully
9144 opaque---PNG allows up to 254 levels of partial transparency.
9145 The PNG library implements partial transparency by combining
9146 the image with a specified background color.
9148 I'm not sure how to handle this here nicely: because the
9149 background on which the image is displayed may change, for
9150 real alpha channel support, it would be necessary to create
9151 a new image for each possible background.
9153 What I'm doing now is that a mask is created if we have
9154 boolean transparency information. Otherwise I'm using
9155 the frame's background color to combine the image with. */
9160 XPutPixel (mask_img
, x
, y
, *p
> 0);
9166 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9167 /* Set IMG's background color from the PNG image, unless the user
9171 if (png_get_bKGD (png_ptr
, info_ptr
, &bg
))
9173 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
9174 img
->background_valid
= 1;
9178 /* Remember colors allocated for this image. */
9179 img
->colors
= colors_in_color_table (&img
->ncolors
);
9180 free_color_table ();
9183 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9188 img
->height
= height
;
9190 /* Maybe fill in the background field while we have ximg handy. */
9191 IMAGE_BACKGROUND (img
, f
, ximg
);
9193 /* Put the image into the pixmap, then free the X image and its buffer. */
9194 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9195 x_destroy_x_image (ximg
);
9197 /* Same for the mask. */
9200 /* Fill in the background_transparent field while we have the mask
9202 image_background_transparent (img
, f
, mask_img
);
9204 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
9205 x_destroy_x_image (mask_img
);
9212 #endif /* HAVE_PNG != 0 */
9216 /***********************************************************************
9218 ***********************************************************************/
9222 /* Work around a warning about HAVE_STDLIB_H being redefined in
9224 #ifdef HAVE_STDLIB_H
9225 #define HAVE_STDLIB_H_1
9226 #undef HAVE_STDLIB_H
9227 #endif /* HAVE_STLIB_H */
9229 #include <jpeglib.h>
9233 #ifdef HAVE_STLIB_H_1
9234 #define HAVE_STDLIB_H 1
9237 static int jpeg_image_p
P_ ((Lisp_Object object
));
9238 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
9240 /* The symbol `jpeg' identifying images of this type. */
9244 /* Indices of image specification fields in gs_format, below. */
9246 enum jpeg_keyword_index
9255 JPEG_HEURISTIC_MASK
,
9261 /* Vector of image_keyword structures describing the format
9262 of valid user-defined image specifications. */
9264 static struct image_keyword jpeg_format
[JPEG_LAST
] =
9266 {":type", IMAGE_SYMBOL_VALUE
, 1},
9267 {":data", IMAGE_STRING_VALUE
, 0},
9268 {":file", IMAGE_STRING_VALUE
, 0},
9269 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9270 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9271 {":relief", IMAGE_INTEGER_VALUE
, 0},
9272 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9273 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9274 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9275 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9278 /* Structure describing the image type `jpeg'. */
9280 static struct image_type jpeg_type
=
9290 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9293 jpeg_image_p (object
)
9296 struct image_keyword fmt
[JPEG_LAST
];
9298 bcopy (jpeg_format
, fmt
, sizeof fmt
);
9300 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
9303 /* Must specify either the :data or :file keyword. */
9304 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9308 struct my_jpeg_error_mgr
9310 struct jpeg_error_mgr pub
;
9311 jmp_buf setjmp_buffer
;
9316 my_error_exit (cinfo
)
9319 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9320 longjmp (mgr
->setjmp_buffer
, 1);
9324 /* Init source method for JPEG data source manager. Called by
9325 jpeg_read_header() before any data is actually read. See
9326 libjpeg.doc from the JPEG lib distribution. */
9329 our_init_source (cinfo
)
9330 j_decompress_ptr cinfo
;
9335 /* Fill input buffer method for JPEG data source manager. Called
9336 whenever more data is needed. We read the whole image in one step,
9337 so this only adds a fake end of input marker at the end. */
9340 our_fill_input_buffer (cinfo
)
9341 j_decompress_ptr cinfo
;
9343 /* Insert a fake EOI marker. */
9344 struct jpeg_source_mgr
*src
= cinfo
->src
;
9345 static JOCTET buffer
[2];
9347 buffer
[0] = (JOCTET
) 0xFF;
9348 buffer
[1] = (JOCTET
) JPEG_EOI
;
9350 src
->next_input_byte
= buffer
;
9351 src
->bytes_in_buffer
= 2;
9356 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9357 is the JPEG data source manager. */
9360 our_skip_input_data (cinfo
, num_bytes
)
9361 j_decompress_ptr cinfo
;
9364 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9368 if (num_bytes
> src
->bytes_in_buffer
)
9369 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9371 src
->bytes_in_buffer
-= num_bytes
;
9372 src
->next_input_byte
+= num_bytes
;
9377 /* Method to terminate data source. Called by
9378 jpeg_finish_decompress() after all data has been processed. */
9381 our_term_source (cinfo
)
9382 j_decompress_ptr cinfo
;
9387 /* Set up the JPEG lib for reading an image from DATA which contains
9388 LEN bytes. CINFO is the decompression info structure created for
9389 reading the image. */
9392 jpeg_memory_src (cinfo
, data
, len
)
9393 j_decompress_ptr cinfo
;
9397 struct jpeg_source_mgr
*src
;
9399 if (cinfo
->src
== NULL
)
9401 /* First time for this JPEG object? */
9402 cinfo
->src
= (struct jpeg_source_mgr
*)
9403 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9404 sizeof (struct jpeg_source_mgr
));
9405 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9406 src
->next_input_byte
= data
;
9409 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9410 src
->init_source
= our_init_source
;
9411 src
->fill_input_buffer
= our_fill_input_buffer
;
9412 src
->skip_input_data
= our_skip_input_data
;
9413 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9414 src
->term_source
= our_term_source
;
9415 src
->bytes_in_buffer
= len
;
9416 src
->next_input_byte
= data
;
9420 /* Load image IMG for use on frame F. Patterned after example.c
9421 from the JPEG lib. */
9428 struct jpeg_decompress_struct cinfo
;
9429 struct my_jpeg_error_mgr mgr
;
9430 Lisp_Object file
, specified_file
;
9431 Lisp_Object specified_data
;
9432 FILE * volatile fp
= NULL
;
9434 int row_stride
, x
, y
;
9435 XImage
*ximg
= NULL
;
9437 unsigned long *colors
;
9439 struct gcpro gcpro1
;
9441 /* Open the JPEG file. */
9442 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9443 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9447 if (NILP (specified_data
))
9449 file
= x_find_image_file (specified_file
);
9450 if (!STRINGP (file
))
9452 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9457 fp
= fopen (SDATA (file
), "r");
9460 image_error ("Cannot open `%s'", file
, Qnil
);
9466 /* Customize libjpeg's error handling to call my_error_exit when an
9467 error is detected. This function will perform a longjmp. */
9468 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9469 mgr
.pub
.error_exit
= my_error_exit
;
9471 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9475 /* Called from my_error_exit. Display a JPEG error. */
9476 char buffer
[JMSG_LENGTH_MAX
];
9477 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9478 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9479 build_string (buffer
));
9482 /* Close the input file and destroy the JPEG object. */
9484 fclose ((FILE *) fp
);
9485 jpeg_destroy_decompress (&cinfo
);
9487 /* If we already have an XImage, free that. */
9488 x_destroy_x_image (ximg
);
9490 /* Free pixmap and colors. */
9491 x_clear_image (f
, img
);
9497 /* Create the JPEG decompression object. Let it read from fp.
9498 Read the JPEG image header. */
9499 jpeg_create_decompress (&cinfo
);
9501 if (NILP (specified_data
))
9502 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9504 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
9505 SBYTES (specified_data
));
9507 jpeg_read_header (&cinfo
, TRUE
);
9509 /* Customize decompression so that color quantization will be used.
9510 Start decompression. */
9511 cinfo
.quantize_colors
= TRUE
;
9512 jpeg_start_decompress (&cinfo
);
9513 width
= img
->width
= cinfo
.output_width
;
9514 height
= img
->height
= cinfo
.output_height
;
9516 /* Create X image and pixmap. */
9517 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9518 longjmp (mgr
.setjmp_buffer
, 2);
9520 /* Allocate colors. When color quantization is used,
9521 cinfo.actual_number_of_colors has been set with the number of
9522 colors generated, and cinfo.colormap is a two-dimensional array
9523 of color indices in the range 0..cinfo.actual_number_of_colors.
9524 No more than 255 colors will be generated. */
9528 if (cinfo
.out_color_components
> 2)
9529 ir
= 0, ig
= 1, ib
= 2;
9530 else if (cinfo
.out_color_components
> 1)
9531 ir
= 0, ig
= 1, ib
= 0;
9533 ir
= 0, ig
= 0, ib
= 0;
9535 /* Use the color table mechanism because it handles colors that
9536 cannot be allocated nicely. Such colors will be replaced with
9537 a default color, and we don't have to care about which colors
9538 can be freed safely, and which can't. */
9539 init_color_table ();
9540 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9543 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9545 /* Multiply RGB values with 255 because X expects RGB values
9546 in the range 0..0xffff. */
9547 int r
= cinfo
.colormap
[ir
][i
] << 8;
9548 int g
= cinfo
.colormap
[ig
][i
] << 8;
9549 int b
= cinfo
.colormap
[ib
][i
] << 8;
9550 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9553 /* Remember those colors actually allocated. */
9554 img
->colors
= colors_in_color_table (&img
->ncolors
);
9555 free_color_table ();
9559 row_stride
= width
* cinfo
.output_components
;
9560 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9562 for (y
= 0; y
< height
; ++y
)
9564 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9565 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9566 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9570 jpeg_finish_decompress (&cinfo
);
9571 jpeg_destroy_decompress (&cinfo
);
9573 fclose ((FILE *) fp
);
9575 /* Maybe fill in the background field while we have ximg handy. */
9576 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9577 IMAGE_BACKGROUND (img
, f
, ximg
);
9579 /* Put the image into the pixmap. */
9580 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9581 x_destroy_x_image (ximg
);
9586 #endif /* HAVE_JPEG */
9590 /***********************************************************************
9592 ***********************************************************************/
9598 static int tiff_image_p
P_ ((Lisp_Object object
));
9599 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9601 /* The symbol `tiff' identifying images of this type. */
9605 /* Indices of image specification fields in tiff_format, below. */
9607 enum tiff_keyword_index
9616 TIFF_HEURISTIC_MASK
,
9622 /* Vector of image_keyword structures describing the format
9623 of valid user-defined image specifications. */
9625 static struct image_keyword tiff_format
[TIFF_LAST
] =
9627 {":type", IMAGE_SYMBOL_VALUE
, 1},
9628 {":data", IMAGE_STRING_VALUE
, 0},
9629 {":file", IMAGE_STRING_VALUE
, 0},
9630 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9631 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9632 {":relief", IMAGE_INTEGER_VALUE
, 0},
9633 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9634 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9635 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9636 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9639 /* Structure describing the image type `tiff'. */
9641 static struct image_type tiff_type
=
9651 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9654 tiff_image_p (object
)
9657 struct image_keyword fmt
[TIFF_LAST
];
9658 bcopy (tiff_format
, fmt
, sizeof fmt
);
9660 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9663 /* Must specify either the :data or :file keyword. */
9664 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9668 /* Reading from a memory buffer for TIFF images Based on the PNG
9669 memory source, but we have to provide a lot of extra functions.
9672 We really only need to implement read and seek, but I am not
9673 convinced that the TIFF library is smart enough not to destroy
9674 itself if we only hand it the function pointers we need to
9679 unsigned char *bytes
;
9687 tiff_read_from_memory (data
, buf
, size
)
9692 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9694 if (size
> src
->len
- src
->index
)
9696 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9703 tiff_write_from_memory (data
, buf
, size
)
9713 tiff_seek_in_memory (data
, off
, whence
)
9718 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9723 case SEEK_SET
: /* Go from beginning of source. */
9727 case SEEK_END
: /* Go from end of source. */
9728 idx
= src
->len
+ off
;
9731 case SEEK_CUR
: /* Go from current position. */
9732 idx
= src
->index
+ off
;
9735 default: /* Invalid `whence'. */
9739 if (idx
> src
->len
|| idx
< 0)
9748 tiff_close_memory (data
)
9757 tiff_mmap_memory (data
, pbase
, psize
)
9762 /* It is already _IN_ memory. */
9768 tiff_unmap_memory (data
, base
, size
)
9773 /* We don't need to do this. */
9778 tiff_size_of_memory (data
)
9781 return ((tiff_memory_source
*) data
)->len
;
9786 tiff_error_handler (title
, format
, ap
)
9787 const char *title
, *format
;
9793 len
= sprintf (buf
, "TIFF error: %s ", title
);
9794 vsprintf (buf
+ len
, format
, ap
);
9795 add_to_log (buf
, Qnil
, Qnil
);
9800 tiff_warning_handler (title
, format
, ap
)
9801 const char *title
, *format
;
9807 len
= sprintf (buf
, "TIFF warning: %s ", title
);
9808 vsprintf (buf
+ len
, format
, ap
);
9809 add_to_log (buf
, Qnil
, Qnil
);
9813 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9821 Lisp_Object file
, specified_file
;
9822 Lisp_Object specified_data
;
9824 int width
, height
, x
, y
;
9828 struct gcpro gcpro1
;
9829 tiff_memory_source memsrc
;
9831 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9832 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9836 TIFFSetErrorHandler (tiff_error_handler
);
9837 TIFFSetWarningHandler (tiff_warning_handler
);
9839 if (NILP (specified_data
))
9841 /* Read from a file */
9842 file
= x_find_image_file (specified_file
);
9843 if (!STRINGP (file
))
9845 image_error ("Cannot find image file `%s'", file
, Qnil
);
9850 /* Try to open the image file. */
9851 tiff
= TIFFOpen (SDATA (file
), "r");
9854 image_error ("Cannot open `%s'", file
, Qnil
);
9861 /* Memory source! */
9862 memsrc
.bytes
= SDATA (specified_data
);
9863 memsrc
.len
= SBYTES (specified_data
);
9866 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9867 (TIFFReadWriteProc
) tiff_read_from_memory
,
9868 (TIFFReadWriteProc
) tiff_write_from_memory
,
9869 tiff_seek_in_memory
,
9871 tiff_size_of_memory
,
9877 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9883 /* Get width and height of the image, and allocate a raster buffer
9884 of width x height 32-bit values. */
9885 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9886 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9887 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9889 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9893 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9899 /* Create the X image and pixmap. */
9900 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9907 /* Initialize the color table. */
9908 init_color_table ();
9910 /* Process the pixel raster. Origin is in the lower-left corner. */
9911 for (y
= 0; y
< height
; ++y
)
9913 uint32
*row
= buf
+ y
* width
;
9915 for (x
= 0; x
< width
; ++x
)
9917 uint32 abgr
= row
[x
];
9918 int r
= TIFFGetR (abgr
) << 8;
9919 int g
= TIFFGetG (abgr
) << 8;
9920 int b
= TIFFGetB (abgr
) << 8;
9921 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9925 /* Remember the colors allocated for the image. Free the color table. */
9926 img
->colors
= colors_in_color_table (&img
->ncolors
);
9927 free_color_table ();
9930 img
->height
= height
;
9932 /* Maybe fill in the background field while we have ximg handy. */
9933 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9934 IMAGE_BACKGROUND (img
, f
, ximg
);
9936 /* Put the image into the pixmap, then free the X image and its buffer. */
9937 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9938 x_destroy_x_image (ximg
);
9945 #endif /* HAVE_TIFF != 0 */
9949 /***********************************************************************
9951 ***********************************************************************/
9955 #include <gif_lib.h>
9957 static int gif_image_p
P_ ((Lisp_Object object
));
9958 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9960 /* The symbol `gif' identifying images of this type. */
9964 /* Indices of image specification fields in gif_format, below. */
9966 enum gif_keyword_index
9982 /* Vector of image_keyword structures describing the format
9983 of valid user-defined image specifications. */
9985 static struct image_keyword gif_format
[GIF_LAST
] =
9987 {":type", IMAGE_SYMBOL_VALUE
, 1},
9988 {":data", IMAGE_STRING_VALUE
, 0},
9989 {":file", IMAGE_STRING_VALUE
, 0},
9990 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9991 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9992 {":relief", IMAGE_INTEGER_VALUE
, 0},
9993 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9994 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9995 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9996 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
9997 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10000 /* Structure describing the image type `gif'. */
10002 static struct image_type gif_type
=
10012 /* Return non-zero if OBJECT is a valid GIF image specification. */
10015 gif_image_p (object
)
10016 Lisp_Object object
;
10018 struct image_keyword fmt
[GIF_LAST
];
10019 bcopy (gif_format
, fmt
, sizeof fmt
);
10021 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
10024 /* Must specify either the :data or :file keyword. */
10025 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
10029 /* Reading a GIF image from memory
10030 Based on the PNG memory stuff to a certain extent. */
10034 unsigned char *bytes
;
10041 /* Make the current memory source available to gif_read_from_memory.
10042 It's done this way because not all versions of libungif support
10043 a UserData field in the GifFileType structure. */
10044 static gif_memory_source
*current_gif_memory_src
;
10047 gif_read_from_memory (file
, buf
, len
)
10052 gif_memory_source
*src
= current_gif_memory_src
;
10054 if (len
> src
->len
- src
->index
)
10057 bcopy (src
->bytes
+ src
->index
, buf
, len
);
10063 /* Load GIF image IMG for use on frame F. Value is non-zero if
10071 Lisp_Object file
, specified_file
;
10072 Lisp_Object specified_data
;
10073 int rc
, width
, height
, x
, y
, i
;
10075 ColorMapObject
*gif_color_map
;
10076 unsigned long pixel_colors
[256];
10078 struct gcpro gcpro1
;
10080 int ino
, image_left
, image_top
, image_width
, image_height
;
10081 gif_memory_source memsrc
;
10082 unsigned char *raster
;
10084 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10085 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10089 if (NILP (specified_data
))
10091 file
= x_find_image_file (specified_file
);
10092 if (!STRINGP (file
))
10094 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
10099 /* Open the GIF file. */
10100 gif
= DGifOpenFileName (SDATA (file
));
10103 image_error ("Cannot open `%s'", file
, Qnil
);
10110 /* Read from memory! */
10111 current_gif_memory_src
= &memsrc
;
10112 memsrc
.bytes
= SDATA (specified_data
);
10113 memsrc
.len
= SBYTES (specified_data
);
10116 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
10119 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
10125 /* Read entire contents. */
10126 rc
= DGifSlurp (gif
);
10127 if (rc
== GIF_ERROR
)
10129 image_error ("Error reading `%s'", img
->spec
, Qnil
);
10130 DGifCloseFile (gif
);
10135 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
10136 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
10137 if (ino
>= gif
->ImageCount
)
10139 image_error ("Invalid image number `%s' in image `%s'",
10141 DGifCloseFile (gif
);
10146 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
10147 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
10149 /* Create the X image and pixmap. */
10150 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
10152 DGifCloseFile (gif
);
10157 /* Allocate colors. */
10158 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
10159 if (!gif_color_map
)
10160 gif_color_map
= gif
->SColorMap
;
10161 init_color_table ();
10162 bzero (pixel_colors
, sizeof pixel_colors
);
10164 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
10166 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
10167 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
10168 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
10169 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
10172 img
->colors
= colors_in_color_table (&img
->ncolors
);
10173 free_color_table ();
10175 /* Clear the part of the screen image that are not covered by
10176 the image from the GIF file. Full animated GIF support
10177 requires more than can be done here (see the gif89 spec,
10178 disposal methods). Let's simply assume that the part
10179 not covered by a sub-image is in the frame's background color. */
10180 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
10181 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
10182 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
10183 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
10185 for (y
= 0; y
< image_top
; ++y
)
10186 for (x
= 0; x
< width
; ++x
)
10187 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10189 for (y
= image_top
+ image_height
; y
< height
; ++y
)
10190 for (x
= 0; x
< width
; ++x
)
10191 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10193 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
10195 for (x
= 0; x
< image_left
; ++x
)
10196 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10197 for (x
= image_left
+ image_width
; x
< width
; ++x
)
10198 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10201 /* Read the GIF image into the X image. We use a local variable
10202 `raster' here because RasterBits below is a char *, and invites
10203 problems with bytes >= 0x80. */
10204 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
10206 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
10208 static int interlace_start
[] = {0, 4, 2, 1};
10209 static int interlace_increment
[] = {8, 8, 4, 2};
10211 int row
= interlace_start
[0];
10215 for (y
= 0; y
< image_height
; y
++)
10217 if (row
>= image_height
)
10219 row
= interlace_start
[++pass
];
10220 while (row
>= image_height
)
10221 row
= interlace_start
[++pass
];
10224 for (x
= 0; x
< image_width
; x
++)
10226 int i
= raster
[(y
* image_width
) + x
];
10227 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
10231 row
+= interlace_increment
[pass
];
10236 for (y
= 0; y
< image_height
; ++y
)
10237 for (x
= 0; x
< image_width
; ++x
)
10239 int i
= raster
[y
* image_width
+ x
];
10240 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
10244 DGifCloseFile (gif
);
10246 /* Maybe fill in the background field while we have ximg handy. */
10247 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
10248 IMAGE_BACKGROUND (img
, f
, ximg
);
10250 /* Put the image into the pixmap, then free the X image and its buffer. */
10251 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10252 x_destroy_x_image (ximg
);
10258 #endif /* HAVE_GIF != 0 */
10262 /***********************************************************************
10264 ***********************************************************************/
10266 static int gs_image_p
P_ ((Lisp_Object object
));
10267 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
10268 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
10270 /* The symbol `postscript' identifying images of this type. */
10272 Lisp_Object Qpostscript
;
10274 /* Keyword symbols. */
10276 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
10278 /* Indices of image specification fields in gs_format, below. */
10280 enum gs_keyword_index
10298 /* Vector of image_keyword structures describing the format
10299 of valid user-defined image specifications. */
10301 static struct image_keyword gs_format
[GS_LAST
] =
10303 {":type", IMAGE_SYMBOL_VALUE
, 1},
10304 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10305 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10306 {":file", IMAGE_STRING_VALUE
, 1},
10307 {":loader", IMAGE_FUNCTION_VALUE
, 0},
10308 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
10309 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10310 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10311 {":relief", IMAGE_INTEGER_VALUE
, 0},
10312 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10313 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10314 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10315 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10318 /* Structure describing the image type `ghostscript'. */
10320 static struct image_type gs_type
=
10330 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10333 gs_clear_image (f
, img
)
10337 /* IMG->data.ptr_val may contain a recorded colormap. */
10338 xfree (img
->data
.ptr_val
);
10339 x_clear_image (f
, img
);
10343 /* Return non-zero if OBJECT is a valid Ghostscript image
10347 gs_image_p (object
)
10348 Lisp_Object object
;
10350 struct image_keyword fmt
[GS_LAST
];
10354 bcopy (gs_format
, fmt
, sizeof fmt
);
10356 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10359 /* Bounding box must be a list or vector containing 4 integers. */
10360 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10363 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10364 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10369 else if (VECTORP (tem
))
10371 if (XVECTOR (tem
)->size
!= 4)
10373 for (i
= 0; i
< 4; ++i
)
10374 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10384 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10393 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10394 struct gcpro gcpro1
, gcpro2
;
10396 double in_width
, in_height
;
10397 Lisp_Object pixel_colors
= Qnil
;
10399 /* Compute pixel size of pixmap needed from the given size in the
10400 image specification. Sizes in the specification are in pt. 1 pt
10401 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10403 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10404 in_width
= XFASTINT (pt_width
) / 72.0;
10405 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10406 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10407 in_height
= XFASTINT (pt_height
) / 72.0;
10408 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10410 /* Create the pixmap. */
10411 xassert (img
->pixmap
== None
);
10412 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10413 img
->width
, img
->height
,
10414 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10418 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10422 /* Call the loader to fill the pixmap. It returns a process object
10423 if successful. We do not record_unwind_protect here because
10424 other places in redisplay like calling window scroll functions
10425 don't either. Let the Lisp loader use `unwind-protect' instead. */
10426 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10428 sprintf (buffer
, "%lu %lu",
10429 (unsigned long) FRAME_X_WINDOW (f
),
10430 (unsigned long) img
->pixmap
);
10431 window_and_pixmap_id
= build_string (buffer
);
10433 sprintf (buffer
, "%lu %lu",
10434 FRAME_FOREGROUND_PIXEL (f
),
10435 FRAME_BACKGROUND_PIXEL (f
));
10436 pixel_colors
= build_string (buffer
);
10438 XSETFRAME (frame
, f
);
10439 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10441 loader
= intern ("gs-load-image");
10443 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10444 make_number (img
->width
),
10445 make_number (img
->height
),
10446 window_and_pixmap_id
,
10449 return PROCESSP (img
->data
.lisp_val
);
10453 /* Kill the Ghostscript process that was started to fill PIXMAP on
10454 frame F. Called from XTread_socket when receiving an event
10455 telling Emacs that Ghostscript has finished drawing. */
10458 x_kill_gs_process (pixmap
, f
)
10462 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10466 /* Find the image containing PIXMAP. */
10467 for (i
= 0; i
< c
->used
; ++i
)
10468 if (c
->images
[i
]->pixmap
== pixmap
)
10471 /* Should someone in between have cleared the image cache, for
10472 instance, give up. */
10476 /* Kill the GS process. We should have found PIXMAP in the image
10477 cache and its image should contain a process object. */
10478 img
= c
->images
[i
];
10479 xassert (PROCESSP (img
->data
.lisp_val
));
10480 Fkill_process (img
->data
.lisp_val
, Qnil
);
10481 img
->data
.lisp_val
= Qnil
;
10483 /* On displays with a mutable colormap, figure out the colors
10484 allocated for the image by looking at the pixels of an XImage for
10486 class = FRAME_X_VISUAL (f
)->class;
10487 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10493 /* Try to get an XImage for img->pixmep. */
10494 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10495 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10500 /* Initialize the color table. */
10501 init_color_table ();
10503 /* For each pixel of the image, look its color up in the
10504 color table. After having done so, the color table will
10505 contain an entry for each color used by the image. */
10506 for (y
= 0; y
< img
->height
; ++y
)
10507 for (x
= 0; x
< img
->width
; ++x
)
10509 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10510 lookup_pixel_color (f
, pixel
);
10513 /* Record colors in the image. Free color table and XImage. */
10514 img
->colors
= colors_in_color_table (&img
->ncolors
);
10515 free_color_table ();
10516 XDestroyImage (ximg
);
10518 #if 0 /* This doesn't seem to be the case. If we free the colors
10519 here, we get a BadAccess later in x_clear_image when
10520 freeing the colors. */
10521 /* We have allocated colors once, but Ghostscript has also
10522 allocated colors on behalf of us. So, to get the
10523 reference counts right, free them once. */
10525 x_free_colors (f
, img
->colors
, img
->ncolors
);
10529 image_error ("Cannot get X image of `%s'; colors will not be freed",
10535 /* Now that we have the pixmap, compute mask and transform the
10536 image if requested. */
10538 postprocess_image (f
, img
);
10544 /***********************************************************************
10546 ***********************************************************************/
10548 DEFUN ("x-change-window-property", Fx_change_window_property
,
10549 Sx_change_window_property
, 2, 3, 0,
10550 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
10551 PROP and VALUE must be strings. FRAME nil or omitted means use the
10552 selected frame. Value is VALUE. */)
10553 (prop
, value
, frame
)
10554 Lisp_Object frame
, prop
, value
;
10556 struct frame
*f
= check_x_frame (frame
);
10559 CHECK_STRING (prop
);
10560 CHECK_STRING (value
);
10563 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10564 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10565 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10566 SDATA (value
), SCHARS (value
));
10568 /* Make sure the property is set when we return. */
10569 XFlush (FRAME_X_DISPLAY (f
));
10576 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10577 Sx_delete_window_property
, 1, 2, 0,
10578 doc
: /* Remove window property PROP from X window of FRAME.
10579 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10581 Lisp_Object prop
, frame
;
10583 struct frame
*f
= check_x_frame (frame
);
10586 CHECK_STRING (prop
);
10588 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10589 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10591 /* Make sure the property is removed when we return. */
10592 XFlush (FRAME_X_DISPLAY (f
));
10599 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10601 doc
: /* Value is the value of window property PROP on FRAME.
10602 If FRAME is nil or omitted, use the selected frame. Value is nil
10603 if FRAME hasn't a property with name PROP or if PROP has no string
10606 Lisp_Object prop
, frame
;
10608 struct frame
*f
= check_x_frame (frame
);
10611 Lisp_Object prop_value
= Qnil
;
10612 char *tmp_data
= NULL
;
10615 unsigned long actual_size
, bytes_remaining
;
10617 CHECK_STRING (prop
);
10619 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10620 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10621 prop_atom
, 0, 0, False
, XA_STRING
,
10622 &actual_type
, &actual_format
, &actual_size
,
10623 &bytes_remaining
, (unsigned char **) &tmp_data
);
10626 int size
= bytes_remaining
;
10631 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10632 prop_atom
, 0, bytes_remaining
,
10634 &actual_type
, &actual_format
,
10635 &actual_size
, &bytes_remaining
,
10636 (unsigned char **) &tmp_data
);
10637 if (rc
== Success
&& tmp_data
)
10638 prop_value
= make_string (tmp_data
, size
);
10649 /***********************************************************************
10651 ***********************************************************************/
10653 /* If non-null, an asynchronous timer that, when it expires, displays
10654 an hourglass cursor on all frames. */
10656 static struct atimer
*hourglass_atimer
;
10658 /* Non-zero means an hourglass cursor is currently shown. */
10660 static int hourglass_shown_p
;
10662 /* Number of seconds to wait before displaying an hourglass cursor. */
10664 static Lisp_Object Vhourglass_delay
;
10666 /* Default number of seconds to wait before displaying an hourglass
10669 #define DEFAULT_HOURGLASS_DELAY 1
10671 /* Function prototypes. */
10673 static void show_hourglass
P_ ((struct atimer
*));
10674 static void hide_hourglass
P_ ((void));
10677 /* Cancel a currently active hourglass timer, and start a new one. */
10683 int secs
, usecs
= 0;
10685 cancel_hourglass ();
10687 if (INTEGERP (Vhourglass_delay
)
10688 && XINT (Vhourglass_delay
) > 0)
10689 secs
= XFASTINT (Vhourglass_delay
);
10690 else if (FLOATP (Vhourglass_delay
)
10691 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10694 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10695 secs
= XFASTINT (tem
);
10696 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10699 secs
= DEFAULT_HOURGLASS_DELAY
;
10701 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10702 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10703 show_hourglass
, NULL
);
10707 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10711 cancel_hourglass ()
10713 if (hourglass_atimer
)
10715 cancel_atimer (hourglass_atimer
);
10716 hourglass_atimer
= NULL
;
10719 if (hourglass_shown_p
)
10724 /* Timer function of hourglass_atimer. TIMER is equal to
10727 Display an hourglass pointer on all frames by mapping the frames'
10728 hourglass_window. Set the hourglass_p flag in the frames'
10729 output_data.x structure to indicate that an hourglass cursor is
10730 shown on the frames. */
10733 show_hourglass (timer
)
10734 struct atimer
*timer
;
10736 /* The timer implementation will cancel this timer automatically
10737 after this function has run. Set hourglass_atimer to null
10738 so that we know the timer doesn't have to be canceled. */
10739 hourglass_atimer
= NULL
;
10741 if (!hourglass_shown_p
)
10743 Lisp_Object rest
, frame
;
10747 FOR_EACH_FRAME (rest
, frame
)
10749 struct frame
*f
= XFRAME (frame
);
10751 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10753 Display
*dpy
= FRAME_X_DISPLAY (f
);
10755 #ifdef USE_X_TOOLKIT
10756 if (f
->output_data
.x
->widget
)
10758 if (FRAME_OUTER_WINDOW (f
))
10761 f
->output_data
.x
->hourglass_p
= 1;
10763 if (!f
->output_data
.x
->hourglass_window
)
10765 unsigned long mask
= CWCursor
;
10766 XSetWindowAttributes attrs
;
10768 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10770 f
->output_data
.x
->hourglass_window
10771 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10772 0, 0, 32000, 32000, 0, 0,
10778 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10784 hourglass_shown_p
= 1;
10790 /* Hide the hourglass pointer on all frames, if it is currently
10796 if (hourglass_shown_p
)
10798 Lisp_Object rest
, frame
;
10801 FOR_EACH_FRAME (rest
, frame
)
10803 struct frame
*f
= XFRAME (frame
);
10806 /* Watch out for newly created frames. */
10807 && f
->output_data
.x
->hourglass_window
)
10809 XUnmapWindow (FRAME_X_DISPLAY (f
),
10810 f
->output_data
.x
->hourglass_window
);
10811 /* Sync here because XTread_socket looks at the
10812 hourglass_p flag that is reset to zero below. */
10813 XSync (FRAME_X_DISPLAY (f
), False
);
10814 f
->output_data
.x
->hourglass_p
= 0;
10818 hourglass_shown_p
= 0;
10825 /***********************************************************************
10827 ***********************************************************************/
10829 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10830 Lisp_Object
, Lisp_Object
));
10831 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10832 Lisp_Object
, int, int, int *, int *));
10834 /* The frame of a currently visible tooltip. */
10836 Lisp_Object tip_frame
;
10838 /* If non-nil, a timer started that hides the last tooltip when it
10841 Lisp_Object tip_timer
;
10844 /* If non-nil, a vector of 3 elements containing the last args
10845 with which x-show-tip was called. See there. */
10847 Lisp_Object last_show_tip_args
;
10849 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10851 Lisp_Object Vx_max_tooltip_size
;
10855 unwind_create_tip_frame (frame
)
10858 Lisp_Object deleted
;
10860 deleted
= unwind_create_frame (frame
);
10861 if (EQ (deleted
, Qt
))
10871 /* Create a frame for a tooltip on the display described by DPYINFO.
10872 PARMS is a list of frame parameters. TEXT is the string to
10873 display in the tip frame. Value is the frame.
10875 Note that functions called here, esp. x_default_parameter can
10876 signal errors, for instance when a specified color name is
10877 undefined. We have to make sure that we're in a consistent state
10878 when this happens. */
10881 x_create_tip_frame (dpyinfo
, parms
, text
)
10882 struct x_display_info
*dpyinfo
;
10883 Lisp_Object parms
, text
;
10886 Lisp_Object frame
, tem
;
10888 long window_prompting
= 0;
10890 int count
= SPECPDL_INDEX ();
10891 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10893 int face_change_count_before
= face_change_count
;
10894 Lisp_Object buffer
;
10895 struct buffer
*old_buffer
;
10899 /* Use this general default value to start with until we know if
10900 this frame has a specified name. */
10901 Vx_resource_name
= Vinvocation_name
;
10903 #ifdef MULTI_KBOARD
10904 kb
= dpyinfo
->kboard
;
10906 kb
= &the_only_kboard
;
10909 /* Get the name of the frame to use for resource lookup. */
10910 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10911 if (!STRINGP (name
)
10912 && !EQ (name
, Qunbound
)
10914 error ("Invalid frame name--not a string or nil");
10915 Vx_resource_name
= name
;
10918 GCPRO3 (parms
, name
, frame
);
10919 f
= make_frame (1);
10920 XSETFRAME (frame
, f
);
10922 buffer
= Fget_buffer_create (build_string (" *tip*"));
10923 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10924 old_buffer
= current_buffer
;
10925 set_buffer_internal_1 (XBUFFER (buffer
));
10926 current_buffer
->truncate_lines
= Qnil
;
10928 Finsert (1, &text
);
10929 set_buffer_internal_1 (old_buffer
);
10931 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10932 record_unwind_protect (unwind_create_tip_frame
, frame
);
10934 /* By setting the output method, we're essentially saying that
10935 the frame is live, as per FRAME_LIVE_P. If we get a signal
10936 from this point on, x_destroy_window might screw up reference
10938 f
->output_method
= output_x_window
;
10939 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10940 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10941 f
->output_data
.x
->icon_bitmap
= -1;
10942 f
->output_data
.x
->fontset
= -1;
10943 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10944 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10945 #ifdef USE_TOOLKIT_SCROLL_BARS
10946 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
10947 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
10948 #endif /* USE_TOOLKIT_SCROLL_BARS */
10949 f
->icon_name
= Qnil
;
10950 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10952 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
10953 dpyinfo_refcount
= dpyinfo
->reference_count
;
10954 #endif /* GLYPH_DEBUG */
10955 #ifdef MULTI_KBOARD
10956 FRAME_KBOARD (f
) = kb
;
10958 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10959 f
->output_data
.x
->explicit_parent
= 0;
10961 /* These colors will be set anyway later, but it's important
10962 to get the color reference counts right, so initialize them! */
10965 struct gcpro gcpro1
;
10967 black
= build_string ("black");
10969 f
->output_data
.x
->foreground_pixel
10970 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10971 f
->output_data
.x
->background_pixel
10972 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10973 f
->output_data
.x
->cursor_pixel
10974 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10975 f
->output_data
.x
->cursor_foreground_pixel
10976 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10977 f
->output_data
.x
->border_pixel
10978 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10979 f
->output_data
.x
->mouse_pixel
10980 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10984 /* Set the name; the functions to which we pass f expect the name to
10986 if (EQ (name
, Qunbound
) || NILP (name
))
10988 f
->name
= build_string (dpyinfo
->x_id_name
);
10989 f
->explicit_name
= 0;
10994 f
->explicit_name
= 1;
10995 /* use the frame's title when getting resources for this frame. */
10996 specbind (Qx_resource_name
, name
);
10999 /* Extract the window parameters from the supplied values that are
11000 needed to determine window geometry. */
11004 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
11007 /* First, try whatever font the caller has specified. */
11008 if (STRINGP (font
))
11010 tem
= Fquery_fontset (font
, Qnil
);
11012 font
= x_new_fontset (f
, SDATA (tem
));
11014 font
= x_new_font (f
, SDATA (font
));
11017 /* Try out a font which we hope has bold and italic variations. */
11018 if (!STRINGP (font
))
11019 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
11020 if (!STRINGP (font
))
11021 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11022 if (! STRINGP (font
))
11023 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11024 if (! STRINGP (font
))
11025 /* This was formerly the first thing tried, but it finds too many fonts
11026 and takes too long. */
11027 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
11028 /* If those didn't work, look for something which will at least work. */
11029 if (! STRINGP (font
))
11030 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
11032 if (! STRINGP (font
))
11033 font
= build_string ("fixed");
11035 x_default_parameter (f
, parms
, Qfont
, font
,
11036 "font", "Font", RES_TYPE_STRING
);
11039 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
11040 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
11042 /* This defaults to 2 in order to match xterm. We recognize either
11043 internalBorderWidth or internalBorder (which is what xterm calls
11045 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11049 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
11050 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
11051 if (! EQ (value
, Qunbound
))
11052 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
11056 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
11057 "internalBorderWidth", "internalBorderWidth",
11060 /* Also do the stuff which must be set before the window exists. */
11061 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
11062 "foreground", "Foreground", RES_TYPE_STRING
);
11063 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
11064 "background", "Background", RES_TYPE_STRING
);
11065 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
11066 "pointerColor", "Foreground", RES_TYPE_STRING
);
11067 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
11068 "cursorColor", "Foreground", RES_TYPE_STRING
);
11069 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
11070 "borderColor", "BorderColor", RES_TYPE_STRING
);
11072 /* Init faces before x_default_parameter is called for scroll-bar
11073 parameters because that function calls x_set_scroll_bar_width,
11074 which calls change_frame_size, which calls Fset_window_buffer,
11075 which runs hooks, which call Fvertical_motion. At the end, we
11076 end up in init_iterator with a null face cache, which should not
11078 init_frame_faces (f
);
11080 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
11081 window_prompting
= x_figure_window_size (f
, parms
);
11083 if (window_prompting
& XNegative
)
11085 if (window_prompting
& YNegative
)
11086 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
11088 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
11092 if (window_prompting
& YNegative
)
11093 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
11095 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11098 f
->output_data
.x
->size_hint_flags
= window_prompting
;
11100 XSetWindowAttributes attrs
;
11101 unsigned long mask
;
11104 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
11105 if (DoesSaveUnders (dpyinfo
->screen
))
11106 mask
|= CWSaveUnder
;
11108 /* Window managers look at the override-redirect flag to determine
11109 whether or net to give windows a decoration (Xlib spec, chapter
11111 attrs
.override_redirect
= True
;
11112 attrs
.save_under
= True
;
11113 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
11114 /* Arrange for getting MapNotify and UnmapNotify events. */
11115 attrs
.event_mask
= StructureNotifyMask
;
11117 = FRAME_X_WINDOW (f
)
11118 = XCreateWindow (FRAME_X_DISPLAY (f
),
11119 FRAME_X_DISPLAY_INFO (f
)->root_window
,
11120 /* x, y, width, height */
11124 CopyFromParent
, InputOutput
, CopyFromParent
,
11131 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
11132 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11133 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
11134 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11135 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
11136 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
11138 /* Dimensions, especially f->height, must be done via change_frame_size.
11139 Change will not be effected unless different from the current
11142 height
= f
->height
;
11144 SET_FRAME_WIDTH (f
, 0);
11145 change_frame_size (f
, height
, width
, 1, 0, 0);
11147 /* Add `tooltip' frame parameter's default value. */
11148 if (NILP (Fframe_parameter (frame
, intern ("tooltip"))))
11149 Fmodify_frame_parameters (frame
, Fcons (Fcons (intern ("tooltip"), Qt
),
11152 /* Set up faces after all frame parameters are known. This call
11153 also merges in face attributes specified for new frames.
11155 Frame parameters may be changed if .Xdefaults contains
11156 specifications for the default font. For example, if there is an
11157 `Emacs.default.attributeBackground: pink', the `background-color'
11158 attribute of the frame get's set, which let's the internal border
11159 of the tooltip frame appear in pink. Prevent this. */
11161 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
11163 /* Set tip_frame here, so that */
11165 call1 (Qface_set_after_frame_default
, frame
);
11167 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
11168 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
11176 /* It is now ok to make the frame official even if we get an error
11177 below. And the frame needs to be on Vframe_list or making it
11178 visible won't work. */
11179 Vframe_list
= Fcons (frame
, Vframe_list
);
11181 /* Now that the frame is official, it counts as a reference to
11183 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
11185 /* Setting attributes of faces of the tooltip frame from resources
11186 and similar will increment face_change_count, which leads to the
11187 clearing of all current matrices. Since this isn't necessary
11188 here, avoid it by resetting face_change_count to the value it
11189 had before we created the tip frame. */
11190 face_change_count
= face_change_count_before
;
11192 /* Discard the unwind_protect. */
11193 return unbind_to (count
, frame
);
11197 /* Compute where to display tip frame F. PARMS is the list of frame
11198 parameters for F. DX and DY are specified offsets from the current
11199 location of the mouse. WIDTH and HEIGHT are the width and height
11200 of the tooltip. Return coordinates relative to the root window of
11201 the display in *ROOT_X, and *ROOT_Y. */
11204 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
11206 Lisp_Object parms
, dx
, dy
;
11208 int *root_x
, *root_y
;
11210 Lisp_Object left
, top
;
11212 Window root
, child
;
11215 /* User-specified position? */
11216 left
= Fcdr (Fassq (Qleft
, parms
));
11217 top
= Fcdr (Fassq (Qtop
, parms
));
11219 /* Move the tooltip window where the mouse pointer is. Resize and
11221 if (!INTEGERP (left
) || !INTEGERP (top
))
11224 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
11225 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
11229 if (INTEGERP (top
))
11230 *root_y
= XINT (top
);
11231 else if (*root_y
+ XINT (dy
) - height
< 0)
11232 *root_y
-= XINT (dy
);
11236 *root_y
+= XINT (dy
);
11239 if (INTEGERP (left
))
11240 *root_x
= XINT (left
);
11241 else if (*root_x
+ XINT (dx
) + width
<= FRAME_X_DISPLAY_INFO (f
)->width
)
11242 /* It fits to the right of the pointer. */
11243 *root_x
+= XINT (dx
);
11244 else if (width
+ XINT (dx
) <= *root_x
)
11245 /* It fits to the left of the pointer. */
11246 *root_x
-= width
+ XINT (dx
);
11248 /* Put it left-justified on the screen--it ought to fit that way. */
11253 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
11254 doc
: /* Show STRING in a "tooltip" window on frame FRAME.
11255 A tooltip window is a small X window displaying a string.
11257 FRAME nil or omitted means use the selected frame.
11259 PARMS is an optional list of frame parameters which can be used to
11260 change the tooltip's appearance.
11262 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11263 means use the default timeout of 5 seconds.
11265 If the list of frame parameters PARAMS contains a `left' parameters,
11266 the tooltip is displayed at that x-position. Otherwise it is
11267 displayed at the mouse position, with offset DX added (default is 5 if
11268 DX isn't specified). Likewise for the y-position; if a `top' frame
11269 parameter is specified, it determines the y-position of the tooltip
11270 window, otherwise it is displayed at the mouse position, with offset
11271 DY added (default is -10).
11273 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11274 Text larger than the specified size is clipped. */)
11275 (string
, frame
, parms
, timeout
, dx
, dy
)
11276 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
11280 int root_x
, root_y
;
11281 struct buffer
*old_buffer
;
11282 struct text_pos pos
;
11283 int i
, width
, height
;
11284 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
11285 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
11286 int count
= SPECPDL_INDEX ();
11288 specbind (Qinhibit_redisplay
, Qt
);
11290 GCPRO4 (string
, parms
, frame
, timeout
);
11292 CHECK_STRING (string
);
11293 f
= check_x_frame (frame
);
11294 if (NILP (timeout
))
11295 timeout
= make_number (5);
11297 CHECK_NATNUM (timeout
);
11300 dx
= make_number (5);
11305 dy
= make_number (-10);
11309 if (NILP (last_show_tip_args
))
11310 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
11312 if (!NILP (tip_frame
))
11314 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
11315 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
11316 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
11318 if (EQ (frame
, last_frame
)
11319 && !NILP (Fequal (last_string
, string
))
11320 && !NILP (Fequal (last_parms
, parms
)))
11322 struct frame
*f
= XFRAME (tip_frame
);
11324 /* Only DX and DY have changed. */
11325 if (!NILP (tip_timer
))
11327 Lisp_Object timer
= tip_timer
;
11329 call1 (Qcancel_timer
, timer
);
11333 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
11334 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
11335 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11342 /* Hide a previous tip, if any. */
11345 ASET (last_show_tip_args
, 0, string
);
11346 ASET (last_show_tip_args
, 1, frame
);
11347 ASET (last_show_tip_args
, 2, parms
);
11349 /* Add default values to frame parameters. */
11350 if (NILP (Fassq (Qname
, parms
)))
11351 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
11352 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11353 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
11354 if (NILP (Fassq (Qborder_width
, parms
)))
11355 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
11356 if (NILP (Fassq (Qborder_color
, parms
)))
11357 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
11358 if (NILP (Fassq (Qbackground_color
, parms
)))
11359 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
11362 /* Create a frame for the tooltip, and record it in the global
11363 variable tip_frame. */
11364 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
11365 f
= XFRAME (frame
);
11367 /* Set up the frame's root window. */
11368 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
11369 w
->left
= w
->top
= make_number (0);
11371 if (CONSP (Vx_max_tooltip_size
)
11372 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11373 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11374 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11375 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11377 w
->width
= XCAR (Vx_max_tooltip_size
);
11378 w
->height
= XCDR (Vx_max_tooltip_size
);
11382 w
->width
= make_number (80);
11383 w
->height
= make_number (40);
11386 f
->window_width
= XINT (w
->width
);
11388 w
->pseudo_window_p
= 1;
11390 /* Display the tooltip text in a temporary buffer. */
11391 old_buffer
= current_buffer
;
11392 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11393 current_buffer
->truncate_lines
= Qnil
;
11394 clear_glyph_matrix (w
->desired_matrix
);
11395 clear_glyph_matrix (w
->current_matrix
);
11396 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11397 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11399 /* Compute width and height of the tooltip. */
11400 width
= height
= 0;
11401 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11403 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11404 struct glyph
*last
;
11407 /* Stop at the first empty row at the end. */
11408 if (!row
->enabled_p
|| !row
->displays_text_p
)
11411 /* Let the row go over the full width of the frame. */
11412 row
->full_width_p
= 1;
11414 /* There's a glyph at the end of rows that is used to place
11415 the cursor there. Don't include the width of this glyph. */
11416 if (row
->used
[TEXT_AREA
])
11418 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11419 row_width
= row
->pixel_width
- last
->pixel_width
;
11422 row_width
= row
->pixel_width
;
11424 height
+= row
->height
;
11425 width
= max (width
, row_width
);
11428 /* Add the frame's internal border to the width and height the X
11429 window should have. */
11430 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11431 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11433 /* Move the tooltip window where the mouse pointer is. Resize and
11435 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11438 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11439 root_x
, root_y
, width
, height
);
11440 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11443 /* Draw into the window. */
11444 w
->must_be_updated_p
= 1;
11445 update_single_window (w
, 1);
11447 /* Restore original current buffer. */
11448 set_buffer_internal_1 (old_buffer
);
11449 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11452 /* Let the tip disappear after timeout seconds. */
11453 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11454 intern ("x-hide-tip"));
11457 return unbind_to (count
, Qnil
);
11461 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11462 doc
: /* Hide the current tooltip window, if there is any.
11463 Value is t if tooltip was open, nil otherwise. */)
11467 Lisp_Object deleted
, frame
, timer
;
11468 struct gcpro gcpro1
, gcpro2
;
11470 /* Return quickly if nothing to do. */
11471 if (NILP (tip_timer
) && NILP (tip_frame
))
11476 GCPRO2 (frame
, timer
);
11477 tip_frame
= tip_timer
= deleted
= Qnil
;
11479 count
= SPECPDL_INDEX ();
11480 specbind (Qinhibit_redisplay
, Qt
);
11481 specbind (Qinhibit_quit
, Qt
);
11484 call1 (Qcancel_timer
, timer
);
11486 if (FRAMEP (frame
))
11488 Fdelete_frame (frame
, Qnil
);
11492 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11493 redisplay procedure is not called when a tip frame over menu
11494 items is unmapped. Redisplay the menu manually... */
11496 struct frame
*f
= SELECTED_FRAME ();
11497 Widget w
= f
->output_data
.x
->menubar_widget
;
11498 extern void xlwmenu_redisplay
P_ ((Widget
));
11500 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11504 xlwmenu_redisplay (w
);
11508 #endif /* USE_LUCID */
11512 return unbind_to (count
, deleted
);
11517 /***********************************************************************
11518 File selection dialog
11519 ***********************************************************************/
11523 /* Callback for "OK" and "Cancel" on file selection dialog. */
11526 file_dialog_cb (widget
, client_data
, call_data
)
11528 XtPointer call_data
, client_data
;
11530 int *result
= (int *) client_data
;
11531 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11532 *result
= cb
->reason
;
11536 /* Callback for unmapping a file selection dialog. This is used to
11537 capture the case where a dialog is closed via a window manager's
11538 closer button, for example. Using a XmNdestroyCallback didn't work
11542 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11544 XtPointer call_data
, client_data
;
11546 int *result
= (int *) client_data
;
11547 *result
= XmCR_CANCEL
;
11551 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11552 doc
: /* Read file name, prompting with PROMPT in directory DIR.
11553 Use a file selection dialog.
11554 Select DEFAULT-FILENAME in the dialog's file selection box, if
11555 specified. Don't let the user enter a file name in the file
11556 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11557 (prompt
, dir
, default_filename
, mustmatch
)
11558 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11561 struct frame
*f
= SELECTED_FRAME ();
11562 Lisp_Object file
= Qnil
;
11563 Widget dialog
, text
, list
, help
;
11566 extern XtAppContext Xt_app_con
;
11567 XmString dir_xmstring
, pattern_xmstring
;
11568 int count
= SPECPDL_INDEX ();
11569 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11571 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11572 CHECK_STRING (prompt
);
11573 CHECK_STRING (dir
);
11575 /* Prevent redisplay. */
11576 specbind (Qinhibit_redisplay
, Qt
);
11580 /* Create the dialog with PROMPT as title, using DIR as initial
11581 directory and using "*" as pattern. */
11582 dir
= Fexpand_file_name (dir
, Qnil
);
11583 dir_xmstring
= XmStringCreateLocalized (SDATA (dir
));
11584 pattern_xmstring
= XmStringCreateLocalized ("*");
11586 XtSetArg (al
[ac
], XmNtitle
, SDATA (prompt
)); ++ac
;
11587 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11588 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11589 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11590 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11591 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11593 XmStringFree (dir_xmstring
);
11594 XmStringFree (pattern_xmstring
);
11596 /* Add callbacks for OK and Cancel. */
11597 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11598 (XtPointer
) &result
);
11599 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11600 (XtPointer
) &result
);
11601 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11602 (XtPointer
) &result
);
11604 /* Disable the help button since we can't display help. */
11605 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11606 XtSetSensitive (help
, False
);
11608 /* Mark OK button as default. */
11609 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11610 XmNshowAsDefault
, True
, NULL
);
11612 /* If MUSTMATCH is non-nil, disable the file entry field of the
11613 dialog, so that the user must select a file from the files list
11614 box. We can't remove it because we wouldn't have a way to get at
11615 the result file name, then. */
11616 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11617 if (!NILP (mustmatch
))
11620 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11621 XtSetSensitive (text
, False
);
11622 XtSetSensitive (label
, False
);
11625 /* Manage the dialog, so that list boxes get filled. */
11626 XtManageChild (dialog
);
11628 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11629 must include the path for this to work. */
11630 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11631 if (STRINGP (default_filename
))
11633 XmString default_xmstring
;
11637 = XmStringCreateLocalized (SDATA (default_filename
));
11639 if (!XmListItemExists (list
, default_xmstring
))
11641 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11642 XmListAddItem (list
, default_xmstring
, 0);
11646 item_pos
= XmListItemPos (list
, default_xmstring
);
11647 XmStringFree (default_xmstring
);
11649 /* Select the item and scroll it into view. */
11650 XmListSelectPos (list
, item_pos
, True
);
11651 XmListSetPos (list
, item_pos
);
11654 /* Process events until the user presses Cancel or OK. Block
11655 and unblock input here so that we get a chance of processing
11659 while (result
== 0)
11662 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11667 /* Get the result. */
11668 if (result
== XmCR_OK
)
11673 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11674 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11675 XmStringFree (text
);
11676 file
= build_string (data
);
11683 XtUnmanageChild (dialog
);
11684 XtDestroyWidget (dialog
);
11688 /* Make "Cancel" equivalent to C-g. */
11690 Fsignal (Qquit
, Qnil
);
11692 return unbind_to (count
, file
);
11695 #endif /* USE_MOTIF */
11699 /***********************************************************************
11701 ***********************************************************************/
11703 #ifdef HAVE_XKBGETKEYBOARD
11704 #include <X11/XKBlib.h>
11705 #include <X11/keysym.h>
11708 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11709 Sx_backspace_delete_keys_p
, 0, 1, 0,
11710 doc
: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11711 FRAME nil means use the selected frame.
11712 Value is t if we know that both keys are present, and are mapped to the
11713 usual X keysyms. */)
11717 #ifdef HAVE_XKBGETKEYBOARD
11719 struct frame
*f
= check_x_frame (frame
);
11720 Display
*dpy
= FRAME_X_DISPLAY (f
);
11721 Lisp_Object have_keys
;
11722 int major
, minor
, op
, event
, error
;
11726 /* Check library version in case we're dynamically linked. */
11727 major
= XkbMajorVersion
;
11728 minor
= XkbMinorVersion
;
11729 if (!XkbLibraryVersion (&major
, &minor
))
11735 /* Check that the server supports XKB. */
11736 major
= XkbMajorVersion
;
11737 minor
= XkbMinorVersion
;
11738 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11745 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11748 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11750 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11752 for (i
= kb
->min_key_code
;
11753 (i
< kb
->max_key_code
11754 && (delete_keycode
== 0 || backspace_keycode
== 0));
11757 /* The XKB symbolic key names can be seen most easily in
11758 the PS file generated by `xkbprint -label name
11760 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11761 delete_keycode
= i
;
11762 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11763 backspace_keycode
= i
;
11766 XkbFreeNames (kb
, 0, True
);
11769 XkbFreeClientMap (kb
, 0, True
);
11772 && backspace_keycode
11773 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11774 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11779 #else /* not HAVE_XKBGETKEYBOARD */
11781 #endif /* not HAVE_XKBGETKEYBOARD */
11786 /***********************************************************************
11788 ***********************************************************************/
11793 /* This is zero if not using X windows. */
11796 /* The section below is built by the lisp expression at the top of the file,
11797 just above where these variables are declared. */
11798 /*&&& init symbols here &&&*/
11799 Qauto_raise
= intern ("auto-raise");
11800 staticpro (&Qauto_raise
);
11801 Qauto_lower
= intern ("auto-lower");
11802 staticpro (&Qauto_lower
);
11803 Qborder_color
= intern ("border-color");
11804 staticpro (&Qborder_color
);
11805 Qborder_width
= intern ("border-width");
11806 staticpro (&Qborder_width
);
11807 Qcursor_color
= intern ("cursor-color");
11808 staticpro (&Qcursor_color
);
11809 Qcursor_type
= intern ("cursor-type");
11810 staticpro (&Qcursor_type
);
11811 Qgeometry
= intern ("geometry");
11812 staticpro (&Qgeometry
);
11813 Qicon_left
= intern ("icon-left");
11814 staticpro (&Qicon_left
);
11815 Qicon_top
= intern ("icon-top");
11816 staticpro (&Qicon_top
);
11817 Qicon_type
= intern ("icon-type");
11818 staticpro (&Qicon_type
);
11819 Qicon_name
= intern ("icon-name");
11820 staticpro (&Qicon_name
);
11821 Qinternal_border_width
= intern ("internal-border-width");
11822 staticpro (&Qinternal_border_width
);
11823 Qleft
= intern ("left");
11824 staticpro (&Qleft
);
11825 Qright
= intern ("right");
11826 staticpro (&Qright
);
11827 Qmouse_color
= intern ("mouse-color");
11828 staticpro (&Qmouse_color
);
11829 Qnone
= intern ("none");
11830 staticpro (&Qnone
);
11831 Qparent_id
= intern ("parent-id");
11832 staticpro (&Qparent_id
);
11833 Qscroll_bar_width
= intern ("scroll-bar-width");
11834 staticpro (&Qscroll_bar_width
);
11835 Qsuppress_icon
= intern ("suppress-icon");
11836 staticpro (&Qsuppress_icon
);
11837 Qundefined_color
= intern ("undefined-color");
11838 staticpro (&Qundefined_color
);
11839 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11840 staticpro (&Qvertical_scroll_bars
);
11841 Qvisibility
= intern ("visibility");
11842 staticpro (&Qvisibility
);
11843 Qwindow_id
= intern ("window-id");
11844 staticpro (&Qwindow_id
);
11845 Qouter_window_id
= intern ("outer-window-id");
11846 staticpro (&Qouter_window_id
);
11847 Qx_frame_parameter
= intern ("x-frame-parameter");
11848 staticpro (&Qx_frame_parameter
);
11849 Qx_resource_name
= intern ("x-resource-name");
11850 staticpro (&Qx_resource_name
);
11851 Quser_position
= intern ("user-position");
11852 staticpro (&Quser_position
);
11853 Quser_size
= intern ("user-size");
11854 staticpro (&Quser_size
);
11855 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11856 staticpro (&Qscroll_bar_foreground
);
11857 Qscroll_bar_background
= intern ("scroll-bar-background");
11858 staticpro (&Qscroll_bar_background
);
11859 Qscreen_gamma
= intern ("screen-gamma");
11860 staticpro (&Qscreen_gamma
);
11861 Qline_spacing
= intern ("line-spacing");
11862 staticpro (&Qline_spacing
);
11863 Qcenter
= intern ("center");
11864 staticpro (&Qcenter
);
11865 Qcompound_text
= intern ("compound-text");
11866 staticpro (&Qcompound_text
);
11867 Qcancel_timer
= intern ("cancel-timer");
11868 staticpro (&Qcancel_timer
);
11869 Qwait_for_wm
= intern ("wait-for-wm");
11870 staticpro (&Qwait_for_wm
);
11871 Qfullscreen
= intern ("fullscreen");
11872 staticpro (&Qfullscreen
);
11873 Qfullwidth
= intern ("fullwidth");
11874 staticpro (&Qfullwidth
);
11875 Qfullheight
= intern ("fullheight");
11876 staticpro (&Qfullheight
);
11877 Qfullboth
= intern ("fullboth");
11878 staticpro (&Qfullboth
);
11879 /* This is the end of symbol initialization. */
11881 /* Text property `display' should be nonsticky by default. */
11882 Vtext_property_default_nonsticky
11883 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11886 Qlaplace
= intern ("laplace");
11887 staticpro (&Qlaplace
);
11888 Qemboss
= intern ("emboss");
11889 staticpro (&Qemboss
);
11890 Qedge_detection
= intern ("edge-detection");
11891 staticpro (&Qedge_detection
);
11892 Qheuristic
= intern ("heuristic");
11893 staticpro (&Qheuristic
);
11894 QCmatrix
= intern (":matrix");
11895 staticpro (&QCmatrix
);
11896 QCcolor_adjustment
= intern (":color-adjustment");
11897 staticpro (&QCcolor_adjustment
);
11898 QCmask
= intern (":mask");
11899 staticpro (&QCmask
);
11901 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11902 staticpro (&Qface_set_after_frame_default
);
11904 Fput (Qundefined_color
, Qerror_conditions
,
11905 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11906 Fput (Qundefined_color
, Qerror_message
,
11907 build_string ("Undefined color"));
11909 init_x_parm_symbols ();
11911 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11912 doc
: /* Non-nil means always draw a cross over disabled images.
11913 Disabled images are those having an `:conversion disabled' property.
11914 A cross is always drawn on black & white displays. */);
11915 cross_disabled_images
= 0;
11917 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11918 doc
: /* List of directories to search for bitmap files for X. */);
11919 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11921 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11922 doc
: /* The shape of the pointer when over text.
11923 Changing the value does not affect existing frames
11924 unless you set the mouse color. */);
11925 Vx_pointer_shape
= Qnil
;
11927 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11928 doc
: /* The name Emacs uses to look up X resources.
11929 `x-get-resource' uses this as the first component of the instance name
11930 when requesting resource values.
11931 Emacs initially sets `x-resource-name' to the name under which Emacs
11932 was invoked, or to the value specified with the `-name' or `-rn'
11933 switches, if present.
11935 It may be useful to bind this variable locally around a call
11936 to `x-get-resource'. See also the variable `x-resource-class'. */);
11937 Vx_resource_name
= Qnil
;
11939 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11940 doc
: /* The class Emacs uses to look up X resources.
11941 `x-get-resource' uses this as the first component of the instance class
11942 when requesting resource values.
11944 Emacs initially sets `x-resource-class' to "Emacs".
11946 Setting this variable permanently is not a reasonable thing to do,
11947 but binding this variable locally around a call to `x-get-resource'
11948 is a reasonable practice. See also the variable `x-resource-name'. */);
11949 Vx_resource_class
= build_string (EMACS_CLASS
);
11951 #if 0 /* This doesn't really do anything. */
11952 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11953 doc
: /* The shape of the pointer when not over text.
11954 This variable takes effect when you create a new frame
11955 or when you set the mouse color. */);
11957 Vx_nontext_pointer_shape
= Qnil
;
11959 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
11960 doc
: /* The shape of the pointer when Emacs is busy.
11961 This variable takes effect when you create a new frame
11962 or when you set the mouse color. */);
11963 Vx_hourglass_pointer_shape
= Qnil
;
11965 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
11966 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
11967 display_hourglass_p
= 1;
11969 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
11970 doc
: /* *Seconds to wait before displaying an hourglass pointer.
11971 Value must be an integer or float. */);
11972 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
11974 #if 0 /* This doesn't really do anything. */
11975 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
11976 doc
: /* The shape of the pointer when over the mode line.
11977 This variable takes effect when you create a new frame
11978 or when you set the mouse color. */);
11980 Vx_mode_pointer_shape
= Qnil
;
11982 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11983 &Vx_sensitive_text_pointer_shape
,
11984 doc
: /* The shape of the pointer when over mouse-sensitive text.
11985 This variable takes effect when you create a new frame
11986 or when you set the mouse color. */);
11987 Vx_sensitive_text_pointer_shape
= Qnil
;
11989 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11990 &Vx_window_horizontal_drag_shape
,
11991 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
11992 This variable takes effect when you create a new frame
11993 or when you set the mouse color. */);
11994 Vx_window_horizontal_drag_shape
= Qnil
;
11996 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
11997 doc
: /* A string indicating the foreground color of the cursor box. */);
11998 Vx_cursor_fore_pixel
= Qnil
;
12000 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
12001 doc
: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
12002 Text larger than this is clipped. */);
12003 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
12005 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
12006 doc
: /* Non-nil if no X window manager is in use.
12007 Emacs doesn't try to figure this out; this is always nil
12008 unless you set it to something else. */);
12009 /* We don't have any way to find this out, so set it to nil
12010 and maybe the user would like to set it to t. */
12011 Vx_no_window_manager
= Qnil
;
12013 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
12014 &Vx_pixel_size_width_font_regexp
,
12015 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
12017 Since Emacs gets width of a font matching with this regexp from
12018 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12019 such a font. This is especially effective for such large fonts as
12020 Chinese, Japanese, and Korean. */);
12021 Vx_pixel_size_width_font_regexp
= Qnil
;
12023 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
12024 doc
: /* Time after which cached images are removed from the cache.
12025 When an image has not been displayed this many seconds, remove it
12026 from the image cache. Value must be an integer or nil with nil
12027 meaning don't clear the cache. */);
12028 Vimage_cache_eviction_delay
= make_number (30 * 60);
12030 #ifdef USE_X_TOOLKIT
12031 Fprovide (intern ("x-toolkit"), Qnil
);
12033 Fprovide (intern ("motif"), Qnil
);
12035 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
12036 doc
: /* Version info for LessTif/Motif. */);
12037 Vmotif_version_string
= build_string (XmVERSION_STRING
);
12038 #endif /* USE_MOTIF */
12039 #endif /* USE_X_TOOLKIT */
12041 defsubr (&Sx_get_resource
);
12043 /* X window properties. */
12044 defsubr (&Sx_change_window_property
);
12045 defsubr (&Sx_delete_window_property
);
12046 defsubr (&Sx_window_property
);
12048 defsubr (&Sxw_display_color_p
);
12049 defsubr (&Sx_display_grayscale_p
);
12050 defsubr (&Sxw_color_defined_p
);
12051 defsubr (&Sxw_color_values
);
12052 defsubr (&Sx_server_max_request_size
);
12053 defsubr (&Sx_server_vendor
);
12054 defsubr (&Sx_server_version
);
12055 defsubr (&Sx_display_pixel_width
);
12056 defsubr (&Sx_display_pixel_height
);
12057 defsubr (&Sx_display_mm_width
);
12058 defsubr (&Sx_display_mm_height
);
12059 defsubr (&Sx_display_screens
);
12060 defsubr (&Sx_display_planes
);
12061 defsubr (&Sx_display_color_cells
);
12062 defsubr (&Sx_display_visual_class
);
12063 defsubr (&Sx_display_backing_store
);
12064 defsubr (&Sx_display_save_under
);
12065 defsubr (&Sx_parse_geometry
);
12066 defsubr (&Sx_create_frame
);
12067 defsubr (&Sx_open_connection
);
12068 defsubr (&Sx_close_connection
);
12069 defsubr (&Sx_display_list
);
12070 defsubr (&Sx_synchronize
);
12071 defsubr (&Sx_focus_frame
);
12072 defsubr (&Sx_backspace_delete_keys_p
);
12074 /* Setting callback functions for fontset handler. */
12075 get_font_info_func
= x_get_font_info
;
12077 #if 0 /* This function pointer doesn't seem to be used anywhere.
12078 And the pointer assigned has the wrong type, anyway. */
12079 list_fonts_func
= x_list_fonts
;
12082 load_font_func
= x_load_font
;
12083 find_ccl_program_func
= x_find_ccl_program
;
12084 query_font_func
= x_query_font
;
12085 set_frame_fontset_func
= x_set_font
;
12086 check_window_system_func
= check_x
;
12089 Qxbm
= intern ("xbm");
12091 QCconversion
= intern (":conversion");
12092 staticpro (&QCconversion
);
12093 QCheuristic_mask
= intern (":heuristic-mask");
12094 staticpro (&QCheuristic_mask
);
12095 QCcolor_symbols
= intern (":color-symbols");
12096 staticpro (&QCcolor_symbols
);
12097 QCascent
= intern (":ascent");
12098 staticpro (&QCascent
);
12099 QCmargin
= intern (":margin");
12100 staticpro (&QCmargin
);
12101 QCrelief
= intern (":relief");
12102 staticpro (&QCrelief
);
12103 Qpostscript
= intern ("postscript");
12104 staticpro (&Qpostscript
);
12105 QCloader
= intern (":loader");
12106 staticpro (&QCloader
);
12107 QCbounding_box
= intern (":bounding-box");
12108 staticpro (&QCbounding_box
);
12109 QCpt_width
= intern (":pt-width");
12110 staticpro (&QCpt_width
);
12111 QCpt_height
= intern (":pt-height");
12112 staticpro (&QCpt_height
);
12113 QCindex
= intern (":index");
12114 staticpro (&QCindex
);
12115 Qpbm
= intern ("pbm");
12119 Qxpm
= intern ("xpm");
12124 Qjpeg
= intern ("jpeg");
12125 staticpro (&Qjpeg
);
12129 Qtiff
= intern ("tiff");
12130 staticpro (&Qtiff
);
12134 Qgif
= intern ("gif");
12139 Qpng
= intern ("png");
12143 defsubr (&Sclear_image_cache
);
12144 defsubr (&Simage_size
);
12145 defsubr (&Simage_mask_p
);
12147 hourglass_atimer
= NULL
;
12148 hourglass_shown_p
= 0;
12150 defsubr (&Sx_show_tip
);
12151 defsubr (&Sx_hide_tip
);
12153 staticpro (&tip_timer
);
12155 staticpro (&tip_frame
);
12157 last_show_tip_args
= Qnil
;
12158 staticpro (&last_show_tip_args
);
12161 defsubr (&Sx_file_dialog
);
12169 image_types
= NULL
;
12170 Vimage_types
= Qnil
;
12172 define_image_type (&xbm_type
);
12173 define_image_type (&gs_type
);
12174 define_image_type (&pbm_type
);
12177 define_image_type (&xpm_type
);
12181 define_image_type (&jpeg_type
);
12185 define_image_type (&tiff_type
);
12189 define_image_type (&gif_type
);
12193 define_image_type (&png_type
);
12197 #endif /* HAVE_X_WINDOWS */