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
;
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 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
1299 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f
)
1301 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1302 store_in_alist (alistptr
, Qwindow_id
,
1303 build_string (buf
));
1304 #ifdef USE_X_TOOLKIT
1305 /* Tooltip frame may not have this widget. */
1306 if (f
->output_data
.x
->widget
)
1308 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1309 store_in_alist (alistptr
, Qouter_window_id
,
1310 build_string (buf
));
1311 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1312 FRAME_SAMPLE_VISIBILITY (f
);
1313 store_in_alist (alistptr
, Qvisibility
,
1314 (FRAME_VISIBLE_P (f
) ? Qt
1315 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1316 store_in_alist (alistptr
, Qdisplay
,
1317 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1319 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1322 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1323 store_in_alist (alistptr
, Qparent_id
, tem
);
1328 /* Gamma-correct COLOR on frame F. */
1331 gamma_correct (f
, color
)
1337 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1338 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1339 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1344 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1345 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1346 allocate the color. Value is zero if COLOR_NAME is invalid, or
1347 no color could be allocated. */
1350 x_defined_color (f
, color_name
, color
, alloc_p
)
1357 Display
*dpy
= FRAME_X_DISPLAY (f
);
1358 Colormap cmap
= FRAME_X_COLORMAP (f
);
1361 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1362 if (success_p
&& alloc_p
)
1363 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1370 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1371 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1372 Signal an error if color can't be allocated. */
1375 x_decode_color (f
, color_name
, mono_color
)
1377 Lisp_Object color_name
;
1382 CHECK_STRING (color_name
);
1384 #if 0 /* Don't do this. It's wrong when we're not using the default
1385 colormap, it makes freeing difficult, and it's probably not
1386 an important optimization. */
1387 if (strcmp (SDATA (color_name
), "black") == 0)
1388 return BLACK_PIX_DEFAULT (f
);
1389 else if (strcmp (SDATA (color_name
), "white") == 0)
1390 return WHITE_PIX_DEFAULT (f
);
1393 /* Return MONO_COLOR for monochrome frames. */
1394 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1397 /* x_defined_color is responsible for coping with failures
1398 by looking for a near-miss. */
1399 if (x_defined_color (f
, SDATA (color_name
), &cdef
, 1))
1402 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1403 Fcons (color_name
, Qnil
)));
1409 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1410 the previous value of that parameter, NEW_VALUE is the new value. */
1413 x_set_line_spacing (f
, new_value
, old_value
)
1415 Lisp_Object new_value
, old_value
;
1417 if (NILP (new_value
))
1418 f
->extra_line_spacing
= 0;
1419 else if (NATNUMP (new_value
))
1420 f
->extra_line_spacing
= XFASTINT (new_value
);
1422 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1423 Fcons (new_value
, Qnil
)));
1424 if (FRAME_VISIBLE_P (f
))
1429 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1430 the previous value of that parameter, NEW_VALUE is the new value.
1431 See also the comment of wait_for_wm in struct x_output. */
1434 x_set_wait_for_wm (f
, new_value
, old_value
)
1436 Lisp_Object new_value
, old_value
;
1438 f
->output_data
.x
->wait_for_wm
= !NILP (new_value
);
1442 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
1443 the previous value of that parameter, NEW_VALUE is the new value. */
1446 x_set_fullscreen (f
, new_value
, old_value
)
1448 Lisp_Object new_value
, old_value
;
1450 if (NILP (new_value
))
1451 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_NONE
;
1452 else if (EQ (new_value
, Qfullboth
))
1453 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_BOTH
;
1454 else if (EQ (new_value
, Qfullwidth
))
1455 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_WIDTH
;
1456 else if (EQ (new_value
, Qfullheight
))
1457 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_HEIGHT
;
1461 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1462 the previous value of that parameter, NEW_VALUE is the new
1466 x_set_screen_gamma (f
, new_value
, old_value
)
1468 Lisp_Object new_value
, old_value
;
1470 if (NILP (new_value
))
1472 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1473 /* The value 0.4545 is the normal viewing gamma. */
1474 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1476 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1477 Fcons (new_value
, Qnil
)));
1479 clear_face_cache (0);
1483 /* Functions called only from `x_set_frame_param'
1484 to set individual parameters.
1486 If FRAME_X_WINDOW (f) is 0,
1487 the frame is being created and its X-window does not exist yet.
1488 In that case, just record the parameter's new value
1489 in the standard place; do not attempt to change the window. */
1492 x_set_foreground_color (f
, arg
, oldval
)
1494 Lisp_Object arg
, oldval
;
1496 struct x_output
*x
= f
->output_data
.x
;
1497 unsigned long fg
, old_fg
;
1499 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1500 old_fg
= x
->foreground_pixel
;
1501 x
->foreground_pixel
= fg
;
1503 if (FRAME_X_WINDOW (f
) != 0)
1505 Display
*dpy
= FRAME_X_DISPLAY (f
);
1508 XSetForeground (dpy
, x
->normal_gc
, fg
);
1509 XSetBackground (dpy
, x
->reverse_gc
, fg
);
1511 if (x
->cursor_pixel
== old_fg
)
1513 unload_color (f
, x
->cursor_pixel
);
1514 x
->cursor_pixel
= x_copy_color (f
, fg
);
1515 XSetBackground (dpy
, x
->cursor_gc
, x
->cursor_pixel
);
1520 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1522 if (FRAME_VISIBLE_P (f
))
1526 unload_color (f
, old_fg
);
1530 x_set_background_color (f
, arg
, oldval
)
1532 Lisp_Object arg
, oldval
;
1534 struct x_output
*x
= f
->output_data
.x
;
1537 bg
= x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1538 unload_color (f
, x
->background_pixel
);
1539 x
->background_pixel
= bg
;
1541 if (FRAME_X_WINDOW (f
) != 0)
1543 Display
*dpy
= FRAME_X_DISPLAY (f
);
1546 XSetBackground (dpy
, x
->normal_gc
, bg
);
1547 XSetForeground (dpy
, x
->reverse_gc
, bg
);
1548 XSetWindowBackground (dpy
, FRAME_X_WINDOW (f
), bg
);
1549 XSetForeground (dpy
, x
->cursor_gc
, bg
);
1551 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1552 toolkit scroll bars. */
1555 for (bar
= FRAME_SCROLL_BARS (f
);
1557 bar
= XSCROLL_BAR (bar
)->next
)
1559 Window window
= SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
));
1560 XSetWindowBackground (dpy
, window
, bg
);
1563 #endif /* USE_TOOLKIT_SCROLL_BARS */
1566 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1568 if (FRAME_VISIBLE_P (f
))
1574 x_set_mouse_color (f
, arg
, oldval
)
1576 Lisp_Object arg
, oldval
;
1578 struct x_output
*x
= f
->output_data
.x
;
1579 Display
*dpy
= FRAME_X_DISPLAY (f
);
1580 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1581 Cursor hourglass_cursor
, horizontal_drag_cursor
;
1583 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1584 unsigned long mask_color
= x
->background_pixel
;
1586 /* Don't let pointers be invisible. */
1587 if (mask_color
== pixel
)
1589 x_free_colors (f
, &pixel
, 1);
1590 pixel
= x_copy_color (f
, x
->foreground_pixel
);
1593 unload_color (f
, x
->mouse_pixel
);
1594 x
->mouse_pixel
= pixel
;
1598 /* It's not okay to crash if the user selects a screwy cursor. */
1599 count
= x_catch_errors (dpy
);
1601 if (!NILP (Vx_pointer_shape
))
1603 CHECK_NUMBER (Vx_pointer_shape
);
1604 cursor
= XCreateFontCursor (dpy
, XINT (Vx_pointer_shape
));
1607 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1608 x_check_errors (dpy
, "bad text pointer cursor: %s");
1610 if (!NILP (Vx_nontext_pointer_shape
))
1612 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1614 = XCreateFontCursor (dpy
, XINT (Vx_nontext_pointer_shape
));
1617 nontext_cursor
= XCreateFontCursor (dpy
, XC_left_ptr
);
1618 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1620 if (!NILP (Vx_hourglass_pointer_shape
))
1622 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1624 = XCreateFontCursor (dpy
, XINT (Vx_hourglass_pointer_shape
));
1627 hourglass_cursor
= XCreateFontCursor (dpy
, XC_watch
);
1628 x_check_errors (dpy
, "bad hourglass pointer cursor: %s");
1630 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1631 if (!NILP (Vx_mode_pointer_shape
))
1633 CHECK_NUMBER (Vx_mode_pointer_shape
);
1634 mode_cursor
= XCreateFontCursor (dpy
, XINT (Vx_mode_pointer_shape
));
1637 mode_cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1638 x_check_errors (dpy
, "bad modeline pointer cursor: %s");
1640 if (!NILP (Vx_sensitive_text_pointer_shape
))
1642 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1644 = XCreateFontCursor (dpy
, XINT (Vx_sensitive_text_pointer_shape
));
1647 cross_cursor
= XCreateFontCursor (dpy
, XC_hand2
);
1649 if (!NILP (Vx_window_horizontal_drag_shape
))
1651 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1652 horizontal_drag_cursor
1653 = XCreateFontCursor (dpy
, XINT (Vx_window_horizontal_drag_shape
));
1656 horizontal_drag_cursor
1657 = XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
1659 /* Check and report errors with the above calls. */
1660 x_check_errors (dpy
, "can't set cursor shape: %s");
1661 x_uncatch_errors (dpy
, count
);
1664 XColor fore_color
, back_color
;
1666 fore_color
.pixel
= x
->mouse_pixel
;
1667 x_query_color (f
, &fore_color
);
1668 back_color
.pixel
= mask_color
;
1669 x_query_color (f
, &back_color
);
1671 XRecolorCursor (dpy
, cursor
, &fore_color
, &back_color
);
1672 XRecolorCursor (dpy
, nontext_cursor
, &fore_color
, &back_color
);
1673 XRecolorCursor (dpy
, mode_cursor
, &fore_color
, &back_color
);
1674 XRecolorCursor (dpy
, cross_cursor
, &fore_color
, &back_color
);
1675 XRecolorCursor (dpy
, hourglass_cursor
, &fore_color
, &back_color
);
1676 XRecolorCursor (dpy
, horizontal_drag_cursor
, &fore_color
, &back_color
);
1679 if (FRAME_X_WINDOW (f
) != 0)
1680 XDefineCursor (dpy
, FRAME_X_WINDOW (f
), cursor
);
1682 if (cursor
!= x
->text_cursor
1683 && x
->text_cursor
!= 0)
1684 XFreeCursor (dpy
, x
->text_cursor
);
1685 x
->text_cursor
= cursor
;
1687 if (nontext_cursor
!= x
->nontext_cursor
1688 && x
->nontext_cursor
!= 0)
1689 XFreeCursor (dpy
, x
->nontext_cursor
);
1690 x
->nontext_cursor
= nontext_cursor
;
1692 if (hourglass_cursor
!= x
->hourglass_cursor
1693 && x
->hourglass_cursor
!= 0)
1694 XFreeCursor (dpy
, x
->hourglass_cursor
);
1695 x
->hourglass_cursor
= hourglass_cursor
;
1697 if (mode_cursor
!= x
->modeline_cursor
1698 && x
->modeline_cursor
!= 0)
1699 XFreeCursor (dpy
, f
->output_data
.x
->modeline_cursor
);
1700 x
->modeline_cursor
= mode_cursor
;
1702 if (cross_cursor
!= x
->cross_cursor
1703 && x
->cross_cursor
!= 0)
1704 XFreeCursor (dpy
, x
->cross_cursor
);
1705 x
->cross_cursor
= cross_cursor
;
1707 if (horizontal_drag_cursor
!= x
->horizontal_drag_cursor
1708 && x
->horizontal_drag_cursor
!= 0)
1709 XFreeCursor (dpy
, x
->horizontal_drag_cursor
);
1710 x
->horizontal_drag_cursor
= horizontal_drag_cursor
;
1715 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1719 x_set_cursor_color (f
, arg
, oldval
)
1721 Lisp_Object arg
, oldval
;
1723 unsigned long fore_pixel
, pixel
;
1724 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1725 struct x_output
*x
= f
->output_data
.x
;
1727 if (!NILP (Vx_cursor_fore_pixel
))
1729 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1730 WHITE_PIX_DEFAULT (f
));
1731 fore_pixel_allocated_p
= 1;
1734 fore_pixel
= x
->background_pixel
;
1736 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1737 pixel_allocated_p
= 1;
1739 /* Make sure that the cursor color differs from the background color. */
1740 if (pixel
== x
->background_pixel
)
1742 if (pixel_allocated_p
)
1744 x_free_colors (f
, &pixel
, 1);
1745 pixel_allocated_p
= 0;
1748 pixel
= x
->mouse_pixel
;
1749 if (pixel
== fore_pixel
)
1751 if (fore_pixel_allocated_p
)
1753 x_free_colors (f
, &fore_pixel
, 1);
1754 fore_pixel_allocated_p
= 0;
1756 fore_pixel
= x
->background_pixel
;
1760 unload_color (f
, x
->cursor_foreground_pixel
);
1761 if (!fore_pixel_allocated_p
)
1762 fore_pixel
= x_copy_color (f
, fore_pixel
);
1763 x
->cursor_foreground_pixel
= fore_pixel
;
1765 unload_color (f
, x
->cursor_pixel
);
1766 if (!pixel_allocated_p
)
1767 pixel
= x_copy_color (f
, pixel
);
1768 x
->cursor_pixel
= pixel
;
1770 if (FRAME_X_WINDOW (f
) != 0)
1773 XSetBackground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, x
->cursor_pixel
);
1774 XSetForeground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, fore_pixel
);
1777 if (FRAME_VISIBLE_P (f
))
1779 x_update_cursor (f
, 0);
1780 x_update_cursor (f
, 1);
1784 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1787 /* Set the border-color of frame F to value described by ARG.
1788 ARG can be a string naming a color.
1789 The border-color is used for the border that is drawn by the X server.
1790 Note that this does not fully take effect if done before
1791 F has an x-window; it must be redone when the window is created.
1793 Note: this is done in two routines because of the way X10 works.
1795 Note: under X11, this is normally the province of the window manager,
1796 and so emacs' border colors may be overridden. */
1799 x_set_border_color (f
, arg
, oldval
)
1801 Lisp_Object arg
, oldval
;
1806 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1807 x_set_border_pixel (f
, pix
);
1808 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1811 /* Set the border-color of frame F to pixel value PIX.
1812 Note that this does not fully take effect if done before
1813 F has an x-window. */
1816 x_set_border_pixel (f
, pix
)
1820 unload_color (f
, f
->output_data
.x
->border_pixel
);
1821 f
->output_data
.x
->border_pixel
= pix
;
1823 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1826 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1827 (unsigned long)pix
);
1830 if (FRAME_VISIBLE_P (f
))
1838 x_set_cursor_type (f
, arg
, oldval
)
1840 Lisp_Object arg
, oldval
;
1842 set_frame_cursor_types (f
, arg
);
1844 /* Make sure the cursor gets redrawn. */
1845 cursor_type_changed
= 1;
1849 x_set_icon_type (f
, arg
, oldval
)
1851 Lisp_Object arg
, oldval
;
1857 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1860 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1865 result
= x_text_icon (f
,
1866 (char *) SDATA ((!NILP (f
->icon_name
)
1870 result
= x_bitmap_icon (f
, arg
);
1875 error ("No icon window available");
1878 XFlush (FRAME_X_DISPLAY (f
));
1882 /* Return non-nil if frame F wants a bitmap icon. */
1890 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1898 x_set_icon_name (f
, arg
, oldval
)
1900 Lisp_Object arg
, oldval
;
1906 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1909 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1914 if (f
->output_data
.x
->icon_bitmap
!= 0)
1919 result
= x_text_icon (f
,
1920 (char *) SDATA ((!NILP (f
->icon_name
)
1929 error ("No icon window available");
1932 XFlush (FRAME_X_DISPLAY (f
));
1937 x_set_font (f
, arg
, oldval
)
1939 Lisp_Object arg
, oldval
;
1942 Lisp_Object fontset_name
;
1944 int old_fontset
= f
->output_data
.x
->fontset
;
1948 fontset_name
= Fquery_fontset (arg
, Qnil
);
1951 result
= (STRINGP (fontset_name
)
1952 ? x_new_fontset (f
, SDATA (fontset_name
))
1953 : x_new_font (f
, SDATA (arg
)));
1956 if (EQ (result
, Qnil
))
1957 error ("Font `%s' is not defined", SDATA (arg
));
1958 else if (EQ (result
, Qt
))
1959 error ("The characters of the given font have varying widths");
1960 else if (STRINGP (result
))
1962 if (STRINGP (fontset_name
))
1964 /* Fontset names are built from ASCII font names, so the
1965 names may be equal despite there was a change. */
1966 if (old_fontset
== f
->output_data
.x
->fontset
)
1969 else if (!NILP (Fequal (result
, oldval
)))
1972 store_frame_param (f
, Qfont
, result
);
1973 recompute_basic_faces (f
);
1978 do_pending_window_change (0);
1980 /* Don't call `face-set-after-frame-default' when faces haven't been
1981 initialized yet. This is the case when called from
1982 Fx_create_frame. In that case, the X widget or window doesn't
1983 exist either, and we can end up in x_report_frame_params with a
1984 null widget which gives a segfault. */
1985 if (FRAME_FACE_CACHE (f
))
1987 XSETFRAME (frame
, f
);
1988 call1 (Qface_set_after_frame_default
, frame
);
1993 x_set_fringe_width (f
, new_value
, old_value
)
1995 Lisp_Object new_value
, old_value
;
1997 x_compute_fringe_widths (f
, 1);
2001 x_set_border_width (f
, arg
, oldval
)
2003 Lisp_Object arg
, oldval
;
2007 if (XINT (arg
) == f
->output_data
.x
->border_width
)
2010 if (FRAME_X_WINDOW (f
) != 0)
2011 error ("Cannot change the border width of a window");
2013 f
->output_data
.x
->border_width
= XINT (arg
);
2017 x_set_internal_border_width (f
, arg
, oldval
)
2019 Lisp_Object arg
, oldval
;
2021 int old
= f
->output_data
.x
->internal_border_width
;
2024 f
->output_data
.x
->internal_border_width
= XINT (arg
);
2025 if (f
->output_data
.x
->internal_border_width
< 0)
2026 f
->output_data
.x
->internal_border_width
= 0;
2028 #ifdef USE_X_TOOLKIT
2029 if (f
->output_data
.x
->edit_widget
)
2030 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
2033 if (f
->output_data
.x
->internal_border_width
== old
)
2036 if (FRAME_X_WINDOW (f
) != 0)
2038 x_set_window_size (f
, 0, f
->width
, f
->height
);
2039 SET_FRAME_GARBAGED (f
);
2040 do_pending_window_change (0);
2043 SET_FRAME_GARBAGED (f
);
2047 x_set_visibility (f
, value
, oldval
)
2049 Lisp_Object value
, oldval
;
2052 XSETFRAME (frame
, f
);
2055 Fmake_frame_invisible (frame
, Qt
);
2056 else if (EQ (value
, Qicon
))
2057 Ficonify_frame (frame
);
2059 Fmake_frame_visible (frame
);
2063 /* Change window heights in windows rooted in WINDOW by N lines. */
2066 x_change_window_heights (window
, n
)
2070 struct window
*w
= XWINDOW (window
);
2072 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
2073 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
2075 if (INTEGERP (w
->orig_top
))
2076 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
2077 if (INTEGERP (w
->orig_height
))
2078 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
2080 /* Handle just the top child in a vertical split. */
2081 if (!NILP (w
->vchild
))
2082 x_change_window_heights (w
->vchild
, n
);
2084 /* Adjust all children in a horizontal split. */
2085 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
2087 w
= XWINDOW (window
);
2088 x_change_window_heights (window
, n
);
2093 x_set_menu_bar_lines (f
, value
, oldval
)
2095 Lisp_Object value
, oldval
;
2098 #ifndef USE_X_TOOLKIT
2099 int olines
= FRAME_MENU_BAR_LINES (f
);
2102 /* Right now, menu bars don't work properly in minibuf-only frames;
2103 most of the commands try to apply themselves to the minibuffer
2104 frame itself, and get an error because you can't switch buffers
2105 in or split the minibuffer window. */
2106 if (FRAME_MINIBUF_ONLY_P (f
))
2109 if (INTEGERP (value
))
2110 nlines
= XINT (value
);
2114 /* Make sure we redisplay all windows in this frame. */
2115 windows_or_buffers_changed
++;
2117 #ifdef USE_X_TOOLKIT
2118 FRAME_MENU_BAR_LINES (f
) = 0;
2121 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2122 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2123 /* Make sure next redisplay shows the menu bar. */
2124 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2128 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2129 free_frame_menubar (f
);
2130 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2132 f
->output_data
.x
->menubar_widget
= 0;
2134 #else /* not USE_X_TOOLKIT */
2135 FRAME_MENU_BAR_LINES (f
) = nlines
;
2136 x_change_window_heights (f
->root_window
, nlines
- olines
);
2137 #endif /* not USE_X_TOOLKIT */
2142 /* Set the number of lines used for the tool bar of frame F to VALUE.
2143 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2144 is the old number of tool bar lines. This function changes the
2145 height of all windows on frame F to match the new tool bar height.
2146 The frame's height doesn't change. */
2149 x_set_tool_bar_lines (f
, value
, oldval
)
2151 Lisp_Object value
, oldval
;
2153 int delta
, nlines
, root_height
;
2154 Lisp_Object root_window
;
2156 /* Treat tool bars like menu bars. */
2157 if (FRAME_MINIBUF_ONLY_P (f
))
2160 /* Use VALUE only if an integer >= 0. */
2161 if (INTEGERP (value
) && XINT (value
) >= 0)
2162 nlines
= XFASTINT (value
);
2166 /* Make sure we redisplay all windows in this frame. */
2167 ++windows_or_buffers_changed
;
2169 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2171 /* Don't resize the tool-bar to more than we have room for. */
2172 root_window
= FRAME_ROOT_WINDOW (f
);
2173 root_height
= XINT (XWINDOW (root_window
)->height
);
2174 if (root_height
- delta
< 1)
2176 delta
= root_height
- 1;
2177 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2180 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2181 x_change_window_heights (root_window
, delta
);
2184 /* We also have to make sure that the internal border at the top of
2185 the frame, below the menu bar or tool bar, is redrawn when the
2186 tool bar disappears. This is so because the internal border is
2187 below the tool bar if one is displayed, but is below the menu bar
2188 if there isn't a tool bar. The tool bar draws into the area
2189 below the menu bar. */
2190 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2194 clear_current_matrices (f
);
2195 updating_frame
= NULL
;
2198 /* If the tool bar gets smaller, the internal border below it
2199 has to be cleared. It was formerly part of the display
2200 of the larger tool bar, and updating windows won't clear it. */
2203 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2204 int width
= PIXEL_WIDTH (f
);
2205 int y
= nlines
* CANON_Y_UNIT (f
);
2208 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2209 0, y
, width
, height
, False
);
2212 if (WINDOWP (f
->tool_bar_window
))
2213 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2218 /* Set the foreground color for scroll bars on frame F to VALUE.
2219 VALUE should be a string, a color name. If it isn't a string or
2220 isn't a valid color name, do nothing. OLDVAL is the old value of
2221 the frame parameter. */
2224 x_set_scroll_bar_foreground (f
, value
, oldval
)
2226 Lisp_Object value
, oldval
;
2228 unsigned long pixel
;
2230 if (STRINGP (value
))
2231 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2235 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2236 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2238 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2239 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2241 /* Remove all scroll bars because they have wrong colors. */
2242 if (condemn_scroll_bars_hook
)
2243 (*condemn_scroll_bars_hook
) (f
);
2244 if (judge_scroll_bars_hook
)
2245 (*judge_scroll_bars_hook
) (f
);
2247 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2253 /* Set the background color for scroll bars on frame F to VALUE VALUE
2254 should be a string, a color name. If it isn't a string or isn't a
2255 valid color name, do nothing. OLDVAL is the old value of the frame
2259 x_set_scroll_bar_background (f
, value
, oldval
)
2261 Lisp_Object value
, oldval
;
2263 unsigned long pixel
;
2265 if (STRINGP (value
))
2266 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2270 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2271 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2273 #ifdef USE_TOOLKIT_SCROLL_BARS
2274 /* Scrollbar shadow colors. */
2275 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
2277 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
2278 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
2280 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
2282 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
2283 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
2285 #endif /* USE_TOOLKIT_SCROLL_BARS */
2287 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2288 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2290 /* Remove all scroll bars because they have wrong colors. */
2291 if (condemn_scroll_bars_hook
)
2292 (*condemn_scroll_bars_hook
) (f
);
2293 if (judge_scroll_bars_hook
)
2294 (*judge_scroll_bars_hook
) (f
);
2296 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2302 /* Encode Lisp string STRING as a text in a format appropriate for
2303 XICCC (X Inter Client Communication Conventions).
2305 If STRING contains only ASCII characters, do no conversion and
2306 return the string data of STRING. Otherwise, encode the text by
2307 CODING_SYSTEM, and return a newly allocated memory area which
2308 should be freed by `xfree' by a caller.
2310 SELECTIONP non-zero means the string is being encoded for an X
2311 selection, so it is safe to run pre-write conversions (which
2314 Store the byte length of resulting text in *TEXT_BYTES.
2316 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2317 which means that the `encoding' of the result can be `STRING'.
2318 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2319 the result should be `COMPOUND_TEXT'. */
2322 x_encode_text (string
, coding_system
, selectionp
, text_bytes
, stringp
)
2323 Lisp_Object string
, coding_system
;
2324 int *text_bytes
, *stringp
;
2327 unsigned char *str
= SDATA (string
);
2328 int chars
= SCHARS (string
);
2329 int bytes
= SBYTES (string
);
2333 struct coding_system coding
;
2334 extern Lisp_Object Qcompound_text_with_extensions
;
2336 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2337 if (charset_info
== 0)
2339 /* No multibyte character in OBJ. We need not encode it. */
2340 *text_bytes
= bytes
;
2345 setup_coding_system (coding_system
, &coding
);
2347 && SYMBOLP (coding
.pre_write_conversion
)
2348 && !NILP (Ffboundp (coding
.pre_write_conversion
)))
2350 string
= run_pre_post_conversion_on_str (string
, &coding
, 1);
2351 str
= SDATA (string
);
2352 chars
= SCHARS (string
);
2353 bytes
= SBYTES (string
);
2355 coding
.src_multibyte
= 1;
2356 coding
.dst_multibyte
= 0;
2357 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2358 if (coding
.type
== coding_type_iso2022
)
2359 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2360 /* We suppress producing escape sequences for composition. */
2361 coding
.composing
= COMPOSITION_DISABLED
;
2362 bufsize
= encoding_buffer_size (&coding
, bytes
);
2363 buf
= (unsigned char *) xmalloc (bufsize
);
2364 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2365 *text_bytes
= coding
.produced
;
2366 *stringp
= (charset_info
== 1
2367 || (!EQ (coding_system
, Qcompound_text
)
2368 && !EQ (coding_system
, Qcompound_text_with_extensions
)));
2373 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2376 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2377 name; if NAME is a string, set F's name to NAME and set
2378 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2380 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2381 suggesting a new name, which lisp code should override; if
2382 F->explicit_name is set, ignore the new name; otherwise, set it. */
2385 x_set_name (f
, name
, explicit)
2390 /* Make sure that requests from lisp code override requests from
2391 Emacs redisplay code. */
2394 /* If we're switching from explicit to implicit, we had better
2395 update the mode lines and thereby update the title. */
2396 if (f
->explicit_name
&& NILP (name
))
2397 update_mode_lines
= 1;
2399 f
->explicit_name
= ! NILP (name
);
2401 else if (f
->explicit_name
)
2404 /* If NAME is nil, set the name to the x_id_name. */
2407 /* Check for no change needed in this very common case
2408 before we do any consing. */
2409 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2412 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2415 CHECK_STRING (name
);
2417 /* Don't change the name if it's already NAME. */
2418 if (! NILP (Fstring_equal (name
, f
->name
)))
2423 /* For setting the frame title, the title parameter should override
2424 the name parameter. */
2425 if (! NILP (f
->title
))
2428 if (FRAME_X_WINDOW (f
))
2433 XTextProperty text
, icon
;
2435 Lisp_Object coding_system
;
2437 coding_system
= Vlocale_coding_system
;
2438 if (NILP (coding_system
))
2439 coding_system
= Qcompound_text
;
2440 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2441 text
.encoding
= (stringp
? XA_STRING
2442 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2444 text
.nitems
= bytes
;
2446 if (NILP (f
->icon_name
))
2452 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2454 icon
.encoding
= (stringp
? XA_STRING
2455 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2457 icon
.nitems
= bytes
;
2459 #ifdef USE_X_TOOLKIT
2460 XSetWMName (FRAME_X_DISPLAY (f
),
2461 XtWindow (f
->output_data
.x
->widget
), &text
);
2462 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2464 #else /* not USE_X_TOOLKIT */
2465 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2466 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2467 #endif /* not USE_X_TOOLKIT */
2468 if (!NILP (f
->icon_name
)
2469 && icon
.value
!= SDATA (f
->icon_name
))
2471 if (text
.value
!= SDATA (name
))
2474 #else /* not HAVE_X11R4 */
2475 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2477 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2479 #endif /* not HAVE_X11R4 */
2484 /* This function should be called when the user's lisp code has
2485 specified a name for the frame; the name will override any set by the
2488 x_explicitly_set_name (f
, arg
, oldval
)
2490 Lisp_Object arg
, oldval
;
2492 x_set_name (f
, arg
, 1);
2495 /* This function should be called by Emacs redisplay code to set the
2496 name; names set this way will never override names set by the user's
2499 x_implicitly_set_name (f
, arg
, oldval
)
2501 Lisp_Object arg
, oldval
;
2503 x_set_name (f
, arg
, 0);
2506 /* Change the title of frame F to NAME.
2507 If NAME is nil, use the frame name as the title.
2509 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2510 name; if NAME is a string, set F's name to NAME and set
2511 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2513 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2514 suggesting a new name, which lisp code should override; if
2515 F->explicit_name is set, ignore the new name; otherwise, set it. */
2518 x_set_title (f
, name
, old_name
)
2520 Lisp_Object name
, old_name
;
2522 /* Don't change the title if it's already NAME. */
2523 if (EQ (name
, f
->title
))
2526 update_mode_lines
= 1;
2533 CHECK_STRING (name
);
2535 if (FRAME_X_WINDOW (f
))
2540 XTextProperty text
, icon
;
2542 Lisp_Object coding_system
;
2544 coding_system
= Vlocale_coding_system
;
2545 if (NILP (coding_system
))
2546 coding_system
= Qcompound_text
;
2547 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2548 text
.encoding
= (stringp
? XA_STRING
2549 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2551 text
.nitems
= bytes
;
2553 if (NILP (f
->icon_name
))
2559 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2561 icon
.encoding
= (stringp
? XA_STRING
2562 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2564 icon
.nitems
= bytes
;
2566 #ifdef USE_X_TOOLKIT
2567 XSetWMName (FRAME_X_DISPLAY (f
),
2568 XtWindow (f
->output_data
.x
->widget
), &text
);
2569 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2571 #else /* not USE_X_TOOLKIT */
2572 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2573 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2574 #endif /* not USE_X_TOOLKIT */
2575 if (!NILP (f
->icon_name
)
2576 && icon
.value
!= SDATA (f
->icon_name
))
2578 if (text
.value
!= SDATA (name
))
2581 #else /* not HAVE_X11R4 */
2582 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2584 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2586 #endif /* not HAVE_X11R4 */
2592 x_set_autoraise (f
, arg
, oldval
)
2594 Lisp_Object arg
, oldval
;
2596 f
->auto_raise
= !EQ (Qnil
, arg
);
2600 x_set_autolower (f
, arg
, oldval
)
2602 Lisp_Object arg
, oldval
;
2604 f
->auto_lower
= !EQ (Qnil
, arg
);
2608 x_set_unsplittable (f
, arg
, oldval
)
2610 Lisp_Object arg
, oldval
;
2612 f
->no_split
= !NILP (arg
);
2616 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2618 Lisp_Object arg
, oldval
;
2620 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2621 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2622 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2623 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2625 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2627 ? vertical_scroll_bar_none
2629 ? vertical_scroll_bar_right
2630 : vertical_scroll_bar_left
);
2632 /* We set this parameter before creating the X window for the
2633 frame, so we can get the geometry right from the start.
2634 However, if the window hasn't been created yet, we shouldn't
2635 call x_set_window_size. */
2636 if (FRAME_X_WINDOW (f
))
2637 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2638 do_pending_window_change (0);
2643 x_set_scroll_bar_width (f
, arg
, oldval
)
2645 Lisp_Object arg
, oldval
;
2647 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2651 #ifdef USE_TOOLKIT_SCROLL_BARS
2652 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2653 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2654 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2655 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2657 /* Make the actual width at least 14 pixels and a multiple of a
2659 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2661 /* Use all of that space (aside from required margins) for the
2663 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2666 if (FRAME_X_WINDOW (f
))
2667 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2668 do_pending_window_change (0);
2670 else if (INTEGERP (arg
) && XINT (arg
) > 0
2671 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2673 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2674 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2676 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2677 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2678 if (FRAME_X_WINDOW (f
))
2679 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2682 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2683 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2684 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2689 /* Subroutines of creating an X frame. */
2691 /* Make sure that Vx_resource_name is set to a reasonable value.
2692 Fix it up, or set it to `emacs' if it is too hopeless. */
2695 validate_x_resource_name ()
2698 /* Number of valid characters in the resource name. */
2700 /* Number of invalid characters in the resource name. */
2705 if (!STRINGP (Vx_resource_class
))
2706 Vx_resource_class
= build_string (EMACS_CLASS
);
2708 if (STRINGP (Vx_resource_name
))
2710 unsigned char *p
= SDATA (Vx_resource_name
);
2713 len
= SBYTES (Vx_resource_name
);
2715 /* Only letters, digits, - and _ are valid in resource names.
2716 Count the valid characters and count the invalid ones. */
2717 for (i
= 0; i
< len
; i
++)
2720 if (! ((c
>= 'a' && c
<= 'z')
2721 || (c
>= 'A' && c
<= 'Z')
2722 || (c
>= '0' && c
<= '9')
2723 || c
== '-' || c
== '_'))
2730 /* Not a string => completely invalid. */
2731 bad_count
= 5, good_count
= 0;
2733 /* If name is valid already, return. */
2737 /* If name is entirely invalid, or nearly so, use `emacs'. */
2739 || (good_count
== 1 && bad_count
> 0))
2741 Vx_resource_name
= build_string ("emacs");
2745 /* Name is partly valid. Copy it and replace the invalid characters
2746 with underscores. */
2748 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2750 for (i
= 0; i
< len
; i
++)
2752 int c
= SREF (new, i
);
2753 if (! ((c
>= 'a' && c
<= 'z')
2754 || (c
>= 'A' && c
<= 'Z')
2755 || (c
>= '0' && c
<= '9')
2756 || c
== '-' || c
== '_'))
2762 extern char *x_get_string_resource ();
2764 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2765 doc
: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2766 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2767 class, where INSTANCE is the name under which Emacs was invoked, or
2768 the name specified by the `-name' or `-rn' command-line arguments.
2770 The optional arguments COMPONENT and SUBCLASS add to the key and the
2771 class, respectively. You must specify both of them or neither.
2772 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2773 and the class is `Emacs.CLASS.SUBCLASS'. */)
2774 (attribute
, class, component
, subclass
)
2775 Lisp_Object attribute
, class, component
, subclass
;
2777 register char *value
;
2783 CHECK_STRING (attribute
);
2784 CHECK_STRING (class);
2786 if (!NILP (component
))
2787 CHECK_STRING (component
);
2788 if (!NILP (subclass
))
2789 CHECK_STRING (subclass
);
2790 if (NILP (component
) != NILP (subclass
))
2791 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2793 validate_x_resource_name ();
2795 /* Allocate space for the components, the dots which separate them,
2796 and the final '\0'. Make them big enough for the worst case. */
2797 name_key
= (char *) alloca (SBYTES (Vx_resource_name
)
2798 + (STRINGP (component
)
2799 ? SBYTES (component
) : 0)
2800 + SBYTES (attribute
)
2803 class_key
= (char *) alloca (SBYTES (Vx_resource_class
)
2805 + (STRINGP (subclass
)
2806 ? SBYTES (subclass
) : 0)
2809 /* Start with emacs.FRAMENAME for the name (the specific one)
2810 and with `Emacs' for the class key (the general one). */
2811 strcpy (name_key
, SDATA (Vx_resource_name
));
2812 strcpy (class_key
, SDATA (Vx_resource_class
));
2814 strcat (class_key
, ".");
2815 strcat (class_key
, SDATA (class));
2817 if (!NILP (component
))
2819 strcat (class_key
, ".");
2820 strcat (class_key
, SDATA (subclass
));
2822 strcat (name_key
, ".");
2823 strcat (name_key
, SDATA (component
));
2826 strcat (name_key
, ".");
2827 strcat (name_key
, SDATA (attribute
));
2829 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2830 name_key
, class_key
);
2832 if (value
!= (char *) 0)
2833 return build_string (value
);
2838 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2841 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2842 struct x_display_info
*dpyinfo
;
2843 Lisp_Object attribute
, class, component
, subclass
;
2845 register char *value
;
2849 CHECK_STRING (attribute
);
2850 CHECK_STRING (class);
2852 if (!NILP (component
))
2853 CHECK_STRING (component
);
2854 if (!NILP (subclass
))
2855 CHECK_STRING (subclass
);
2856 if (NILP (component
) != NILP (subclass
))
2857 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2859 validate_x_resource_name ();
2861 /* Allocate space for the components, the dots which separate them,
2862 and the final '\0'. Make them big enough for the worst case. */
2863 name_key
= (char *) alloca (SBYTES (Vx_resource_name
)
2864 + (STRINGP (component
)
2865 ? SBYTES (component
) : 0)
2866 + SBYTES (attribute
)
2869 class_key
= (char *) alloca (SBYTES (Vx_resource_class
)
2871 + (STRINGP (subclass
)
2872 ? SBYTES (subclass
) : 0)
2875 /* Start with emacs.FRAMENAME for the name (the specific one)
2876 and with `Emacs' for the class key (the general one). */
2877 strcpy (name_key
, SDATA (Vx_resource_name
));
2878 strcpy (class_key
, SDATA (Vx_resource_class
));
2880 strcat (class_key
, ".");
2881 strcat (class_key
, SDATA (class));
2883 if (!NILP (component
))
2885 strcat (class_key
, ".");
2886 strcat (class_key
, SDATA (subclass
));
2888 strcat (name_key
, ".");
2889 strcat (name_key
, SDATA (component
));
2892 strcat (name_key
, ".");
2893 strcat (name_key
, SDATA (attribute
));
2895 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2897 if (value
!= (char *) 0)
2898 return build_string (value
);
2903 /* Used when C code wants a resource value. */
2906 x_get_resource_string (attribute
, class)
2907 char *attribute
, *class;
2911 struct frame
*sf
= SELECTED_FRAME ();
2913 /* Allocate space for the components, the dots which separate them,
2914 and the final '\0'. */
2915 name_key
= (char *) alloca (SBYTES (Vinvocation_name
)
2916 + strlen (attribute
) + 2);
2917 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2918 + strlen (class) + 2);
2920 sprintf (name_key
, "%s.%s",
2921 SDATA (Vinvocation_name
),
2923 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2925 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2926 name_key
, class_key
);
2929 /* Types we might convert a resource string into. */
2939 /* Return the value of parameter PARAM.
2941 First search ALIST, then Vdefault_frame_alist, then the X defaults
2942 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2944 Convert the resource to the type specified by desired_type.
2946 If no default is specified, return Qunbound. If you call
2947 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2948 and don't let it get stored in any Lisp-visible variables! */
2951 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2952 struct x_display_info
*dpyinfo
;
2953 Lisp_Object alist
, param
;
2956 enum resource_types type
;
2958 register Lisp_Object tem
;
2960 tem
= Fassq (param
, alist
);
2962 tem
= Fassq (param
, Vdefault_frame_alist
);
2968 tem
= display_x_get_resource (dpyinfo
,
2969 build_string (attribute
),
2970 build_string (class),
2978 case RES_TYPE_NUMBER
:
2979 return make_number (atoi (SDATA (tem
)));
2981 case RES_TYPE_FLOAT
:
2982 return make_float (atof (SDATA (tem
)));
2984 case RES_TYPE_BOOLEAN
:
2985 tem
= Fdowncase (tem
);
2986 if (!strcmp (SDATA (tem
), "on")
2987 || !strcmp (SDATA (tem
), "true"))
2992 case RES_TYPE_STRING
:
2995 case RES_TYPE_SYMBOL
:
2996 /* As a special case, we map the values `true' and `on'
2997 to Qt, and `false' and `off' to Qnil. */
3000 lower
= Fdowncase (tem
);
3001 if (!strcmp (SDATA (lower
), "on")
3002 || !strcmp (SDATA (lower
), "true"))
3004 else if (!strcmp (SDATA (lower
), "off")
3005 || !strcmp (SDATA (lower
), "false"))
3008 return Fintern (tem
, Qnil
);
3021 /* Like x_get_arg, but also record the value in f->param_alist. */
3024 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
3026 Lisp_Object alist
, param
;
3029 enum resource_types type
;
3033 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
3034 attribute
, class, type
);
3036 store_frame_param (f
, param
, value
);
3041 /* Record in frame F the specified or default value according to ALIST
3042 of the parameter named PROP (a Lisp symbol).
3043 If no value is specified for PROP, look for an X default for XPROP
3044 on the frame named NAME.
3045 If that is not found either, use the value DEFLT. */
3048 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
3055 enum resource_types type
;
3059 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
3060 if (EQ (tem
, Qunbound
))
3062 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3067 /* Record in frame F the specified or default value according to ALIST
3068 of the parameter named PROP (a Lisp symbol). If no value is
3069 specified for PROP, look for an X default for XPROP on the frame
3070 named NAME. If that is not found either, use the value DEFLT. */
3073 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
3082 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3085 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
3086 if (EQ (tem
, Qunbound
))
3088 #ifdef USE_TOOLKIT_SCROLL_BARS
3090 /* See if an X resource for the scroll bar color has been
3092 tem
= display_x_get_resource (dpyinfo
,
3093 build_string (foreground_p
3097 build_string ("verticalScrollBar"),
3101 /* If nothing has been specified, scroll bars will use a
3102 toolkit-dependent default. Because these defaults are
3103 difficult to get at without actually creating a scroll
3104 bar, use nil to indicate that no color has been
3109 #else /* not USE_TOOLKIT_SCROLL_BARS */
3113 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3116 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3122 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3123 doc
: /* Parse an X-style geometry string STRING.
3124 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3125 The properties returned may include `top', `left', `height', and `width'.
3126 The value of `left' or `top' may be an integer,
3127 or a list (+ N) meaning N pixels relative to top/left corner,
3128 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3133 unsigned int width
, height
;
3136 CHECK_STRING (string
);
3138 geometry
= XParseGeometry ((char *) SDATA (string
),
3139 &x
, &y
, &width
, &height
);
3142 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3143 error ("Must specify both x and y position, or neither");
3147 if (geometry
& XValue
)
3149 Lisp_Object element
;
3151 if (x
>= 0 && (geometry
& XNegative
))
3152 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3153 else if (x
< 0 && ! (geometry
& XNegative
))
3154 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3156 element
= Fcons (Qleft
, make_number (x
));
3157 result
= Fcons (element
, result
);
3160 if (geometry
& YValue
)
3162 Lisp_Object element
;
3164 if (y
>= 0 && (geometry
& YNegative
))
3165 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3166 else if (y
< 0 && ! (geometry
& YNegative
))
3167 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3169 element
= Fcons (Qtop
, make_number (y
));
3170 result
= Fcons (element
, result
);
3173 if (geometry
& WidthValue
)
3174 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3175 if (geometry
& HeightValue
)
3176 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3181 /* Calculate the desired size and position of this window,
3182 and return the flags saying which aspects were specified.
3184 This function does not make the coordinates positive. */
3186 #define DEFAULT_ROWS 40
3187 #define DEFAULT_COLS 80
3190 x_figure_window_size (f
, parms
)
3194 register Lisp_Object tem0
, tem1
, tem2
;
3195 long window_prompting
= 0;
3196 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3198 /* Default values if we fall through.
3199 Actually, if that happens we should get
3200 window manager prompting. */
3201 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3202 f
->height
= DEFAULT_ROWS
;
3203 /* Window managers expect that if program-specified
3204 positions are not (0,0), they're intentional, not defaults. */
3205 f
->output_data
.x
->top_pos
= 0;
3206 f
->output_data
.x
->left_pos
= 0;
3208 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3209 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3210 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3211 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3213 if (!EQ (tem0
, Qunbound
))
3215 CHECK_NUMBER (tem0
);
3216 f
->height
= XINT (tem0
);
3218 if (!EQ (tem1
, Qunbound
))
3220 CHECK_NUMBER (tem1
);
3221 SET_FRAME_WIDTH (f
, XINT (tem1
));
3223 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3224 window_prompting
|= USSize
;
3226 window_prompting
|= PSize
;
3229 f
->output_data
.x
->vertical_scroll_bar_extra
3230 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3232 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3234 x_compute_fringe_widths (f
, 0);
3236 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3237 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3239 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3240 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3241 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3242 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3244 if (EQ (tem0
, Qminus
))
3246 f
->output_data
.x
->top_pos
= 0;
3247 window_prompting
|= YNegative
;
3249 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3250 && CONSP (XCDR (tem0
))
3251 && INTEGERP (XCAR (XCDR (tem0
))))
3253 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3254 window_prompting
|= YNegative
;
3256 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3257 && CONSP (XCDR (tem0
))
3258 && INTEGERP (XCAR (XCDR (tem0
))))
3260 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3262 else if (EQ (tem0
, Qunbound
))
3263 f
->output_data
.x
->top_pos
= 0;
3266 CHECK_NUMBER (tem0
);
3267 f
->output_data
.x
->top_pos
= XINT (tem0
);
3268 if (f
->output_data
.x
->top_pos
< 0)
3269 window_prompting
|= YNegative
;
3272 if (EQ (tem1
, Qminus
))
3274 f
->output_data
.x
->left_pos
= 0;
3275 window_prompting
|= XNegative
;
3277 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3278 && CONSP (XCDR (tem1
))
3279 && INTEGERP (XCAR (XCDR (tem1
))))
3281 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3282 window_prompting
|= XNegative
;
3284 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3285 && CONSP (XCDR (tem1
))
3286 && INTEGERP (XCAR (XCDR (tem1
))))
3288 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3290 else if (EQ (tem1
, Qunbound
))
3291 f
->output_data
.x
->left_pos
= 0;
3294 CHECK_NUMBER (tem1
);
3295 f
->output_data
.x
->left_pos
= XINT (tem1
);
3296 if (f
->output_data
.x
->left_pos
< 0)
3297 window_prompting
|= XNegative
;
3300 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3301 window_prompting
|= USPosition
;
3303 window_prompting
|= PPosition
;
3306 if (f
->output_data
.x
->want_fullscreen
!= FULLSCREEN_NONE
)
3311 /* It takes both for some WM:s to place it where we want */
3312 window_prompting
= USPosition
| PPosition
;
3313 x_fullscreen_adjust (f
, &width
, &height
, &top
, &left
);
3316 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3317 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3318 f
->output_data
.x
->left_pos
= left
;
3319 f
->output_data
.x
->top_pos
= top
;
3322 return window_prompting
;
3325 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3328 XSetWMProtocols (dpy
, w
, protocols
, count
)
3335 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3336 if (prop
== None
) return False
;
3337 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3338 (unsigned char *) protocols
, count
);
3341 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3343 #ifdef USE_X_TOOLKIT
3345 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3346 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3347 already be present because of the toolkit (Motif adds some of them,
3348 for example, but Xt doesn't). */
3351 hack_wm_protocols (f
, widget
)
3355 Display
*dpy
= XtDisplay (widget
);
3356 Window w
= XtWindow (widget
);
3357 int need_delete
= 1;
3363 Atom type
, *atoms
= 0;
3365 unsigned long nitems
= 0;
3366 unsigned long bytes_after
;
3368 if ((XGetWindowProperty (dpy
, w
,
3369 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3370 (long)0, (long)100, False
, XA_ATOM
,
3371 &type
, &format
, &nitems
, &bytes_after
,
3372 (unsigned char **) &atoms
)
3374 && format
== 32 && type
== XA_ATOM
)
3378 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3380 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3382 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3385 if (atoms
) XFree ((char *) atoms
);
3391 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3393 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3395 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3397 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3398 XA_ATOM
, 32, PropModeAppend
,
3399 (unsigned char *) props
, count
);
3407 /* Support routines for XIC (X Input Context). */
3411 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3412 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3415 /* Supported XIM styles, ordered by preferenc. */
3417 static XIMStyle supported_xim_styles
[] =
3419 XIMPreeditPosition
| XIMStatusArea
,
3420 XIMPreeditPosition
| XIMStatusNothing
,
3421 XIMPreeditPosition
| XIMStatusNone
,
3422 XIMPreeditNothing
| XIMStatusArea
,
3423 XIMPreeditNothing
| XIMStatusNothing
,
3424 XIMPreeditNothing
| XIMStatusNone
,
3425 XIMPreeditNone
| XIMStatusArea
,
3426 XIMPreeditNone
| XIMStatusNothing
,
3427 XIMPreeditNone
| XIMStatusNone
,
3432 /* Create an X fontset on frame F with base font name
3436 xic_create_xfontset (f
, base_fontname
)
3438 char *base_fontname
;
3441 char **missing_list
;
3445 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3446 base_fontname
, &missing_list
,
3447 &missing_count
, &def_string
);
3449 XFreeStringList (missing_list
);
3451 /* No need to free def_string. */
3456 /* Value is the best input style, given user preferences USER (already
3457 checked to be supported by Emacs), and styles supported by the
3458 input method XIM. */
3461 best_xim_style (user
, xim
)
3467 for (i
= 0; i
< user
->count_styles
; ++i
)
3468 for (j
= 0; j
< xim
->count_styles
; ++j
)
3469 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3470 return user
->supported_styles
[i
];
3472 /* Return the default style. */
3473 return XIMPreeditNothing
| XIMStatusNothing
;
3476 /* Create XIC for frame F. */
3478 static XIMStyle xic_style
;
3481 create_frame_xic (f
)
3486 XFontSet xfs
= NULL
;
3491 xim
= FRAME_X_XIM (f
);
3496 XVaNestedList preedit_attr
;
3497 XVaNestedList status_attr
;
3498 char *base_fontname
;
3501 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3502 spot
.x
= 0; spot
.y
= 1;
3503 /* Create X fontset. */
3504 fontset
= FRAME_FONTSET (f
);
3506 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3509 /* Determine the base fontname from the ASCII font name of
3511 char *ascii_font
= (char *) SDATA (fontset_ascii (fontset
));
3512 char *p
= ascii_font
;
3515 for (i
= 0; *p
; p
++)
3518 /* As the font name doesn't conform to XLFD, we can't
3519 modify it to get a suitable base fontname for the
3521 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3524 int len
= strlen (ascii_font
) + 1;
3527 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3536 base_fontname
= (char *) alloca (len
);
3537 bzero (base_fontname
, len
);
3538 strcpy (base_fontname
, "-*-*-");
3539 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3540 strcat (base_fontname
, "*-*-*-*-*-*-*");
3543 xfs
= xic_create_xfontset (f
, base_fontname
);
3545 /* Determine XIC style. */
3548 XIMStyles supported_list
;
3549 supported_list
.count_styles
= (sizeof supported_xim_styles
3550 / sizeof supported_xim_styles
[0]);
3551 supported_list
.supported_styles
= supported_xim_styles
;
3552 xic_style
= best_xim_style (&supported_list
,
3553 FRAME_X_XIM_STYLES (f
));
3556 preedit_attr
= XVaCreateNestedList (0,
3559 FRAME_FOREGROUND_PIXEL (f
),
3561 FRAME_BACKGROUND_PIXEL (f
),
3562 (xic_style
& XIMPreeditPosition
3567 status_attr
= XVaCreateNestedList (0,
3573 FRAME_FOREGROUND_PIXEL (f
),
3575 FRAME_BACKGROUND_PIXEL (f
),
3578 xic
= XCreateIC (xim
,
3579 XNInputStyle
, xic_style
,
3580 XNClientWindow
, FRAME_X_WINDOW(f
),
3581 XNFocusWindow
, FRAME_X_WINDOW(f
),
3582 XNStatusAttributes
, status_attr
,
3583 XNPreeditAttributes
, preedit_attr
,
3585 XFree (preedit_attr
);
3586 XFree (status_attr
);
3589 FRAME_XIC (f
) = xic
;
3590 FRAME_XIC_STYLE (f
) = xic_style
;
3591 FRAME_XIC_FONTSET (f
) = xfs
;
3595 /* Destroy XIC and free XIC fontset of frame F, if any. */
3601 if (FRAME_XIC (f
) == NULL
)
3604 XDestroyIC (FRAME_XIC (f
));
3605 if (FRAME_XIC_FONTSET (f
))
3606 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3608 FRAME_XIC (f
) = NULL
;
3609 FRAME_XIC_FONTSET (f
) = NULL
;
3613 /* Place preedit area for XIC of window W's frame to specified
3614 pixel position X/Y. X and Y are relative to window W. */
3617 xic_set_preeditarea (w
, x
, y
)
3621 struct frame
*f
= XFRAME (w
->frame
);
3625 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3626 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3627 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3628 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3633 /* Place status area for XIC in bottom right corner of frame F.. */
3636 xic_set_statusarea (f
)
3639 XIC xic
= FRAME_XIC (f
);
3644 /* Negotiate geometry of status area. If input method has existing
3645 status area, use its current size. */
3646 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3647 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3648 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3651 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3652 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3655 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3657 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3658 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3662 area
.width
= needed
->width
;
3663 area
.height
= needed
->height
;
3664 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3665 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3666 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3669 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3670 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3675 /* Set X fontset for XIC of frame F, using base font name
3676 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3679 xic_set_xfontset (f
, base_fontname
)
3681 char *base_fontname
;
3686 xfs
= xic_create_xfontset (f
, base_fontname
);
3688 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3689 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3690 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3691 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3692 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3695 if (FRAME_XIC_FONTSET (f
))
3696 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3697 FRAME_XIC_FONTSET (f
) = xfs
;
3700 #endif /* HAVE_X_I18N */
3704 #ifdef USE_X_TOOLKIT
3706 /* Create and set up the X widget for frame F. */
3709 x_window (f
, window_prompting
, minibuffer_only
)
3711 long window_prompting
;
3712 int minibuffer_only
;
3714 XClassHint class_hints
;
3715 XSetWindowAttributes attributes
;
3716 unsigned long attribute_mask
;
3717 Widget shell_widget
;
3719 Widget frame_widget
;
3725 /* Use the resource name as the top-level widget name
3726 for looking up resources. Make a non-Lisp copy
3727 for the window manager, so GC relocation won't bother it.
3729 Elsewhere we specify the window name for the window manager. */
3732 char *str
= (char *) SDATA (Vx_resource_name
);
3733 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3734 strcpy (f
->namebuf
, str
);
3738 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3739 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3740 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3741 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3742 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3743 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3744 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3745 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3746 applicationShellWidgetClass
,
3747 FRAME_X_DISPLAY (f
), al
, ac
);
3749 f
->output_data
.x
->widget
= shell_widget
;
3750 /* maybe_set_screen_title_format (shell_widget); */
3752 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3753 (widget_value
*) NULL
,
3754 shell_widget
, False
,
3758 (lw_callback
) NULL
);
3761 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3762 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3763 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3764 XtSetValues (pane_widget
, al
, ac
);
3765 f
->output_data
.x
->column_widget
= pane_widget
;
3767 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3768 the emacs screen when changing menubar. This reduces flickering. */
3771 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3772 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3773 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3774 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3775 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3776 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3777 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3778 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3779 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3782 f
->output_data
.x
->edit_widget
= frame_widget
;
3784 XtManageChild (frame_widget
);
3786 /* Do some needed geometry management. */
3789 char *tem
, shell_position
[32];
3792 int extra_borders
= 0;
3794 = (f
->output_data
.x
->menubar_widget
3795 ? (f
->output_data
.x
->menubar_widget
->core
.height
3796 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3799 #if 0 /* Experimentally, we now get the right results
3800 for -geometry -0-0 without this. 24 Aug 96, rms. */
3801 if (FRAME_EXTERNAL_MENU_BAR (f
))
3804 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3805 menubar_size
+= ibw
;
3809 f
->output_data
.x
->menubar_height
= menubar_size
;
3812 /* Motif seems to need this amount added to the sizes
3813 specified for the shell widget. The Athena/Lucid widgets don't.
3814 Both conclusions reached experimentally. -- rms. */
3815 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3816 &extra_borders
, NULL
);
3820 /* Convert our geometry parameters into a geometry string
3822 Note that we do not specify here whether the position
3823 is a user-specified or program-specified one.
3824 We pass that information later, in x_wm_set_size_hints. */
3826 int left
= f
->output_data
.x
->left_pos
;
3827 int xneg
= window_prompting
& XNegative
;
3828 int top
= f
->output_data
.x
->top_pos
;
3829 int yneg
= window_prompting
& YNegative
;
3835 if (window_prompting
& USPosition
)
3836 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3837 PIXEL_WIDTH (f
) + extra_borders
,
3838 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3839 (xneg
? '-' : '+'), left
,
3840 (yneg
? '-' : '+'), top
);
3842 sprintf (shell_position
, "=%dx%d",
3843 PIXEL_WIDTH (f
) + extra_borders
,
3844 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3847 len
= strlen (shell_position
) + 1;
3848 /* We don't free this because we don't know whether
3849 it is safe to free it while the frame exists.
3850 It isn't worth the trouble of arranging to free it
3851 when the frame is deleted. */
3852 tem
= (char *) xmalloc (len
);
3853 strncpy (tem
, shell_position
, len
);
3854 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3855 XtSetValues (shell_widget
, al
, ac
);
3858 XtManageChild (pane_widget
);
3859 XtRealizeWidget (shell_widget
);
3861 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3863 validate_x_resource_name ();
3865 class_hints
.res_name
= (char *) SDATA (Vx_resource_name
);
3866 class_hints
.res_class
= (char *) SDATA (Vx_resource_class
);
3867 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3870 FRAME_XIC (f
) = NULL
;
3872 create_frame_xic (f
);
3876 f
->output_data
.x
->wm_hints
.input
= True
;
3877 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3878 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3879 &f
->output_data
.x
->wm_hints
);
3881 hack_wm_protocols (f
, shell_widget
);
3884 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3887 /* Do a stupid property change to force the server to generate a
3888 PropertyNotify event so that the event_stream server timestamp will
3889 be initialized to something relevant to the time we created the window.
3891 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3892 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3893 XA_ATOM
, 32, PropModeAppend
,
3894 (unsigned char*) NULL
, 0);
3896 /* Make all the standard events reach the Emacs frame. */
3897 attributes
.event_mask
= STANDARD_EVENT_SET
;
3902 /* XIM server might require some X events. */
3903 unsigned long fevent
= NoEventMask
;
3904 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3905 attributes
.event_mask
|= fevent
;
3907 #endif /* HAVE_X_I18N */
3909 attribute_mask
= CWEventMask
;
3910 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3911 attribute_mask
, &attributes
);
3913 XtMapWidget (frame_widget
);
3915 /* x_set_name normally ignores requests to set the name if the
3916 requested name is the same as the current name. This is the one
3917 place where that assumption isn't correct; f->name is set, but
3918 the X server hasn't been told. */
3921 int explicit = f
->explicit_name
;
3923 f
->explicit_name
= 0;
3926 x_set_name (f
, name
, explicit);
3929 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3930 f
->output_data
.x
->text_cursor
);
3934 /* This is a no-op, except under Motif. Make sure main areas are
3935 set to something reasonable, in case we get an error later. */
3936 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3939 #else /* not USE_X_TOOLKIT */
3941 /* Create and set up the X window for frame F. */
3948 XClassHint class_hints
;
3949 XSetWindowAttributes attributes
;
3950 unsigned long attribute_mask
;
3952 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3953 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3954 attributes
.bit_gravity
= StaticGravity
;
3955 attributes
.backing_store
= NotUseful
;
3956 attributes
.save_under
= True
;
3957 attributes
.event_mask
= STANDARD_EVENT_SET
;
3958 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3959 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3964 = XCreateWindow (FRAME_X_DISPLAY (f
),
3965 f
->output_data
.x
->parent_desc
,
3966 f
->output_data
.x
->left_pos
,
3967 f
->output_data
.x
->top_pos
,
3968 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3969 f
->output_data
.x
->border_width
,
3970 CopyFromParent
, /* depth */
3971 InputOutput
, /* class */
3973 attribute_mask
, &attributes
);
3977 create_frame_xic (f
);
3980 /* XIM server might require some X events. */
3981 unsigned long fevent
= NoEventMask
;
3982 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3983 attributes
.event_mask
|= fevent
;
3984 attribute_mask
= CWEventMask
;
3985 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3986 attribute_mask
, &attributes
);
3989 #endif /* HAVE_X_I18N */
3991 validate_x_resource_name ();
3993 class_hints
.res_name
= (char *) SDATA (Vx_resource_name
);
3994 class_hints
.res_class
= (char *) SDATA (Vx_resource_class
);
3995 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3997 /* The menubar is part of the ordinary display;
3998 it does not count in addition to the height of the window. */
3999 f
->output_data
.x
->menubar_height
= 0;
4001 /* This indicates that we use the "Passive Input" input model.
4002 Unless we do this, we don't get the Focus{In,Out} events that we
4003 need to draw the cursor correctly. Accursed bureaucrats.
4004 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
4006 f
->output_data
.x
->wm_hints
.input
= True
;
4007 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
4008 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4009 &f
->output_data
.x
->wm_hints
);
4010 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
4012 /* Request "save yourself" and "delete window" commands from wm. */
4015 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
4016 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
4017 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
4020 /* x_set_name normally ignores requests to set the name if the
4021 requested name is the same as the current name. This is the one
4022 place where that assumption isn't correct; f->name is set, but
4023 the X server hasn't been told. */
4026 int explicit = f
->explicit_name
;
4028 f
->explicit_name
= 0;
4031 x_set_name (f
, name
, explicit);
4034 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4035 f
->output_data
.x
->text_cursor
);
4039 if (FRAME_X_WINDOW (f
) == 0)
4040 error ("Unable to create window");
4043 #endif /* not USE_X_TOOLKIT */
4045 /* Handle the icon stuff for this window. Perhaps later we might
4046 want an x_set_icon_position which can be called interactively as
4054 Lisp_Object icon_x
, icon_y
;
4055 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4057 /* Set the position of the icon. Note that twm groups all
4058 icons in an icon window. */
4059 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4060 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4061 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4063 CHECK_NUMBER (icon_x
);
4064 CHECK_NUMBER (icon_y
);
4066 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4067 error ("Both left and top icon corners of icon must be specified");
4071 if (! EQ (icon_x
, Qunbound
))
4072 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4074 /* Start up iconic or window? */
4075 x_wm_set_window_state
4076 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
4081 x_text_icon (f
, (char *) SDATA ((!NILP (f
->icon_name
)
4088 /* Make the GCs needed for this window, setting the
4089 background, border and mouse colors; also create the
4090 mouse cursor and the gray border tile. */
4092 static char cursor_bits
[] =
4094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4096 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4097 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4104 XGCValues gc_values
;
4108 /* Create the GCs of this frame.
4109 Note that many default values are used. */
4112 gc_values
.font
= f
->output_data
.x
->font
->fid
;
4113 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
4114 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4115 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
4116 f
->output_data
.x
->normal_gc
4117 = XCreateGC (FRAME_X_DISPLAY (f
),
4119 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
4122 /* Reverse video style. */
4123 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4124 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4125 f
->output_data
.x
->reverse_gc
4126 = XCreateGC (FRAME_X_DISPLAY (f
),
4128 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
4131 /* Cursor has cursor-color background, background-color foreground. */
4132 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4133 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
4134 gc_values
.fill_style
= FillOpaqueStippled
;
4136 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4137 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4138 cursor_bits
, 16, 16);
4139 f
->output_data
.x
->cursor_gc
4140 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4141 (GCFont
| GCForeground
| GCBackground
4142 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
4146 f
->output_data
.x
->white_relief
.gc
= 0;
4147 f
->output_data
.x
->black_relief
.gc
= 0;
4149 /* Create the gray border tile used when the pointer is not in
4150 the frame. Since this depends on the frame's pixel values,
4151 this must be done on a per-frame basis. */
4152 f
->output_data
.x
->border_tile
4153 = (XCreatePixmapFromBitmapData
4154 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
4155 gray_bits
, gray_width
, gray_height
,
4156 f
->output_data
.x
->foreground_pixel
,
4157 f
->output_data
.x
->background_pixel
,
4158 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4164 /* Free what was was allocated in x_make_gc. */
4170 Display
*dpy
= FRAME_X_DISPLAY (f
);
4174 if (f
->output_data
.x
->normal_gc
)
4176 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4177 f
->output_data
.x
->normal_gc
= 0;
4180 if (f
->output_data
.x
->reverse_gc
)
4182 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4183 f
->output_data
.x
->reverse_gc
= 0;
4186 if (f
->output_data
.x
->cursor_gc
)
4188 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4189 f
->output_data
.x
->cursor_gc
= 0;
4192 if (f
->output_data
.x
->border_tile
)
4194 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4195 f
->output_data
.x
->border_tile
= 0;
4202 /* Handler for signals raised during x_create_frame and
4203 x_create_top_frame. FRAME is the frame which is partially
4207 unwind_create_frame (frame
)
4210 struct frame
*f
= XFRAME (frame
);
4212 /* If frame is ``official'', nothing to do. */
4213 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4216 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4219 x_free_frame_resources (f
);
4221 /* Check that reference counts are indeed correct. */
4222 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4223 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4231 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4233 doc
: /* Make a new X window, which is called a "frame" in Emacs terms.
4234 Returns an Emacs frame object.
4235 ALIST is an alist of frame parameters.
4236 If the parameters specify that the frame should not have a minibuffer,
4237 and do not specify a specific minibuffer window to use,
4238 then `default-minibuffer-frame' must be a frame whose minibuffer can
4239 be shared by the new frame.
4241 This function is an internal primitive--use `make-frame' instead. */)
4246 Lisp_Object frame
, tem
;
4248 int minibuffer_only
= 0;
4249 long window_prompting
= 0;
4251 int count
= SPECPDL_INDEX ();
4252 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4253 Lisp_Object display
;
4254 struct x_display_info
*dpyinfo
= NULL
;
4260 /* Use this general default value to start with
4261 until we know if this frame has a specified name. */
4262 Vx_resource_name
= Vinvocation_name
;
4264 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4265 if (EQ (display
, Qunbound
))
4267 dpyinfo
= check_x_display_info (display
);
4269 kb
= dpyinfo
->kboard
;
4271 kb
= &the_only_kboard
;
4274 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4276 && ! EQ (name
, Qunbound
)
4278 error ("Invalid frame name--not a string or nil");
4281 Vx_resource_name
= name
;
4283 /* See if parent window is specified. */
4284 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4285 if (EQ (parent
, Qunbound
))
4287 if (! NILP (parent
))
4288 CHECK_NUMBER (parent
);
4290 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4291 /* No need to protect DISPLAY because that's not used after passing
4292 it to make_frame_without_minibuffer. */
4294 GCPRO4 (parms
, parent
, name
, frame
);
4295 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4297 if (EQ (tem
, Qnone
) || NILP (tem
))
4298 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4299 else if (EQ (tem
, Qonly
))
4301 f
= make_minibuffer_frame ();
4302 minibuffer_only
= 1;
4304 else if (WINDOWP (tem
))
4305 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4309 XSETFRAME (frame
, f
);
4311 /* Note that X Windows does support scroll bars. */
4312 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4314 f
->output_method
= output_x_window
;
4315 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4316 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4317 f
->output_data
.x
->icon_bitmap
= -1;
4318 f
->output_data
.x
->fontset
= -1;
4319 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4320 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4321 #ifdef USE_TOOLKIT_SCROLL_BARS
4322 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
4323 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
4324 #endif /* USE_TOOLKIT_SCROLL_BARS */
4325 record_unwind_protect (unwind_create_frame
, frame
);
4328 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4330 if (! STRINGP (f
->icon_name
))
4331 f
->icon_name
= Qnil
;
4333 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4335 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4336 dpyinfo_refcount
= dpyinfo
->reference_count
;
4337 #endif /* GLYPH_DEBUG */
4339 FRAME_KBOARD (f
) = kb
;
4342 /* These colors will be set anyway later, but it's important
4343 to get the color reference counts right, so initialize them! */
4346 struct gcpro gcpro1
;
4348 /* Function x_decode_color can signal an error. Make
4349 sure to initialize color slots so that we won't try
4350 to free colors we haven't allocated. */
4351 f
->output_data
.x
->foreground_pixel
= -1;
4352 f
->output_data
.x
->background_pixel
= -1;
4353 f
->output_data
.x
->cursor_pixel
= -1;
4354 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4355 f
->output_data
.x
->border_pixel
= -1;
4356 f
->output_data
.x
->mouse_pixel
= -1;
4358 black
= build_string ("black");
4360 f
->output_data
.x
->foreground_pixel
4361 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4362 f
->output_data
.x
->background_pixel
4363 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4364 f
->output_data
.x
->cursor_pixel
4365 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4366 f
->output_data
.x
->cursor_foreground_pixel
4367 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4368 f
->output_data
.x
->border_pixel
4369 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4370 f
->output_data
.x
->mouse_pixel
4371 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4375 /* Specify the parent under which to make this X window. */
4379 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4380 f
->output_data
.x
->explicit_parent
= 1;
4384 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4385 f
->output_data
.x
->explicit_parent
= 0;
4388 /* Set the name; the functions to which we pass f expect the name to
4390 if (EQ (name
, Qunbound
) || NILP (name
))
4392 f
->name
= build_string (dpyinfo
->x_id_name
);
4393 f
->explicit_name
= 0;
4398 f
->explicit_name
= 1;
4399 /* use the frame's title when getting resources for this frame. */
4400 specbind (Qx_resource_name
, name
);
4403 /* Extract the window parameters from the supplied values
4404 that are needed to determine window geometry. */
4408 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4411 /* First, try whatever font the caller has specified. */
4414 tem
= Fquery_fontset (font
, Qnil
);
4416 font
= x_new_fontset (f
, SDATA (tem
));
4418 font
= x_new_font (f
, SDATA (font
));
4421 /* Try out a font which we hope has bold and italic variations. */
4422 if (!STRINGP (font
))
4423 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4424 if (!STRINGP (font
))
4425 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4426 if (! STRINGP (font
))
4427 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4428 if (! STRINGP (font
))
4429 /* This was formerly the first thing tried, but it finds too many fonts
4430 and takes too long. */
4431 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4432 /* If those didn't work, look for something which will at least work. */
4433 if (! STRINGP (font
))
4434 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4436 if (! STRINGP (font
))
4437 font
= build_string ("fixed");
4439 x_default_parameter (f
, parms
, Qfont
, font
,
4440 "font", "Font", RES_TYPE_STRING
);
4444 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4445 whereby it fails to get any font. */
4446 xlwmenu_default_font
= f
->output_data
.x
->font
;
4449 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4450 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4452 /* This defaults to 1 in order to match xterm. We recognize either
4453 internalBorderWidth or internalBorder (which is what xterm calls
4455 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4459 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4460 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4461 if (! EQ (value
, Qunbound
))
4462 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4465 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4466 "internalBorderWidth", "internalBorderWidth",
4468 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4469 "verticalScrollBars", "ScrollBars",
4472 /* Also do the stuff which must be set before the window exists. */
4473 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4474 "foreground", "Foreground", RES_TYPE_STRING
);
4475 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4476 "background", "Background", RES_TYPE_STRING
);
4477 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4478 "pointerColor", "Foreground", RES_TYPE_STRING
);
4479 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4480 "cursorColor", "Foreground", RES_TYPE_STRING
);
4481 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4482 "borderColor", "BorderColor", RES_TYPE_STRING
);
4483 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4484 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4485 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4486 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4487 x_default_parameter (f
, parms
, Qleft_fringe
, Qnil
,
4488 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4489 x_default_parameter (f
, parms
, Qright_fringe
, Qnil
,
4490 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4492 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4493 "scrollBarForeground",
4494 "ScrollBarForeground", 1);
4495 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4496 "scrollBarBackground",
4497 "ScrollBarBackground", 0);
4499 /* Init faces before x_default_parameter is called for scroll-bar
4500 parameters because that function calls x_set_scroll_bar_width,
4501 which calls change_frame_size, which calls Fset_window_buffer,
4502 which runs hooks, which call Fvertical_motion. At the end, we
4503 end up in init_iterator with a null face cache, which should not
4505 init_frame_faces (f
);
4507 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4508 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4509 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4510 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4511 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4512 "bufferPredicate", "BufferPredicate",
4514 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4515 "title", "Title", RES_TYPE_STRING
);
4516 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4517 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4518 x_default_parameter (f
, parms
, Qfullscreen
, Qnil
,
4519 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4521 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4523 /* Add the tool-bar height to the initial frame height so that the
4524 user gets a text display area of the size he specified with -g or
4525 via .Xdefaults. Later changes of the tool-bar height don't
4526 change the frame size. This is done so that users can create
4527 tall Emacs frames without having to guess how tall the tool-bar
4529 if (FRAME_TOOL_BAR_LINES (f
))
4531 int margin
, relief
, bar_height
;
4533 relief
= (tool_bar_button_relief
>= 0
4534 ? tool_bar_button_relief
4535 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4537 if (INTEGERP (Vtool_bar_button_margin
)
4538 && XINT (Vtool_bar_button_margin
) > 0)
4539 margin
= XFASTINT (Vtool_bar_button_margin
);
4540 else if (CONSP (Vtool_bar_button_margin
)
4541 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4542 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4543 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4547 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4548 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4551 /* Compute the size of the X window. */
4552 window_prompting
= x_figure_window_size (f
, parms
);
4554 if (window_prompting
& XNegative
)
4556 if (window_prompting
& YNegative
)
4557 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4559 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4563 if (window_prompting
& YNegative
)
4564 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4566 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4569 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4571 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4572 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4574 /* Create the X widget or window. */
4575 #ifdef USE_X_TOOLKIT
4576 x_window (f
, window_prompting
, minibuffer_only
);
4584 /* Now consider the frame official. */
4585 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4586 Vframe_list
= Fcons (frame
, Vframe_list
);
4588 /* We need to do this after creating the X window, so that the
4589 icon-creation functions can say whose icon they're describing. */
4590 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4591 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4593 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4594 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4595 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4596 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4597 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4598 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4599 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4600 "scrollBarWidth", "ScrollBarWidth",
4603 /* Dimensions, especially f->height, must be done via change_frame_size.
4604 Change will not be effected unless different from the current
4610 SET_FRAME_WIDTH (f
, 0);
4611 change_frame_size (f
, height
, width
, 1, 0, 0);
4613 /* Set up faces after all frame parameters are known. This call
4614 also merges in face attributes specified for new frames. If we
4615 don't do this, the `menu' face for instance won't have the right
4616 colors, and the menu bar won't appear in the specified colors for
4618 call1 (Qface_set_after_frame_default
, frame
);
4620 #ifdef USE_X_TOOLKIT
4621 /* Create the menu bar. */
4622 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4624 /* If this signals an error, we haven't set size hints for the
4625 frame and we didn't make it visible. */
4626 initialize_frame_menubar (f
);
4628 /* This is a no-op, except under Motif where it arranges the
4629 main window for the widgets on it. */
4630 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4631 f
->output_data
.x
->menubar_widget
,
4632 f
->output_data
.x
->edit_widget
);
4634 #endif /* USE_X_TOOLKIT */
4636 /* Tell the server what size and position, etc, we want, and how
4637 badly we want them. This should be done after we have the menu
4638 bar so that its size can be taken into account. */
4640 x_wm_set_size_hint (f
, window_prompting
, 0);
4643 /* Make the window appear on the frame and enable display, unless
4644 the caller says not to. However, with explicit parent, Emacs
4645 cannot control visibility, so don't try. */
4646 if (! f
->output_data
.x
->explicit_parent
)
4648 Lisp_Object visibility
;
4650 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4652 if (EQ (visibility
, Qunbound
))
4655 if (EQ (visibility
, Qicon
))
4656 x_iconify_frame (f
);
4657 else if (! NILP (visibility
))
4658 x_make_frame_visible (f
);
4660 /* Must have been Qnil. */
4666 /* Make sure windows on this frame appear in calls to next-window
4667 and similar functions. */
4668 Vwindow_list
= Qnil
;
4670 return unbind_to (count
, frame
);
4674 /* FRAME is used only to get a handle on the X display. We don't pass the
4675 display info directly because we're called from frame.c, which doesn't
4676 know about that structure. */
4679 x_get_focus_frame (frame
)
4680 struct frame
*frame
;
4682 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4684 if (! dpyinfo
->x_focus_frame
)
4687 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4692 /* In certain situations, when the window manager follows a
4693 click-to-focus policy, there seems to be no way around calling
4694 XSetInputFocus to give another frame the input focus .
4696 In an ideal world, XSetInputFocus should generally be avoided so
4697 that applications don't interfere with the window manager's focus
4698 policy. But I think it's okay to use when it's clearly done
4699 following a user-command. */
4701 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4702 doc
: /* Set the input focus to FRAME.
4703 FRAME nil means use the selected frame. */)
4707 struct frame
*f
= check_x_frame (frame
);
4708 Display
*dpy
= FRAME_X_DISPLAY (f
);
4712 count
= x_catch_errors (dpy
);
4713 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4714 RevertToParent
, CurrentTime
);
4715 x_uncatch_errors (dpy
, count
);
4722 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4723 doc
: /* Internal function called by `color-defined-p', which see. */)
4725 Lisp_Object color
, frame
;
4728 FRAME_PTR f
= check_x_frame (frame
);
4730 CHECK_STRING (color
);
4732 if (x_defined_color (f
, SDATA (color
), &foo
, 0))
4738 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4739 doc
: /* Internal function called by `color-values', which see. */)
4741 Lisp_Object color
, frame
;
4744 FRAME_PTR f
= check_x_frame (frame
);
4746 CHECK_STRING (color
);
4748 if (x_defined_color (f
, SDATA (color
), &foo
, 0))
4752 rgb
[0] = make_number (foo
.red
);
4753 rgb
[1] = make_number (foo
.green
);
4754 rgb
[2] = make_number (foo
.blue
);
4755 return Flist (3, rgb
);
4761 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4762 doc
: /* Internal function called by `display-color-p', which see. */)
4764 Lisp_Object display
;
4766 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4768 if (dpyinfo
->n_planes
<= 2)
4771 switch (dpyinfo
->visual
->class)
4784 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4786 doc
: /* Return t if the X display supports shades of gray.
4787 Note that color displays do support shades of gray.
4788 The optional argument DISPLAY specifies which display to ask about.
4789 DISPLAY should be either a frame or a display name (a string).
4790 If omitted or nil, that stands for the selected frame's display. */)
4792 Lisp_Object display
;
4794 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4796 if (dpyinfo
->n_planes
<= 1)
4799 switch (dpyinfo
->visual
->class)
4814 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4816 doc
: /* Returns the width in pixels of the X display DISPLAY.
4817 The optional argument DISPLAY specifies which display to ask about.
4818 DISPLAY should be either a frame or a display name (a string).
4819 If omitted or nil, that stands for the selected frame's display. */)
4821 Lisp_Object display
;
4823 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4825 return make_number (dpyinfo
->width
);
4828 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4829 Sx_display_pixel_height
, 0, 1, 0,
4830 doc
: /* Returns the height in pixels of the X display DISPLAY.
4831 The optional argument DISPLAY specifies which display to ask about.
4832 DISPLAY should be either a frame or a display name (a string).
4833 If omitted or nil, that stands for the selected frame's display. */)
4835 Lisp_Object display
;
4837 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4839 return make_number (dpyinfo
->height
);
4842 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4844 doc
: /* Returns the number of bitplanes of the X display DISPLAY.
4845 The optional argument DISPLAY specifies which display to ask about.
4846 DISPLAY should be either a frame or a display name (a string).
4847 If omitted or nil, that stands for the selected frame's display. */)
4849 Lisp_Object display
;
4851 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4853 return make_number (dpyinfo
->n_planes
);
4856 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4858 doc
: /* Returns the number of color cells of the X display DISPLAY.
4859 The optional argument DISPLAY specifies which display to ask about.
4860 DISPLAY should be either a frame or a display name (a string).
4861 If omitted or nil, that stands for the selected frame's display. */)
4863 Lisp_Object display
;
4865 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4867 return make_number (DisplayCells (dpyinfo
->display
,
4868 XScreenNumberOfScreen (dpyinfo
->screen
)));
4871 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4872 Sx_server_max_request_size
,
4874 doc
: /* Returns the maximum request size of the X server of display DISPLAY.
4875 The optional argument DISPLAY specifies which display to ask about.
4876 DISPLAY should be either a frame or a display name (a string).
4877 If omitted or nil, that stands for the selected frame's display. */)
4879 Lisp_Object display
;
4881 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4883 return make_number (MAXREQUEST (dpyinfo
->display
));
4886 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4887 doc
: /* Returns the vendor ID string of the X server of display DISPLAY.
4888 The optional argument DISPLAY specifies which display to ask about.
4889 DISPLAY should be either a frame or a display name (a string).
4890 If omitted or nil, that stands for the selected frame's display. */)
4892 Lisp_Object display
;
4894 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4895 char *vendor
= ServerVendor (dpyinfo
->display
);
4897 if (! vendor
) vendor
= "";
4898 return build_string (vendor
);
4901 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4902 doc
: /* Returns the version numbers of the X server of display DISPLAY.
4903 The value is a list of three integers: the major and minor
4904 version numbers of the X Protocol in use, and the vendor-specific release
4905 number. See also the function `x-server-vendor'.
4907 The optional argument DISPLAY specifies which display to ask about.
4908 DISPLAY should be either a frame or a display name (a string).
4909 If omitted or nil, that stands for the selected frame's display. */)
4911 Lisp_Object display
;
4913 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4914 Display
*dpy
= dpyinfo
->display
;
4916 return Fcons (make_number (ProtocolVersion (dpy
)),
4917 Fcons (make_number (ProtocolRevision (dpy
)),
4918 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4921 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4922 doc
: /* Return the number of screens on the X server of display DISPLAY.
4923 The optional argument DISPLAY specifies which display to ask about.
4924 DISPLAY should be either a frame or a display name (a string).
4925 If omitted or nil, that stands for the selected frame's display. */)
4927 Lisp_Object display
;
4929 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4931 return make_number (ScreenCount (dpyinfo
->display
));
4934 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4935 doc
: /* Return the height in millimeters of the X display DISPLAY.
4936 The optional argument DISPLAY specifies which display to ask about.
4937 DISPLAY should be either a frame or a display name (a string).
4938 If omitted or nil, that stands for the selected frame's display. */)
4940 Lisp_Object display
;
4942 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4944 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4947 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4948 doc
: /* Return the width in millimeters of the X display DISPLAY.
4949 The optional argument DISPLAY specifies which display to ask about.
4950 DISPLAY should be either a frame or a display name (a string).
4951 If omitted or nil, that stands for the selected frame's display. */)
4953 Lisp_Object display
;
4955 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4957 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4960 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4961 Sx_display_backing_store
, 0, 1, 0,
4962 doc
: /* Returns an indication of whether X display DISPLAY does backing store.
4963 The value may be `always', `when-mapped', or `not-useful'.
4964 The optional argument DISPLAY specifies which display to ask about.
4965 DISPLAY should be either a frame or a display name (a string).
4966 If omitted or nil, that stands for the selected frame's display. */)
4968 Lisp_Object display
;
4970 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4973 switch (DoesBackingStore (dpyinfo
->screen
))
4976 result
= intern ("always");
4980 result
= intern ("when-mapped");
4984 result
= intern ("not-useful");
4988 error ("Strange value for BackingStore parameter of screen");
4995 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4996 Sx_display_visual_class
, 0, 1, 0,
4997 doc
: /* Return the visual class of the X display DISPLAY.
4998 The value is one of the symbols `static-gray', `gray-scale',
4999 `static-color', `pseudo-color', `true-color', or `direct-color'.
5001 The optional argument DISPLAY specifies which display to ask about.
5002 DISPLAY should be either a frame or a display name (a string).
5003 If omitted or nil, that stands for the selected frame's display. */)
5005 Lisp_Object display
;
5007 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5010 switch (dpyinfo
->visual
->class)
5013 result
= intern ("static-gray");
5016 result
= intern ("gray-scale");
5019 result
= intern ("static-color");
5022 result
= intern ("pseudo-color");
5025 result
= intern ("true-color");
5028 result
= intern ("direct-color");
5031 error ("Display has an unknown visual class");
5038 DEFUN ("x-display-save-under", Fx_display_save_under
,
5039 Sx_display_save_under
, 0, 1, 0,
5040 doc
: /* Returns t if the X display DISPLAY supports the save-under feature.
5041 The optional argument DISPLAY specifies which display to ask about.
5042 DISPLAY should be either a frame or a display name (a string).
5043 If omitted or nil, that stands for the selected frame's display. */)
5045 Lisp_Object display
;
5047 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5049 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
5057 register struct frame
*f
;
5059 return PIXEL_WIDTH (f
);
5064 register struct frame
*f
;
5066 return PIXEL_HEIGHT (f
);
5071 register struct frame
*f
;
5073 return FONT_WIDTH (f
->output_data
.x
->font
);
5078 register struct frame
*f
;
5080 return f
->output_data
.x
->line_height
;
5085 register struct frame
*f
;
5087 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
5092 /************************************************************************
5094 ************************************************************************/
5097 /* Mapping visual names to visuals. */
5099 static struct visual_class
5106 {"StaticGray", StaticGray
},
5107 {"GrayScale", GrayScale
},
5108 {"StaticColor", StaticColor
},
5109 {"PseudoColor", PseudoColor
},
5110 {"TrueColor", TrueColor
},
5111 {"DirectColor", DirectColor
},
5116 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5118 /* Value is the screen number of screen SCR. This is a substitute for
5119 the X function with the same name when that doesn't exist. */
5122 XScreenNumberOfScreen (scr
)
5123 register Screen
*scr
;
5125 Display
*dpy
= scr
->display
;
5128 for (i
= 0; i
< dpy
->nscreens
; ++i
)
5129 if (scr
== dpy
->screens
+ i
)
5135 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5138 /* Select the visual that should be used on display DPYINFO. Set
5139 members of DPYINFO appropriately. Called from x_term_init. */
5142 select_visual (dpyinfo
)
5143 struct x_display_info
*dpyinfo
;
5145 Display
*dpy
= dpyinfo
->display
;
5146 Screen
*screen
= dpyinfo
->screen
;
5149 /* See if a visual is specified. */
5150 value
= display_x_get_resource (dpyinfo
,
5151 build_string ("visualClass"),
5152 build_string ("VisualClass"),
5154 if (STRINGP (value
))
5156 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5157 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5158 depth, a decimal number. NAME is compared with case ignored. */
5159 char *s
= (char *) alloca (SBYTES (value
) + 1);
5164 strcpy (s
, SDATA (value
));
5165 dash
= index (s
, '-');
5168 dpyinfo
->n_planes
= atoi (dash
+ 1);
5172 /* We won't find a matching visual with depth 0, so that
5173 an error will be printed below. */
5174 dpyinfo
->n_planes
= 0;
5176 /* Determine the visual class. */
5177 for (i
= 0; visual_classes
[i
].name
; ++i
)
5178 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5180 class = visual_classes
[i
].class;
5184 /* Look up a matching visual for the specified class. */
5186 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5187 dpyinfo
->n_planes
, class, &vinfo
))
5188 fatal ("Invalid visual specification `%s'", SDATA (value
));
5190 dpyinfo
->visual
= vinfo
.visual
;
5195 XVisualInfo
*vinfo
, vinfo_template
;
5197 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5200 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5202 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5204 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5205 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5206 &vinfo_template
, &n_visuals
);
5208 fatal ("Can't get proper X visual info");
5210 dpyinfo
->n_planes
= vinfo
->depth
;
5211 XFree ((char *) vinfo
);
5216 /* Return the X display structure for the display named NAME.
5217 Open a new connection if necessary. */
5219 struct x_display_info
*
5220 x_display_info_for_name (name
)
5224 struct x_display_info
*dpyinfo
;
5226 CHECK_STRING (name
);
5228 if (! EQ (Vwindow_system
, intern ("x")))
5229 error ("Not using X Windows");
5231 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5233 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5236 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5241 /* Use this general default value to start with. */
5242 Vx_resource_name
= Vinvocation_name
;
5244 validate_x_resource_name ();
5246 dpyinfo
= x_term_init (name
, (char *)0,
5247 (char *) SDATA (Vx_resource_name
));
5250 error ("Cannot connect to X server %s", SDATA (name
));
5253 XSETFASTINT (Vwindow_system_version
, 11);
5259 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5261 doc
: /* Open a connection to an X server.
5262 DISPLAY is the name of the display to connect to.
5263 Optional second arg XRM-STRING is a string of resources in xrdb format.
5264 If the optional third arg MUST-SUCCEED is non-nil,
5265 terminate Emacs if we can't open the connection. */)
5266 (display
, xrm_string
, must_succeed
)
5267 Lisp_Object display
, xrm_string
, must_succeed
;
5269 unsigned char *xrm_option
;
5270 struct x_display_info
*dpyinfo
;
5272 CHECK_STRING (display
);
5273 if (! NILP (xrm_string
))
5274 CHECK_STRING (xrm_string
);
5276 if (! EQ (Vwindow_system
, intern ("x")))
5277 error ("Not using X Windows");
5279 if (! NILP (xrm_string
))
5280 xrm_option
= (unsigned char *) SDATA (xrm_string
);
5282 xrm_option
= (unsigned char *) 0;
5284 validate_x_resource_name ();
5286 /* This is what opens the connection and sets x_current_display.
5287 This also initializes many symbols, such as those used for input. */
5288 dpyinfo
= x_term_init (display
, xrm_option
,
5289 (char *) SDATA (Vx_resource_name
));
5293 if (!NILP (must_succeed
))
5294 fatal ("Cannot connect to X server %s.\n\
5295 Check the DISPLAY environment variable or use `-d'.\n\
5296 Also use the `xauth' program to verify that you have the proper\n\
5297 authorization information needed to connect the X server.\n\
5298 An insecure way to solve the problem may be to use `xhost'.\n",
5301 error ("Cannot connect to X server %s", SDATA (display
));
5306 XSETFASTINT (Vwindow_system_version
, 11);
5310 DEFUN ("x-close-connection", Fx_close_connection
,
5311 Sx_close_connection
, 1, 1, 0,
5312 doc
: /* Close the connection to DISPLAY's X server.
5313 For DISPLAY, specify either a frame or a display name (a string).
5314 If DISPLAY is nil, that stands for the selected frame's display. */)
5316 Lisp_Object display
;
5318 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5321 if (dpyinfo
->reference_count
> 0)
5322 error ("Display still has frames on it");
5325 /* Free the fonts in the font table. */
5326 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5327 if (dpyinfo
->font_table
[i
].name
)
5329 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5330 xfree (dpyinfo
->font_table
[i
].full_name
);
5331 xfree (dpyinfo
->font_table
[i
].name
);
5332 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5335 x_destroy_all_bitmaps (dpyinfo
);
5336 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5338 #ifdef USE_X_TOOLKIT
5339 XtCloseDisplay (dpyinfo
->display
);
5341 XCloseDisplay (dpyinfo
->display
);
5344 x_delete_display (dpyinfo
);
5350 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5351 doc
: /* Return the list of display names that Emacs has connections to. */)
5354 Lisp_Object tail
, result
;
5357 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5358 result
= Fcons (XCAR (XCAR (tail
)), result
);
5363 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5364 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5365 If ON is nil, allow buffering of requests.
5366 Turning on synchronization prohibits the Xlib routines from buffering
5367 requests and seriously degrades performance, but makes debugging much
5369 The optional second argument DISPLAY specifies which display to act on.
5370 DISPLAY should be either a frame or a display name (a string).
5371 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5373 Lisp_Object display
, on
;
5375 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5377 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5382 /* Wait for responses to all X commands issued so far for frame F. */
5389 XSync (FRAME_X_DISPLAY (f
), False
);
5394 /***********************************************************************
5396 ***********************************************************************/
5398 /* Value is the number of elements of vector VECTOR. */
5400 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5402 /* List of supported image types. Use define_image_type to add new
5403 types. Use lookup_image_type to find a type for a given symbol. */
5405 static struct image_type
*image_types
;
5407 /* The symbol `image' which is the car of the lists used to represent
5410 extern Lisp_Object Qimage
;
5412 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5418 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5419 extern Lisp_Object QCdata
, QCtype
;
5420 Lisp_Object QCascent
, QCmargin
, QCrelief
;
5421 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5422 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5424 /* Other symbols. */
5426 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5428 /* Time in seconds after which images should be removed from the cache
5429 if not displayed. */
5431 Lisp_Object Vimage_cache_eviction_delay
;
5433 /* Function prototypes. */
5435 static void define_image_type
P_ ((struct image_type
*type
));
5436 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5437 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5438 static void x_laplace
P_ ((struct frame
*, struct image
*));
5439 static void x_emboss
P_ ((struct frame
*, struct image
*));
5440 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5444 /* Define a new image type from TYPE. This adds a copy of TYPE to
5445 image_types and adds the symbol *TYPE->type to Vimage_types. */
5448 define_image_type (type
)
5449 struct image_type
*type
;
5451 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5452 The initialized data segment is read-only. */
5453 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5454 bcopy (type
, p
, sizeof *p
);
5455 p
->next
= image_types
;
5457 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5461 /* Look up image type SYMBOL, and return a pointer to its image_type
5462 structure. Value is null if SYMBOL is not a known image type. */
5464 static INLINE
struct image_type
*
5465 lookup_image_type (symbol
)
5468 struct image_type
*type
;
5470 for (type
= image_types
; type
; type
= type
->next
)
5471 if (EQ (symbol
, *type
->type
))
5478 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5479 valid image specification is a list whose car is the symbol
5480 `image', and whose rest is a property list. The property list must
5481 contain a value for key `:type'. That value must be the name of a
5482 supported image type. The rest of the property list depends on the
5486 valid_image_p (object
)
5491 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5495 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5496 if (EQ (XCAR (tem
), QCtype
))
5499 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5501 struct image_type
*type
;
5502 type
= lookup_image_type (XCAR (tem
));
5504 valid_p
= type
->valid_p (object
);
5515 /* Log error message with format string FORMAT and argument ARG.
5516 Signaling an error, e.g. when an image cannot be loaded, is not a
5517 good idea because this would interrupt redisplay, and the error
5518 message display would lead to another redisplay. This function
5519 therefore simply displays a message. */
5522 image_error (format
, arg1
, arg2
)
5524 Lisp_Object arg1
, arg2
;
5526 add_to_log (format
, arg1
, arg2
);
5531 /***********************************************************************
5532 Image specifications
5533 ***********************************************************************/
5535 enum image_value_type
5537 IMAGE_DONT_CHECK_VALUE_TYPE
,
5539 IMAGE_STRING_OR_NIL_VALUE
,
5541 IMAGE_POSITIVE_INTEGER_VALUE
,
5542 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5543 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5545 IMAGE_INTEGER_VALUE
,
5546 IMAGE_FUNCTION_VALUE
,
5551 /* Structure used when parsing image specifications. */
5553 struct image_keyword
5555 /* Name of keyword. */
5558 /* The type of value allowed. */
5559 enum image_value_type type
;
5561 /* Non-zero means key must be present. */
5564 /* Used to recognize duplicate keywords in a property list. */
5567 /* The value that was found. */
5572 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5574 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5577 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5578 has the format (image KEYWORD VALUE ...). One of the keyword/
5579 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5580 image_keywords structures of size NKEYWORDS describing other
5581 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5584 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5586 struct image_keyword
*keywords
;
5593 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5596 plist
= XCDR (spec
);
5597 while (CONSP (plist
))
5599 Lisp_Object key
, value
;
5601 /* First element of a pair must be a symbol. */
5603 plist
= XCDR (plist
);
5607 /* There must follow a value. */
5610 value
= XCAR (plist
);
5611 plist
= XCDR (plist
);
5613 /* Find key in KEYWORDS. Error if not found. */
5614 for (i
= 0; i
< nkeywords
; ++i
)
5615 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
5621 /* Record that we recognized the keyword. If a keywords
5622 was found more than once, it's an error. */
5623 keywords
[i
].value
= value
;
5624 ++keywords
[i
].count
;
5626 if (keywords
[i
].count
> 1)
5629 /* Check type of value against allowed type. */
5630 switch (keywords
[i
].type
)
5632 case IMAGE_STRING_VALUE
:
5633 if (!STRINGP (value
))
5637 case IMAGE_STRING_OR_NIL_VALUE
:
5638 if (!STRINGP (value
) && !NILP (value
))
5642 case IMAGE_SYMBOL_VALUE
:
5643 if (!SYMBOLP (value
))
5647 case IMAGE_POSITIVE_INTEGER_VALUE
:
5648 if (!INTEGERP (value
) || XINT (value
) <= 0)
5652 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5653 if (INTEGERP (value
) && XINT (value
) >= 0)
5656 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5657 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5661 case IMAGE_ASCENT_VALUE
:
5662 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5664 else if (INTEGERP (value
)
5665 && XINT (value
) >= 0
5666 && XINT (value
) <= 100)
5670 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5671 if (!INTEGERP (value
) || XINT (value
) < 0)
5675 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5678 case IMAGE_FUNCTION_VALUE
:
5679 value
= indirect_function (value
);
5681 || COMPILEDP (value
)
5682 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5686 case IMAGE_NUMBER_VALUE
:
5687 if (!INTEGERP (value
) && !FLOATP (value
))
5691 case IMAGE_INTEGER_VALUE
:
5692 if (!INTEGERP (value
))
5696 case IMAGE_BOOL_VALUE
:
5697 if (!NILP (value
) && !EQ (value
, Qt
))
5706 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5710 /* Check that all mandatory fields are present. */
5711 for (i
= 0; i
< nkeywords
; ++i
)
5712 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5715 return NILP (plist
);
5719 /* Return the value of KEY in image specification SPEC. Value is nil
5720 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5721 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5724 image_spec_value (spec
, key
, found
)
5725 Lisp_Object spec
, key
;
5730 xassert (valid_image_p (spec
));
5732 for (tail
= XCDR (spec
);
5733 CONSP (tail
) && CONSP (XCDR (tail
));
5734 tail
= XCDR (XCDR (tail
)))
5736 if (EQ (XCAR (tail
), key
))
5740 return XCAR (XCDR (tail
));
5750 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5751 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5752 PIXELS non-nil means return the size in pixels, otherwise return the
5753 size in canonical character units.
5754 FRAME is the frame on which the image will be displayed. FRAME nil
5755 or omitted means use the selected frame. */)
5756 (spec
, pixels
, frame
)
5757 Lisp_Object spec
, pixels
, frame
;
5762 if (valid_image_p (spec
))
5764 struct frame
*f
= check_x_frame (frame
);
5765 int id
= lookup_image (f
, spec
);
5766 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5767 int width
= img
->width
+ 2 * img
->hmargin
;
5768 int height
= img
->height
+ 2 * img
->vmargin
;
5771 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5772 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5774 size
= Fcons (make_number (width
), make_number (height
));
5777 error ("Invalid image specification");
5783 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5784 doc
: /* Return t if image SPEC has a mask bitmap.
5785 FRAME is the frame on which the image will be displayed. FRAME nil
5786 or omitted means use the selected frame. */)
5788 Lisp_Object spec
, frame
;
5793 if (valid_image_p (spec
))
5795 struct frame
*f
= check_x_frame (frame
);
5796 int id
= lookup_image (f
, spec
);
5797 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5802 error ("Invalid image specification");
5809 /***********************************************************************
5810 Image type independent image structures
5811 ***********************************************************************/
5813 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5814 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5817 /* Allocate and return a new image structure for image specification
5818 SPEC. SPEC has a hash value of HASH. */
5820 static struct image
*
5821 make_image (spec
, hash
)
5825 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5827 xassert (valid_image_p (spec
));
5828 bzero (img
, sizeof *img
);
5829 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5830 xassert (img
->type
!= NULL
);
5832 img
->data
.lisp_val
= Qnil
;
5833 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5839 /* Free image IMG which was used on frame F, including its resources. */
5848 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5850 /* Remove IMG from the hash table of its cache. */
5852 img
->prev
->next
= img
->next
;
5854 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5857 img
->next
->prev
= img
->prev
;
5859 c
->images
[img
->id
] = NULL
;
5861 /* Free resources, then free IMG. */
5862 img
->type
->free (f
, img
);
5868 /* Prepare image IMG for display on frame F. Must be called before
5869 drawing an image. */
5872 prepare_image_for_display (f
, img
)
5878 /* We're about to display IMG, so set its timestamp to `now'. */
5880 img
->timestamp
= EMACS_SECS (t
);
5882 /* If IMG doesn't have a pixmap yet, load it now, using the image
5883 type dependent loader function. */
5884 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5885 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5889 /* Value is the number of pixels for the ascent of image IMG when
5890 drawn in face FACE. */
5893 image_ascent (img
, face
)
5897 int height
= img
->height
+ img
->vmargin
;
5900 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5903 /* This expression is arranged so that if the image can't be
5904 exactly centered, it will be moved slightly up. This is
5905 because a typical font is `top-heavy' (due to the presence
5906 uppercase letters), so the image placement should err towards
5907 being top-heavy too. It also just generally looks better. */
5908 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5910 ascent
= height
/ 2;
5913 ascent
= height
* img
->ascent
/ 100.0;
5919 /* Image background colors. */
5921 static unsigned long
5922 four_corners_best (ximg
, width
, height
)
5924 unsigned long width
, height
;
5926 unsigned long corners
[4], best
;
5929 /* Get the colors at the corners of ximg. */
5930 corners
[0] = XGetPixel (ximg
, 0, 0);
5931 corners
[1] = XGetPixel (ximg
, width
- 1, 0);
5932 corners
[2] = XGetPixel (ximg
, width
- 1, height
- 1);
5933 corners
[3] = XGetPixel (ximg
, 0, height
- 1);
5935 /* Choose the most frequently found color as background. */
5936 for (i
= best_count
= 0; i
< 4; ++i
)
5940 for (j
= n
= 0; j
< 4; ++j
)
5941 if (corners
[i
] == corners
[j
])
5945 best
= corners
[i
], best_count
= n
;
5951 /* Return the `background' field of IMG. If IMG doesn't have one yet,
5952 it is guessed heuristically. If non-zero, XIMG is an existing XImage
5953 object to use for the heuristic. */
5956 image_background (img
, f
, ximg
)
5961 if (! img
->background_valid
)
5962 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5964 int free_ximg
= !ximg
;
5967 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5968 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5970 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
5973 XDestroyImage (ximg
);
5975 img
->background_valid
= 1;
5978 return img
->background
;
5981 /* Return the `background_transparent' field of IMG. If IMG doesn't
5982 have one yet, it is guessed heuristically. If non-zero, MASK is an
5983 existing XImage object to use for the heuristic. */
5986 image_background_transparent (img
, f
, mask
)
5991 if (! img
->background_transparent_valid
)
5992 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5996 int free_mask
= !mask
;
5999 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
6000 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6002 img
->background_transparent
6003 = !four_corners_best (mask
, img
->width
, img
->height
);
6006 XDestroyImage (mask
);
6009 img
->background_transparent
= 0;
6011 img
->background_transparent_valid
= 1;
6014 return img
->background_transparent
;
6018 /***********************************************************************
6019 Helper functions for X image types
6020 ***********************************************************************/
6022 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
6024 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
6025 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
6027 Lisp_Object color_name
,
6028 unsigned long dflt
));
6031 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6032 free the pixmap if any. MASK_P non-zero means clear the mask
6033 pixmap if any. COLORS_P non-zero means free colors allocated for
6034 the image, if any. */
6037 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
6040 int pixmap_p
, mask_p
, colors_p
;
6042 if (pixmap_p
&& img
->pixmap
)
6044 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6046 img
->background_valid
= 0;
6049 if (mask_p
&& img
->mask
)
6051 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6053 img
->background_transparent_valid
= 0;
6056 if (colors_p
&& img
->ncolors
)
6058 x_free_colors (f
, img
->colors
, img
->ncolors
);
6059 xfree (img
->colors
);
6065 /* Free X resources of image IMG which is used on frame F. */
6068 x_clear_image (f
, img
)
6073 x_clear_image_1 (f
, img
, 1, 1, 1);
6078 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6079 cannot be allocated, use DFLT. Add a newly allocated color to
6080 IMG->colors, so that it can be freed again. Value is the pixel
6083 static unsigned long
6084 x_alloc_image_color (f
, img
, color_name
, dflt
)
6087 Lisp_Object color_name
;
6091 unsigned long result
;
6093 xassert (STRINGP (color_name
));
6095 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
6097 /* This isn't called frequently so we get away with simply
6098 reallocating the color vector to the needed size, here. */
6101 (unsigned long *) xrealloc (img
->colors
,
6102 img
->ncolors
* sizeof *img
->colors
);
6103 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
6104 result
= color
.pixel
;
6114 /***********************************************************************
6116 ***********************************************************************/
6118 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
6119 static void postprocess_image
P_ ((struct frame
*, struct image
*));
6122 /* Return a new, initialized image cache that is allocated from the
6123 heap. Call free_image_cache to free an image cache. */
6125 struct image_cache
*
6128 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
6131 bzero (c
, sizeof *c
);
6133 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
6134 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
6135 c
->buckets
= (struct image
**) xmalloc (size
);
6136 bzero (c
->buckets
, size
);
6141 /* Free image cache of frame F. Be aware that X frames share images
6145 free_image_cache (f
)
6148 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6153 /* Cache should not be referenced by any frame when freed. */
6154 xassert (c
->refcount
== 0);
6156 for (i
= 0; i
< c
->used
; ++i
)
6157 free_image (f
, c
->images
[i
]);
6161 FRAME_X_IMAGE_CACHE (f
) = NULL
;
6166 /* Clear image cache of frame F. FORCE_P non-zero means free all
6167 images. FORCE_P zero means clear only images that haven't been
6168 displayed for some time. Should be called from time to time to
6169 reduce the number of loaded images. If image-eviction-seconds is
6170 non-nil, this frees images in the cache which weren't displayed for
6171 at least that many seconds. */
6174 clear_image_cache (f
, force_p
)
6178 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6180 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
6187 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
6189 /* Block input so that we won't be interrupted by a SIGIO
6190 while being in an inconsistent state. */
6193 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
6195 struct image
*img
= c
->images
[i
];
6197 && (force_p
|| img
->timestamp
< old
))
6199 free_image (f
, img
);
6204 /* We may be clearing the image cache because, for example,
6205 Emacs was iconified for a longer period of time. In that
6206 case, current matrices may still contain references to
6207 images freed above. So, clear these matrices. */
6210 Lisp_Object tail
, frame
;
6212 FOR_EACH_FRAME (tail
, frame
)
6214 struct frame
*f
= XFRAME (frame
);
6216 && FRAME_X_IMAGE_CACHE (f
) == c
)
6217 clear_current_matrices (f
);
6220 ++windows_or_buffers_changed
;
6228 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
6230 doc
: /* Clear the image cache of FRAME.
6231 FRAME nil or omitted means use the selected frame.
6232 FRAME t means clear the image caches of all frames. */)
6240 FOR_EACH_FRAME (tail
, frame
)
6241 if (FRAME_X_P (XFRAME (frame
)))
6242 clear_image_cache (XFRAME (frame
), 1);
6245 clear_image_cache (check_x_frame (frame
), 1);
6251 /* Compute masks and transform image IMG on frame F, as specified
6252 by the image's specification, */
6255 postprocess_image (f
, img
)
6259 /* Manipulation of the image's mask. */
6262 Lisp_Object conversion
, spec
;
6267 /* `:heuristic-mask t'
6269 means build a mask heuristically.
6270 `:heuristic-mask (R G B)'
6271 `:mask (heuristic (R G B))'
6272 means build a mask from color (R G B) in the
6275 means remove a mask, if any. */
6277 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6279 x_build_heuristic_mask (f
, img
, mask
);
6284 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6286 if (EQ (mask
, Qheuristic
))
6287 x_build_heuristic_mask (f
, img
, Qt
);
6288 else if (CONSP (mask
)
6289 && EQ (XCAR (mask
), Qheuristic
))
6291 if (CONSP (XCDR (mask
)))
6292 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6294 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6296 else if (NILP (mask
) && found_p
&& img
->mask
)
6298 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6304 /* Should we apply an image transformation algorithm? */
6305 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6306 if (EQ (conversion
, Qdisabled
))
6307 x_disable_image (f
, img
);
6308 else if (EQ (conversion
, Qlaplace
))
6310 else if (EQ (conversion
, Qemboss
))
6312 else if (CONSP (conversion
)
6313 && EQ (XCAR (conversion
), Qedge_detection
))
6316 tem
= XCDR (conversion
);
6318 x_edge_detection (f
, img
,
6319 Fplist_get (tem
, QCmatrix
),
6320 Fplist_get (tem
, QCcolor_adjustment
));
6326 /* Return the id of image with Lisp specification SPEC on frame F.
6327 SPEC must be a valid Lisp image specification (see valid_image_p). */
6330 lookup_image (f
, spec
)
6334 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6338 struct gcpro gcpro1
;
6341 /* F must be a window-system frame, and SPEC must be a valid image
6343 xassert (FRAME_WINDOW_P (f
));
6344 xassert (valid_image_p (spec
));
6348 /* Look up SPEC in the hash table of the image cache. */
6349 hash
= sxhash (spec
, 0);
6350 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6352 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6353 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6356 /* If not found, create a new image and cache it. */
6359 extern Lisp_Object Qpostscript
;
6362 img
= make_image (spec
, hash
);
6363 cache_image (f
, img
);
6364 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6366 /* If we can't load the image, and we don't have a width and
6367 height, use some arbitrary width and height so that we can
6368 draw a rectangle for it. */
6369 if (img
->load_failed_p
)
6373 value
= image_spec_value (spec
, QCwidth
, NULL
);
6374 img
->width
= (INTEGERP (value
)
6375 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6376 value
= image_spec_value (spec
, QCheight
, NULL
);
6377 img
->height
= (INTEGERP (value
)
6378 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6382 /* Handle image type independent image attributes
6383 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6384 `:background COLOR'. */
6385 Lisp_Object ascent
, margin
, relief
, bg
;
6387 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6388 if (INTEGERP (ascent
))
6389 img
->ascent
= XFASTINT (ascent
);
6390 else if (EQ (ascent
, Qcenter
))
6391 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6393 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6394 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6395 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6396 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6397 && INTEGERP (XCDR (margin
)))
6399 if (XINT (XCAR (margin
)) > 0)
6400 img
->hmargin
= XFASTINT (XCAR (margin
));
6401 if (XINT (XCDR (margin
)) > 0)
6402 img
->vmargin
= XFASTINT (XCDR (margin
));
6405 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6406 if (INTEGERP (relief
))
6408 img
->relief
= XINT (relief
);
6409 img
->hmargin
+= abs (img
->relief
);
6410 img
->vmargin
+= abs (img
->relief
);
6413 if (! img
->background_valid
)
6415 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6419 = x_alloc_image_color (f
, img
, bg
,
6420 FRAME_BACKGROUND_PIXEL (f
));
6421 img
->background_valid
= 1;
6425 /* Do image transformations and compute masks, unless we
6426 don't have the image yet. */
6427 if (!EQ (*img
->type
->type
, Qpostscript
))
6428 postprocess_image (f
, img
);
6432 xassert (!interrupt_input_blocked
);
6435 /* We're using IMG, so set its timestamp to `now'. */
6436 EMACS_GET_TIME (now
);
6437 img
->timestamp
= EMACS_SECS (now
);
6441 /* Value is the image id. */
6446 /* Cache image IMG in the image cache of frame F. */
6449 cache_image (f
, img
)
6453 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6456 /* Find a free slot in c->images. */
6457 for (i
= 0; i
< c
->used
; ++i
)
6458 if (c
->images
[i
] == NULL
)
6461 /* If no free slot found, maybe enlarge c->images. */
6462 if (i
== c
->used
&& c
->used
== c
->size
)
6465 c
->images
= (struct image
**) xrealloc (c
->images
,
6466 c
->size
* sizeof *c
->images
);
6469 /* Add IMG to c->images, and assign IMG an id. */
6475 /* Add IMG to the cache's hash table. */
6476 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6477 img
->next
= c
->buckets
[i
];
6479 img
->next
->prev
= img
;
6481 c
->buckets
[i
] = img
;
6485 /* Call FN on every image in the image cache of frame F. Used to mark
6486 Lisp Objects in the image cache. */
6489 forall_images_in_image_cache (f
, fn
)
6491 void (*fn
) P_ ((struct image
*img
));
6493 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6495 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6499 for (i
= 0; i
< c
->used
; ++i
)
6508 /***********************************************************************
6510 ***********************************************************************/
6512 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6513 XImage
**, Pixmap
*));
6514 static void x_destroy_x_image
P_ ((XImage
*));
6515 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6518 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6519 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6520 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6521 via xmalloc. Print error messages via image_error if an error
6522 occurs. Value is non-zero if successful. */
6525 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6527 int width
, height
, depth
;
6531 Display
*display
= FRAME_X_DISPLAY (f
);
6532 Screen
*screen
= FRAME_X_SCREEN (f
);
6533 Window window
= FRAME_X_WINDOW (f
);
6535 xassert (interrupt_input_blocked
);
6538 depth
= DefaultDepthOfScreen (screen
);
6539 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6540 depth
, ZPixmap
, 0, NULL
, width
, height
,
6541 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6544 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6548 /* Allocate image raster. */
6549 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6551 /* Allocate a pixmap of the same size. */
6552 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6553 if (*pixmap
== None
)
6555 x_destroy_x_image (*ximg
);
6557 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6565 /* Destroy XImage XIMG. Free XIMG->data. */
6568 x_destroy_x_image (ximg
)
6571 xassert (interrupt_input_blocked
);
6576 XDestroyImage (ximg
);
6581 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6582 are width and height of both the image and pixmap. */
6585 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6592 xassert (interrupt_input_blocked
);
6593 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6594 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6595 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6600 /***********************************************************************
6602 ***********************************************************************/
6604 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6605 static char *slurp_file
P_ ((char *, int *));
6608 /* Find image file FILE. Look in data-directory, then
6609 x-bitmap-file-path. Value is the full name of the file found, or
6610 nil if not found. */
6613 x_find_image_file (file
)
6616 Lisp_Object file_found
, search_path
;
6617 struct gcpro gcpro1
, gcpro2
;
6621 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6622 GCPRO2 (file_found
, search_path
);
6624 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6625 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
6637 /* Read FILE into memory. Value is a pointer to a buffer allocated
6638 with xmalloc holding FILE's contents. Value is null if an error
6639 occurred. *SIZE is set to the size of the file. */
6642 slurp_file (file
, size
)
6650 if (stat (file
, &st
) == 0
6651 && (fp
= fopen (file
, "r")) != NULL
6652 && (buf
= (char *) xmalloc (st
.st_size
),
6653 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6674 /***********************************************************************
6676 ***********************************************************************/
6678 static int xbm_scan
P_ ((char **, char *, char *, int *));
6679 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6680 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6682 static int xbm_image_p
P_ ((Lisp_Object object
));
6683 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6685 static int xbm_file_p
P_ ((Lisp_Object
));
6688 /* Indices of image specification fields in xbm_format, below. */
6690 enum xbm_keyword_index
6708 /* Vector of image_keyword structures describing the format
6709 of valid XBM image specifications. */
6711 static struct image_keyword xbm_format
[XBM_LAST
] =
6713 {":type", IMAGE_SYMBOL_VALUE
, 1},
6714 {":file", IMAGE_STRING_VALUE
, 0},
6715 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6716 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6717 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6718 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6719 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6720 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6721 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6722 {":relief", IMAGE_INTEGER_VALUE
, 0},
6723 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6724 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6725 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6728 /* Structure describing the image type XBM. */
6730 static struct image_type xbm_type
=
6739 /* Tokens returned from xbm_scan. */
6748 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6749 A valid specification is a list starting with the symbol `image'
6750 The rest of the list is a property list which must contain an
6753 If the specification specifies a file to load, it must contain
6754 an entry `:file FILENAME' where FILENAME is a string.
6756 If the specification is for a bitmap loaded from memory it must
6757 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6758 WIDTH and HEIGHT are integers > 0. DATA may be:
6760 1. a string large enough to hold the bitmap data, i.e. it must
6761 have a size >= (WIDTH + 7) / 8 * HEIGHT
6763 2. a bool-vector of size >= WIDTH * HEIGHT
6765 3. a vector of strings or bool-vectors, one for each line of the
6768 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6769 may not be specified in this case because they are defined in the
6772 Both the file and data forms may contain the additional entries
6773 `:background COLOR' and `:foreground COLOR'. If not present,
6774 foreground and background of the frame on which the image is
6775 displayed is used. */
6778 xbm_image_p (object
)
6781 struct image_keyword kw
[XBM_LAST
];
6783 bcopy (xbm_format
, kw
, sizeof kw
);
6784 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6787 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6789 if (kw
[XBM_FILE
].count
)
6791 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6794 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6796 /* In-memory XBM file. */
6797 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6805 /* Entries for `:width', `:height' and `:data' must be present. */
6806 if (!kw
[XBM_WIDTH
].count
6807 || !kw
[XBM_HEIGHT
].count
6808 || !kw
[XBM_DATA
].count
)
6811 data
= kw
[XBM_DATA
].value
;
6812 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6813 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6815 /* Check type of data, and width and height against contents of
6821 /* Number of elements of the vector must be >= height. */
6822 if (XVECTOR (data
)->size
< height
)
6825 /* Each string or bool-vector in data must be large enough
6826 for one line of the image. */
6827 for (i
= 0; i
< height
; ++i
)
6829 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6834 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6837 else if (BOOL_VECTOR_P (elt
))
6839 if (XBOOL_VECTOR (elt
)->size
< width
)
6846 else if (STRINGP (data
))
6849 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6852 else if (BOOL_VECTOR_P (data
))
6854 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6865 /* Scan a bitmap file. FP is the stream to read from. Value is
6866 either an enumerator from enum xbm_token, or a character for a
6867 single-character token, or 0 at end of file. If scanning an
6868 identifier, store the lexeme of the identifier in SVAL. If
6869 scanning a number, store its value in *IVAL. */
6872 xbm_scan (s
, end
, sval
, ival
)
6881 /* Skip white space. */
6882 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6887 else if (isdigit (c
))
6889 int value
= 0, digit
;
6891 if (c
== '0' && *s
< end
)
6894 if (c
== 'x' || c
== 'X')
6901 else if (c
>= 'a' && c
<= 'f')
6902 digit
= c
- 'a' + 10;
6903 else if (c
>= 'A' && c
<= 'F')
6904 digit
= c
- 'A' + 10;
6907 value
= 16 * value
+ digit
;
6910 else if (isdigit (c
))
6914 && (c
= *(*s
)++, isdigit (c
)))
6915 value
= 8 * value
+ c
- '0';
6922 && (c
= *(*s
)++, isdigit (c
)))
6923 value
= 10 * value
+ c
- '0';
6931 else if (isalpha (c
) || c
== '_')
6935 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6942 else if (c
== '/' && **s
== '*')
6944 /* C-style comment. */
6946 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6959 /* Replacement for XReadBitmapFileData which isn't available under old
6960 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6961 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6962 the image. Return in *DATA the bitmap data allocated with xmalloc.
6963 Value is non-zero if successful. DATA null means just test if
6964 CONTENTS looks like an in-memory XBM file. */
6967 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
6968 char *contents
, *end
;
6969 int *width
, *height
;
6970 unsigned char **data
;
6973 char buffer
[BUFSIZ
];
6976 int bytes_per_line
, i
, nbytes
;
6982 LA1 = xbm_scan (&s, end, buffer, &value)
6984 #define expect(TOKEN) \
6985 if (LA1 != (TOKEN)) \
6990 #define expect_ident(IDENT) \
6991 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6996 *width
= *height
= -1;
6999 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
7001 /* Parse defines for width, height and hot-spots. */
7005 expect_ident ("define");
7006 expect (XBM_TK_IDENT
);
7008 if (LA1
== XBM_TK_NUMBER
);
7010 char *p
= strrchr (buffer
, '_');
7011 p
= p
? p
+ 1 : buffer
;
7012 if (strcmp (p
, "width") == 0)
7014 else if (strcmp (p
, "height") == 0)
7017 expect (XBM_TK_NUMBER
);
7020 if (*width
< 0 || *height
< 0)
7022 else if (data
== NULL
)
7025 /* Parse bits. Must start with `static'. */
7026 expect_ident ("static");
7027 if (LA1
== XBM_TK_IDENT
)
7029 if (strcmp (buffer
, "unsigned") == 0)
7032 expect_ident ("char");
7034 else if (strcmp (buffer
, "short") == 0)
7038 if (*width
% 16 && *width
% 16 < 9)
7041 else if (strcmp (buffer
, "char") == 0)
7049 expect (XBM_TK_IDENT
);
7055 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
7056 nbytes
= bytes_per_line
* *height
;
7057 p
= *data
= (char *) xmalloc (nbytes
);
7061 for (i
= 0; i
< nbytes
; i
+= 2)
7064 expect (XBM_TK_NUMBER
);
7067 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
7070 if (LA1
== ',' || LA1
== '}')
7078 for (i
= 0; i
< nbytes
; ++i
)
7081 expect (XBM_TK_NUMBER
);
7085 if (LA1
== ',' || LA1
== '}')
7110 /* Load XBM image IMG which will be displayed on frame F from buffer
7111 CONTENTS. END is the end of the buffer. Value is non-zero if
7115 xbm_load_image (f
, img
, contents
, end
)
7118 char *contents
, *end
;
7121 unsigned char *data
;
7124 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
7127 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7128 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7129 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7132 xassert (img
->width
> 0 && img
->height
> 0);
7134 /* Get foreground and background colors, maybe allocate colors. */
7135 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
7137 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
7138 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7141 background
= x_alloc_image_color (f
, img
, value
, background
);
7142 img
->background
= background
;
7143 img
->background_valid
= 1;
7147 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7150 img
->width
, img
->height
,
7151 foreground
, background
,
7155 if (img
->pixmap
== None
)
7157 x_clear_image (f
, img
);
7158 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
7164 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7170 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7177 return (STRINGP (data
)
7178 && xbm_read_bitmap_data (SDATA (data
),
7185 /* Fill image IMG which is used on frame F with pixmap data. Value is
7186 non-zero if successful. */
7194 Lisp_Object file_name
;
7196 xassert (xbm_image_p (img
->spec
));
7198 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7199 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7200 if (STRINGP (file_name
))
7205 struct gcpro gcpro1
;
7207 file
= x_find_image_file (file_name
);
7209 if (!STRINGP (file
))
7211 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7216 contents
= slurp_file (SDATA (file
), &size
);
7217 if (contents
== NULL
)
7219 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7224 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
7229 struct image_keyword fmt
[XBM_LAST
];
7232 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7233 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7236 int in_memory_file_p
= 0;
7238 /* See if data looks like an in-memory XBM file. */
7239 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7240 in_memory_file_p
= xbm_file_p (data
);
7242 /* Parse the image specification. */
7243 bcopy (xbm_format
, fmt
, sizeof fmt
);
7244 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
7247 /* Get specified width, and height. */
7248 if (!in_memory_file_p
)
7250 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
7251 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
7252 xassert (img
->width
> 0 && img
->height
> 0);
7255 /* Get foreground and background colors, maybe allocate colors. */
7256 if (fmt
[XBM_FOREGROUND
].count
7257 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
7258 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
7260 if (fmt
[XBM_BACKGROUND
].count
7261 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
7262 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7265 if (in_memory_file_p
)
7266 success_p
= xbm_load_image (f
, img
, SDATA (data
),
7275 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7277 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7278 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7280 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7282 bcopy (SDATA (line
), p
, nbytes
);
7284 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7287 else if (STRINGP (data
))
7288 bits
= SDATA (data
);
7290 bits
= XBOOL_VECTOR (data
)->data
;
7292 /* Create the pixmap. */
7293 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7295 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7298 img
->width
, img
->height
,
7299 foreground
, background
,
7305 image_error ("Unable to create pixmap for XBM image `%s'",
7307 x_clear_image (f
, img
);
7317 /***********************************************************************
7319 ***********************************************************************/
7323 static int xpm_image_p
P_ ((Lisp_Object object
));
7324 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7325 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7327 #include "X11/xpm.h"
7329 /* The symbol `xpm' identifying XPM-format images. */
7333 /* Indices of image specification fields in xpm_format, below. */
7335 enum xpm_keyword_index
7351 /* Vector of image_keyword structures describing the format
7352 of valid XPM image specifications. */
7354 static struct image_keyword xpm_format
[XPM_LAST
] =
7356 {":type", IMAGE_SYMBOL_VALUE
, 1},
7357 {":file", IMAGE_STRING_VALUE
, 0},
7358 {":data", IMAGE_STRING_VALUE
, 0},
7359 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7360 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7361 {":relief", IMAGE_INTEGER_VALUE
, 0},
7362 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7363 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7364 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7365 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7366 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7369 /* Structure describing the image type XBM. */
7371 static struct image_type xpm_type
=
7381 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7382 functions for allocating image colors. Our own functions handle
7383 color allocation failures more gracefully than the ones on the XPM
7386 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7387 #define ALLOC_XPM_COLORS
7390 #ifdef ALLOC_XPM_COLORS
7392 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7393 static void xpm_free_color_cache
P_ ((void));
7394 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7395 static int xpm_color_bucket
P_ ((char *));
7396 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7399 /* An entry in a hash table used to cache color definitions of named
7400 colors. This cache is necessary to speed up XPM image loading in
7401 case we do color allocations ourselves. Without it, we would need
7402 a call to XParseColor per pixel in the image. */
7404 struct xpm_cached_color
7406 /* Next in collision chain. */
7407 struct xpm_cached_color
*next
;
7409 /* Color definition (RGB and pixel color). */
7416 /* The hash table used for the color cache, and its bucket vector
7419 #define XPM_COLOR_CACHE_BUCKETS 1001
7420 struct xpm_cached_color
**xpm_color_cache
;
7422 /* Initialize the color cache. */
7425 xpm_init_color_cache (f
, attrs
)
7427 XpmAttributes
*attrs
;
7429 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7430 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7431 memset (xpm_color_cache
, 0, nbytes
);
7432 init_color_table ();
7434 if (attrs
->valuemask
& XpmColorSymbols
)
7439 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7440 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7441 attrs
->colorsymbols
[i
].value
, &color
))
7443 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7445 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7451 /* Free the color cache. */
7454 xpm_free_color_cache ()
7456 struct xpm_cached_color
*p
, *next
;
7459 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7460 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7466 xfree (xpm_color_cache
);
7467 xpm_color_cache
= NULL
;
7468 free_color_table ();
7472 /* Return the bucket index for color named COLOR_NAME in the color
7476 xpm_color_bucket (color_name
)
7482 for (s
= color_name
; *s
; ++s
)
7484 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7488 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7489 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7492 static struct xpm_cached_color
*
7493 xpm_cache_color (f
, color_name
, color
, bucket
)
7500 struct xpm_cached_color
*p
;
7503 bucket
= xpm_color_bucket (color_name
);
7505 nbytes
= sizeof *p
+ strlen (color_name
);
7506 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7507 strcpy (p
->name
, color_name
);
7509 p
->next
= xpm_color_cache
[bucket
];
7510 xpm_color_cache
[bucket
] = p
;
7515 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7516 return the cached definition in *COLOR. Otherwise, make a new
7517 entry in the cache and allocate the color. Value is zero if color
7518 allocation failed. */
7521 xpm_lookup_color (f
, color_name
, color
)
7526 struct xpm_cached_color
*p
;
7527 int h
= xpm_color_bucket (color_name
);
7529 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7530 if (strcmp (p
->name
, color_name
) == 0)
7535 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7538 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7540 p
= xpm_cache_color (f
, color_name
, color
, h
);
7547 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7548 CLOSURE is a pointer to the frame on which we allocate the
7549 color. Return in *COLOR the allocated color. Value is non-zero
7553 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7560 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7564 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7565 is a pointer to the frame on which we allocate the color. Value is
7566 non-zero if successful. */
7569 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7579 #endif /* ALLOC_XPM_COLORS */
7582 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7583 for XPM images. Such a list must consist of conses whose car and
7587 xpm_valid_color_symbols_p (color_symbols
)
7588 Lisp_Object color_symbols
;
7590 while (CONSP (color_symbols
))
7592 Lisp_Object sym
= XCAR (color_symbols
);
7594 || !STRINGP (XCAR (sym
))
7595 || !STRINGP (XCDR (sym
)))
7597 color_symbols
= XCDR (color_symbols
);
7600 return NILP (color_symbols
);
7604 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7607 xpm_image_p (object
)
7610 struct image_keyword fmt
[XPM_LAST
];
7611 bcopy (xpm_format
, fmt
, sizeof fmt
);
7612 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7613 /* Either `:file' or `:data' must be present. */
7614 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7615 /* Either no `:color-symbols' or it's a list of conses
7616 whose car and cdr are strings. */
7617 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7618 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7622 /* Load image IMG which will be displayed on frame F. Value is
7623 non-zero if successful. */
7631 XpmAttributes attrs
;
7632 Lisp_Object specified_file
, color_symbols
;
7634 /* Configure the XPM lib. Use the visual of frame F. Allocate
7635 close colors. Return colors allocated. */
7636 bzero (&attrs
, sizeof attrs
);
7637 attrs
.visual
= FRAME_X_VISUAL (f
);
7638 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7639 attrs
.valuemask
|= XpmVisual
;
7640 attrs
.valuemask
|= XpmColormap
;
7642 #ifdef ALLOC_XPM_COLORS
7643 /* Allocate colors with our own functions which handle
7644 failing color allocation more gracefully. */
7645 attrs
.color_closure
= f
;
7646 attrs
.alloc_color
= xpm_alloc_color
;
7647 attrs
.free_colors
= xpm_free_colors
;
7648 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7649 #else /* not ALLOC_XPM_COLORS */
7650 /* Let the XPM lib allocate colors. */
7651 attrs
.valuemask
|= XpmReturnAllocPixels
;
7652 #ifdef XpmAllocCloseColors
7653 attrs
.alloc_close_colors
= 1;
7654 attrs
.valuemask
|= XpmAllocCloseColors
;
7655 #else /* not XpmAllocCloseColors */
7656 attrs
.closeness
= 600;
7657 attrs
.valuemask
|= XpmCloseness
;
7658 #endif /* not XpmAllocCloseColors */
7659 #endif /* ALLOC_XPM_COLORS */
7661 /* If image specification contains symbolic color definitions, add
7662 these to `attrs'. */
7663 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7664 if (CONSP (color_symbols
))
7667 XpmColorSymbol
*xpm_syms
;
7670 attrs
.valuemask
|= XpmColorSymbols
;
7672 /* Count number of symbols. */
7673 attrs
.numsymbols
= 0;
7674 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7677 /* Allocate an XpmColorSymbol array. */
7678 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7679 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7680 bzero (xpm_syms
, size
);
7681 attrs
.colorsymbols
= xpm_syms
;
7683 /* Fill the color symbol array. */
7684 for (tail
= color_symbols
, i
= 0;
7686 ++i
, tail
= XCDR (tail
))
7688 Lisp_Object name
= XCAR (XCAR (tail
));
7689 Lisp_Object color
= XCDR (XCAR (tail
));
7690 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
7691 strcpy (xpm_syms
[i
].name
, SDATA (name
));
7692 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
7693 strcpy (xpm_syms
[i
].value
, SDATA (color
));
7697 /* Create a pixmap for the image, either from a file, or from a
7698 string buffer containing data in the same format as an XPM file. */
7699 #ifdef ALLOC_XPM_COLORS
7700 xpm_init_color_cache (f
, &attrs
);
7703 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7704 if (STRINGP (specified_file
))
7706 Lisp_Object file
= x_find_image_file (specified_file
);
7707 if (!STRINGP (file
))
7709 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7713 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7714 SDATA (file
), &img
->pixmap
, &img
->mask
,
7719 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7720 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7722 &img
->pixmap
, &img
->mask
,
7726 if (rc
== XpmSuccess
)
7728 #ifdef ALLOC_XPM_COLORS
7729 img
->colors
= colors_in_color_table (&img
->ncolors
);
7730 #else /* not ALLOC_XPM_COLORS */
7733 img
->ncolors
= attrs
.nalloc_pixels
;
7734 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7735 * sizeof *img
->colors
);
7736 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7738 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7739 #ifdef DEBUG_X_COLORS
7740 register_color (img
->colors
[i
]);
7743 #endif /* not ALLOC_XPM_COLORS */
7745 img
->width
= attrs
.width
;
7746 img
->height
= attrs
.height
;
7747 xassert (img
->width
> 0 && img
->height
> 0);
7749 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7750 XpmFreeAttributes (&attrs
);
7757 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7760 case XpmFileInvalid
:
7761 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7765 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7768 case XpmColorFailed
:
7769 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7773 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7778 #ifdef ALLOC_XPM_COLORS
7779 xpm_free_color_cache ();
7781 return rc
== XpmSuccess
;
7784 #endif /* HAVE_XPM != 0 */
7787 /***********************************************************************
7789 ***********************************************************************/
7791 /* An entry in the color table mapping an RGB color to a pixel color. */
7796 unsigned long pixel
;
7798 /* Next in color table collision list. */
7799 struct ct_color
*next
;
7802 /* The bucket vector size to use. Must be prime. */
7806 /* Value is a hash of the RGB color given by R, G, and B. */
7808 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7810 /* The color hash table. */
7812 struct ct_color
**ct_table
;
7814 /* Number of entries in the color table. */
7816 int ct_colors_allocated
;
7818 /* Initialize the color table. */
7823 int size
= CT_SIZE
* sizeof (*ct_table
);
7824 ct_table
= (struct ct_color
**) xmalloc (size
);
7825 bzero (ct_table
, size
);
7826 ct_colors_allocated
= 0;
7830 /* Free memory associated with the color table. */
7836 struct ct_color
*p
, *next
;
7838 for (i
= 0; i
< CT_SIZE
; ++i
)
7839 for (p
= ct_table
[i
]; p
; p
= next
)
7850 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7851 entry for that color already is in the color table, return the
7852 pixel color of that entry. Otherwise, allocate a new color for R,
7853 G, B, and make an entry in the color table. */
7855 static unsigned long
7856 lookup_rgb_color (f
, r
, g
, b
)
7860 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7861 int i
= hash
% CT_SIZE
;
7864 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7865 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7878 cmap
= FRAME_X_COLORMAP (f
);
7879 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7883 ++ct_colors_allocated
;
7885 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7889 p
->pixel
= color
.pixel
;
7890 p
->next
= ct_table
[i
];
7894 return FRAME_FOREGROUND_PIXEL (f
);
7901 /* Look up pixel color PIXEL which is used on frame F in the color
7902 table. If not already present, allocate it. Value is PIXEL. */
7904 static unsigned long
7905 lookup_pixel_color (f
, pixel
)
7907 unsigned long pixel
;
7909 int i
= pixel
% CT_SIZE
;
7912 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7913 if (p
->pixel
== pixel
)
7922 cmap
= FRAME_X_COLORMAP (f
);
7923 color
.pixel
= pixel
;
7924 x_query_color (f
, &color
);
7925 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7929 ++ct_colors_allocated
;
7931 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7936 p
->next
= ct_table
[i
];
7940 return FRAME_FOREGROUND_PIXEL (f
);
7947 /* Value is a vector of all pixel colors contained in the color table,
7948 allocated via xmalloc. Set *N to the number of colors. */
7950 static unsigned long *
7951 colors_in_color_table (n
)
7956 unsigned long *colors
;
7958 if (ct_colors_allocated
== 0)
7965 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7967 *n
= ct_colors_allocated
;
7969 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7970 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7971 colors
[j
++] = p
->pixel
;
7979 /***********************************************************************
7981 ***********************************************************************/
7983 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
7984 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
7985 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
7987 /* Non-zero means draw a cross on images having `:conversion
7990 int cross_disabled_images
;
7992 /* Edge detection matrices for different edge-detection
7995 static int emboss_matrix
[9] = {
7997 2, -1, 0, /* y - 1 */
7999 0, 1, -2 /* y + 1 */
8002 static int laplace_matrix
[9] = {
8004 1, 0, 0, /* y - 1 */
8006 0, 0, -1 /* y + 1 */
8009 /* Value is the intensity of the color whose red/green/blue values
8012 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8015 /* On frame F, return an array of XColor structures describing image
8016 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8017 non-zero means also fill the red/green/blue members of the XColor
8018 structures. Value is a pointer to the array of XColors structures,
8019 allocated with xmalloc; it must be freed by the caller. */
8022 x_to_xcolors (f
, img
, rgb_p
)
8031 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
8033 /* Get the X image IMG->pixmap. */
8034 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8035 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8037 /* Fill the `pixel' members of the XColor array. I wished there
8038 were an easy and portable way to circumvent XGetPixel. */
8040 for (y
= 0; y
< img
->height
; ++y
)
8044 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8045 p
->pixel
= XGetPixel (ximg
, x
, y
);
8048 x_query_colors (f
, row
, img
->width
);
8051 XDestroyImage (ximg
);
8056 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8057 RGB members are set. F is the frame on which this all happens.
8058 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8061 x_from_xcolors (f
, img
, colors
)
8071 init_color_table ();
8073 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
8076 for (y
= 0; y
< img
->height
; ++y
)
8077 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8079 unsigned long pixel
;
8080 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
8081 XPutPixel (oimg
, x
, y
, pixel
);
8085 x_clear_image_1 (f
, img
, 1, 0, 1);
8087 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
8088 x_destroy_x_image (oimg
);
8089 img
->pixmap
= pixmap
;
8090 img
->colors
= colors_in_color_table (&img
->ncolors
);
8091 free_color_table ();
8095 /* On frame F, perform edge-detection on image IMG.
8097 MATRIX is a nine-element array specifying the transformation
8098 matrix. See emboss_matrix for an example.
8100 COLOR_ADJUST is a color adjustment added to each pixel of the
8104 x_detect_edges (f
, img
, matrix
, color_adjust
)
8107 int matrix
[9], color_adjust
;
8109 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8113 for (i
= sum
= 0; i
< 9; ++i
)
8114 sum
+= abs (matrix
[i
]);
8116 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8118 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
8120 for (y
= 0; y
< img
->height
; ++y
)
8122 p
= COLOR (new, 0, y
);
8123 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8124 p
= COLOR (new, img
->width
- 1, y
);
8125 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8128 for (x
= 1; x
< img
->width
- 1; ++x
)
8130 p
= COLOR (new, x
, 0);
8131 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8132 p
= COLOR (new, x
, img
->height
- 1);
8133 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8136 for (y
= 1; y
< img
->height
- 1; ++y
)
8138 p
= COLOR (new, 1, y
);
8140 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
8142 int r
, g
, b
, y1
, x1
;
8145 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
8146 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
8149 XColor
*t
= COLOR (colors
, x1
, y1
);
8150 r
+= matrix
[i
] * t
->red
;
8151 g
+= matrix
[i
] * t
->green
;
8152 b
+= matrix
[i
] * t
->blue
;
8155 r
= (r
/ sum
+ color_adjust
) & 0xffff;
8156 g
= (g
/ sum
+ color_adjust
) & 0xffff;
8157 b
= (b
/ sum
+ color_adjust
) & 0xffff;
8158 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
8163 x_from_xcolors (f
, img
, new);
8169 /* Perform the pre-defined `emboss' edge-detection on image IMG
8177 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
8181 /* Perform the pre-defined `laplace' edge-detection on image IMG
8189 x_detect_edges (f
, img
, laplace_matrix
, 45000);
8193 /* Perform edge-detection on image IMG on frame F, with specified
8194 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8196 MATRIX must be either
8198 - a list of at least 9 numbers in row-major form
8199 - a vector of at least 9 numbers
8201 COLOR_ADJUST nil means use a default; otherwise it must be a
8205 x_edge_detection (f
, img
, matrix
, color_adjust
)
8208 Lisp_Object matrix
, color_adjust
;
8216 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
8217 ++i
, matrix
= XCDR (matrix
))
8218 trans
[i
] = XFLOATINT (XCAR (matrix
));
8220 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
8222 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
8223 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
8226 if (NILP (color_adjust
))
8227 color_adjust
= make_number (0xffff / 2);
8229 if (i
== 9 && NUMBERP (color_adjust
))
8230 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
8234 /* Transform image IMG on frame F so that it looks disabled. */
8237 x_disable_image (f
, img
)
8241 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8243 if (dpyinfo
->n_planes
>= 2)
8245 /* Color (or grayscale). Convert to gray, and equalize. Just
8246 drawing such images with a stipple can look very odd, so
8247 we're using this method instead. */
8248 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8250 const int h
= 15000;
8251 const int l
= 30000;
8253 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
8257 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
8258 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
8259 p
->red
= p
->green
= p
->blue
= i2
;
8262 x_from_xcolors (f
, img
, colors
);
8265 /* Draw a cross over the disabled image, if we must or if we
8267 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
8269 Display
*dpy
= FRAME_X_DISPLAY (f
);
8272 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
8273 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
8274 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
8275 img
->width
- 1, img
->height
- 1);
8276 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
8282 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
8283 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8284 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8285 img
->width
- 1, img
->height
- 1);
8286 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8294 /* Build a mask for image IMG which is used on frame F. FILE is the
8295 name of an image file, for error messages. HOW determines how to
8296 determine the background color of IMG. If it is a list '(R G B)',
8297 with R, G, and B being integers >= 0, take that as the color of the
8298 background. Otherwise, determine the background color of IMG
8299 heuristically. Value is non-zero if successful. */
8302 x_build_heuristic_mask (f
, img
, how
)
8307 Display
*dpy
= FRAME_X_DISPLAY (f
);
8308 XImage
*ximg
, *mask_img
;
8309 int x
, y
, rc
, use_img_background
;
8310 unsigned long bg
= 0;
8314 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8316 img
->background_transparent_valid
= 0;
8319 /* Create an image and pixmap serving as mask. */
8320 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8321 &mask_img
, &img
->mask
);
8325 /* Get the X image of IMG->pixmap. */
8326 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8329 /* Determine the background color of ximg. If HOW is `(R G B)'
8330 take that as color. Otherwise, use the image's background color. */
8331 use_img_background
= 1;
8337 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
8339 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8343 if (i
== 3 && NILP (how
))
8345 char color_name
[30];
8346 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8347 bg
= x_alloc_image_color (f
, img
, build_string (color_name
), 0);
8348 use_img_background
= 0;
8352 if (use_img_background
)
8353 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
8355 /* Set all bits in mask_img to 1 whose color in ximg is different
8356 from the background color bg. */
8357 for (y
= 0; y
< img
->height
; ++y
)
8358 for (x
= 0; x
< img
->width
; ++x
)
8359 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8361 /* Fill in the background_transparent field while we have the mask handy. */
8362 image_background_transparent (img
, f
, mask_img
);
8364 /* Put mask_img into img->mask. */
8365 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8366 x_destroy_x_image (mask_img
);
8367 XDestroyImage (ximg
);
8374 /***********************************************************************
8375 PBM (mono, gray, color)
8376 ***********************************************************************/
8378 static int pbm_image_p
P_ ((Lisp_Object object
));
8379 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8380 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8382 /* The symbol `pbm' identifying images of this type. */
8386 /* Indices of image specification fields in gs_format, below. */
8388 enum pbm_keyword_index
8404 /* Vector of image_keyword structures describing the format
8405 of valid user-defined image specifications. */
8407 static struct image_keyword pbm_format
[PBM_LAST
] =
8409 {":type", IMAGE_SYMBOL_VALUE
, 1},
8410 {":file", IMAGE_STRING_VALUE
, 0},
8411 {":data", IMAGE_STRING_VALUE
, 0},
8412 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8413 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8414 {":relief", IMAGE_INTEGER_VALUE
, 0},
8415 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8416 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8417 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8418 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8419 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8422 /* Structure describing the image type `pbm'. */
8424 static struct image_type pbm_type
=
8434 /* Return non-zero if OBJECT is a valid PBM image specification. */
8437 pbm_image_p (object
)
8440 struct image_keyword fmt
[PBM_LAST
];
8442 bcopy (pbm_format
, fmt
, sizeof fmt
);
8444 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8447 /* Must specify either :data or :file. */
8448 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8452 /* Scan a decimal number from *S and return it. Advance *S while
8453 reading the number. END is the end of the string. Value is -1 at
8457 pbm_scan_number (s
, end
)
8458 unsigned char **s
, *end
;
8460 int c
= 0, val
= -1;
8464 /* Skip white-space. */
8465 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8470 /* Skip comment to end of line. */
8471 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8474 else if (isdigit (c
))
8476 /* Read decimal number. */
8478 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8479 val
= 10 * val
+ c
- '0';
8490 /* Load PBM image IMG for use on frame F. */
8498 int width
, height
, max_color_idx
= 0;
8500 Lisp_Object file
, specified_file
;
8501 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8502 struct gcpro gcpro1
;
8503 unsigned char *contents
= NULL
;
8504 unsigned char *end
, *p
;
8507 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8511 if (STRINGP (specified_file
))
8513 file
= x_find_image_file (specified_file
);
8514 if (!STRINGP (file
))
8516 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8521 contents
= slurp_file (SDATA (file
), &size
);
8522 if (contents
== NULL
)
8524 image_error ("Error reading `%s'", file
, Qnil
);
8530 end
= contents
+ size
;
8535 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8537 end
= p
+ SBYTES (data
);
8540 /* Check magic number. */
8541 if (end
- p
< 2 || *p
++ != 'P')
8543 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8553 raw_p
= 0, type
= PBM_MONO
;
8557 raw_p
= 0, type
= PBM_GRAY
;
8561 raw_p
= 0, type
= PBM_COLOR
;
8565 raw_p
= 1, type
= PBM_MONO
;
8569 raw_p
= 1, type
= PBM_GRAY
;
8573 raw_p
= 1, type
= PBM_COLOR
;
8577 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8581 /* Read width, height, maximum color-component. Characters
8582 starting with `#' up to the end of a line are ignored. */
8583 width
= pbm_scan_number (&p
, end
);
8584 height
= pbm_scan_number (&p
, end
);
8586 if (type
!= PBM_MONO
)
8588 max_color_idx
= pbm_scan_number (&p
, end
);
8589 if (raw_p
&& max_color_idx
> 255)
8590 max_color_idx
= 255;
8595 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8598 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8599 &ximg
, &img
->pixmap
))
8602 /* Initialize the color hash table. */
8603 init_color_table ();
8605 if (type
== PBM_MONO
)
8608 struct image_keyword fmt
[PBM_LAST
];
8609 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8610 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8612 /* Parse the image specification. */
8613 bcopy (pbm_format
, fmt
, sizeof fmt
);
8614 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8616 /* Get foreground and background colors, maybe allocate colors. */
8617 if (fmt
[PBM_FOREGROUND
].count
8618 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8619 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8620 if (fmt
[PBM_BACKGROUND
].count
8621 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8623 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8624 img
->background
= bg
;
8625 img
->background_valid
= 1;
8628 for (y
= 0; y
< height
; ++y
)
8629 for (x
= 0; x
< width
; ++x
)
8639 g
= pbm_scan_number (&p
, end
);
8641 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8646 for (y
= 0; y
< height
; ++y
)
8647 for (x
= 0; x
< width
; ++x
)
8651 if (type
== PBM_GRAY
)
8652 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8661 r
= pbm_scan_number (&p
, end
);
8662 g
= pbm_scan_number (&p
, end
);
8663 b
= pbm_scan_number (&p
, end
);
8666 if (r
< 0 || g
< 0 || b
< 0)
8670 XDestroyImage (ximg
);
8671 image_error ("Invalid pixel value in image `%s'",
8676 /* RGB values are now in the range 0..max_color_idx.
8677 Scale this to the range 0..0xffff supported by X. */
8678 r
= (double) r
* 65535 / max_color_idx
;
8679 g
= (double) g
* 65535 / max_color_idx
;
8680 b
= (double) b
* 65535 / max_color_idx
;
8681 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8685 /* Store in IMG->colors the colors allocated for the image, and
8686 free the color table. */
8687 img
->colors
= colors_in_color_table (&img
->ncolors
);
8688 free_color_table ();
8690 /* Maybe fill in the background field while we have ximg handy. */
8691 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8692 IMAGE_BACKGROUND (img
, f
, ximg
);
8694 /* Put the image into a pixmap. */
8695 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8696 x_destroy_x_image (ximg
);
8699 img
->height
= height
;
8708 /***********************************************************************
8710 ***********************************************************************/
8716 /* Function prototypes. */
8718 static int png_image_p
P_ ((Lisp_Object object
));
8719 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8721 /* The symbol `png' identifying images of this type. */
8725 /* Indices of image specification fields in png_format, below. */
8727 enum png_keyword_index
8742 /* Vector of image_keyword structures describing the format
8743 of valid user-defined image specifications. */
8745 static struct image_keyword png_format
[PNG_LAST
] =
8747 {":type", IMAGE_SYMBOL_VALUE
, 1},
8748 {":data", IMAGE_STRING_VALUE
, 0},
8749 {":file", IMAGE_STRING_VALUE
, 0},
8750 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8751 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8752 {":relief", IMAGE_INTEGER_VALUE
, 0},
8753 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8754 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8755 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8756 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8759 /* Structure describing the image type `png'. */
8761 static struct image_type png_type
=
8771 /* Return non-zero if OBJECT is a valid PNG image specification. */
8774 png_image_p (object
)
8777 struct image_keyword fmt
[PNG_LAST
];
8778 bcopy (png_format
, fmt
, sizeof fmt
);
8780 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8783 /* Must specify either the :data or :file keyword. */
8784 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8788 /* Error and warning handlers installed when the PNG library
8792 my_png_error (png_ptr
, msg
)
8793 png_struct
*png_ptr
;
8796 xassert (png_ptr
!= NULL
);
8797 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8798 longjmp (png_ptr
->jmpbuf
, 1);
8803 my_png_warning (png_ptr
, msg
)
8804 png_struct
*png_ptr
;
8807 xassert (png_ptr
!= NULL
);
8808 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8811 /* Memory source for PNG decoding. */
8813 struct png_memory_storage
8815 unsigned char *bytes
; /* The data */
8816 size_t len
; /* How big is it? */
8817 int index
; /* Where are we? */
8821 /* Function set as reader function when reading PNG image from memory.
8822 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8823 bytes from the input to DATA. */
8826 png_read_from_memory (png_ptr
, data
, length
)
8827 png_structp png_ptr
;
8831 struct png_memory_storage
*tbr
8832 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8834 if (length
> tbr
->len
- tbr
->index
)
8835 png_error (png_ptr
, "Read error");
8837 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8838 tbr
->index
= tbr
->index
+ length
;
8841 /* Load PNG image IMG for use on frame F. Value is non-zero if
8849 Lisp_Object file
, specified_file
;
8850 Lisp_Object specified_data
;
8852 XImage
*ximg
, *mask_img
= NULL
;
8853 struct gcpro gcpro1
;
8854 png_struct
*png_ptr
= NULL
;
8855 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8856 FILE *volatile fp
= NULL
;
8858 png_byte
* volatile pixels
= NULL
;
8859 png_byte
** volatile rows
= NULL
;
8860 png_uint_32 width
, height
;
8861 int bit_depth
, color_type
, interlace_type
;
8863 png_uint_32 row_bytes
;
8865 double screen_gamma
, image_gamma
;
8867 struct png_memory_storage tbr
; /* Data to be read */
8869 /* Find out what file to load. */
8870 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8871 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8875 if (NILP (specified_data
))
8877 file
= x_find_image_file (specified_file
);
8878 if (!STRINGP (file
))
8880 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8885 /* Open the image file. */
8886 fp
= fopen (SDATA (file
), "rb");
8889 image_error ("Cannot open image file `%s'", file
, Qnil
);
8895 /* Check PNG signature. */
8896 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8897 || !png_check_sig (sig
, sizeof sig
))
8899 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8907 /* Read from memory. */
8908 tbr
.bytes
= SDATA (specified_data
);
8909 tbr
.len
= SBYTES (specified_data
);
8912 /* Check PNG signature. */
8913 if (tbr
.len
< sizeof sig
8914 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8916 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8921 /* Need to skip past the signature. */
8922 tbr
.bytes
+= sizeof (sig
);
8925 /* Initialize read and info structs for PNG lib. */
8926 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8927 my_png_error
, my_png_warning
);
8930 if (fp
) fclose (fp
);
8935 info_ptr
= png_create_info_struct (png_ptr
);
8938 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8939 if (fp
) fclose (fp
);
8944 end_info
= png_create_info_struct (png_ptr
);
8947 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8948 if (fp
) fclose (fp
);
8953 /* Set error jump-back. We come back here when the PNG library
8954 detects an error. */
8955 if (setjmp (png_ptr
->jmpbuf
))
8959 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8962 if (fp
) fclose (fp
);
8967 /* Read image info. */
8968 if (!NILP (specified_data
))
8969 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
8971 png_init_io (png_ptr
, fp
);
8973 png_set_sig_bytes (png_ptr
, sizeof sig
);
8974 png_read_info (png_ptr
, info_ptr
);
8975 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8976 &interlace_type
, NULL
, NULL
);
8978 /* If image contains simply transparency data, we prefer to
8979 construct a clipping mask. */
8980 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8985 /* This function is easier to write if we only have to handle
8986 one data format: RGB or RGBA with 8 bits per channel. Let's
8987 transform other formats into that format. */
8989 /* Strip more than 8 bits per channel. */
8990 if (bit_depth
== 16)
8991 png_set_strip_16 (png_ptr
);
8993 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8995 png_set_expand (png_ptr
);
8997 /* Convert grayscale images to RGB. */
8998 if (color_type
== PNG_COLOR_TYPE_GRAY
8999 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
9000 png_set_gray_to_rgb (png_ptr
);
9002 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
9004 /* Tell the PNG lib to handle gamma correction for us. */
9006 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9007 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
9008 /* The libpng documentation says this is right in this case. */
9009 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9012 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
9013 /* Image contains gamma information. */
9014 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
9016 /* Use the standard default for the image gamma. */
9017 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9019 /* Handle alpha channel by combining the image with a background
9020 color. Do this only if a real alpha channel is supplied. For
9021 simple transparency, we prefer a clipping mask. */
9024 png_color_16
*image_bg
;
9025 Lisp_Object specified_bg
9026 = image_spec_value (img
->spec
, QCbackground
, NULL
);
9028 if (STRINGP (specified_bg
))
9029 /* The user specified `:background', use that. */
9032 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
9034 png_color_16 user_bg
;
9036 bzero (&user_bg
, sizeof user_bg
);
9037 user_bg
.red
= color
.red
;
9038 user_bg
.green
= color
.green
;
9039 user_bg
.blue
= color
.blue
;
9041 png_set_background (png_ptr
, &user_bg
,
9042 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9045 else if (png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
9046 /* Image contains a background color with which to
9047 combine the image. */
9048 png_set_background (png_ptr
, image_bg
,
9049 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
9052 /* Image does not contain a background color with which
9053 to combine the image data via an alpha channel. Use
9054 the frame's background instead. */
9057 png_color_16 frame_background
;
9059 cmap
= FRAME_X_COLORMAP (f
);
9060 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
9061 x_query_color (f
, &color
);
9063 bzero (&frame_background
, sizeof frame_background
);
9064 frame_background
.red
= color
.red
;
9065 frame_background
.green
= color
.green
;
9066 frame_background
.blue
= color
.blue
;
9068 png_set_background (png_ptr
, &frame_background
,
9069 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9073 /* Update info structure. */
9074 png_read_update_info (png_ptr
, info_ptr
);
9076 /* Get number of channels. Valid values are 1 for grayscale images
9077 and images with a palette, 2 for grayscale images with transparency
9078 information (alpha channel), 3 for RGB images, and 4 for RGB
9079 images with alpha channel, i.e. RGBA. If conversions above were
9080 sufficient we should only have 3 or 4 channels here. */
9081 channels
= png_get_channels (png_ptr
, info_ptr
);
9082 xassert (channels
== 3 || channels
== 4);
9084 /* Number of bytes needed for one row of the image. */
9085 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
9087 /* Allocate memory for the image. */
9088 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
9089 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
9090 for (i
= 0; i
< height
; ++i
)
9091 rows
[i
] = pixels
+ i
* row_bytes
;
9093 /* Read the entire image. */
9094 png_read_image (png_ptr
, rows
);
9095 png_read_end (png_ptr
, info_ptr
);
9102 /* Create the X image and pixmap. */
9103 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
9107 /* Create an image and pixmap serving as mask if the PNG image
9108 contains an alpha channel. */
9111 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
9112 &mask_img
, &img
->mask
))
9114 x_destroy_x_image (ximg
);
9115 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
9120 /* Fill the X image and mask from PNG data. */
9121 init_color_table ();
9123 for (y
= 0; y
< height
; ++y
)
9125 png_byte
*p
= rows
[y
];
9127 for (x
= 0; x
< width
; ++x
)
9134 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
9136 /* An alpha channel, aka mask channel, associates variable
9137 transparency with an image. Where other image formats
9138 support binary transparency---fully transparent or fully
9139 opaque---PNG allows up to 254 levels of partial transparency.
9140 The PNG library implements partial transparency by combining
9141 the image with a specified background color.
9143 I'm not sure how to handle this here nicely: because the
9144 background on which the image is displayed may change, for
9145 real alpha channel support, it would be necessary to create
9146 a new image for each possible background.
9148 What I'm doing now is that a mask is created if we have
9149 boolean transparency information. Otherwise I'm using
9150 the frame's background color to combine the image with. */
9155 XPutPixel (mask_img
, x
, y
, *p
> 0);
9161 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9162 /* Set IMG's background color from the PNG image, unless the user
9166 if (png_get_bKGD (png_ptr
, info_ptr
, &bg
))
9168 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
9169 img
->background_valid
= 1;
9173 /* Remember colors allocated for this image. */
9174 img
->colors
= colors_in_color_table (&img
->ncolors
);
9175 free_color_table ();
9178 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9183 img
->height
= height
;
9185 /* Maybe fill in the background field while we have ximg handy. */
9186 IMAGE_BACKGROUND (img
, f
, ximg
);
9188 /* Put the image into the pixmap, then free the X image and its buffer. */
9189 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9190 x_destroy_x_image (ximg
);
9192 /* Same for the mask. */
9195 /* Fill in the background_transparent field while we have the mask
9197 image_background_transparent (img
, f
, mask_img
);
9199 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
9200 x_destroy_x_image (mask_img
);
9207 #endif /* HAVE_PNG != 0 */
9211 /***********************************************************************
9213 ***********************************************************************/
9217 /* Work around a warning about HAVE_STDLIB_H being redefined in
9219 #ifdef HAVE_STDLIB_H
9220 #define HAVE_STDLIB_H_1
9221 #undef HAVE_STDLIB_H
9222 #endif /* HAVE_STLIB_H */
9224 #include <jpeglib.h>
9228 #ifdef HAVE_STLIB_H_1
9229 #define HAVE_STDLIB_H 1
9232 static int jpeg_image_p
P_ ((Lisp_Object object
));
9233 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
9235 /* The symbol `jpeg' identifying images of this type. */
9239 /* Indices of image specification fields in gs_format, below. */
9241 enum jpeg_keyword_index
9250 JPEG_HEURISTIC_MASK
,
9256 /* Vector of image_keyword structures describing the format
9257 of valid user-defined image specifications. */
9259 static struct image_keyword jpeg_format
[JPEG_LAST
] =
9261 {":type", IMAGE_SYMBOL_VALUE
, 1},
9262 {":data", IMAGE_STRING_VALUE
, 0},
9263 {":file", IMAGE_STRING_VALUE
, 0},
9264 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9265 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9266 {":relief", IMAGE_INTEGER_VALUE
, 0},
9267 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9268 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9269 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9270 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9273 /* Structure describing the image type `jpeg'. */
9275 static struct image_type jpeg_type
=
9285 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9288 jpeg_image_p (object
)
9291 struct image_keyword fmt
[JPEG_LAST
];
9293 bcopy (jpeg_format
, fmt
, sizeof fmt
);
9295 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
9298 /* Must specify either the :data or :file keyword. */
9299 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9303 struct my_jpeg_error_mgr
9305 struct jpeg_error_mgr pub
;
9306 jmp_buf setjmp_buffer
;
9311 my_error_exit (cinfo
)
9314 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9315 longjmp (mgr
->setjmp_buffer
, 1);
9319 /* Init source method for JPEG data source manager. Called by
9320 jpeg_read_header() before any data is actually read. See
9321 libjpeg.doc from the JPEG lib distribution. */
9324 our_init_source (cinfo
)
9325 j_decompress_ptr cinfo
;
9330 /* Fill input buffer method for JPEG data source manager. Called
9331 whenever more data is needed. We read the whole image in one step,
9332 so this only adds a fake end of input marker at the end. */
9335 our_fill_input_buffer (cinfo
)
9336 j_decompress_ptr cinfo
;
9338 /* Insert a fake EOI marker. */
9339 struct jpeg_source_mgr
*src
= cinfo
->src
;
9340 static JOCTET buffer
[2];
9342 buffer
[0] = (JOCTET
) 0xFF;
9343 buffer
[1] = (JOCTET
) JPEG_EOI
;
9345 src
->next_input_byte
= buffer
;
9346 src
->bytes_in_buffer
= 2;
9351 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9352 is the JPEG data source manager. */
9355 our_skip_input_data (cinfo
, num_bytes
)
9356 j_decompress_ptr cinfo
;
9359 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9363 if (num_bytes
> src
->bytes_in_buffer
)
9364 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9366 src
->bytes_in_buffer
-= num_bytes
;
9367 src
->next_input_byte
+= num_bytes
;
9372 /* Method to terminate data source. Called by
9373 jpeg_finish_decompress() after all data has been processed. */
9376 our_term_source (cinfo
)
9377 j_decompress_ptr cinfo
;
9382 /* Set up the JPEG lib for reading an image from DATA which contains
9383 LEN bytes. CINFO is the decompression info structure created for
9384 reading the image. */
9387 jpeg_memory_src (cinfo
, data
, len
)
9388 j_decompress_ptr cinfo
;
9392 struct jpeg_source_mgr
*src
;
9394 if (cinfo
->src
== NULL
)
9396 /* First time for this JPEG object? */
9397 cinfo
->src
= (struct jpeg_source_mgr
*)
9398 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9399 sizeof (struct jpeg_source_mgr
));
9400 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9401 src
->next_input_byte
= data
;
9404 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9405 src
->init_source
= our_init_source
;
9406 src
->fill_input_buffer
= our_fill_input_buffer
;
9407 src
->skip_input_data
= our_skip_input_data
;
9408 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9409 src
->term_source
= our_term_source
;
9410 src
->bytes_in_buffer
= len
;
9411 src
->next_input_byte
= data
;
9415 /* Load image IMG for use on frame F. Patterned after example.c
9416 from the JPEG lib. */
9423 struct jpeg_decompress_struct cinfo
;
9424 struct my_jpeg_error_mgr mgr
;
9425 Lisp_Object file
, specified_file
;
9426 Lisp_Object specified_data
;
9427 FILE * volatile fp
= NULL
;
9429 int row_stride
, x
, y
;
9430 XImage
*ximg
= NULL
;
9432 unsigned long *colors
;
9434 struct gcpro gcpro1
;
9436 /* Open the JPEG file. */
9437 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9438 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9442 if (NILP (specified_data
))
9444 file
= x_find_image_file (specified_file
);
9445 if (!STRINGP (file
))
9447 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9452 fp
= fopen (SDATA (file
), "r");
9455 image_error ("Cannot open `%s'", file
, Qnil
);
9461 /* Customize libjpeg's error handling to call my_error_exit when an
9462 error is detected. This function will perform a longjmp. */
9463 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9464 mgr
.pub
.error_exit
= my_error_exit
;
9466 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9470 /* Called from my_error_exit. Display a JPEG error. */
9471 char buffer
[JMSG_LENGTH_MAX
];
9472 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9473 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9474 build_string (buffer
));
9477 /* Close the input file and destroy the JPEG object. */
9479 fclose ((FILE *) fp
);
9480 jpeg_destroy_decompress (&cinfo
);
9482 /* If we already have an XImage, free that. */
9483 x_destroy_x_image (ximg
);
9485 /* Free pixmap and colors. */
9486 x_clear_image (f
, img
);
9492 /* Create the JPEG decompression object. Let it read from fp.
9493 Read the JPEG image header. */
9494 jpeg_create_decompress (&cinfo
);
9496 if (NILP (specified_data
))
9497 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9499 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
9500 SBYTES (specified_data
));
9502 jpeg_read_header (&cinfo
, TRUE
);
9504 /* Customize decompression so that color quantization will be used.
9505 Start decompression. */
9506 cinfo
.quantize_colors
= TRUE
;
9507 jpeg_start_decompress (&cinfo
);
9508 width
= img
->width
= cinfo
.output_width
;
9509 height
= img
->height
= cinfo
.output_height
;
9511 /* Create X image and pixmap. */
9512 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9513 longjmp (mgr
.setjmp_buffer
, 2);
9515 /* Allocate colors. When color quantization is used,
9516 cinfo.actual_number_of_colors has been set with the number of
9517 colors generated, and cinfo.colormap is a two-dimensional array
9518 of color indices in the range 0..cinfo.actual_number_of_colors.
9519 No more than 255 colors will be generated. */
9523 if (cinfo
.out_color_components
> 2)
9524 ir
= 0, ig
= 1, ib
= 2;
9525 else if (cinfo
.out_color_components
> 1)
9526 ir
= 0, ig
= 1, ib
= 0;
9528 ir
= 0, ig
= 0, ib
= 0;
9530 /* Use the color table mechanism because it handles colors that
9531 cannot be allocated nicely. Such colors will be replaced with
9532 a default color, and we don't have to care about which colors
9533 can be freed safely, and which can't. */
9534 init_color_table ();
9535 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9538 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9540 /* Multiply RGB values with 255 because X expects RGB values
9541 in the range 0..0xffff. */
9542 int r
= cinfo
.colormap
[ir
][i
] << 8;
9543 int g
= cinfo
.colormap
[ig
][i
] << 8;
9544 int b
= cinfo
.colormap
[ib
][i
] << 8;
9545 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9548 /* Remember those colors actually allocated. */
9549 img
->colors
= colors_in_color_table (&img
->ncolors
);
9550 free_color_table ();
9554 row_stride
= width
* cinfo
.output_components
;
9555 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9557 for (y
= 0; y
< height
; ++y
)
9559 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9560 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9561 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9565 jpeg_finish_decompress (&cinfo
);
9566 jpeg_destroy_decompress (&cinfo
);
9568 fclose ((FILE *) fp
);
9570 /* Maybe fill in the background field while we have ximg handy. */
9571 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9572 IMAGE_BACKGROUND (img
, f
, ximg
);
9574 /* Put the image into the pixmap. */
9575 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9576 x_destroy_x_image (ximg
);
9581 #endif /* HAVE_JPEG */
9585 /***********************************************************************
9587 ***********************************************************************/
9593 static int tiff_image_p
P_ ((Lisp_Object object
));
9594 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9596 /* The symbol `tiff' identifying images of this type. */
9600 /* Indices of image specification fields in tiff_format, below. */
9602 enum tiff_keyword_index
9611 TIFF_HEURISTIC_MASK
,
9617 /* Vector of image_keyword structures describing the format
9618 of valid user-defined image specifications. */
9620 static struct image_keyword tiff_format
[TIFF_LAST
] =
9622 {":type", IMAGE_SYMBOL_VALUE
, 1},
9623 {":data", IMAGE_STRING_VALUE
, 0},
9624 {":file", IMAGE_STRING_VALUE
, 0},
9625 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9626 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9627 {":relief", IMAGE_INTEGER_VALUE
, 0},
9628 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9629 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9630 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9631 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9634 /* Structure describing the image type `tiff'. */
9636 static struct image_type tiff_type
=
9646 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9649 tiff_image_p (object
)
9652 struct image_keyword fmt
[TIFF_LAST
];
9653 bcopy (tiff_format
, fmt
, sizeof fmt
);
9655 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9658 /* Must specify either the :data or :file keyword. */
9659 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9663 /* Reading from a memory buffer for TIFF images Based on the PNG
9664 memory source, but we have to provide a lot of extra functions.
9667 We really only need to implement read and seek, but I am not
9668 convinced that the TIFF library is smart enough not to destroy
9669 itself if we only hand it the function pointers we need to
9674 unsigned char *bytes
;
9682 tiff_read_from_memory (data
, buf
, size
)
9687 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9689 if (size
> src
->len
- src
->index
)
9691 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9698 tiff_write_from_memory (data
, buf
, size
)
9708 tiff_seek_in_memory (data
, off
, whence
)
9713 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9718 case SEEK_SET
: /* Go from beginning of source. */
9722 case SEEK_END
: /* Go from end of source. */
9723 idx
= src
->len
+ off
;
9726 case SEEK_CUR
: /* Go from current position. */
9727 idx
= src
->index
+ off
;
9730 default: /* Invalid `whence'. */
9734 if (idx
> src
->len
|| idx
< 0)
9743 tiff_close_memory (data
)
9752 tiff_mmap_memory (data
, pbase
, psize
)
9757 /* It is already _IN_ memory. */
9763 tiff_unmap_memory (data
, base
, size
)
9768 /* We don't need to do this. */
9773 tiff_size_of_memory (data
)
9776 return ((tiff_memory_source
*) data
)->len
;
9781 tiff_error_handler (title
, format
, ap
)
9782 const char *title
, *format
;
9788 len
= sprintf (buf
, "TIFF error: %s ", title
);
9789 vsprintf (buf
+ len
, format
, ap
);
9790 add_to_log (buf
, Qnil
, Qnil
);
9795 tiff_warning_handler (title
, format
, ap
)
9796 const char *title
, *format
;
9802 len
= sprintf (buf
, "TIFF warning: %s ", title
);
9803 vsprintf (buf
+ len
, format
, ap
);
9804 add_to_log (buf
, Qnil
, Qnil
);
9808 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9816 Lisp_Object file
, specified_file
;
9817 Lisp_Object specified_data
;
9819 int width
, height
, x
, y
;
9823 struct gcpro gcpro1
;
9824 tiff_memory_source memsrc
;
9826 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9827 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9831 TIFFSetErrorHandler (tiff_error_handler
);
9832 TIFFSetWarningHandler (tiff_warning_handler
);
9834 if (NILP (specified_data
))
9836 /* Read from a file */
9837 file
= x_find_image_file (specified_file
);
9838 if (!STRINGP (file
))
9840 image_error ("Cannot find image file `%s'", file
, Qnil
);
9845 /* Try to open the image file. */
9846 tiff
= TIFFOpen (SDATA (file
), "r");
9849 image_error ("Cannot open `%s'", file
, Qnil
);
9856 /* Memory source! */
9857 memsrc
.bytes
= SDATA (specified_data
);
9858 memsrc
.len
= SBYTES (specified_data
);
9861 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9862 (TIFFReadWriteProc
) tiff_read_from_memory
,
9863 (TIFFReadWriteProc
) tiff_write_from_memory
,
9864 tiff_seek_in_memory
,
9866 tiff_size_of_memory
,
9872 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9878 /* Get width and height of the image, and allocate a raster buffer
9879 of width x height 32-bit values. */
9880 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9881 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9882 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9884 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9888 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9894 /* Create the X image and pixmap. */
9895 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9902 /* Initialize the color table. */
9903 init_color_table ();
9905 /* Process the pixel raster. Origin is in the lower-left corner. */
9906 for (y
= 0; y
< height
; ++y
)
9908 uint32
*row
= buf
+ y
* width
;
9910 for (x
= 0; x
< width
; ++x
)
9912 uint32 abgr
= row
[x
];
9913 int r
= TIFFGetR (abgr
) << 8;
9914 int g
= TIFFGetG (abgr
) << 8;
9915 int b
= TIFFGetB (abgr
) << 8;
9916 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9920 /* Remember the colors allocated for the image. Free the color table. */
9921 img
->colors
= colors_in_color_table (&img
->ncolors
);
9922 free_color_table ();
9925 img
->height
= height
;
9927 /* Maybe fill in the background field while we have ximg handy. */
9928 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9929 IMAGE_BACKGROUND (img
, f
, ximg
);
9931 /* Put the image into the pixmap, then free the X image and its buffer. */
9932 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9933 x_destroy_x_image (ximg
);
9940 #endif /* HAVE_TIFF != 0 */
9944 /***********************************************************************
9946 ***********************************************************************/
9950 #include <gif_lib.h>
9952 static int gif_image_p
P_ ((Lisp_Object object
));
9953 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9955 /* The symbol `gif' identifying images of this type. */
9959 /* Indices of image specification fields in gif_format, below. */
9961 enum gif_keyword_index
9977 /* Vector of image_keyword structures describing the format
9978 of valid user-defined image specifications. */
9980 static struct image_keyword gif_format
[GIF_LAST
] =
9982 {":type", IMAGE_SYMBOL_VALUE
, 1},
9983 {":data", IMAGE_STRING_VALUE
, 0},
9984 {":file", IMAGE_STRING_VALUE
, 0},
9985 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9986 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9987 {":relief", IMAGE_INTEGER_VALUE
, 0},
9988 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9989 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9990 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9991 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
9992 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9995 /* Structure describing the image type `gif'. */
9997 static struct image_type gif_type
=
10007 /* Return non-zero if OBJECT is a valid GIF image specification. */
10010 gif_image_p (object
)
10011 Lisp_Object object
;
10013 struct image_keyword fmt
[GIF_LAST
];
10014 bcopy (gif_format
, fmt
, sizeof fmt
);
10016 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
10019 /* Must specify either the :data or :file keyword. */
10020 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
10024 /* Reading a GIF image from memory
10025 Based on the PNG memory stuff to a certain extent. */
10029 unsigned char *bytes
;
10036 /* Make the current memory source available to gif_read_from_memory.
10037 It's done this way because not all versions of libungif support
10038 a UserData field in the GifFileType structure. */
10039 static gif_memory_source
*current_gif_memory_src
;
10042 gif_read_from_memory (file
, buf
, len
)
10047 gif_memory_source
*src
= current_gif_memory_src
;
10049 if (len
> src
->len
- src
->index
)
10052 bcopy (src
->bytes
+ src
->index
, buf
, len
);
10058 /* Load GIF image IMG for use on frame F. Value is non-zero if
10066 Lisp_Object file
, specified_file
;
10067 Lisp_Object specified_data
;
10068 int rc
, width
, height
, x
, y
, i
;
10070 ColorMapObject
*gif_color_map
;
10071 unsigned long pixel_colors
[256];
10073 struct gcpro gcpro1
;
10075 int ino
, image_left
, image_top
, image_width
, image_height
;
10076 gif_memory_source memsrc
;
10077 unsigned char *raster
;
10079 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10080 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10084 if (NILP (specified_data
))
10086 file
= x_find_image_file (specified_file
);
10087 if (!STRINGP (file
))
10089 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
10094 /* Open the GIF file. */
10095 gif
= DGifOpenFileName (SDATA (file
));
10098 image_error ("Cannot open `%s'", file
, Qnil
);
10105 /* Read from memory! */
10106 current_gif_memory_src
= &memsrc
;
10107 memsrc
.bytes
= SDATA (specified_data
);
10108 memsrc
.len
= SBYTES (specified_data
);
10111 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
10114 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
10120 /* Read entire contents. */
10121 rc
= DGifSlurp (gif
);
10122 if (rc
== GIF_ERROR
)
10124 image_error ("Error reading `%s'", img
->spec
, Qnil
);
10125 DGifCloseFile (gif
);
10130 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
10131 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
10132 if (ino
>= gif
->ImageCount
)
10134 image_error ("Invalid image number `%s' in image `%s'",
10136 DGifCloseFile (gif
);
10141 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
10142 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
10144 /* Create the X image and pixmap. */
10145 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
10147 DGifCloseFile (gif
);
10152 /* Allocate colors. */
10153 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
10154 if (!gif_color_map
)
10155 gif_color_map
= gif
->SColorMap
;
10156 init_color_table ();
10157 bzero (pixel_colors
, sizeof pixel_colors
);
10159 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
10161 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
10162 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
10163 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
10164 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
10167 img
->colors
= colors_in_color_table (&img
->ncolors
);
10168 free_color_table ();
10170 /* Clear the part of the screen image that are not covered by
10171 the image from the GIF file. Full animated GIF support
10172 requires more than can be done here (see the gif89 spec,
10173 disposal methods). Let's simply assume that the part
10174 not covered by a sub-image is in the frame's background color. */
10175 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
10176 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
10177 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
10178 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
10180 for (y
= 0; y
< image_top
; ++y
)
10181 for (x
= 0; x
< width
; ++x
)
10182 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10184 for (y
= image_top
+ image_height
; y
< height
; ++y
)
10185 for (x
= 0; x
< width
; ++x
)
10186 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10188 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
10190 for (x
= 0; x
< image_left
; ++x
)
10191 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10192 for (x
= image_left
+ image_width
; x
< width
; ++x
)
10193 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10196 /* Read the GIF image into the X image. We use a local variable
10197 `raster' here because RasterBits below is a char *, and invites
10198 problems with bytes >= 0x80. */
10199 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
10201 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
10203 static int interlace_start
[] = {0, 4, 2, 1};
10204 static int interlace_increment
[] = {8, 8, 4, 2};
10206 int row
= interlace_start
[0];
10210 for (y
= 0; y
< image_height
; y
++)
10212 if (row
>= image_height
)
10214 row
= interlace_start
[++pass
];
10215 while (row
>= image_height
)
10216 row
= interlace_start
[++pass
];
10219 for (x
= 0; x
< image_width
; x
++)
10221 int i
= raster
[(y
* image_width
) + x
];
10222 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
10226 row
+= interlace_increment
[pass
];
10231 for (y
= 0; y
< image_height
; ++y
)
10232 for (x
= 0; x
< image_width
; ++x
)
10234 int i
= raster
[y
* image_width
+ x
];
10235 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
10239 DGifCloseFile (gif
);
10241 /* Maybe fill in the background field while we have ximg handy. */
10242 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
10243 IMAGE_BACKGROUND (img
, f
, ximg
);
10245 /* Put the image into the pixmap, then free the X image and its buffer. */
10246 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10247 x_destroy_x_image (ximg
);
10253 #endif /* HAVE_GIF != 0 */
10257 /***********************************************************************
10259 ***********************************************************************/
10261 static int gs_image_p
P_ ((Lisp_Object object
));
10262 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
10263 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
10265 /* The symbol `postscript' identifying images of this type. */
10267 Lisp_Object Qpostscript
;
10269 /* Keyword symbols. */
10271 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
10273 /* Indices of image specification fields in gs_format, below. */
10275 enum gs_keyword_index
10293 /* Vector of image_keyword structures describing the format
10294 of valid user-defined image specifications. */
10296 static struct image_keyword gs_format
[GS_LAST
] =
10298 {":type", IMAGE_SYMBOL_VALUE
, 1},
10299 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10300 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10301 {":file", IMAGE_STRING_VALUE
, 1},
10302 {":loader", IMAGE_FUNCTION_VALUE
, 0},
10303 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
10304 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10305 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10306 {":relief", IMAGE_INTEGER_VALUE
, 0},
10307 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10308 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10309 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10310 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10313 /* Structure describing the image type `ghostscript'. */
10315 static struct image_type gs_type
=
10325 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10328 gs_clear_image (f
, img
)
10332 /* IMG->data.ptr_val may contain a recorded colormap. */
10333 xfree (img
->data
.ptr_val
);
10334 x_clear_image (f
, img
);
10338 /* Return non-zero if OBJECT is a valid Ghostscript image
10342 gs_image_p (object
)
10343 Lisp_Object object
;
10345 struct image_keyword fmt
[GS_LAST
];
10349 bcopy (gs_format
, fmt
, sizeof fmt
);
10351 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10354 /* Bounding box must be a list or vector containing 4 integers. */
10355 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10358 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10359 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10364 else if (VECTORP (tem
))
10366 if (XVECTOR (tem
)->size
!= 4)
10368 for (i
= 0; i
< 4; ++i
)
10369 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10379 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10388 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10389 struct gcpro gcpro1
, gcpro2
;
10391 double in_width
, in_height
;
10392 Lisp_Object pixel_colors
= Qnil
;
10394 /* Compute pixel size of pixmap needed from the given size in the
10395 image specification. Sizes in the specification are in pt. 1 pt
10396 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10398 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10399 in_width
= XFASTINT (pt_width
) / 72.0;
10400 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10401 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10402 in_height
= XFASTINT (pt_height
) / 72.0;
10403 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10405 /* Create the pixmap. */
10406 xassert (img
->pixmap
== None
);
10407 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10408 img
->width
, img
->height
,
10409 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10413 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10417 /* Call the loader to fill the pixmap. It returns a process object
10418 if successful. We do not record_unwind_protect here because
10419 other places in redisplay like calling window scroll functions
10420 don't either. Let the Lisp loader use `unwind-protect' instead. */
10421 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10423 sprintf (buffer
, "%lu %lu",
10424 (unsigned long) FRAME_X_WINDOW (f
),
10425 (unsigned long) img
->pixmap
);
10426 window_and_pixmap_id
= build_string (buffer
);
10428 sprintf (buffer
, "%lu %lu",
10429 FRAME_FOREGROUND_PIXEL (f
),
10430 FRAME_BACKGROUND_PIXEL (f
));
10431 pixel_colors
= build_string (buffer
);
10433 XSETFRAME (frame
, f
);
10434 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10436 loader
= intern ("gs-load-image");
10438 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10439 make_number (img
->width
),
10440 make_number (img
->height
),
10441 window_and_pixmap_id
,
10444 return PROCESSP (img
->data
.lisp_val
);
10448 /* Kill the Ghostscript process that was started to fill PIXMAP on
10449 frame F. Called from XTread_socket when receiving an event
10450 telling Emacs that Ghostscript has finished drawing. */
10453 x_kill_gs_process (pixmap
, f
)
10457 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10461 /* Find the image containing PIXMAP. */
10462 for (i
= 0; i
< c
->used
; ++i
)
10463 if (c
->images
[i
]->pixmap
== pixmap
)
10466 /* Should someone in between have cleared the image cache, for
10467 instance, give up. */
10471 /* Kill the GS process. We should have found PIXMAP in the image
10472 cache and its image should contain a process object. */
10473 img
= c
->images
[i
];
10474 xassert (PROCESSP (img
->data
.lisp_val
));
10475 Fkill_process (img
->data
.lisp_val
, Qnil
);
10476 img
->data
.lisp_val
= Qnil
;
10478 /* On displays with a mutable colormap, figure out the colors
10479 allocated for the image by looking at the pixels of an XImage for
10481 class = FRAME_X_VISUAL (f
)->class;
10482 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10488 /* Try to get an XImage for img->pixmep. */
10489 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10490 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10495 /* Initialize the color table. */
10496 init_color_table ();
10498 /* For each pixel of the image, look its color up in the
10499 color table. After having done so, the color table will
10500 contain an entry for each color used by the image. */
10501 for (y
= 0; y
< img
->height
; ++y
)
10502 for (x
= 0; x
< img
->width
; ++x
)
10504 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10505 lookup_pixel_color (f
, pixel
);
10508 /* Record colors in the image. Free color table and XImage. */
10509 img
->colors
= colors_in_color_table (&img
->ncolors
);
10510 free_color_table ();
10511 XDestroyImage (ximg
);
10513 #if 0 /* This doesn't seem to be the case. If we free the colors
10514 here, we get a BadAccess later in x_clear_image when
10515 freeing the colors. */
10516 /* We have allocated colors once, but Ghostscript has also
10517 allocated colors on behalf of us. So, to get the
10518 reference counts right, free them once. */
10520 x_free_colors (f
, img
->colors
, img
->ncolors
);
10524 image_error ("Cannot get X image of `%s'; colors will not be freed",
10530 /* Now that we have the pixmap, compute mask and transform the
10531 image if requested. */
10533 postprocess_image (f
, img
);
10539 /***********************************************************************
10541 ***********************************************************************/
10543 DEFUN ("x-change-window-property", Fx_change_window_property
,
10544 Sx_change_window_property
, 2, 3, 0,
10545 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
10546 PROP and VALUE must be strings. FRAME nil or omitted means use the
10547 selected frame. Value is VALUE. */)
10548 (prop
, value
, frame
)
10549 Lisp_Object frame
, prop
, value
;
10551 struct frame
*f
= check_x_frame (frame
);
10554 CHECK_STRING (prop
);
10555 CHECK_STRING (value
);
10558 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10559 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10560 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10561 SDATA (value
), SCHARS (value
));
10563 /* Make sure the property is set when we return. */
10564 XFlush (FRAME_X_DISPLAY (f
));
10571 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10572 Sx_delete_window_property
, 1, 2, 0,
10573 doc
: /* Remove window property PROP from X window of FRAME.
10574 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10576 Lisp_Object prop
, frame
;
10578 struct frame
*f
= check_x_frame (frame
);
10581 CHECK_STRING (prop
);
10583 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10584 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10586 /* Make sure the property is removed when we return. */
10587 XFlush (FRAME_X_DISPLAY (f
));
10594 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10596 doc
: /* Value is the value of window property PROP on FRAME.
10597 If FRAME is nil or omitted, use the selected frame. Value is nil
10598 if FRAME hasn't a property with name PROP or if PROP has no string
10601 Lisp_Object prop
, frame
;
10603 struct frame
*f
= check_x_frame (frame
);
10606 Lisp_Object prop_value
= Qnil
;
10607 char *tmp_data
= NULL
;
10610 unsigned long actual_size
, bytes_remaining
;
10612 CHECK_STRING (prop
);
10614 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10615 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10616 prop_atom
, 0, 0, False
, XA_STRING
,
10617 &actual_type
, &actual_format
, &actual_size
,
10618 &bytes_remaining
, (unsigned char **) &tmp_data
);
10621 int size
= bytes_remaining
;
10626 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10627 prop_atom
, 0, bytes_remaining
,
10629 &actual_type
, &actual_format
,
10630 &actual_size
, &bytes_remaining
,
10631 (unsigned char **) &tmp_data
);
10632 if (rc
== Success
&& tmp_data
)
10633 prop_value
= make_string (tmp_data
, size
);
10644 /***********************************************************************
10646 ***********************************************************************/
10648 /* If non-null, an asynchronous timer that, when it expires, displays
10649 an hourglass cursor on all frames. */
10651 static struct atimer
*hourglass_atimer
;
10653 /* Non-zero means an hourglass cursor is currently shown. */
10655 static int hourglass_shown_p
;
10657 /* Number of seconds to wait before displaying an hourglass cursor. */
10659 static Lisp_Object Vhourglass_delay
;
10661 /* Default number of seconds to wait before displaying an hourglass
10664 #define DEFAULT_HOURGLASS_DELAY 1
10666 /* Function prototypes. */
10668 static void show_hourglass
P_ ((struct atimer
*));
10669 static void hide_hourglass
P_ ((void));
10672 /* Cancel a currently active hourglass timer, and start a new one. */
10678 int secs
, usecs
= 0;
10680 cancel_hourglass ();
10682 if (INTEGERP (Vhourglass_delay
)
10683 && XINT (Vhourglass_delay
) > 0)
10684 secs
= XFASTINT (Vhourglass_delay
);
10685 else if (FLOATP (Vhourglass_delay
)
10686 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10689 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10690 secs
= XFASTINT (tem
);
10691 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10694 secs
= DEFAULT_HOURGLASS_DELAY
;
10696 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10697 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10698 show_hourglass
, NULL
);
10702 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10706 cancel_hourglass ()
10708 if (hourglass_atimer
)
10710 cancel_atimer (hourglass_atimer
);
10711 hourglass_atimer
= NULL
;
10714 if (hourglass_shown_p
)
10719 /* Timer function of hourglass_atimer. TIMER is equal to
10722 Display an hourglass pointer on all frames by mapping the frames'
10723 hourglass_window. Set the hourglass_p flag in the frames'
10724 output_data.x structure to indicate that an hourglass cursor is
10725 shown on the frames. */
10728 show_hourglass (timer
)
10729 struct atimer
*timer
;
10731 /* The timer implementation will cancel this timer automatically
10732 after this function has run. Set hourglass_atimer to null
10733 so that we know the timer doesn't have to be canceled. */
10734 hourglass_atimer
= NULL
;
10736 if (!hourglass_shown_p
)
10738 Lisp_Object rest
, frame
;
10742 FOR_EACH_FRAME (rest
, frame
)
10744 struct frame
*f
= XFRAME (frame
);
10746 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10748 Display
*dpy
= FRAME_X_DISPLAY (f
);
10750 #ifdef USE_X_TOOLKIT
10751 if (f
->output_data
.x
->widget
)
10753 if (FRAME_OUTER_WINDOW (f
))
10756 f
->output_data
.x
->hourglass_p
= 1;
10758 if (!f
->output_data
.x
->hourglass_window
)
10760 unsigned long mask
= CWCursor
;
10761 XSetWindowAttributes attrs
;
10763 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10765 f
->output_data
.x
->hourglass_window
10766 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10767 0, 0, 32000, 32000, 0, 0,
10773 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10779 hourglass_shown_p
= 1;
10785 /* Hide the hourglass pointer on all frames, if it is currently
10791 if (hourglass_shown_p
)
10793 Lisp_Object rest
, frame
;
10796 FOR_EACH_FRAME (rest
, frame
)
10798 struct frame
*f
= XFRAME (frame
);
10801 /* Watch out for newly created frames. */
10802 && f
->output_data
.x
->hourglass_window
)
10804 XUnmapWindow (FRAME_X_DISPLAY (f
),
10805 f
->output_data
.x
->hourglass_window
);
10806 /* Sync here because XTread_socket looks at the
10807 hourglass_p flag that is reset to zero below. */
10808 XSync (FRAME_X_DISPLAY (f
), False
);
10809 f
->output_data
.x
->hourglass_p
= 0;
10813 hourglass_shown_p
= 0;
10820 /***********************************************************************
10822 ***********************************************************************/
10824 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10825 Lisp_Object
, Lisp_Object
));
10826 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10827 Lisp_Object
, int, int, int *, int *));
10829 /* The frame of a currently visible tooltip. */
10831 Lisp_Object tip_frame
;
10833 /* If non-nil, a timer started that hides the last tooltip when it
10836 Lisp_Object tip_timer
;
10839 /* If non-nil, a vector of 3 elements containing the last args
10840 with which x-show-tip was called. See there. */
10842 Lisp_Object last_show_tip_args
;
10844 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10846 Lisp_Object Vx_max_tooltip_size
;
10850 unwind_create_tip_frame (frame
)
10853 Lisp_Object deleted
;
10855 deleted
= unwind_create_frame (frame
);
10856 if (EQ (deleted
, Qt
))
10866 /* Create a frame for a tooltip on the display described by DPYINFO.
10867 PARMS is a list of frame parameters. TEXT is the string to
10868 display in the tip frame. Value is the frame.
10870 Note that functions called here, esp. x_default_parameter can
10871 signal errors, for instance when a specified color name is
10872 undefined. We have to make sure that we're in a consistent state
10873 when this happens. */
10876 x_create_tip_frame (dpyinfo
, parms
, text
)
10877 struct x_display_info
*dpyinfo
;
10878 Lisp_Object parms
, text
;
10881 Lisp_Object frame
, tem
;
10883 long window_prompting
= 0;
10885 int count
= SPECPDL_INDEX ();
10886 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10888 int face_change_count_before
= face_change_count
;
10889 Lisp_Object buffer
;
10890 struct buffer
*old_buffer
;
10894 /* Use this general default value to start with until we know if
10895 this frame has a specified name. */
10896 Vx_resource_name
= Vinvocation_name
;
10898 #ifdef MULTI_KBOARD
10899 kb
= dpyinfo
->kboard
;
10901 kb
= &the_only_kboard
;
10904 /* Get the name of the frame to use for resource lookup. */
10905 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10906 if (!STRINGP (name
)
10907 && !EQ (name
, Qunbound
)
10909 error ("Invalid frame name--not a string or nil");
10910 Vx_resource_name
= name
;
10913 GCPRO3 (parms
, name
, frame
);
10914 f
= make_frame (1);
10915 XSETFRAME (frame
, f
);
10917 buffer
= Fget_buffer_create (build_string (" *tip*"));
10918 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10919 old_buffer
= current_buffer
;
10920 set_buffer_internal_1 (XBUFFER (buffer
));
10921 current_buffer
->truncate_lines
= Qnil
;
10923 Finsert (1, &text
);
10924 set_buffer_internal_1 (old_buffer
);
10926 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10927 record_unwind_protect (unwind_create_tip_frame
, frame
);
10929 /* By setting the output method, we're essentially saying that
10930 the frame is live, as per FRAME_LIVE_P. If we get a signal
10931 from this point on, x_destroy_window might screw up reference
10933 f
->output_method
= output_x_window
;
10934 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10935 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10936 f
->output_data
.x
->icon_bitmap
= -1;
10937 f
->output_data
.x
->fontset
= -1;
10938 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10939 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10940 #ifdef USE_TOOLKIT_SCROLL_BARS
10941 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
10942 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
10943 #endif /* USE_TOOLKIT_SCROLL_BARS */
10944 f
->icon_name
= Qnil
;
10945 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10947 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
10948 dpyinfo_refcount
= dpyinfo
->reference_count
;
10949 #endif /* GLYPH_DEBUG */
10950 #ifdef MULTI_KBOARD
10951 FRAME_KBOARD (f
) = kb
;
10953 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10954 f
->output_data
.x
->explicit_parent
= 0;
10956 /* These colors will be set anyway later, but it's important
10957 to get the color reference counts right, so initialize them! */
10960 struct gcpro gcpro1
;
10962 black
= build_string ("black");
10964 f
->output_data
.x
->foreground_pixel
10965 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10966 f
->output_data
.x
->background_pixel
10967 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10968 f
->output_data
.x
->cursor_pixel
10969 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10970 f
->output_data
.x
->cursor_foreground_pixel
10971 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10972 f
->output_data
.x
->border_pixel
10973 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10974 f
->output_data
.x
->mouse_pixel
10975 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10979 /* Set the name; the functions to which we pass f expect the name to
10981 if (EQ (name
, Qunbound
) || NILP (name
))
10983 f
->name
= build_string (dpyinfo
->x_id_name
);
10984 f
->explicit_name
= 0;
10989 f
->explicit_name
= 1;
10990 /* use the frame's title when getting resources for this frame. */
10991 specbind (Qx_resource_name
, name
);
10994 /* Extract the window parameters from the supplied values that are
10995 needed to determine window geometry. */
10999 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
11002 /* First, try whatever font the caller has specified. */
11003 if (STRINGP (font
))
11005 tem
= Fquery_fontset (font
, Qnil
);
11007 font
= x_new_fontset (f
, SDATA (tem
));
11009 font
= x_new_font (f
, SDATA (font
));
11012 /* Try out a font which we hope has bold and italic variations. */
11013 if (!STRINGP (font
))
11014 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
11015 if (!STRINGP (font
))
11016 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11017 if (! STRINGP (font
))
11018 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11019 if (! STRINGP (font
))
11020 /* This was formerly the first thing tried, but it finds too many fonts
11021 and takes too long. */
11022 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
11023 /* If those didn't work, look for something which will at least work. */
11024 if (! STRINGP (font
))
11025 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
11027 if (! STRINGP (font
))
11028 font
= build_string ("fixed");
11030 x_default_parameter (f
, parms
, Qfont
, font
,
11031 "font", "Font", RES_TYPE_STRING
);
11034 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
11035 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
11037 /* This defaults to 2 in order to match xterm. We recognize either
11038 internalBorderWidth or internalBorder (which is what xterm calls
11040 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11044 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
11045 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
11046 if (! EQ (value
, Qunbound
))
11047 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
11051 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
11052 "internalBorderWidth", "internalBorderWidth",
11055 /* Also do the stuff which must be set before the window exists. */
11056 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
11057 "foreground", "Foreground", RES_TYPE_STRING
);
11058 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
11059 "background", "Background", RES_TYPE_STRING
);
11060 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
11061 "pointerColor", "Foreground", RES_TYPE_STRING
);
11062 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
11063 "cursorColor", "Foreground", RES_TYPE_STRING
);
11064 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
11065 "borderColor", "BorderColor", RES_TYPE_STRING
);
11067 /* Init faces before x_default_parameter is called for scroll-bar
11068 parameters because that function calls x_set_scroll_bar_width,
11069 which calls change_frame_size, which calls Fset_window_buffer,
11070 which runs hooks, which call Fvertical_motion. At the end, we
11071 end up in init_iterator with a null face cache, which should not
11073 init_frame_faces (f
);
11075 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
11076 window_prompting
= x_figure_window_size (f
, parms
);
11078 if (window_prompting
& XNegative
)
11080 if (window_prompting
& YNegative
)
11081 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
11083 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
11087 if (window_prompting
& YNegative
)
11088 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
11090 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11093 f
->output_data
.x
->size_hint_flags
= window_prompting
;
11095 XSetWindowAttributes attrs
;
11096 unsigned long mask
;
11099 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
11100 if (DoesSaveUnders (dpyinfo
->screen
))
11101 mask
|= CWSaveUnder
;
11103 /* Window managers look at the override-redirect flag to determine
11104 whether or net to give windows a decoration (Xlib spec, chapter
11106 attrs
.override_redirect
= True
;
11107 attrs
.save_under
= True
;
11108 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
11109 /* Arrange for getting MapNotify and UnmapNotify events. */
11110 attrs
.event_mask
= StructureNotifyMask
;
11112 = FRAME_X_WINDOW (f
)
11113 = XCreateWindow (FRAME_X_DISPLAY (f
),
11114 FRAME_X_DISPLAY_INFO (f
)->root_window
,
11115 /* x, y, width, height */
11119 CopyFromParent
, InputOutput
, CopyFromParent
,
11126 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
11127 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11128 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
11129 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11130 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
11131 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
11133 /* Dimensions, especially f->height, must be done via change_frame_size.
11134 Change will not be effected unless different from the current
11137 height
= f
->height
;
11139 SET_FRAME_WIDTH (f
, 0);
11140 change_frame_size (f
, height
, width
, 1, 0, 0);
11142 /* Set up faces after all frame parameters are known. This call
11143 also merges in face attributes specified for new frames.
11145 Frame parameters may be changed if .Xdefaults contains
11146 specifications for the default font. For example, if there is an
11147 `Emacs.default.attributeBackground: pink', the `background-color'
11148 attribute of the frame get's set, which let's the internal border
11149 of the tooltip frame appear in pink. Prevent this. */
11151 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
11153 /* Set tip_frame here, so that */
11155 call1 (Qface_set_after_frame_default
, frame
);
11157 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
11158 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
11166 /* It is now ok to make the frame official even if we get an error
11167 below. And the frame needs to be on Vframe_list or making it
11168 visible won't work. */
11169 Vframe_list
= Fcons (frame
, Vframe_list
);
11171 /* Now that the frame is official, it counts as a reference to
11173 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
11175 /* Setting attributes of faces of the tooltip frame from resources
11176 and similar will increment face_change_count, which leads to the
11177 clearing of all current matrices. Since this isn't necessary
11178 here, avoid it by resetting face_change_count to the value it
11179 had before we created the tip frame. */
11180 face_change_count
= face_change_count_before
;
11182 /* Discard the unwind_protect. */
11183 return unbind_to (count
, frame
);
11187 /* Compute where to display tip frame F. PARMS is the list of frame
11188 parameters for F. DX and DY are specified offsets from the current
11189 location of the mouse. WIDTH and HEIGHT are the width and height
11190 of the tooltip. Return coordinates relative to the root window of
11191 the display in *ROOT_X, and *ROOT_Y. */
11194 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
11196 Lisp_Object parms
, dx
, dy
;
11198 int *root_x
, *root_y
;
11200 Lisp_Object left
, top
;
11202 Window root
, child
;
11205 /* User-specified position? */
11206 left
= Fcdr (Fassq (Qleft
, parms
));
11207 top
= Fcdr (Fassq (Qtop
, parms
));
11209 /* Move the tooltip window where the mouse pointer is. Resize and
11211 if (!INTEGERP (left
) || !INTEGERP (top
))
11214 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
11215 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
11219 if (INTEGERP (top
))
11220 *root_y
= XINT (top
);
11221 else if (*root_y
+ XINT (dy
) - height
< 0)
11222 *root_y
-= XINT (dy
);
11226 *root_y
+= XINT (dy
);
11229 if (INTEGERP (left
))
11230 *root_x
= XINT (left
);
11231 else if (*root_x
+ XINT (dx
) + width
<= FRAME_X_DISPLAY_INFO (f
)->width
)
11232 /* It fits to the right of the pointer. */
11233 *root_x
+= XINT (dx
);
11234 else if (width
+ XINT (dx
) <= *root_x
)
11235 /* It fits to the left of the pointer. */
11236 *root_x
-= width
+ XINT (dx
);
11238 /* Put it left-justified on the screen--it ought to fit that way. */
11243 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
11244 doc
: /* Show STRING in a "tooltip" window on frame FRAME.
11245 A tooltip window is a small X window displaying a string.
11247 FRAME nil or omitted means use the selected frame.
11249 PARMS is an optional list of frame parameters which can be used to
11250 change the tooltip's appearance.
11252 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11253 means use the default timeout of 5 seconds.
11255 If the list of frame parameters PARAMS contains a `left' parameters,
11256 the tooltip is displayed at that x-position. Otherwise it is
11257 displayed at the mouse position, with offset DX added (default is 5 if
11258 DX isn't specified). Likewise for the y-position; if a `top' frame
11259 parameter is specified, it determines the y-position of the tooltip
11260 window, otherwise it is displayed at the mouse position, with offset
11261 DY added (default is -10).
11263 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11264 Text larger than the specified size is clipped. */)
11265 (string
, frame
, parms
, timeout
, dx
, dy
)
11266 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
11270 int root_x
, root_y
;
11271 struct buffer
*old_buffer
;
11272 struct text_pos pos
;
11273 int i
, width
, height
;
11274 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
11275 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
11276 int count
= SPECPDL_INDEX ();
11278 specbind (Qinhibit_redisplay
, Qt
);
11280 GCPRO4 (string
, parms
, frame
, timeout
);
11282 CHECK_STRING (string
);
11283 f
= check_x_frame (frame
);
11284 if (NILP (timeout
))
11285 timeout
= make_number (5);
11287 CHECK_NATNUM (timeout
);
11290 dx
= make_number (5);
11295 dy
= make_number (-10);
11299 if (NILP (last_show_tip_args
))
11300 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
11302 if (!NILP (tip_frame
))
11304 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
11305 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
11306 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
11308 if (EQ (frame
, last_frame
)
11309 && !NILP (Fequal (last_string
, string
))
11310 && !NILP (Fequal (last_parms
, parms
)))
11312 struct frame
*f
= XFRAME (tip_frame
);
11314 /* Only DX and DY have changed. */
11315 if (!NILP (tip_timer
))
11317 Lisp_Object timer
= tip_timer
;
11319 call1 (Qcancel_timer
, timer
);
11323 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
11324 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
11325 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11332 /* Hide a previous tip, if any. */
11335 ASET (last_show_tip_args
, 0, string
);
11336 ASET (last_show_tip_args
, 1, frame
);
11337 ASET (last_show_tip_args
, 2, parms
);
11339 /* Add default values to frame parameters. */
11340 if (NILP (Fassq (Qname
, parms
)))
11341 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
11342 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11343 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
11344 if (NILP (Fassq (Qborder_width
, parms
)))
11345 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
11346 if (NILP (Fassq (Qborder_color
, parms
)))
11347 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
11348 if (NILP (Fassq (Qbackground_color
, parms
)))
11349 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
11352 /* Create a frame for the tooltip, and record it in the global
11353 variable tip_frame. */
11354 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
11355 f
= XFRAME (frame
);
11357 /* Set up the frame's root window. */
11358 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
11359 w
->left
= w
->top
= make_number (0);
11361 if (CONSP (Vx_max_tooltip_size
)
11362 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11363 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11364 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11365 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11367 w
->width
= XCAR (Vx_max_tooltip_size
);
11368 w
->height
= XCDR (Vx_max_tooltip_size
);
11372 w
->width
= make_number (80);
11373 w
->height
= make_number (40);
11376 f
->window_width
= XINT (w
->width
);
11378 w
->pseudo_window_p
= 1;
11380 /* Display the tooltip text in a temporary buffer. */
11381 old_buffer
= current_buffer
;
11382 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11383 current_buffer
->truncate_lines
= Qnil
;
11384 clear_glyph_matrix (w
->desired_matrix
);
11385 clear_glyph_matrix (w
->current_matrix
);
11386 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11387 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11389 /* Compute width and height of the tooltip. */
11390 width
= height
= 0;
11391 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11393 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11394 struct glyph
*last
;
11397 /* Stop at the first empty row at the end. */
11398 if (!row
->enabled_p
|| !row
->displays_text_p
)
11401 /* Let the row go over the full width of the frame. */
11402 row
->full_width_p
= 1;
11404 /* There's a glyph at the end of rows that is used to place
11405 the cursor there. Don't include the width of this glyph. */
11406 if (row
->used
[TEXT_AREA
])
11408 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11409 row_width
= row
->pixel_width
- last
->pixel_width
;
11412 row_width
= row
->pixel_width
;
11414 height
+= row
->height
;
11415 width
= max (width
, row_width
);
11418 /* Add the frame's internal border to the width and height the X
11419 window should have. */
11420 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11421 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11423 /* Move the tooltip window where the mouse pointer is. Resize and
11425 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11428 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11429 root_x
, root_y
, width
, height
);
11430 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11433 /* Draw into the window. */
11434 w
->must_be_updated_p
= 1;
11435 update_single_window (w
, 1);
11437 /* Restore original current buffer. */
11438 set_buffer_internal_1 (old_buffer
);
11439 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11442 /* Let the tip disappear after timeout seconds. */
11443 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11444 intern ("x-hide-tip"));
11447 return unbind_to (count
, Qnil
);
11451 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11452 doc
: /* Hide the current tooltip window, if there is any.
11453 Value is t if tooltip was open, nil otherwise. */)
11457 Lisp_Object deleted
, frame
, timer
;
11458 struct gcpro gcpro1
, gcpro2
;
11460 /* Return quickly if nothing to do. */
11461 if (NILP (tip_timer
) && NILP (tip_frame
))
11466 GCPRO2 (frame
, timer
);
11467 tip_frame
= tip_timer
= deleted
= Qnil
;
11469 count
= SPECPDL_INDEX ();
11470 specbind (Qinhibit_redisplay
, Qt
);
11471 specbind (Qinhibit_quit
, Qt
);
11474 call1 (Qcancel_timer
, timer
);
11476 if (FRAMEP (frame
))
11478 Fdelete_frame (frame
, Qnil
);
11482 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11483 redisplay procedure is not called when a tip frame over menu
11484 items is unmapped. Redisplay the menu manually... */
11486 struct frame
*f
= SELECTED_FRAME ();
11487 Widget w
= f
->output_data
.x
->menubar_widget
;
11488 extern void xlwmenu_redisplay
P_ ((Widget
));
11490 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11494 xlwmenu_redisplay (w
);
11498 #endif /* USE_LUCID */
11502 return unbind_to (count
, deleted
);
11507 /***********************************************************************
11508 File selection dialog
11509 ***********************************************************************/
11513 /* Callback for "OK" and "Cancel" on file selection dialog. */
11516 file_dialog_cb (widget
, client_data
, call_data
)
11518 XtPointer call_data
, client_data
;
11520 int *result
= (int *) client_data
;
11521 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11522 *result
= cb
->reason
;
11526 /* Callback for unmapping a file selection dialog. This is used to
11527 capture the case where a dialog is closed via a window manager's
11528 closer button, for example. Using a XmNdestroyCallback didn't work
11532 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11534 XtPointer call_data
, client_data
;
11536 int *result
= (int *) client_data
;
11537 *result
= XmCR_CANCEL
;
11541 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11542 doc
: /* Read file name, prompting with PROMPT in directory DIR.
11543 Use a file selection dialog.
11544 Select DEFAULT-FILENAME in the dialog's file selection box, if
11545 specified. Don't let the user enter a file name in the file
11546 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11547 (prompt
, dir
, default_filename
, mustmatch
)
11548 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11551 struct frame
*f
= SELECTED_FRAME ();
11552 Lisp_Object file
= Qnil
;
11553 Widget dialog
, text
, list
, help
;
11556 extern XtAppContext Xt_app_con
;
11557 XmString dir_xmstring
, pattern_xmstring
;
11558 int count
= SPECPDL_INDEX ();
11559 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11561 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11562 CHECK_STRING (prompt
);
11563 CHECK_STRING (dir
);
11565 /* Prevent redisplay. */
11566 specbind (Qinhibit_redisplay
, Qt
);
11570 /* Create the dialog with PROMPT as title, using DIR as initial
11571 directory and using "*" as pattern. */
11572 dir
= Fexpand_file_name (dir
, Qnil
);
11573 dir_xmstring
= XmStringCreateLocalized (SDATA (dir
));
11574 pattern_xmstring
= XmStringCreateLocalized ("*");
11576 XtSetArg (al
[ac
], XmNtitle
, SDATA (prompt
)); ++ac
;
11577 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11578 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11579 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11580 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11581 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11583 XmStringFree (dir_xmstring
);
11584 XmStringFree (pattern_xmstring
);
11586 /* Add callbacks for OK and Cancel. */
11587 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11588 (XtPointer
) &result
);
11589 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11590 (XtPointer
) &result
);
11591 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11592 (XtPointer
) &result
);
11594 /* Disable the help button since we can't display help. */
11595 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11596 XtSetSensitive (help
, False
);
11598 /* Mark OK button as default. */
11599 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11600 XmNshowAsDefault
, True
, NULL
);
11602 /* If MUSTMATCH is non-nil, disable the file entry field of the
11603 dialog, so that the user must select a file from the files list
11604 box. We can't remove it because we wouldn't have a way to get at
11605 the result file name, then. */
11606 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11607 if (!NILP (mustmatch
))
11610 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11611 XtSetSensitive (text
, False
);
11612 XtSetSensitive (label
, False
);
11615 /* Manage the dialog, so that list boxes get filled. */
11616 XtManageChild (dialog
);
11618 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11619 must include the path for this to work. */
11620 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11621 if (STRINGP (default_filename
))
11623 XmString default_xmstring
;
11627 = XmStringCreateLocalized (SDATA (default_filename
));
11629 if (!XmListItemExists (list
, default_xmstring
))
11631 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11632 XmListAddItem (list
, default_xmstring
, 0);
11636 item_pos
= XmListItemPos (list
, default_xmstring
);
11637 XmStringFree (default_xmstring
);
11639 /* Select the item and scroll it into view. */
11640 XmListSelectPos (list
, item_pos
, True
);
11641 XmListSetPos (list
, item_pos
);
11644 /* Process events until the user presses Cancel or OK. Block
11645 and unblock input here so that we get a chance of processing
11649 while (result
== 0)
11652 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11657 /* Get the result. */
11658 if (result
== XmCR_OK
)
11663 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11664 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11665 XmStringFree (text
);
11666 file
= build_string (data
);
11673 XtUnmanageChild (dialog
);
11674 XtDestroyWidget (dialog
);
11678 /* Make "Cancel" equivalent to C-g. */
11680 Fsignal (Qquit
, Qnil
);
11682 return unbind_to (count
, file
);
11685 #endif /* USE_MOTIF */
11689 /***********************************************************************
11691 ***********************************************************************/
11693 #ifdef HAVE_XKBGETKEYBOARD
11694 #include <X11/XKBlib.h>
11695 #include <X11/keysym.h>
11698 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11699 Sx_backspace_delete_keys_p
, 0, 1, 0,
11700 doc
: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11701 FRAME nil means use the selected frame.
11702 Value is t if we know that both keys are present, and are mapped to the
11703 usual X keysyms. */)
11707 #ifdef HAVE_XKBGETKEYBOARD
11709 struct frame
*f
= check_x_frame (frame
);
11710 Display
*dpy
= FRAME_X_DISPLAY (f
);
11711 Lisp_Object have_keys
;
11712 int major
, minor
, op
, event
, error
;
11716 /* Check library version in case we're dynamically linked. */
11717 major
= XkbMajorVersion
;
11718 minor
= XkbMinorVersion
;
11719 if (!XkbLibraryVersion (&major
, &minor
))
11725 /* Check that the server supports XKB. */
11726 major
= XkbMajorVersion
;
11727 minor
= XkbMinorVersion
;
11728 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11735 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11738 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11740 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11742 for (i
= kb
->min_key_code
;
11743 (i
< kb
->max_key_code
11744 && (delete_keycode
== 0 || backspace_keycode
== 0));
11747 /* The XKB symbolic key names can be seen most easily in
11748 the PS file generated by `xkbprint -label name
11750 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11751 delete_keycode
= i
;
11752 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11753 backspace_keycode
= i
;
11756 XkbFreeNames (kb
, 0, True
);
11759 XkbFreeClientMap (kb
, 0, True
);
11762 && backspace_keycode
11763 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11764 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11769 #else /* not HAVE_XKBGETKEYBOARD */
11771 #endif /* not HAVE_XKBGETKEYBOARD */
11776 /***********************************************************************
11778 ***********************************************************************/
11783 /* This is zero if not using X windows. */
11786 /* The section below is built by the lisp expression at the top of the file,
11787 just above where these variables are declared. */
11788 /*&&& init symbols here &&&*/
11789 Qauto_raise
= intern ("auto-raise");
11790 staticpro (&Qauto_raise
);
11791 Qauto_lower
= intern ("auto-lower");
11792 staticpro (&Qauto_lower
);
11793 Qborder_color
= intern ("border-color");
11794 staticpro (&Qborder_color
);
11795 Qborder_width
= intern ("border-width");
11796 staticpro (&Qborder_width
);
11797 Qcursor_color
= intern ("cursor-color");
11798 staticpro (&Qcursor_color
);
11799 Qcursor_type
= intern ("cursor-type");
11800 staticpro (&Qcursor_type
);
11801 Qgeometry
= intern ("geometry");
11802 staticpro (&Qgeometry
);
11803 Qicon_left
= intern ("icon-left");
11804 staticpro (&Qicon_left
);
11805 Qicon_top
= intern ("icon-top");
11806 staticpro (&Qicon_top
);
11807 Qicon_type
= intern ("icon-type");
11808 staticpro (&Qicon_type
);
11809 Qicon_name
= intern ("icon-name");
11810 staticpro (&Qicon_name
);
11811 Qinternal_border_width
= intern ("internal-border-width");
11812 staticpro (&Qinternal_border_width
);
11813 Qleft
= intern ("left");
11814 staticpro (&Qleft
);
11815 Qright
= intern ("right");
11816 staticpro (&Qright
);
11817 Qmouse_color
= intern ("mouse-color");
11818 staticpro (&Qmouse_color
);
11819 Qnone
= intern ("none");
11820 staticpro (&Qnone
);
11821 Qparent_id
= intern ("parent-id");
11822 staticpro (&Qparent_id
);
11823 Qscroll_bar_width
= intern ("scroll-bar-width");
11824 staticpro (&Qscroll_bar_width
);
11825 Qsuppress_icon
= intern ("suppress-icon");
11826 staticpro (&Qsuppress_icon
);
11827 Qundefined_color
= intern ("undefined-color");
11828 staticpro (&Qundefined_color
);
11829 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11830 staticpro (&Qvertical_scroll_bars
);
11831 Qvisibility
= intern ("visibility");
11832 staticpro (&Qvisibility
);
11833 Qwindow_id
= intern ("window-id");
11834 staticpro (&Qwindow_id
);
11835 Qouter_window_id
= intern ("outer-window-id");
11836 staticpro (&Qouter_window_id
);
11837 Qx_frame_parameter
= intern ("x-frame-parameter");
11838 staticpro (&Qx_frame_parameter
);
11839 Qx_resource_name
= intern ("x-resource-name");
11840 staticpro (&Qx_resource_name
);
11841 Quser_position
= intern ("user-position");
11842 staticpro (&Quser_position
);
11843 Quser_size
= intern ("user-size");
11844 staticpro (&Quser_size
);
11845 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11846 staticpro (&Qscroll_bar_foreground
);
11847 Qscroll_bar_background
= intern ("scroll-bar-background");
11848 staticpro (&Qscroll_bar_background
);
11849 Qscreen_gamma
= intern ("screen-gamma");
11850 staticpro (&Qscreen_gamma
);
11851 Qline_spacing
= intern ("line-spacing");
11852 staticpro (&Qline_spacing
);
11853 Qcenter
= intern ("center");
11854 staticpro (&Qcenter
);
11855 Qcompound_text
= intern ("compound-text");
11856 staticpro (&Qcompound_text
);
11857 Qcancel_timer
= intern ("cancel-timer");
11858 staticpro (&Qcancel_timer
);
11859 Qwait_for_wm
= intern ("wait-for-wm");
11860 staticpro (&Qwait_for_wm
);
11861 Qfullscreen
= intern ("fullscreen");
11862 staticpro (&Qfullscreen
);
11863 Qfullwidth
= intern ("fullwidth");
11864 staticpro (&Qfullwidth
);
11865 Qfullheight
= intern ("fullheight");
11866 staticpro (&Qfullheight
);
11867 Qfullboth
= intern ("fullboth");
11868 staticpro (&Qfullboth
);
11869 /* This is the end of symbol initialization. */
11871 /* Text property `display' should be nonsticky by default. */
11872 Vtext_property_default_nonsticky
11873 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11876 Qlaplace
= intern ("laplace");
11877 staticpro (&Qlaplace
);
11878 Qemboss
= intern ("emboss");
11879 staticpro (&Qemboss
);
11880 Qedge_detection
= intern ("edge-detection");
11881 staticpro (&Qedge_detection
);
11882 Qheuristic
= intern ("heuristic");
11883 staticpro (&Qheuristic
);
11884 QCmatrix
= intern (":matrix");
11885 staticpro (&QCmatrix
);
11886 QCcolor_adjustment
= intern (":color-adjustment");
11887 staticpro (&QCcolor_adjustment
);
11888 QCmask
= intern (":mask");
11889 staticpro (&QCmask
);
11891 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11892 staticpro (&Qface_set_after_frame_default
);
11894 Fput (Qundefined_color
, Qerror_conditions
,
11895 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11896 Fput (Qundefined_color
, Qerror_message
,
11897 build_string ("Undefined color"));
11899 init_x_parm_symbols ();
11901 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11902 doc
: /* Non-nil means always draw a cross over disabled images.
11903 Disabled images are those having an `:conversion disabled' property.
11904 A cross is always drawn on black & white displays. */);
11905 cross_disabled_images
= 0;
11907 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11908 doc
: /* List of directories to search for bitmap files for X. */);
11909 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11911 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11912 doc
: /* The shape of the pointer when over text.
11913 Changing the value does not affect existing frames
11914 unless you set the mouse color. */);
11915 Vx_pointer_shape
= Qnil
;
11917 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11918 doc
: /* The name Emacs uses to look up X resources.
11919 `x-get-resource' uses this as the first component of the instance name
11920 when requesting resource values.
11921 Emacs initially sets `x-resource-name' to the name under which Emacs
11922 was invoked, or to the value specified with the `-name' or `-rn'
11923 switches, if present.
11925 It may be useful to bind this variable locally around a call
11926 to `x-get-resource'. See also the variable `x-resource-class'. */);
11927 Vx_resource_name
= Qnil
;
11929 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11930 doc
: /* The class Emacs uses to look up X resources.
11931 `x-get-resource' uses this as the first component of the instance class
11932 when requesting resource values.
11934 Emacs initially sets `x-resource-class' to "Emacs".
11936 Setting this variable permanently is not a reasonable thing to do,
11937 but binding this variable locally around a call to `x-get-resource'
11938 is a reasonable practice. See also the variable `x-resource-name'. */);
11939 Vx_resource_class
= build_string (EMACS_CLASS
);
11941 #if 0 /* This doesn't really do anything. */
11942 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11943 doc
: /* The shape of the pointer when not over text.
11944 This variable takes effect when you create a new frame
11945 or when you set the mouse color. */);
11947 Vx_nontext_pointer_shape
= Qnil
;
11949 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
11950 doc
: /* The shape of the pointer when Emacs is busy.
11951 This variable takes effect when you create a new frame
11952 or when you set the mouse color. */);
11953 Vx_hourglass_pointer_shape
= Qnil
;
11955 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
11956 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
11957 display_hourglass_p
= 1;
11959 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
11960 doc
: /* *Seconds to wait before displaying an hourglass pointer.
11961 Value must be an integer or float. */);
11962 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
11964 #if 0 /* This doesn't really do anything. */
11965 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
11966 doc
: /* The shape of the pointer when over the mode line.
11967 This variable takes effect when you create a new frame
11968 or when you set the mouse color. */);
11970 Vx_mode_pointer_shape
= Qnil
;
11972 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11973 &Vx_sensitive_text_pointer_shape
,
11974 doc
: /* The shape of the pointer when over mouse-sensitive text.
11975 This variable takes effect when you create a new frame
11976 or when you set the mouse color. */);
11977 Vx_sensitive_text_pointer_shape
= Qnil
;
11979 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11980 &Vx_window_horizontal_drag_shape
,
11981 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
11982 This variable takes effect when you create a new frame
11983 or when you set the mouse color. */);
11984 Vx_window_horizontal_drag_shape
= Qnil
;
11986 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
11987 doc
: /* A string indicating the foreground color of the cursor box. */);
11988 Vx_cursor_fore_pixel
= Qnil
;
11990 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
11991 doc
: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
11992 Text larger than this is clipped. */);
11993 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
11995 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
11996 doc
: /* Non-nil if no X window manager is in use.
11997 Emacs doesn't try to figure this out; this is always nil
11998 unless you set it to something else. */);
11999 /* We don't have any way to find this out, so set it to nil
12000 and maybe the user would like to set it to t. */
12001 Vx_no_window_manager
= Qnil
;
12003 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
12004 &Vx_pixel_size_width_font_regexp
,
12005 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
12007 Since Emacs gets width of a font matching with this regexp from
12008 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12009 such a font. This is especially effective for such large fonts as
12010 Chinese, Japanese, and Korean. */);
12011 Vx_pixel_size_width_font_regexp
= Qnil
;
12013 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
12014 doc
: /* Time after which cached images are removed from the cache.
12015 When an image has not been displayed this many seconds, remove it
12016 from the image cache. Value must be an integer or nil with nil
12017 meaning don't clear the cache. */);
12018 Vimage_cache_eviction_delay
= make_number (30 * 60);
12020 #ifdef USE_X_TOOLKIT
12021 Fprovide (intern ("x-toolkit"), Qnil
);
12023 Fprovide (intern ("motif"), Qnil
);
12025 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
12026 doc
: /* Version info for LessTif/Motif. */);
12027 Vmotif_version_string
= build_string (XmVERSION_STRING
);
12028 #endif /* USE_MOTIF */
12029 #endif /* USE_X_TOOLKIT */
12031 defsubr (&Sx_get_resource
);
12033 /* X window properties. */
12034 defsubr (&Sx_change_window_property
);
12035 defsubr (&Sx_delete_window_property
);
12036 defsubr (&Sx_window_property
);
12038 defsubr (&Sxw_display_color_p
);
12039 defsubr (&Sx_display_grayscale_p
);
12040 defsubr (&Sxw_color_defined_p
);
12041 defsubr (&Sxw_color_values
);
12042 defsubr (&Sx_server_max_request_size
);
12043 defsubr (&Sx_server_vendor
);
12044 defsubr (&Sx_server_version
);
12045 defsubr (&Sx_display_pixel_width
);
12046 defsubr (&Sx_display_pixel_height
);
12047 defsubr (&Sx_display_mm_width
);
12048 defsubr (&Sx_display_mm_height
);
12049 defsubr (&Sx_display_screens
);
12050 defsubr (&Sx_display_planes
);
12051 defsubr (&Sx_display_color_cells
);
12052 defsubr (&Sx_display_visual_class
);
12053 defsubr (&Sx_display_backing_store
);
12054 defsubr (&Sx_display_save_under
);
12055 defsubr (&Sx_parse_geometry
);
12056 defsubr (&Sx_create_frame
);
12057 defsubr (&Sx_open_connection
);
12058 defsubr (&Sx_close_connection
);
12059 defsubr (&Sx_display_list
);
12060 defsubr (&Sx_synchronize
);
12061 defsubr (&Sx_focus_frame
);
12062 defsubr (&Sx_backspace_delete_keys_p
);
12064 /* Setting callback functions for fontset handler. */
12065 get_font_info_func
= x_get_font_info
;
12067 #if 0 /* This function pointer doesn't seem to be used anywhere.
12068 And the pointer assigned has the wrong type, anyway. */
12069 list_fonts_func
= x_list_fonts
;
12072 load_font_func
= x_load_font
;
12073 find_ccl_program_func
= x_find_ccl_program
;
12074 query_font_func
= x_query_font
;
12075 set_frame_fontset_func
= x_set_font
;
12076 check_window_system_func
= check_x
;
12079 Qxbm
= intern ("xbm");
12081 QCconversion
= intern (":conversion");
12082 staticpro (&QCconversion
);
12083 QCheuristic_mask
= intern (":heuristic-mask");
12084 staticpro (&QCheuristic_mask
);
12085 QCcolor_symbols
= intern (":color-symbols");
12086 staticpro (&QCcolor_symbols
);
12087 QCascent
= intern (":ascent");
12088 staticpro (&QCascent
);
12089 QCmargin
= intern (":margin");
12090 staticpro (&QCmargin
);
12091 QCrelief
= intern (":relief");
12092 staticpro (&QCrelief
);
12093 Qpostscript
= intern ("postscript");
12094 staticpro (&Qpostscript
);
12095 QCloader
= intern (":loader");
12096 staticpro (&QCloader
);
12097 QCbounding_box
= intern (":bounding-box");
12098 staticpro (&QCbounding_box
);
12099 QCpt_width
= intern (":pt-width");
12100 staticpro (&QCpt_width
);
12101 QCpt_height
= intern (":pt-height");
12102 staticpro (&QCpt_height
);
12103 QCindex
= intern (":index");
12104 staticpro (&QCindex
);
12105 Qpbm
= intern ("pbm");
12109 Qxpm
= intern ("xpm");
12114 Qjpeg
= intern ("jpeg");
12115 staticpro (&Qjpeg
);
12119 Qtiff
= intern ("tiff");
12120 staticpro (&Qtiff
);
12124 Qgif
= intern ("gif");
12129 Qpng
= intern ("png");
12133 defsubr (&Sclear_image_cache
);
12134 defsubr (&Simage_size
);
12135 defsubr (&Simage_mask_p
);
12137 hourglass_atimer
= NULL
;
12138 hourglass_shown_p
= 0;
12140 defsubr (&Sx_show_tip
);
12141 defsubr (&Sx_hide_tip
);
12143 staticpro (&tip_timer
);
12145 staticpro (&tip_frame
);
12147 last_show_tip_args
= Qnil
;
12148 staticpro (&last_show_tip_args
);
12151 defsubr (&Sx_file_dialog
);
12159 image_types
= NULL
;
12160 Vimage_types
= Qnil
;
12162 define_image_type (&xbm_type
);
12163 define_image_type (&gs_type
);
12164 define_image_type (&pbm_type
);
12167 define_image_type (&xpm_type
);
12171 define_image_type (&jpeg_type
);
12175 define_image_type (&tiff_type
);
12179 define_image_type (&gif_type
);
12183 define_image_type (&png_type
);
12187 #endif /* HAVE_X_WINDOWS */