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 Qbar
, Qhbar
;
189 Lisp_Object Qborder_color
;
190 Lisp_Object Qborder_width
;
192 Lisp_Object Qcursor_color
;
193 Lisp_Object Qcursor_type
;
194 Lisp_Object Qgeometry
;
195 Lisp_Object Qicon_left
;
196 Lisp_Object Qicon_top
;
197 Lisp_Object Qicon_type
;
198 Lisp_Object Qicon_name
;
199 Lisp_Object Qinternal_border_width
;
202 Lisp_Object Qmouse_color
;
204 Lisp_Object Qouter_window_id
;
205 Lisp_Object Qparent_id
;
206 Lisp_Object Qscroll_bar_width
;
207 Lisp_Object Qsuppress_icon
;
208 extern Lisp_Object Qtop
;
209 Lisp_Object Qundefined_color
;
210 Lisp_Object Qvertical_scroll_bars
;
211 Lisp_Object Qvisibility
;
212 Lisp_Object Qwindow_id
;
213 Lisp_Object Qx_frame_parameter
;
214 Lisp_Object Qx_resource_name
;
215 Lisp_Object Quser_position
;
216 Lisp_Object Quser_size
;
217 extern Lisp_Object Qdisplay
;
218 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
219 Lisp_Object Qscreen_gamma
, Qline_spacing
, Qcenter
;
220 Lisp_Object Qcompound_text
, Qcancel_timer
;
221 Lisp_Object Qwait_for_wm
;
222 Lisp_Object Qfullscreen
;
223 Lisp_Object Qfullwidth
;
224 Lisp_Object Qfullheight
;
225 Lisp_Object Qfullboth
;
227 /* The below are defined in frame.c. */
229 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
230 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
231 extern Lisp_Object Qtool_bar_lines
;
233 extern Lisp_Object Vwindow_system_version
;
235 Lisp_Object Qface_set_after_frame_default
;
238 int image_cache_refcount
, dpyinfo_refcount
;
243 /* Error if we are not connected to X. */
249 error ("X windows are not in use or not initialized");
252 /* Nonzero if we can use mouse menus.
253 You should not call this unless HAVE_MENUS is defined. */
261 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
262 and checking validity for X. */
265 check_x_frame (frame
)
271 frame
= selected_frame
;
272 CHECK_LIVE_FRAME (frame
);
275 error ("Non-X frame used");
279 /* Let the user specify an X display with a frame.
280 nil stands for the selected frame--or, if that is not an X frame,
281 the first X display on the list. */
283 static struct x_display_info
*
284 check_x_display_info (frame
)
287 struct x_display_info
*dpyinfo
= NULL
;
291 struct frame
*sf
= XFRAME (selected_frame
);
293 if (FRAME_X_P (sf
) && FRAME_LIVE_P (sf
))
294 dpyinfo
= FRAME_X_DISPLAY_INFO (sf
);
295 else if (x_display_list
!= 0)
296 dpyinfo
= x_display_list
;
298 error ("X windows are not in use or not initialized");
300 else if (STRINGP (frame
))
301 dpyinfo
= x_display_info_for_name (frame
);
304 FRAME_PTR f
= check_x_frame (frame
);
305 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
312 /* Return the Emacs frame-object corresponding to an X window.
313 It could be the frame's main window or an icon window. */
315 /* This function can be called during GC, so use GC_xxx type test macros. */
318 x_window_to_frame (dpyinfo
, wdesc
)
319 struct x_display_info
*dpyinfo
;
322 Lisp_Object tail
, frame
;
325 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
328 if (!GC_FRAMEP (frame
))
331 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
333 if (f
->output_data
.x
->hourglass_window
== wdesc
)
336 if ((f
->output_data
.x
->edit_widget
337 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
338 /* A tooltip frame? */
339 || (!f
->output_data
.x
->edit_widget
340 && FRAME_X_WINDOW (f
) == wdesc
)
341 || f
->output_data
.x
->icon_desc
== wdesc
)
343 #else /* not USE_X_TOOLKIT */
344 if (FRAME_X_WINDOW (f
) == wdesc
345 || f
->output_data
.x
->icon_desc
== wdesc
)
347 #endif /* not USE_X_TOOLKIT */
353 /* Like x_window_to_frame but also compares the window with the widget's
357 x_any_window_to_frame (dpyinfo
, wdesc
)
358 struct x_display_info
*dpyinfo
;
361 Lisp_Object tail
, frame
;
362 struct frame
*f
, *found
;
366 for (tail
= Vframe_list
; GC_CONSP (tail
) && !found
; tail
= XCDR (tail
))
369 if (!GC_FRAMEP (frame
))
373 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
375 /* This frame matches if the window is any of its widgets. */
376 x
= f
->output_data
.x
;
377 if (x
->hourglass_window
== wdesc
)
381 if (wdesc
== XtWindow (x
->widget
)
382 || wdesc
== XtWindow (x
->column_widget
)
383 || wdesc
== XtWindow (x
->edit_widget
))
385 /* Match if the window is this frame's menubar. */
386 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
389 else if (FRAME_X_WINDOW (f
) == wdesc
)
390 /* A tooltip frame. */
398 /* Likewise, but exclude the menu bar widget. */
401 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
402 struct x_display_info
*dpyinfo
;
405 Lisp_Object tail
, frame
;
409 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
412 if (!GC_FRAMEP (frame
))
415 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
417 x
= f
->output_data
.x
;
418 /* This frame matches if the window is any of its widgets. */
419 if (x
->hourglass_window
== wdesc
)
423 if (wdesc
== XtWindow (x
->widget
)
424 || wdesc
== XtWindow (x
->column_widget
)
425 || wdesc
== XtWindow (x
->edit_widget
))
428 else if (FRAME_X_WINDOW (f
) == wdesc
)
429 /* A tooltip frame. */
435 /* Likewise, but consider only the menu bar widget. */
438 x_menubar_window_to_frame (dpyinfo
, wdesc
)
439 struct x_display_info
*dpyinfo
;
442 Lisp_Object tail
, frame
;
446 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
449 if (!GC_FRAMEP (frame
))
452 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
454 x
= f
->output_data
.x
;
455 /* Match if the window is this frame's menubar. */
456 if (x
->menubar_widget
457 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
463 /* Return the frame whose principal (outermost) window is WDESC.
464 If WDESC is some other (smaller) window, we return 0. */
467 x_top_window_to_frame (dpyinfo
, wdesc
)
468 struct x_display_info
*dpyinfo
;
471 Lisp_Object tail
, frame
;
475 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
478 if (!GC_FRAMEP (frame
))
481 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
483 x
= f
->output_data
.x
;
487 /* This frame matches if the window is its topmost widget. */
488 if (wdesc
== XtWindow (x
->widget
))
490 #if 0 /* I don't know why it did this,
491 but it seems logically wrong,
492 and it causes trouble for MapNotify events. */
493 /* Match if the window is this frame's menubar. */
494 if (x
->menubar_widget
495 && wdesc
== XtWindow (x
->menubar_widget
))
499 else if (FRAME_X_WINDOW (f
) == wdesc
)
505 #endif /* USE_X_TOOLKIT */
509 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
510 id, which is just an int that this section returns. Bitmaps are
511 reference counted so they can be shared among frames.
513 Bitmap indices are guaranteed to be > 0, so a negative number can
514 be used to indicate no bitmap.
516 If you use x_create_bitmap_from_data, then you must keep track of
517 the bitmaps yourself. That is, creating a bitmap from the same
518 data more than once will not be caught. */
521 /* Functions to access the contents of a bitmap, given an id. */
524 x_bitmap_height (f
, id
)
528 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
532 x_bitmap_width (f
, id
)
536 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
540 x_bitmap_pixmap (f
, id
)
544 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
548 /* Allocate a new bitmap record. Returns index of new record. */
551 x_allocate_bitmap_record (f
)
554 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
557 if (dpyinfo
->bitmaps
== NULL
)
559 dpyinfo
->bitmaps_size
= 10;
561 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
562 dpyinfo
->bitmaps_last
= 1;
566 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
567 return ++dpyinfo
->bitmaps_last
;
569 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
570 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
573 dpyinfo
->bitmaps_size
*= 2;
575 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
576 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
577 return ++dpyinfo
->bitmaps_last
;
580 /* Add one reference to the reference count of the bitmap with id ID. */
583 x_reference_bitmap (f
, id
)
587 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
590 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
593 x_create_bitmap_from_data (f
, bits
, width
, height
)
596 unsigned int width
, height
;
598 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
602 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
603 bits
, width
, height
);
608 id
= x_allocate_bitmap_record (f
);
609 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
610 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
611 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
612 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
613 dpyinfo
->bitmaps
[id
- 1].height
= height
;
614 dpyinfo
->bitmaps
[id
- 1].width
= width
;
619 /* Create bitmap from file FILE for frame F. */
622 x_create_bitmap_from_file (f
, file
)
626 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
627 unsigned int width
, height
;
629 int xhot
, yhot
, result
, id
;
634 /* Look for an existing bitmap with the same name. */
635 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
637 if (dpyinfo
->bitmaps
[id
].refcount
638 && dpyinfo
->bitmaps
[id
].file
639 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
641 ++dpyinfo
->bitmaps
[id
].refcount
;
646 /* Search bitmap-file-path for the file, if appropriate. */
647 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
652 filename
= (char *) SDATA (found
);
654 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
655 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
656 if (result
!= BitmapSuccess
)
659 id
= x_allocate_bitmap_record (f
);
660 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
661 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
662 dpyinfo
->bitmaps
[id
- 1].file
663 = (char *) xmalloc (SBYTES (file
) + 1);
664 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
665 dpyinfo
->bitmaps
[id
- 1].height
= height
;
666 dpyinfo
->bitmaps
[id
- 1].width
= width
;
667 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
672 /* Remove reference to bitmap with id number ID. */
675 x_destroy_bitmap (f
, id
)
679 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
683 --dpyinfo
->bitmaps
[id
- 1].refcount
;
684 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
687 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
688 if (dpyinfo
->bitmaps
[id
- 1].file
)
690 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
691 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
698 /* Free all the bitmaps for the display specified by DPYINFO. */
701 x_destroy_all_bitmaps (dpyinfo
)
702 struct x_display_info
*dpyinfo
;
705 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
706 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
708 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
709 if (dpyinfo
->bitmaps
[i
].file
)
710 xfree (dpyinfo
->bitmaps
[i
].file
);
712 dpyinfo
->bitmaps_last
= 0;
715 /* Connect the frame-parameter names for X frames
716 to the ways of passing the parameter values to the window system.
718 The name of a parameter, as a Lisp symbol,
719 has an `x-frame-parameter' property which is an integer in Lisp
720 that is an index in this table. */
722 struct x_frame_parm_table
725 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
728 static Lisp_Object unwind_create_frame
P_ ((Lisp_Object
));
729 static Lisp_Object unwind_create_tip_frame
P_ ((Lisp_Object
));
730 static void x_change_window_heights
P_ ((Lisp_Object
, int));
731 static void x_disable_image
P_ ((struct frame
*, struct image
*));
732 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
733 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
734 static void x_set_wait_for_wm
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
735 static void x_set_fullscreen
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
736 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
737 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
738 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
739 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
740 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
741 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
742 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
743 static void x_set_fringe_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
744 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
745 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
746 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
748 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
749 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
750 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
751 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
753 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
754 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
755 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
756 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
757 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
758 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
759 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
761 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
763 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
768 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
769 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
771 static void init_color_table
P_ ((void));
772 static void free_color_table
P_ ((void));
773 static unsigned long *colors_in_color_table
P_ ((int *n
));
774 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
775 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
779 static struct x_frame_parm_table x_frame_parms
[] =
781 {"auto-raise", x_set_autoraise
},
782 {"auto-lower", x_set_autolower
},
783 {"background-color", x_set_background_color
},
784 {"border-color", x_set_border_color
},
785 {"border-width", x_set_border_width
},
786 {"cursor-color", x_set_cursor_color
},
787 {"cursor-type", x_set_cursor_type
},
788 {"font", x_set_font
},
789 {"foreground-color", x_set_foreground_color
},
790 {"icon-name", x_set_icon_name
},
791 {"icon-type", x_set_icon_type
},
792 {"internal-border-width", x_set_internal_border_width
},
793 {"menu-bar-lines", x_set_menu_bar_lines
},
794 {"mouse-color", x_set_mouse_color
},
795 {"name", x_explicitly_set_name
},
796 {"scroll-bar-width", x_set_scroll_bar_width
},
797 {"title", x_set_title
},
798 {"unsplittable", x_set_unsplittable
},
799 {"vertical-scroll-bars", x_set_vertical_scroll_bars
},
800 {"visibility", x_set_visibility
},
801 {"tool-bar-lines", x_set_tool_bar_lines
},
802 {"scroll-bar-foreground", x_set_scroll_bar_foreground
},
803 {"scroll-bar-background", x_set_scroll_bar_background
},
804 {"screen-gamma", x_set_screen_gamma
},
805 {"line-spacing", x_set_line_spacing
},
806 {"left-fringe", x_set_fringe_width
},
807 {"right-fringe", x_set_fringe_width
},
808 {"wait-for-wm", x_set_wait_for_wm
},
809 {"fullscreen", x_set_fullscreen
},
813 /* Attach the `x-frame-parameter' properties to
814 the Lisp symbol names of parameters relevant to X. */
817 init_x_parm_symbols ()
821 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
822 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
827 /* Really try to move where we want to be in case of fullscreen. Some WMs
828 moves the window where we tell them. Some (mwm, twm) moves the outer
829 window manager window there instead.
830 Try to compensate for those WM here. */
832 x_fullscreen_move (f
, new_top
, new_left
)
837 if (new_top
!= f
->output_data
.x
->top_pos
838 || new_left
!= f
->output_data
.x
->left_pos
)
840 int move_x
= new_left
+ f
->output_data
.x
->x_pixels_outer_diff
;
841 int move_y
= new_top
+ f
->output_data
.x
->y_pixels_outer_diff
;
843 f
->output_data
.x
->want_fullscreen
|= FULLSCREEN_MOVE_WAIT
;
844 x_set_offset (f
, move_x
, move_y
, 1);
848 /* Change the parameters of frame F as specified by ALIST.
849 If a parameter is not specially recognized, do nothing special;
850 otherwise call the `x_set_...' function for that parameter.
851 Except for certain geometry properties, always call store_frame_param
852 to store the new value in the parameter alist. */
855 x_set_frame_parameters (f
, alist
)
861 /* If both of these parameters are present, it's more efficient to
862 set them both at once. So we wait until we've looked at the
863 entire list before we set them. */
867 Lisp_Object left
, top
;
869 /* Same with these. */
870 Lisp_Object icon_left
, icon_top
;
872 /* Record in these vectors all the parms specified. */
876 int left_no_change
= 0, top_no_change
= 0;
877 int icon_left_no_change
= 0, icon_top_no_change
= 0;
878 int fullscreen_is_being_set
= 0;
880 struct gcpro gcpro1
, gcpro2
;
883 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
886 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
887 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
889 /* Extract parm names and values into those vectors. */
892 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
897 parms
[i
] = Fcar (elt
);
898 values
[i
] = Fcdr (elt
);
901 /* TAIL and ALIST are not used again below here. */
904 GCPRO2 (*parms
, *values
);
908 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
909 because their values appear in VALUES and strings are not valid. */
910 top
= left
= Qunbound
;
911 icon_left
= icon_top
= Qunbound
;
913 /* Provide default values for HEIGHT and WIDTH. */
914 if (FRAME_NEW_WIDTH (f
))
915 width
= FRAME_NEW_WIDTH (f
);
917 width
= FRAME_WIDTH (f
);
919 if (FRAME_NEW_HEIGHT (f
))
920 height
= FRAME_NEW_HEIGHT (f
);
922 height
= FRAME_HEIGHT (f
);
924 /* Process foreground_color and background_color before anything else.
925 They are independent of other properties, but other properties (e.g.,
926 cursor_color) are dependent upon them. */
927 /* Process default font as well, since fringe widths depends on it. */
928 /* Also, process fullscreen, width and height depend upon that */
929 for (p
= 0; p
< i
; p
++)
931 Lisp_Object prop
, val
;
935 if (EQ (prop
, Qforeground_color
)
936 || EQ (prop
, Qbackground_color
)
938 || EQ (prop
, Qfullscreen
))
940 register Lisp_Object param_index
, old_value
;
942 old_value
= get_frame_param (f
, prop
);
943 fullscreen_is_being_set
|= EQ (prop
, Qfullscreen
);
945 if (NILP (Fequal (val
, old_value
)))
947 store_frame_param (f
, prop
, val
);
949 param_index
= Fget (prop
, Qx_frame_parameter
);
950 if (NATNUMP (param_index
)
951 && (XFASTINT (param_index
)
952 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
953 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
958 /* Now process them in reverse of specified order. */
959 for (i
--; i
>= 0; i
--)
961 Lisp_Object prop
, val
;
966 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
967 width
= XFASTINT (val
);
968 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
969 height
= XFASTINT (val
);
970 else if (EQ (prop
, Qtop
))
972 else if (EQ (prop
, Qleft
))
974 else if (EQ (prop
, Qicon_top
))
976 else if (EQ (prop
, Qicon_left
))
978 else if (EQ (prop
, Qforeground_color
)
979 || EQ (prop
, Qbackground_color
)
981 || EQ (prop
, Qfullscreen
))
982 /* Processed above. */
986 register Lisp_Object param_index
, old_value
;
988 old_value
= get_frame_param (f
, prop
);
990 store_frame_param (f
, prop
, val
);
992 param_index
= Fget (prop
, Qx_frame_parameter
);
993 if (NATNUMP (param_index
)
994 && (XFASTINT (param_index
)
995 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
996 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
1000 /* Don't die if just one of these was set. */
1001 if (EQ (left
, Qunbound
))
1004 if (f
->output_data
.x
->left_pos
< 0)
1005 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
1007 XSETINT (left
, f
->output_data
.x
->left_pos
);
1009 if (EQ (top
, Qunbound
))
1012 if (f
->output_data
.x
->top_pos
< 0)
1013 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
1015 XSETINT (top
, f
->output_data
.x
->top_pos
);
1018 /* If one of the icon positions was not set, preserve or default it. */
1019 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
1021 icon_left_no_change
= 1;
1022 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
1023 if (NILP (icon_left
))
1024 XSETINT (icon_left
, 0);
1026 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
1028 icon_top_no_change
= 1;
1029 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
1030 if (NILP (icon_top
))
1031 XSETINT (icon_top
, 0);
1034 if (FRAME_VISIBLE_P (f
) && fullscreen_is_being_set
)
1036 /* If the frame is visible already and the fullscreen parameter is
1037 being set, it is too late to set WM manager hints to specify
1039 Here we first get the width, height and position that applies to
1040 fullscreen. We then move the frame to the appropriate
1041 position. Resize of the frame is taken care of in the code after
1042 this if-statement. */
1043 int new_left
, new_top
;
1045 x_fullscreen_adjust (f
, &width
, &height
, &new_top
, &new_left
);
1046 x_fullscreen_move (f
, new_top
, new_left
);
1049 /* Don't set these parameters unless they've been explicitly
1050 specified. The window might be mapped or resized while we're in
1051 this function, and we don't want to override that unless the lisp
1052 code has asked for it.
1054 Don't set these parameters unless they actually differ from the
1055 window's current parameters; the window may not actually exist
1060 check_frame_size (f
, &height
, &width
);
1062 XSETFRAME (frame
, f
);
1064 if (width
!= FRAME_WIDTH (f
)
1065 || height
!= FRAME_HEIGHT (f
)
1066 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
1067 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1069 if ((!NILP (left
) || !NILP (top
))
1070 && ! (left_no_change
&& top_no_change
)
1071 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1072 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1077 /* Record the signs. */
1078 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1079 if (EQ (left
, Qminus
))
1080 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1081 else if (INTEGERP (left
))
1083 leftpos
= XINT (left
);
1085 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1087 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1088 && CONSP (XCDR (left
))
1089 && INTEGERP (XCAR (XCDR (left
))))
1091 leftpos
= - XINT (XCAR (XCDR (left
)));
1092 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1094 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1095 && CONSP (XCDR (left
))
1096 && INTEGERP (XCAR (XCDR (left
))))
1098 leftpos
= XINT (XCAR (XCDR (left
)));
1101 if (EQ (top
, Qminus
))
1102 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1103 else if (INTEGERP (top
))
1105 toppos
= XINT (top
);
1107 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1109 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1110 && CONSP (XCDR (top
))
1111 && INTEGERP (XCAR (XCDR (top
))))
1113 toppos
= - XINT (XCAR (XCDR (top
)));
1114 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1116 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1117 && CONSP (XCDR (top
))
1118 && INTEGERP (XCAR (XCDR (top
))))
1120 toppos
= XINT (XCAR (XCDR (top
)));
1124 /* Store the numeric value of the position. */
1125 f
->output_data
.x
->top_pos
= toppos
;
1126 f
->output_data
.x
->left_pos
= leftpos
;
1128 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1130 /* Actually set that position, and convert to absolute. */
1131 x_set_offset (f
, leftpos
, toppos
, -1);
1134 if ((!NILP (icon_left
) || !NILP (icon_top
))
1135 && ! (icon_left_no_change
&& icon_top_no_change
))
1136 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1142 /* Store the screen positions of frame F into XPTR and YPTR.
1143 These are the positions of the containing window manager window,
1144 not Emacs's own window. */
1147 x_real_positions (f
, xptr
, yptr
)
1151 int win_x
, win_y
, outer_x
, outer_y
;
1152 int real_x
= 0, real_y
= 0;
1154 Window win
= f
->output_data
.x
->parent_desc
;
1160 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1162 if (win
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1163 win
= FRAME_OUTER_WINDOW (f
);
1165 /* This loop traverses up the containment tree until we hit the root
1166 window. Window managers may intersect many windows between our window
1167 and the root window. The window we find just before the root window
1168 should be the outer WM window. */
1171 Window wm_window
, rootw
;
1172 Window
*tmp_children
;
1173 unsigned int tmp_nchildren
;
1176 success
= XQueryTree (FRAME_X_DISPLAY (f
), win
, &rootw
,
1177 &wm_window
, &tmp_children
, &tmp_nchildren
);
1179 had_errors
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1181 /* Don't free tmp_children if XQueryTree failed. */
1185 XFree ((char *) tmp_children
);
1187 if (wm_window
== rootw
|| had_errors
)
1196 Window child
, rootw
;
1198 /* Get the real coordinates for the WM window upper left corner */
1199 XGetGeometry (FRAME_X_DISPLAY (f
), win
,
1200 &rootw
, &real_x
, &real_y
, &ign
, &ign
, &ign
, &ign
);
1202 /* Translate real coordinates to coordinates relative to our
1203 window. For our window, the upper left corner is 0, 0.
1204 Since the upper left corner of the WM window is outside
1205 our window, win_x and win_y will be negative:
1207 ------------------ ---> x
1209 | ----------------- v y
1212 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1214 /* From-window, to-window. */
1215 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1218 /* From-position, to-position. */
1219 real_x
, real_y
, &win_x
, &win_y
,
1224 if (FRAME_X_WINDOW (f
) == FRAME_OUTER_WINDOW (f
))
1231 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1233 /* From-window, to-window. */
1234 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1235 FRAME_OUTER_WINDOW (f
),
1237 /* From-position, to-position. */
1238 real_x
, real_y
, &outer_x
, &outer_y
,
1244 had_errors
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1247 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1251 if (had_errors
) return;
1253 f
->output_data
.x
->x_pixels_diff
= -win_x
;
1254 f
->output_data
.x
->y_pixels_diff
= -win_y
;
1255 f
->output_data
.x
->x_pixels_outer_diff
= -outer_x
;
1256 f
->output_data
.x
->y_pixels_outer_diff
= -outer_y
;
1262 /* Insert a description of internally-recorded parameters of frame X
1263 into the parameter alist *ALISTPTR that is to be given to the user.
1264 Only parameters that are specific to the X window system
1265 and whose values are not correctly recorded in the frame's
1266 param_alist need to be considered here. */
1269 x_report_frame_params (f
, alistptr
)
1271 Lisp_Object
*alistptr
;
1276 /* Represent negative positions (off the top or left screen edge)
1277 in a way that Fmodify_frame_parameters will understand correctly. */
1278 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1279 if (f
->output_data
.x
->left_pos
>= 0)
1280 store_in_alist (alistptr
, Qleft
, tem
);
1282 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1284 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1285 if (f
->output_data
.x
->top_pos
>= 0)
1286 store_in_alist (alistptr
, Qtop
, tem
);
1288 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1290 store_in_alist (alistptr
, Qborder_width
,
1291 make_number (f
->output_data
.x
->border_width
));
1292 store_in_alist (alistptr
, Qinternal_border_width
,
1293 make_number (f
->output_data
.x
->internal_border_width
));
1294 store_in_alist (alistptr
, Qleft_fringe
,
1295 make_number (f
->output_data
.x
->left_fringe_width
));
1296 store_in_alist (alistptr
, Qright_fringe
,
1297 make_number (f
->output_data
.x
->right_fringe_width
));
1298 store_in_alist (alistptr
, Qscroll_bar_width
,
1299 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
1300 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f
)
1302 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1303 store_in_alist (alistptr
, Qwindow_id
,
1304 build_string (buf
));
1305 #ifdef USE_X_TOOLKIT
1306 /* Tooltip frame may not have this widget. */
1307 if (f
->output_data
.x
->widget
)
1309 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1310 store_in_alist (alistptr
, Qouter_window_id
,
1311 build_string (buf
));
1312 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1313 FRAME_SAMPLE_VISIBILITY (f
);
1314 store_in_alist (alistptr
, Qvisibility
,
1315 (FRAME_VISIBLE_P (f
) ? Qt
1316 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1317 store_in_alist (alistptr
, Qdisplay
,
1318 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1320 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1323 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1324 store_in_alist (alistptr
, Qparent_id
, tem
);
1329 /* Gamma-correct COLOR on frame F. */
1332 gamma_correct (f
, color
)
1338 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1339 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1340 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1345 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1346 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1347 allocate the color. Value is zero if COLOR_NAME is invalid, or
1348 no color could be allocated. */
1351 x_defined_color (f
, color_name
, color
, alloc_p
)
1358 Display
*dpy
= FRAME_X_DISPLAY (f
);
1359 Colormap cmap
= FRAME_X_COLORMAP (f
);
1362 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1363 if (success_p
&& alloc_p
)
1364 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1371 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1372 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1373 Signal an error if color can't be allocated. */
1376 x_decode_color (f
, color_name
, mono_color
)
1378 Lisp_Object color_name
;
1383 CHECK_STRING (color_name
);
1385 #if 0 /* Don't do this. It's wrong when we're not using the default
1386 colormap, it makes freeing difficult, and it's probably not
1387 an important optimization. */
1388 if (strcmp (SDATA (color_name
), "black") == 0)
1389 return BLACK_PIX_DEFAULT (f
);
1390 else if (strcmp (SDATA (color_name
), "white") == 0)
1391 return WHITE_PIX_DEFAULT (f
);
1394 /* Return MONO_COLOR for monochrome frames. */
1395 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1398 /* x_defined_color is responsible for coping with failures
1399 by looking for a near-miss. */
1400 if (x_defined_color (f
, SDATA (color_name
), &cdef
, 1))
1403 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1404 Fcons (color_name
, Qnil
)));
1410 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1411 the previous value of that parameter, NEW_VALUE is the new value. */
1414 x_set_line_spacing (f
, new_value
, old_value
)
1416 Lisp_Object new_value
, old_value
;
1418 if (NILP (new_value
))
1419 f
->extra_line_spacing
= 0;
1420 else if (NATNUMP (new_value
))
1421 f
->extra_line_spacing
= XFASTINT (new_value
);
1423 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1424 Fcons (new_value
, Qnil
)));
1425 if (FRAME_VISIBLE_P (f
))
1430 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1431 the previous value of that parameter, NEW_VALUE is the new value.
1432 See also the comment of wait_for_wm in struct x_output. */
1435 x_set_wait_for_wm (f
, new_value
, old_value
)
1437 Lisp_Object new_value
, old_value
;
1439 f
->output_data
.x
->wait_for_wm
= !NILP (new_value
);
1443 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
1444 the previous value of that parameter, NEW_VALUE is the new value. */
1447 x_set_fullscreen (f
, new_value
, old_value
)
1449 Lisp_Object new_value
, old_value
;
1451 if (NILP (new_value
))
1452 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_NONE
;
1453 else if (EQ (new_value
, Qfullboth
))
1454 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_BOTH
;
1455 else if (EQ (new_value
, Qfullwidth
))
1456 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_WIDTH
;
1457 else if (EQ (new_value
, Qfullheight
))
1458 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_HEIGHT
;
1462 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1463 the previous value of that parameter, NEW_VALUE is the new
1467 x_set_screen_gamma (f
, new_value
, old_value
)
1469 Lisp_Object new_value
, old_value
;
1471 if (NILP (new_value
))
1473 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1474 /* The value 0.4545 is the normal viewing gamma. */
1475 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1477 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1478 Fcons (new_value
, Qnil
)));
1480 clear_face_cache (0);
1484 /* Functions called only from `x_set_frame_param'
1485 to set individual parameters.
1487 If FRAME_X_WINDOW (f) is 0,
1488 the frame is being created and its X-window does not exist yet.
1489 In that case, just record the parameter's new value
1490 in the standard place; do not attempt to change the window. */
1493 x_set_foreground_color (f
, arg
, oldval
)
1495 Lisp_Object arg
, oldval
;
1497 struct x_output
*x
= f
->output_data
.x
;
1498 unsigned long fg
, old_fg
;
1500 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1501 old_fg
= x
->foreground_pixel
;
1502 x
->foreground_pixel
= fg
;
1504 if (FRAME_X_WINDOW (f
) != 0)
1506 Display
*dpy
= FRAME_X_DISPLAY (f
);
1509 XSetForeground (dpy
, x
->normal_gc
, fg
);
1510 XSetBackground (dpy
, x
->reverse_gc
, fg
);
1512 if (x
->cursor_pixel
== old_fg
)
1514 unload_color (f
, x
->cursor_pixel
);
1515 x
->cursor_pixel
= x_copy_color (f
, fg
);
1516 XSetBackground (dpy
, x
->cursor_gc
, x
->cursor_pixel
);
1521 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1523 if (FRAME_VISIBLE_P (f
))
1527 unload_color (f
, old_fg
);
1531 x_set_background_color (f
, arg
, oldval
)
1533 Lisp_Object arg
, oldval
;
1535 struct x_output
*x
= f
->output_data
.x
;
1538 bg
= x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1539 unload_color (f
, x
->background_pixel
);
1540 x
->background_pixel
= bg
;
1542 if (FRAME_X_WINDOW (f
) != 0)
1544 Display
*dpy
= FRAME_X_DISPLAY (f
);
1547 XSetBackground (dpy
, x
->normal_gc
, bg
);
1548 XSetForeground (dpy
, x
->reverse_gc
, bg
);
1549 XSetWindowBackground (dpy
, FRAME_X_WINDOW (f
), bg
);
1550 XSetForeground (dpy
, x
->cursor_gc
, bg
);
1552 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1553 toolkit scroll bars. */
1556 for (bar
= FRAME_SCROLL_BARS (f
);
1558 bar
= XSCROLL_BAR (bar
)->next
)
1560 Window window
= SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
));
1561 XSetWindowBackground (dpy
, window
, bg
);
1564 #endif /* USE_TOOLKIT_SCROLL_BARS */
1567 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1569 if (FRAME_VISIBLE_P (f
))
1575 x_set_mouse_color (f
, arg
, oldval
)
1577 Lisp_Object arg
, oldval
;
1579 struct x_output
*x
= f
->output_data
.x
;
1580 Display
*dpy
= FRAME_X_DISPLAY (f
);
1581 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1582 Cursor hourglass_cursor
, horizontal_drag_cursor
;
1584 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1585 unsigned long mask_color
= x
->background_pixel
;
1587 /* Don't let pointers be invisible. */
1588 if (mask_color
== pixel
)
1590 x_free_colors (f
, &pixel
, 1);
1591 pixel
= x_copy_color (f
, x
->foreground_pixel
);
1594 unload_color (f
, x
->mouse_pixel
);
1595 x
->mouse_pixel
= pixel
;
1599 /* It's not okay to crash if the user selects a screwy cursor. */
1600 count
= x_catch_errors (dpy
);
1602 if (!NILP (Vx_pointer_shape
))
1604 CHECK_NUMBER (Vx_pointer_shape
);
1605 cursor
= XCreateFontCursor (dpy
, XINT (Vx_pointer_shape
));
1608 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1609 x_check_errors (dpy
, "bad text pointer cursor: %s");
1611 if (!NILP (Vx_nontext_pointer_shape
))
1613 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1615 = XCreateFontCursor (dpy
, XINT (Vx_nontext_pointer_shape
));
1618 nontext_cursor
= XCreateFontCursor (dpy
, XC_left_ptr
);
1619 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1621 if (!NILP (Vx_hourglass_pointer_shape
))
1623 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1625 = XCreateFontCursor (dpy
, XINT (Vx_hourglass_pointer_shape
));
1628 hourglass_cursor
= XCreateFontCursor (dpy
, XC_watch
);
1629 x_check_errors (dpy
, "bad hourglass pointer cursor: %s");
1631 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1632 if (!NILP (Vx_mode_pointer_shape
))
1634 CHECK_NUMBER (Vx_mode_pointer_shape
);
1635 mode_cursor
= XCreateFontCursor (dpy
, XINT (Vx_mode_pointer_shape
));
1638 mode_cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1639 x_check_errors (dpy
, "bad modeline pointer cursor: %s");
1641 if (!NILP (Vx_sensitive_text_pointer_shape
))
1643 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1645 = XCreateFontCursor (dpy
, XINT (Vx_sensitive_text_pointer_shape
));
1648 cross_cursor
= XCreateFontCursor (dpy
, XC_hand2
);
1650 if (!NILP (Vx_window_horizontal_drag_shape
))
1652 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1653 horizontal_drag_cursor
1654 = XCreateFontCursor (dpy
, XINT (Vx_window_horizontal_drag_shape
));
1657 horizontal_drag_cursor
1658 = XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
1660 /* Check and report errors with the above calls. */
1661 x_check_errors (dpy
, "can't set cursor shape: %s");
1662 x_uncatch_errors (dpy
, count
);
1665 XColor fore_color
, back_color
;
1667 fore_color
.pixel
= x
->mouse_pixel
;
1668 x_query_color (f
, &fore_color
);
1669 back_color
.pixel
= mask_color
;
1670 x_query_color (f
, &back_color
);
1672 XRecolorCursor (dpy
, cursor
, &fore_color
, &back_color
);
1673 XRecolorCursor (dpy
, nontext_cursor
, &fore_color
, &back_color
);
1674 XRecolorCursor (dpy
, mode_cursor
, &fore_color
, &back_color
);
1675 XRecolorCursor (dpy
, cross_cursor
, &fore_color
, &back_color
);
1676 XRecolorCursor (dpy
, hourglass_cursor
, &fore_color
, &back_color
);
1677 XRecolorCursor (dpy
, horizontal_drag_cursor
, &fore_color
, &back_color
);
1680 if (FRAME_X_WINDOW (f
) != 0)
1681 XDefineCursor (dpy
, FRAME_X_WINDOW (f
), cursor
);
1683 if (cursor
!= x
->text_cursor
1684 && x
->text_cursor
!= 0)
1685 XFreeCursor (dpy
, x
->text_cursor
);
1686 x
->text_cursor
= cursor
;
1688 if (nontext_cursor
!= x
->nontext_cursor
1689 && x
->nontext_cursor
!= 0)
1690 XFreeCursor (dpy
, x
->nontext_cursor
);
1691 x
->nontext_cursor
= nontext_cursor
;
1693 if (hourglass_cursor
!= x
->hourglass_cursor
1694 && x
->hourglass_cursor
!= 0)
1695 XFreeCursor (dpy
, x
->hourglass_cursor
);
1696 x
->hourglass_cursor
= hourglass_cursor
;
1698 if (mode_cursor
!= x
->modeline_cursor
1699 && x
->modeline_cursor
!= 0)
1700 XFreeCursor (dpy
, f
->output_data
.x
->modeline_cursor
);
1701 x
->modeline_cursor
= mode_cursor
;
1703 if (cross_cursor
!= x
->cross_cursor
1704 && x
->cross_cursor
!= 0)
1705 XFreeCursor (dpy
, x
->cross_cursor
);
1706 x
->cross_cursor
= cross_cursor
;
1708 if (horizontal_drag_cursor
!= x
->horizontal_drag_cursor
1709 && x
->horizontal_drag_cursor
!= 0)
1710 XFreeCursor (dpy
, x
->horizontal_drag_cursor
);
1711 x
->horizontal_drag_cursor
= horizontal_drag_cursor
;
1716 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1720 x_set_cursor_color (f
, arg
, oldval
)
1722 Lisp_Object arg
, oldval
;
1724 unsigned long fore_pixel
, pixel
;
1725 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1726 struct x_output
*x
= f
->output_data
.x
;
1728 if (!NILP (Vx_cursor_fore_pixel
))
1730 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1731 WHITE_PIX_DEFAULT (f
));
1732 fore_pixel_allocated_p
= 1;
1735 fore_pixel
= x
->background_pixel
;
1737 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1738 pixel_allocated_p
= 1;
1740 /* Make sure that the cursor color differs from the background color. */
1741 if (pixel
== x
->background_pixel
)
1743 if (pixel_allocated_p
)
1745 x_free_colors (f
, &pixel
, 1);
1746 pixel_allocated_p
= 0;
1749 pixel
= x
->mouse_pixel
;
1750 if (pixel
== fore_pixel
)
1752 if (fore_pixel_allocated_p
)
1754 x_free_colors (f
, &fore_pixel
, 1);
1755 fore_pixel_allocated_p
= 0;
1757 fore_pixel
= x
->background_pixel
;
1761 unload_color (f
, x
->cursor_foreground_pixel
);
1762 if (!fore_pixel_allocated_p
)
1763 fore_pixel
= x_copy_color (f
, fore_pixel
);
1764 x
->cursor_foreground_pixel
= fore_pixel
;
1766 unload_color (f
, x
->cursor_pixel
);
1767 if (!pixel_allocated_p
)
1768 pixel
= x_copy_color (f
, pixel
);
1769 x
->cursor_pixel
= pixel
;
1771 if (FRAME_X_WINDOW (f
) != 0)
1774 XSetBackground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, x
->cursor_pixel
);
1775 XSetForeground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, fore_pixel
);
1778 if (FRAME_VISIBLE_P (f
))
1780 x_update_cursor (f
, 0);
1781 x_update_cursor (f
, 1);
1785 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1788 /* Set the border-color of frame F to value described by ARG.
1789 ARG can be a string naming a color.
1790 The border-color is used for the border that is drawn by the X server.
1791 Note that this does not fully take effect if done before
1792 F has an x-window; it must be redone when the window is created.
1794 Note: this is done in two routines because of the way X10 works.
1796 Note: under X11, this is normally the province of the window manager,
1797 and so emacs' border colors may be overridden. */
1800 x_set_border_color (f
, arg
, oldval
)
1802 Lisp_Object arg
, oldval
;
1807 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1808 x_set_border_pixel (f
, pix
);
1809 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1812 /* Set the border-color of frame F to pixel value PIX.
1813 Note that this does not fully take effect if done before
1814 F has an x-window. */
1817 x_set_border_pixel (f
, pix
)
1821 unload_color (f
, f
->output_data
.x
->border_pixel
);
1822 f
->output_data
.x
->border_pixel
= pix
;
1824 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1827 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1828 (unsigned long)pix
);
1831 if (FRAME_VISIBLE_P (f
))
1837 /* Value is the internal representation of the specified cursor type
1838 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1839 of the bar cursor. */
1841 enum text_cursor_kinds
1842 x_specified_cursor_type (arg
, width
)
1846 enum text_cursor_kinds type
;
1853 else if (CONSP (arg
)
1854 && EQ (XCAR (arg
), Qbar
)
1855 && INTEGERP (XCDR (arg
))
1856 && XINT (XCDR (arg
)) >= 0)
1859 *width
= XINT (XCDR (arg
));
1861 else if (EQ (arg
, Qhbar
))
1866 else if (CONSP (arg
)
1867 && EQ (XCAR (arg
), Qhbar
)
1868 && INTEGERP (XCDR (arg
))
1869 && XINT (XCDR (arg
)) >= 0)
1872 *width
= XINT (XCDR (arg
));
1874 else if (NILP (arg
))
1877 /* Treat anything unknown as "box cursor".
1878 It was bad to signal an error; people have trouble fixing
1879 .Xdefaults with Emacs, when it has something bad in it. */
1880 type
= FILLED_BOX_CURSOR
;
1886 x_set_cursor_type (f
, arg
, oldval
)
1888 Lisp_Object arg
, oldval
;
1892 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1893 f
->output_data
.x
->cursor_width
= width
;
1895 /* Make sure the cursor gets redrawn. */
1896 cursor_type_changed
= 1;
1900 x_set_icon_type (f
, arg
, oldval
)
1902 Lisp_Object arg
, oldval
;
1908 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1911 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1916 result
= x_text_icon (f
,
1917 (char *) SDATA ((!NILP (f
->icon_name
)
1921 result
= x_bitmap_icon (f
, arg
);
1926 error ("No icon window available");
1929 XFlush (FRAME_X_DISPLAY (f
));
1933 /* Return non-nil if frame F wants a bitmap icon. */
1941 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1949 x_set_icon_name (f
, arg
, oldval
)
1951 Lisp_Object arg
, oldval
;
1957 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1960 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1965 if (f
->output_data
.x
->icon_bitmap
!= 0)
1970 result
= x_text_icon (f
,
1971 (char *) SDATA ((!NILP (f
->icon_name
)
1980 error ("No icon window available");
1983 XFlush (FRAME_X_DISPLAY (f
));
1988 x_set_font (f
, arg
, oldval
)
1990 Lisp_Object arg
, oldval
;
1993 Lisp_Object fontset_name
;
1995 int old_fontset
= f
->output_data
.x
->fontset
;
1999 fontset_name
= Fquery_fontset (arg
, Qnil
);
2002 result
= (STRINGP (fontset_name
)
2003 ? x_new_fontset (f
, SDATA (fontset_name
))
2004 : x_new_font (f
, SDATA (arg
)));
2007 if (EQ (result
, Qnil
))
2008 error ("Font `%s' is not defined", SDATA (arg
));
2009 else if (EQ (result
, Qt
))
2010 error ("The characters of the given font have varying widths");
2011 else if (STRINGP (result
))
2013 if (STRINGP (fontset_name
))
2015 /* Fontset names are built from ASCII font names, so the
2016 names may be equal despite there was a change. */
2017 if (old_fontset
== f
->output_data
.x
->fontset
)
2020 else if (!NILP (Fequal (result
, oldval
)))
2023 store_frame_param (f
, Qfont
, result
);
2024 recompute_basic_faces (f
);
2029 do_pending_window_change (0);
2031 /* Don't call `face-set-after-frame-default' when faces haven't been
2032 initialized yet. This is the case when called from
2033 Fx_create_frame. In that case, the X widget or window doesn't
2034 exist either, and we can end up in x_report_frame_params with a
2035 null widget which gives a segfault. */
2036 if (FRAME_FACE_CACHE (f
))
2038 XSETFRAME (frame
, f
);
2039 call1 (Qface_set_after_frame_default
, frame
);
2044 x_set_fringe_width (f
, new_value
, old_value
)
2046 Lisp_Object new_value
, old_value
;
2048 x_compute_fringe_widths (f
, 1);
2052 x_set_border_width (f
, arg
, oldval
)
2054 Lisp_Object arg
, oldval
;
2058 if (XINT (arg
) == f
->output_data
.x
->border_width
)
2061 if (FRAME_X_WINDOW (f
) != 0)
2062 error ("Cannot change the border width of a window");
2064 f
->output_data
.x
->border_width
= XINT (arg
);
2068 x_set_internal_border_width (f
, arg
, oldval
)
2070 Lisp_Object arg
, oldval
;
2072 int old
= f
->output_data
.x
->internal_border_width
;
2075 f
->output_data
.x
->internal_border_width
= XINT (arg
);
2076 if (f
->output_data
.x
->internal_border_width
< 0)
2077 f
->output_data
.x
->internal_border_width
= 0;
2079 #ifdef USE_X_TOOLKIT
2080 if (f
->output_data
.x
->edit_widget
)
2081 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
2084 if (f
->output_data
.x
->internal_border_width
== old
)
2087 if (FRAME_X_WINDOW (f
) != 0)
2089 x_set_window_size (f
, 0, f
->width
, f
->height
);
2090 SET_FRAME_GARBAGED (f
);
2091 do_pending_window_change (0);
2094 SET_FRAME_GARBAGED (f
);
2098 x_set_visibility (f
, value
, oldval
)
2100 Lisp_Object value
, oldval
;
2103 XSETFRAME (frame
, f
);
2106 Fmake_frame_invisible (frame
, Qt
);
2107 else if (EQ (value
, Qicon
))
2108 Ficonify_frame (frame
);
2110 Fmake_frame_visible (frame
);
2114 /* Change window heights in windows rooted in WINDOW by N lines. */
2117 x_change_window_heights (window
, n
)
2121 struct window
*w
= XWINDOW (window
);
2123 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
2124 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
2126 if (INTEGERP (w
->orig_top
))
2127 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
2128 if (INTEGERP (w
->orig_height
))
2129 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
2131 /* Handle just the top child in a vertical split. */
2132 if (!NILP (w
->vchild
))
2133 x_change_window_heights (w
->vchild
, n
);
2135 /* Adjust all children in a horizontal split. */
2136 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
2138 w
= XWINDOW (window
);
2139 x_change_window_heights (window
, n
);
2144 x_set_menu_bar_lines (f
, value
, oldval
)
2146 Lisp_Object value
, oldval
;
2149 #ifndef USE_X_TOOLKIT
2150 int olines
= FRAME_MENU_BAR_LINES (f
);
2153 /* Right now, menu bars don't work properly in minibuf-only frames;
2154 most of the commands try to apply themselves to the minibuffer
2155 frame itself, and get an error because you can't switch buffers
2156 in or split the minibuffer window. */
2157 if (FRAME_MINIBUF_ONLY_P (f
))
2160 if (INTEGERP (value
))
2161 nlines
= XINT (value
);
2165 /* Make sure we redisplay all windows in this frame. */
2166 windows_or_buffers_changed
++;
2168 #ifdef USE_X_TOOLKIT
2169 FRAME_MENU_BAR_LINES (f
) = 0;
2172 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2173 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2174 /* Make sure next redisplay shows the menu bar. */
2175 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2179 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2180 free_frame_menubar (f
);
2181 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2183 f
->output_data
.x
->menubar_widget
= 0;
2185 #else /* not USE_X_TOOLKIT */
2186 FRAME_MENU_BAR_LINES (f
) = nlines
;
2187 x_change_window_heights (f
->root_window
, nlines
- olines
);
2188 #endif /* not USE_X_TOOLKIT */
2193 /* Set the number of lines used for the tool bar of frame F to VALUE.
2194 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2195 is the old number of tool bar lines. This function changes the
2196 height of all windows on frame F to match the new tool bar height.
2197 The frame's height doesn't change. */
2200 x_set_tool_bar_lines (f
, value
, oldval
)
2202 Lisp_Object value
, oldval
;
2204 int delta
, nlines
, root_height
;
2205 Lisp_Object root_window
;
2207 /* Treat tool bars like menu bars. */
2208 if (FRAME_MINIBUF_ONLY_P (f
))
2211 /* Use VALUE only if an integer >= 0. */
2212 if (INTEGERP (value
) && XINT (value
) >= 0)
2213 nlines
= XFASTINT (value
);
2217 /* Make sure we redisplay all windows in this frame. */
2218 ++windows_or_buffers_changed
;
2220 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2222 /* Don't resize the tool-bar to more than we have room for. */
2223 root_window
= FRAME_ROOT_WINDOW (f
);
2224 root_height
= XINT (XWINDOW (root_window
)->height
);
2225 if (root_height
- delta
< 1)
2227 delta
= root_height
- 1;
2228 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2231 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2232 x_change_window_heights (root_window
, delta
);
2235 /* We also have to make sure that the internal border at the top of
2236 the frame, below the menu bar or tool bar, is redrawn when the
2237 tool bar disappears. This is so because the internal border is
2238 below the tool bar if one is displayed, but is below the menu bar
2239 if there isn't a tool bar. The tool bar draws into the area
2240 below the menu bar. */
2241 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2245 clear_current_matrices (f
);
2246 updating_frame
= NULL
;
2249 /* If the tool bar gets smaller, the internal border below it
2250 has to be cleared. It was formerly part of the display
2251 of the larger tool bar, and updating windows won't clear it. */
2254 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2255 int width
= PIXEL_WIDTH (f
);
2256 int y
= nlines
* CANON_Y_UNIT (f
);
2259 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2260 0, y
, width
, height
, False
);
2263 if (WINDOWP (f
->tool_bar_window
))
2264 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2269 /* Set the foreground color for scroll bars on frame F to VALUE.
2270 VALUE should be a string, a color name. If it isn't a string or
2271 isn't a valid color name, do nothing. OLDVAL is the old value of
2272 the frame parameter. */
2275 x_set_scroll_bar_foreground (f
, value
, oldval
)
2277 Lisp_Object value
, oldval
;
2279 unsigned long pixel
;
2281 if (STRINGP (value
))
2282 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2286 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2287 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2289 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2290 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2292 /* Remove all scroll bars because they have wrong colors. */
2293 if (condemn_scroll_bars_hook
)
2294 (*condemn_scroll_bars_hook
) (f
);
2295 if (judge_scroll_bars_hook
)
2296 (*judge_scroll_bars_hook
) (f
);
2298 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2304 /* Set the background color for scroll bars on frame F to VALUE VALUE
2305 should be a string, a color name. If it isn't a string or isn't a
2306 valid color name, do nothing. OLDVAL is the old value of the frame
2310 x_set_scroll_bar_background (f
, value
, oldval
)
2312 Lisp_Object value
, oldval
;
2314 unsigned long pixel
;
2316 if (STRINGP (value
))
2317 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2321 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2322 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2324 #ifdef USE_TOOLKIT_SCROLL_BARS
2325 /* Scrollbar shadow colors. */
2326 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
2328 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
2329 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
2331 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
2333 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
2334 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
2336 #endif /* USE_TOOLKIT_SCROLL_BARS */
2338 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2339 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2341 /* Remove all scroll bars because they have wrong colors. */
2342 if (condemn_scroll_bars_hook
)
2343 (*condemn_scroll_bars_hook
) (f
);
2344 if (judge_scroll_bars_hook
)
2345 (*judge_scroll_bars_hook
) (f
);
2347 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2353 /* Encode Lisp string STRING as a text in a format appropriate for
2354 XICCC (X Inter Client Communication Conventions).
2356 If STRING contains only ASCII characters, do no conversion and
2357 return the string data of STRING. Otherwise, encode the text by
2358 CODING_SYSTEM, and return a newly allocated memory area which
2359 should be freed by `xfree' by a caller.
2361 SELECTIONP non-zero means the string is being encoded for an X
2362 selection, so it is safe to run pre-write conversions (which
2365 Store the byte length of resulting text in *TEXT_BYTES.
2367 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2368 which means that the `encoding' of the result can be `STRING'.
2369 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2370 the result should be `COMPOUND_TEXT'. */
2373 x_encode_text (string
, coding_system
, selectionp
, text_bytes
, stringp
)
2374 Lisp_Object string
, coding_system
;
2375 int *text_bytes
, *stringp
;
2378 unsigned char *str
= SDATA (string
);
2379 int chars
= SCHARS (string
);
2380 int bytes
= SBYTES (string
);
2384 struct coding_system coding
;
2385 extern Lisp_Object Qcompound_text_with_extensions
;
2387 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2388 if (charset_info
== 0)
2390 /* No multibyte character in OBJ. We need not encode it. */
2391 *text_bytes
= bytes
;
2396 setup_coding_system (coding_system
, &coding
);
2398 && SYMBOLP (coding
.pre_write_conversion
)
2399 && !NILP (Ffboundp (coding
.pre_write_conversion
)))
2401 string
= run_pre_post_conversion_on_str (string
, &coding
, 1);
2402 str
= SDATA (string
);
2403 chars
= SCHARS (string
);
2404 bytes
= SBYTES (string
);
2406 coding
.src_multibyte
= 1;
2407 coding
.dst_multibyte
= 0;
2408 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2409 if (coding
.type
== coding_type_iso2022
)
2410 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2411 /* We suppress producing escape sequences for composition. */
2412 coding
.composing
= COMPOSITION_DISABLED
;
2413 bufsize
= encoding_buffer_size (&coding
, bytes
);
2414 buf
= (unsigned char *) xmalloc (bufsize
);
2415 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2416 *text_bytes
= coding
.produced
;
2417 *stringp
= (charset_info
== 1
2418 || (!EQ (coding_system
, Qcompound_text
)
2419 && !EQ (coding_system
, Qcompound_text_with_extensions
)));
2424 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2427 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2428 name; if NAME is a string, set F's name to NAME and set
2429 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2431 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2432 suggesting a new name, which lisp code should override; if
2433 F->explicit_name is set, ignore the new name; otherwise, set it. */
2436 x_set_name (f
, name
, explicit)
2441 /* Make sure that requests from lisp code override requests from
2442 Emacs redisplay code. */
2445 /* If we're switching from explicit to implicit, we had better
2446 update the mode lines and thereby update the title. */
2447 if (f
->explicit_name
&& NILP (name
))
2448 update_mode_lines
= 1;
2450 f
->explicit_name
= ! NILP (name
);
2452 else if (f
->explicit_name
)
2455 /* If NAME is nil, set the name to the x_id_name. */
2458 /* Check for no change needed in this very common case
2459 before we do any consing. */
2460 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2463 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2466 CHECK_STRING (name
);
2468 /* Don't change the name if it's already NAME. */
2469 if (! NILP (Fstring_equal (name
, f
->name
)))
2474 /* For setting the frame title, the title parameter should override
2475 the name parameter. */
2476 if (! NILP (f
->title
))
2479 if (FRAME_X_WINDOW (f
))
2484 XTextProperty text
, icon
;
2486 Lisp_Object coding_system
;
2488 coding_system
= Vlocale_coding_system
;
2489 if (NILP (coding_system
))
2490 coding_system
= Qcompound_text
;
2491 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2492 text
.encoding
= (stringp
? XA_STRING
2493 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2495 text
.nitems
= bytes
;
2497 if (NILP (f
->icon_name
))
2503 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2505 icon
.encoding
= (stringp
? XA_STRING
2506 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2508 icon
.nitems
= bytes
;
2510 #ifdef USE_X_TOOLKIT
2511 XSetWMName (FRAME_X_DISPLAY (f
),
2512 XtWindow (f
->output_data
.x
->widget
), &text
);
2513 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2515 #else /* not USE_X_TOOLKIT */
2516 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2517 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2518 #endif /* not USE_X_TOOLKIT */
2519 if (!NILP (f
->icon_name
)
2520 && icon
.value
!= SDATA (f
->icon_name
))
2522 if (text
.value
!= SDATA (name
))
2525 #else /* not HAVE_X11R4 */
2526 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2528 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2530 #endif /* not HAVE_X11R4 */
2535 /* This function should be called when the user's lisp code has
2536 specified a name for the frame; the name will override any set by the
2539 x_explicitly_set_name (f
, arg
, oldval
)
2541 Lisp_Object arg
, oldval
;
2543 x_set_name (f
, arg
, 1);
2546 /* This function should be called by Emacs redisplay code to set the
2547 name; names set this way will never override names set by the user's
2550 x_implicitly_set_name (f
, arg
, oldval
)
2552 Lisp_Object arg
, oldval
;
2554 x_set_name (f
, arg
, 0);
2557 /* Change the title of frame F to NAME.
2558 If NAME is nil, use the frame name as the title.
2560 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2561 name; if NAME is a string, set F's name to NAME and set
2562 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2564 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2565 suggesting a new name, which lisp code should override; if
2566 F->explicit_name is set, ignore the new name; otherwise, set it. */
2569 x_set_title (f
, name
, old_name
)
2571 Lisp_Object name
, old_name
;
2573 /* Don't change the title if it's already NAME. */
2574 if (EQ (name
, f
->title
))
2577 update_mode_lines
= 1;
2584 CHECK_STRING (name
);
2586 if (FRAME_X_WINDOW (f
))
2591 XTextProperty text
, icon
;
2593 Lisp_Object coding_system
;
2595 coding_system
= Vlocale_coding_system
;
2596 if (NILP (coding_system
))
2597 coding_system
= Qcompound_text
;
2598 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2599 text
.encoding
= (stringp
? XA_STRING
2600 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2602 text
.nitems
= bytes
;
2604 if (NILP (f
->icon_name
))
2610 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2612 icon
.encoding
= (stringp
? XA_STRING
2613 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2615 icon
.nitems
= bytes
;
2617 #ifdef USE_X_TOOLKIT
2618 XSetWMName (FRAME_X_DISPLAY (f
),
2619 XtWindow (f
->output_data
.x
->widget
), &text
);
2620 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2622 #else /* not USE_X_TOOLKIT */
2623 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2624 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2625 #endif /* not USE_X_TOOLKIT */
2626 if (!NILP (f
->icon_name
)
2627 && icon
.value
!= SDATA (f
->icon_name
))
2629 if (text
.value
!= SDATA (name
))
2632 #else /* not HAVE_X11R4 */
2633 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2635 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2637 #endif /* not HAVE_X11R4 */
2643 x_set_autoraise (f
, arg
, oldval
)
2645 Lisp_Object arg
, oldval
;
2647 f
->auto_raise
= !EQ (Qnil
, arg
);
2651 x_set_autolower (f
, arg
, oldval
)
2653 Lisp_Object arg
, oldval
;
2655 f
->auto_lower
= !EQ (Qnil
, arg
);
2659 x_set_unsplittable (f
, arg
, oldval
)
2661 Lisp_Object arg
, oldval
;
2663 f
->no_split
= !NILP (arg
);
2667 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2669 Lisp_Object arg
, oldval
;
2671 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2672 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2673 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2674 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2676 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2678 ? vertical_scroll_bar_none
2680 ? vertical_scroll_bar_right
2681 : vertical_scroll_bar_left
);
2683 /* We set this parameter before creating the X window for the
2684 frame, so we can get the geometry right from the start.
2685 However, if the window hasn't been created yet, we shouldn't
2686 call x_set_window_size. */
2687 if (FRAME_X_WINDOW (f
))
2688 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2689 do_pending_window_change (0);
2694 x_set_scroll_bar_width (f
, arg
, oldval
)
2696 Lisp_Object arg
, oldval
;
2698 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2702 #ifdef USE_TOOLKIT_SCROLL_BARS
2703 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2704 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2705 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2706 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2708 /* Make the actual width at least 14 pixels and a multiple of a
2710 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2712 /* Use all of that space (aside from required margins) for the
2714 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2717 if (FRAME_X_WINDOW (f
))
2718 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2719 do_pending_window_change (0);
2721 else if (INTEGERP (arg
) && XINT (arg
) > 0
2722 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2724 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2725 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2727 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2728 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2729 if (FRAME_X_WINDOW (f
))
2730 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2733 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2734 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2735 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2740 /* Subroutines of creating an X frame. */
2742 /* Make sure that Vx_resource_name is set to a reasonable value.
2743 Fix it up, or set it to `emacs' if it is too hopeless. */
2746 validate_x_resource_name ()
2749 /* Number of valid characters in the resource name. */
2751 /* Number of invalid characters in the resource name. */
2756 if (!STRINGP (Vx_resource_class
))
2757 Vx_resource_class
= build_string (EMACS_CLASS
);
2759 if (STRINGP (Vx_resource_name
))
2761 unsigned char *p
= SDATA (Vx_resource_name
);
2764 len
= SBYTES (Vx_resource_name
);
2766 /* Only letters, digits, - and _ are valid in resource names.
2767 Count the valid characters and count the invalid ones. */
2768 for (i
= 0; i
< len
; i
++)
2771 if (! ((c
>= 'a' && c
<= 'z')
2772 || (c
>= 'A' && c
<= 'Z')
2773 || (c
>= '0' && c
<= '9')
2774 || c
== '-' || c
== '_'))
2781 /* Not a string => completely invalid. */
2782 bad_count
= 5, good_count
= 0;
2784 /* If name is valid already, return. */
2788 /* If name is entirely invalid, or nearly so, use `emacs'. */
2790 || (good_count
== 1 && bad_count
> 0))
2792 Vx_resource_name
= build_string ("emacs");
2796 /* Name is partly valid. Copy it and replace the invalid characters
2797 with underscores. */
2799 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2801 for (i
= 0; i
< len
; i
++)
2803 int c
= SREF (new, i
);
2804 if (! ((c
>= 'a' && c
<= 'z')
2805 || (c
>= 'A' && c
<= 'Z')
2806 || (c
>= '0' && c
<= '9')
2807 || c
== '-' || c
== '_'))
2813 extern char *x_get_string_resource ();
2815 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2816 doc
: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2817 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2818 class, where INSTANCE is the name under which Emacs was invoked, or
2819 the name specified by the `-name' or `-rn' command-line arguments.
2821 The optional arguments COMPONENT and SUBCLASS add to the key and the
2822 class, respectively. You must specify both of them or neither.
2823 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2824 and the class is `Emacs.CLASS.SUBCLASS'. */)
2825 (attribute
, class, component
, subclass
)
2826 Lisp_Object attribute
, class, component
, subclass
;
2828 register char *value
;
2834 CHECK_STRING (attribute
);
2835 CHECK_STRING (class);
2837 if (!NILP (component
))
2838 CHECK_STRING (component
);
2839 if (!NILP (subclass
))
2840 CHECK_STRING (subclass
);
2841 if (NILP (component
) != NILP (subclass
))
2842 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2844 validate_x_resource_name ();
2846 /* Allocate space for the components, the dots which separate them,
2847 and the final '\0'. Make them big enough for the worst case. */
2848 name_key
= (char *) alloca (SBYTES (Vx_resource_name
)
2849 + (STRINGP (component
)
2850 ? SBYTES (component
) : 0)
2851 + SBYTES (attribute
)
2854 class_key
= (char *) alloca (SBYTES (Vx_resource_class
)
2856 + (STRINGP (subclass
)
2857 ? SBYTES (subclass
) : 0)
2860 /* Start with emacs.FRAMENAME for the name (the specific one)
2861 and with `Emacs' for the class key (the general one). */
2862 strcpy (name_key
, SDATA (Vx_resource_name
));
2863 strcpy (class_key
, SDATA (Vx_resource_class
));
2865 strcat (class_key
, ".");
2866 strcat (class_key
, SDATA (class));
2868 if (!NILP (component
))
2870 strcat (class_key
, ".");
2871 strcat (class_key
, SDATA (subclass
));
2873 strcat (name_key
, ".");
2874 strcat (name_key
, SDATA (component
));
2877 strcat (name_key
, ".");
2878 strcat (name_key
, SDATA (attribute
));
2880 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2881 name_key
, class_key
);
2883 if (value
!= (char *) 0)
2884 return build_string (value
);
2889 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2892 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2893 struct x_display_info
*dpyinfo
;
2894 Lisp_Object attribute
, class, component
, subclass
;
2896 register char *value
;
2900 CHECK_STRING (attribute
);
2901 CHECK_STRING (class);
2903 if (!NILP (component
))
2904 CHECK_STRING (component
);
2905 if (!NILP (subclass
))
2906 CHECK_STRING (subclass
);
2907 if (NILP (component
) != NILP (subclass
))
2908 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2910 validate_x_resource_name ();
2912 /* Allocate space for the components, the dots which separate them,
2913 and the final '\0'. Make them big enough for the worst case. */
2914 name_key
= (char *) alloca (SBYTES (Vx_resource_name
)
2915 + (STRINGP (component
)
2916 ? SBYTES (component
) : 0)
2917 + SBYTES (attribute
)
2920 class_key
= (char *) alloca (SBYTES (Vx_resource_class
)
2922 + (STRINGP (subclass
)
2923 ? SBYTES (subclass
) : 0)
2926 /* Start with emacs.FRAMENAME for the name (the specific one)
2927 and with `Emacs' for the class key (the general one). */
2928 strcpy (name_key
, SDATA (Vx_resource_name
));
2929 strcpy (class_key
, SDATA (Vx_resource_class
));
2931 strcat (class_key
, ".");
2932 strcat (class_key
, SDATA (class));
2934 if (!NILP (component
))
2936 strcat (class_key
, ".");
2937 strcat (class_key
, SDATA (subclass
));
2939 strcat (name_key
, ".");
2940 strcat (name_key
, SDATA (component
));
2943 strcat (name_key
, ".");
2944 strcat (name_key
, SDATA (attribute
));
2946 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2948 if (value
!= (char *) 0)
2949 return build_string (value
);
2954 /* Used when C code wants a resource value. */
2957 x_get_resource_string (attribute
, class)
2958 char *attribute
, *class;
2962 struct frame
*sf
= SELECTED_FRAME ();
2964 /* Allocate space for the components, the dots which separate them,
2965 and the final '\0'. */
2966 name_key
= (char *) alloca (SBYTES (Vinvocation_name
)
2967 + strlen (attribute
) + 2);
2968 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2969 + strlen (class) + 2);
2971 sprintf (name_key
, "%s.%s",
2972 SDATA (Vinvocation_name
),
2974 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2976 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2977 name_key
, class_key
);
2980 /* Types we might convert a resource string into. */
2990 /* Return the value of parameter PARAM.
2992 First search ALIST, then Vdefault_frame_alist, then the X defaults
2993 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2995 Convert the resource to the type specified by desired_type.
2997 If no default is specified, return Qunbound. If you call
2998 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2999 and don't let it get stored in any Lisp-visible variables! */
3002 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
3003 struct x_display_info
*dpyinfo
;
3004 Lisp_Object alist
, param
;
3007 enum resource_types type
;
3009 register Lisp_Object tem
;
3011 tem
= Fassq (param
, alist
);
3013 tem
= Fassq (param
, Vdefault_frame_alist
);
3019 tem
= display_x_get_resource (dpyinfo
,
3020 build_string (attribute
),
3021 build_string (class),
3029 case RES_TYPE_NUMBER
:
3030 return make_number (atoi (SDATA (tem
)));
3032 case RES_TYPE_FLOAT
:
3033 return make_float (atof (SDATA (tem
)));
3035 case RES_TYPE_BOOLEAN
:
3036 tem
= Fdowncase (tem
);
3037 if (!strcmp (SDATA (tem
), "on")
3038 || !strcmp (SDATA (tem
), "true"))
3043 case RES_TYPE_STRING
:
3046 case RES_TYPE_SYMBOL
:
3047 /* As a special case, we map the values `true' and `on'
3048 to Qt, and `false' and `off' to Qnil. */
3051 lower
= Fdowncase (tem
);
3052 if (!strcmp (SDATA (lower
), "on")
3053 || !strcmp (SDATA (lower
), "true"))
3055 else if (!strcmp (SDATA (lower
), "off")
3056 || !strcmp (SDATA (lower
), "false"))
3059 return Fintern (tem
, Qnil
);
3072 /* Like x_get_arg, but also record the value in f->param_alist. */
3075 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
3077 Lisp_Object alist
, param
;
3080 enum resource_types type
;
3084 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
3085 attribute
, class, type
);
3087 store_frame_param (f
, param
, value
);
3092 /* Record in frame F the specified or default value according to ALIST
3093 of the parameter named PROP (a Lisp symbol).
3094 If no value is specified for PROP, look for an X default for XPROP
3095 on the frame named NAME.
3096 If that is not found either, use the value DEFLT. */
3099 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
3106 enum resource_types type
;
3110 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
3111 if (EQ (tem
, Qunbound
))
3113 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3118 /* Record in frame F the specified or default value according to ALIST
3119 of the parameter named PROP (a Lisp symbol). If no value is
3120 specified for PROP, look for an X default for XPROP on the frame
3121 named NAME. If that is not found either, use the value DEFLT. */
3124 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
3133 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3136 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
3137 if (EQ (tem
, Qunbound
))
3139 #ifdef USE_TOOLKIT_SCROLL_BARS
3141 /* See if an X resource for the scroll bar color has been
3143 tem
= display_x_get_resource (dpyinfo
,
3144 build_string (foreground_p
3148 build_string ("verticalScrollBar"),
3152 /* If nothing has been specified, scroll bars will use a
3153 toolkit-dependent default. Because these defaults are
3154 difficult to get at without actually creating a scroll
3155 bar, use nil to indicate that no color has been
3160 #else /* not USE_TOOLKIT_SCROLL_BARS */
3164 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3167 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3173 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3174 doc
: /* Parse an X-style geometry string STRING.
3175 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3176 The properties returned may include `top', `left', `height', and `width'.
3177 The value of `left' or `top' may be an integer,
3178 or a list (+ N) meaning N pixels relative to top/left corner,
3179 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3184 unsigned int width
, height
;
3187 CHECK_STRING (string
);
3189 geometry
= XParseGeometry ((char *) SDATA (string
),
3190 &x
, &y
, &width
, &height
);
3193 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3194 error ("Must specify both x and y position, or neither");
3198 if (geometry
& XValue
)
3200 Lisp_Object element
;
3202 if (x
>= 0 && (geometry
& XNegative
))
3203 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3204 else if (x
< 0 && ! (geometry
& XNegative
))
3205 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3207 element
= Fcons (Qleft
, make_number (x
));
3208 result
= Fcons (element
, result
);
3211 if (geometry
& YValue
)
3213 Lisp_Object element
;
3215 if (y
>= 0 && (geometry
& YNegative
))
3216 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3217 else if (y
< 0 && ! (geometry
& YNegative
))
3218 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3220 element
= Fcons (Qtop
, make_number (y
));
3221 result
= Fcons (element
, result
);
3224 if (geometry
& WidthValue
)
3225 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3226 if (geometry
& HeightValue
)
3227 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3232 /* Calculate the desired size and position of this window,
3233 and return the flags saying which aspects were specified.
3235 This function does not make the coordinates positive. */
3237 #define DEFAULT_ROWS 40
3238 #define DEFAULT_COLS 80
3241 x_figure_window_size (f
, parms
)
3245 register Lisp_Object tem0
, tem1
, tem2
;
3246 long window_prompting
= 0;
3247 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3249 /* Default values if we fall through.
3250 Actually, if that happens we should get
3251 window manager prompting. */
3252 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3253 f
->height
= DEFAULT_ROWS
;
3254 /* Window managers expect that if program-specified
3255 positions are not (0,0), they're intentional, not defaults. */
3256 f
->output_data
.x
->top_pos
= 0;
3257 f
->output_data
.x
->left_pos
= 0;
3259 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3260 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3261 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3262 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3264 if (!EQ (tem0
, Qunbound
))
3266 CHECK_NUMBER (tem0
);
3267 f
->height
= XINT (tem0
);
3269 if (!EQ (tem1
, Qunbound
))
3271 CHECK_NUMBER (tem1
);
3272 SET_FRAME_WIDTH (f
, XINT (tem1
));
3274 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3275 window_prompting
|= USSize
;
3277 window_prompting
|= PSize
;
3280 f
->output_data
.x
->vertical_scroll_bar_extra
3281 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3283 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3285 x_compute_fringe_widths (f
, 0);
3287 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3288 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3290 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3291 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3292 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3293 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3295 if (EQ (tem0
, Qminus
))
3297 f
->output_data
.x
->top_pos
= 0;
3298 window_prompting
|= YNegative
;
3300 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3301 && CONSP (XCDR (tem0
))
3302 && INTEGERP (XCAR (XCDR (tem0
))))
3304 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3305 window_prompting
|= YNegative
;
3307 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3308 && CONSP (XCDR (tem0
))
3309 && INTEGERP (XCAR (XCDR (tem0
))))
3311 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3313 else if (EQ (tem0
, Qunbound
))
3314 f
->output_data
.x
->top_pos
= 0;
3317 CHECK_NUMBER (tem0
);
3318 f
->output_data
.x
->top_pos
= XINT (tem0
);
3319 if (f
->output_data
.x
->top_pos
< 0)
3320 window_prompting
|= YNegative
;
3323 if (EQ (tem1
, Qminus
))
3325 f
->output_data
.x
->left_pos
= 0;
3326 window_prompting
|= XNegative
;
3328 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3329 && CONSP (XCDR (tem1
))
3330 && INTEGERP (XCAR (XCDR (tem1
))))
3332 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3333 window_prompting
|= XNegative
;
3335 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3336 && CONSP (XCDR (tem1
))
3337 && INTEGERP (XCAR (XCDR (tem1
))))
3339 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3341 else if (EQ (tem1
, Qunbound
))
3342 f
->output_data
.x
->left_pos
= 0;
3345 CHECK_NUMBER (tem1
);
3346 f
->output_data
.x
->left_pos
= XINT (tem1
);
3347 if (f
->output_data
.x
->left_pos
< 0)
3348 window_prompting
|= XNegative
;
3351 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3352 window_prompting
|= USPosition
;
3354 window_prompting
|= PPosition
;
3357 if (f
->output_data
.x
->want_fullscreen
!= FULLSCREEN_NONE
)
3362 /* It takes both for some WM:s to place it where we want */
3363 window_prompting
= USPosition
| PPosition
;
3364 x_fullscreen_adjust (f
, &width
, &height
, &top
, &left
);
3367 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3368 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3369 f
->output_data
.x
->left_pos
= left
;
3370 f
->output_data
.x
->top_pos
= top
;
3373 return window_prompting
;
3376 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3379 XSetWMProtocols (dpy
, w
, protocols
, count
)
3386 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3387 if (prop
== None
) return False
;
3388 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3389 (unsigned char *) protocols
, count
);
3392 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3394 #ifdef USE_X_TOOLKIT
3396 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3397 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3398 already be present because of the toolkit (Motif adds some of them,
3399 for example, but Xt doesn't). */
3402 hack_wm_protocols (f
, widget
)
3406 Display
*dpy
= XtDisplay (widget
);
3407 Window w
= XtWindow (widget
);
3408 int need_delete
= 1;
3414 Atom type
, *atoms
= 0;
3416 unsigned long nitems
= 0;
3417 unsigned long bytes_after
;
3419 if ((XGetWindowProperty (dpy
, w
,
3420 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3421 (long)0, (long)100, False
, XA_ATOM
,
3422 &type
, &format
, &nitems
, &bytes_after
,
3423 (unsigned char **) &atoms
)
3425 && format
== 32 && type
== XA_ATOM
)
3429 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3431 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3433 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3436 if (atoms
) XFree ((char *) atoms
);
3442 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3444 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3446 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3448 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3449 XA_ATOM
, 32, PropModeAppend
,
3450 (unsigned char *) props
, count
);
3458 /* Support routines for XIC (X Input Context). */
3462 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3463 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3466 /* Supported XIM styles, ordered by preferenc. */
3468 static XIMStyle supported_xim_styles
[] =
3470 XIMPreeditPosition
| XIMStatusArea
,
3471 XIMPreeditPosition
| XIMStatusNothing
,
3472 XIMPreeditPosition
| XIMStatusNone
,
3473 XIMPreeditNothing
| XIMStatusArea
,
3474 XIMPreeditNothing
| XIMStatusNothing
,
3475 XIMPreeditNothing
| XIMStatusNone
,
3476 XIMPreeditNone
| XIMStatusArea
,
3477 XIMPreeditNone
| XIMStatusNothing
,
3478 XIMPreeditNone
| XIMStatusNone
,
3483 /* Create an X fontset on frame F with base font name
3487 xic_create_xfontset (f
, base_fontname
)
3489 char *base_fontname
;
3492 char **missing_list
;
3496 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3497 base_fontname
, &missing_list
,
3498 &missing_count
, &def_string
);
3500 XFreeStringList (missing_list
);
3502 /* No need to free def_string. */
3507 /* Value is the best input style, given user preferences USER (already
3508 checked to be supported by Emacs), and styles supported by the
3509 input method XIM. */
3512 best_xim_style (user
, xim
)
3518 for (i
= 0; i
< user
->count_styles
; ++i
)
3519 for (j
= 0; j
< xim
->count_styles
; ++j
)
3520 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3521 return user
->supported_styles
[i
];
3523 /* Return the default style. */
3524 return XIMPreeditNothing
| XIMStatusNothing
;
3527 /* Create XIC for frame F. */
3529 static XIMStyle xic_style
;
3532 create_frame_xic (f
)
3537 XFontSet xfs
= NULL
;
3542 xim
= FRAME_X_XIM (f
);
3547 XVaNestedList preedit_attr
;
3548 XVaNestedList status_attr
;
3549 char *base_fontname
;
3552 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3553 spot
.x
= 0; spot
.y
= 1;
3554 /* Create X fontset. */
3555 fontset
= FRAME_FONTSET (f
);
3557 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3560 /* Determine the base fontname from the ASCII font name of
3562 char *ascii_font
= (char *) SDATA (fontset_ascii (fontset
));
3563 char *p
= ascii_font
;
3566 for (i
= 0; *p
; p
++)
3569 /* As the font name doesn't conform to XLFD, we can't
3570 modify it to get a suitable base fontname for the
3572 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3575 int len
= strlen (ascii_font
) + 1;
3578 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3587 base_fontname
= (char *) alloca (len
);
3588 bzero (base_fontname
, len
);
3589 strcpy (base_fontname
, "-*-*-");
3590 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3591 strcat (base_fontname
, "*-*-*-*-*-*-*");
3594 xfs
= xic_create_xfontset (f
, base_fontname
);
3596 /* Determine XIC style. */
3599 XIMStyles supported_list
;
3600 supported_list
.count_styles
= (sizeof supported_xim_styles
3601 / sizeof supported_xim_styles
[0]);
3602 supported_list
.supported_styles
= supported_xim_styles
;
3603 xic_style
= best_xim_style (&supported_list
,
3604 FRAME_X_XIM_STYLES (f
));
3607 preedit_attr
= XVaCreateNestedList (0,
3610 FRAME_FOREGROUND_PIXEL (f
),
3612 FRAME_BACKGROUND_PIXEL (f
),
3613 (xic_style
& XIMPreeditPosition
3618 status_attr
= XVaCreateNestedList (0,
3624 FRAME_FOREGROUND_PIXEL (f
),
3626 FRAME_BACKGROUND_PIXEL (f
),
3629 xic
= XCreateIC (xim
,
3630 XNInputStyle
, xic_style
,
3631 XNClientWindow
, FRAME_X_WINDOW(f
),
3632 XNFocusWindow
, FRAME_X_WINDOW(f
),
3633 XNStatusAttributes
, status_attr
,
3634 XNPreeditAttributes
, preedit_attr
,
3636 XFree (preedit_attr
);
3637 XFree (status_attr
);
3640 FRAME_XIC (f
) = xic
;
3641 FRAME_XIC_STYLE (f
) = xic_style
;
3642 FRAME_XIC_FONTSET (f
) = xfs
;
3646 /* Destroy XIC and free XIC fontset of frame F, if any. */
3652 if (FRAME_XIC (f
) == NULL
)
3655 XDestroyIC (FRAME_XIC (f
));
3656 if (FRAME_XIC_FONTSET (f
))
3657 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3659 FRAME_XIC (f
) = NULL
;
3660 FRAME_XIC_FONTSET (f
) = NULL
;
3664 /* Place preedit area for XIC of window W's frame to specified
3665 pixel position X/Y. X and Y are relative to window W. */
3668 xic_set_preeditarea (w
, x
, y
)
3672 struct frame
*f
= XFRAME (w
->frame
);
3676 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3677 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3678 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3679 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3684 /* Place status area for XIC in bottom right corner of frame F.. */
3687 xic_set_statusarea (f
)
3690 XIC xic
= FRAME_XIC (f
);
3695 /* Negotiate geometry of status area. If input method has existing
3696 status area, use its current size. */
3697 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3698 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3699 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3702 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3703 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3706 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3708 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3709 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3713 area
.width
= needed
->width
;
3714 area
.height
= needed
->height
;
3715 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3716 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3717 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3720 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3721 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3726 /* Set X fontset for XIC of frame F, using base font name
3727 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3730 xic_set_xfontset (f
, base_fontname
)
3732 char *base_fontname
;
3737 xfs
= xic_create_xfontset (f
, base_fontname
);
3739 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3740 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3741 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3742 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3743 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3746 if (FRAME_XIC_FONTSET (f
))
3747 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3748 FRAME_XIC_FONTSET (f
) = xfs
;
3751 #endif /* HAVE_X_I18N */
3755 #ifdef USE_X_TOOLKIT
3757 /* Create and set up the X widget for frame F. */
3760 x_window (f
, window_prompting
, minibuffer_only
)
3762 long window_prompting
;
3763 int minibuffer_only
;
3765 XClassHint class_hints
;
3766 XSetWindowAttributes attributes
;
3767 unsigned long attribute_mask
;
3768 Widget shell_widget
;
3770 Widget frame_widget
;
3776 /* Use the resource name as the top-level widget name
3777 for looking up resources. Make a non-Lisp copy
3778 for the window manager, so GC relocation won't bother it.
3780 Elsewhere we specify the window name for the window manager. */
3783 char *str
= (char *) SDATA (Vx_resource_name
);
3784 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3785 strcpy (f
->namebuf
, str
);
3789 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3790 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3791 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3792 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3793 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3794 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3795 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3796 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3797 applicationShellWidgetClass
,
3798 FRAME_X_DISPLAY (f
), al
, ac
);
3800 f
->output_data
.x
->widget
= shell_widget
;
3801 /* maybe_set_screen_title_format (shell_widget); */
3803 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3804 (widget_value
*) NULL
,
3805 shell_widget
, False
,
3809 (lw_callback
) NULL
);
3812 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3813 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3814 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3815 XtSetValues (pane_widget
, al
, ac
);
3816 f
->output_data
.x
->column_widget
= pane_widget
;
3818 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3819 the emacs screen when changing menubar. This reduces flickering. */
3822 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3823 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3824 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3825 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3826 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3827 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3828 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3829 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3830 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3833 f
->output_data
.x
->edit_widget
= frame_widget
;
3835 XtManageChild (frame_widget
);
3837 /* Do some needed geometry management. */
3840 char *tem
, shell_position
[32];
3843 int extra_borders
= 0;
3845 = (f
->output_data
.x
->menubar_widget
3846 ? (f
->output_data
.x
->menubar_widget
->core
.height
3847 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3850 #if 0 /* Experimentally, we now get the right results
3851 for -geometry -0-0 without this. 24 Aug 96, rms. */
3852 if (FRAME_EXTERNAL_MENU_BAR (f
))
3855 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3856 menubar_size
+= ibw
;
3860 f
->output_data
.x
->menubar_height
= menubar_size
;
3863 /* Motif seems to need this amount added to the sizes
3864 specified for the shell widget. The Athena/Lucid widgets don't.
3865 Both conclusions reached experimentally. -- rms. */
3866 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3867 &extra_borders
, NULL
);
3871 /* Convert our geometry parameters into a geometry string
3873 Note that we do not specify here whether the position
3874 is a user-specified or program-specified one.
3875 We pass that information later, in x_wm_set_size_hints. */
3877 int left
= f
->output_data
.x
->left_pos
;
3878 int xneg
= window_prompting
& XNegative
;
3879 int top
= f
->output_data
.x
->top_pos
;
3880 int yneg
= window_prompting
& YNegative
;
3886 if (window_prompting
& USPosition
)
3887 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3888 PIXEL_WIDTH (f
) + extra_borders
,
3889 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3890 (xneg
? '-' : '+'), left
,
3891 (yneg
? '-' : '+'), top
);
3893 sprintf (shell_position
, "=%dx%d",
3894 PIXEL_WIDTH (f
) + extra_borders
,
3895 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3898 len
= strlen (shell_position
) + 1;
3899 /* We don't free this because we don't know whether
3900 it is safe to free it while the frame exists.
3901 It isn't worth the trouble of arranging to free it
3902 when the frame is deleted. */
3903 tem
= (char *) xmalloc (len
);
3904 strncpy (tem
, shell_position
, len
);
3905 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3906 XtSetValues (shell_widget
, al
, ac
);
3909 XtManageChild (pane_widget
);
3910 XtRealizeWidget (shell_widget
);
3912 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3914 validate_x_resource_name ();
3916 class_hints
.res_name
= (char *) SDATA (Vx_resource_name
);
3917 class_hints
.res_class
= (char *) SDATA (Vx_resource_class
);
3918 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3921 FRAME_XIC (f
) = NULL
;
3923 create_frame_xic (f
);
3927 f
->output_data
.x
->wm_hints
.input
= True
;
3928 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3929 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3930 &f
->output_data
.x
->wm_hints
);
3932 hack_wm_protocols (f
, shell_widget
);
3935 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3938 /* Do a stupid property change to force the server to generate a
3939 PropertyNotify event so that the event_stream server timestamp will
3940 be initialized to something relevant to the time we created the window.
3942 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3943 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3944 XA_ATOM
, 32, PropModeAppend
,
3945 (unsigned char*) NULL
, 0);
3947 /* Make all the standard events reach the Emacs frame. */
3948 attributes
.event_mask
= STANDARD_EVENT_SET
;
3953 /* XIM server might require some X events. */
3954 unsigned long fevent
= NoEventMask
;
3955 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3956 attributes
.event_mask
|= fevent
;
3958 #endif /* HAVE_X_I18N */
3960 attribute_mask
= CWEventMask
;
3961 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3962 attribute_mask
, &attributes
);
3964 XtMapWidget (frame_widget
);
3966 /* x_set_name normally ignores requests to set the name if the
3967 requested name is the same as the current name. This is the one
3968 place where that assumption isn't correct; f->name is set, but
3969 the X server hasn't been told. */
3972 int explicit = f
->explicit_name
;
3974 f
->explicit_name
= 0;
3977 x_set_name (f
, name
, explicit);
3980 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3981 f
->output_data
.x
->text_cursor
);
3985 /* This is a no-op, except under Motif. Make sure main areas are
3986 set to something reasonable, in case we get an error later. */
3987 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3990 #else /* not USE_X_TOOLKIT */
3992 /* Create and set up the X window for frame F. */
3999 XClassHint class_hints
;
4000 XSetWindowAttributes attributes
;
4001 unsigned long attribute_mask
;
4003 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
4004 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
4005 attributes
.bit_gravity
= StaticGravity
;
4006 attributes
.backing_store
= NotUseful
;
4007 attributes
.save_under
= True
;
4008 attributes
.event_mask
= STANDARD_EVENT_SET
;
4009 attributes
.colormap
= FRAME_X_COLORMAP (f
);
4010 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
4015 = XCreateWindow (FRAME_X_DISPLAY (f
),
4016 f
->output_data
.x
->parent_desc
,
4017 f
->output_data
.x
->left_pos
,
4018 f
->output_data
.x
->top_pos
,
4019 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
4020 f
->output_data
.x
->border_width
,
4021 CopyFromParent
, /* depth */
4022 InputOutput
, /* class */
4024 attribute_mask
, &attributes
);
4028 create_frame_xic (f
);
4031 /* XIM server might require some X events. */
4032 unsigned long fevent
= NoEventMask
;
4033 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
4034 attributes
.event_mask
|= fevent
;
4035 attribute_mask
= CWEventMask
;
4036 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4037 attribute_mask
, &attributes
);
4040 #endif /* HAVE_X_I18N */
4042 validate_x_resource_name ();
4044 class_hints
.res_name
= (char *) SDATA (Vx_resource_name
);
4045 class_hints
.res_class
= (char *) SDATA (Vx_resource_class
);
4046 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
4048 /* The menubar is part of the ordinary display;
4049 it does not count in addition to the height of the window. */
4050 f
->output_data
.x
->menubar_height
= 0;
4052 /* This indicates that we use the "Passive Input" input model.
4053 Unless we do this, we don't get the Focus{In,Out} events that we
4054 need to draw the cursor correctly. Accursed bureaucrats.
4055 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
4057 f
->output_data
.x
->wm_hints
.input
= True
;
4058 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
4059 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4060 &f
->output_data
.x
->wm_hints
);
4061 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
4063 /* Request "save yourself" and "delete window" commands from wm. */
4066 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
4067 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
4068 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
4071 /* x_set_name normally ignores requests to set the name if the
4072 requested name is the same as the current name. This is the one
4073 place where that assumption isn't correct; f->name is set, but
4074 the X server hasn't been told. */
4077 int explicit = f
->explicit_name
;
4079 f
->explicit_name
= 0;
4082 x_set_name (f
, name
, explicit);
4085 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4086 f
->output_data
.x
->text_cursor
);
4090 if (FRAME_X_WINDOW (f
) == 0)
4091 error ("Unable to create window");
4094 #endif /* not USE_X_TOOLKIT */
4096 /* Handle the icon stuff for this window. Perhaps later we might
4097 want an x_set_icon_position which can be called interactively as
4105 Lisp_Object icon_x
, icon_y
;
4106 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4108 /* Set the position of the icon. Note that twm groups all
4109 icons in an icon window. */
4110 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4111 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4112 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4114 CHECK_NUMBER (icon_x
);
4115 CHECK_NUMBER (icon_y
);
4117 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4118 error ("Both left and top icon corners of icon must be specified");
4122 if (! EQ (icon_x
, Qunbound
))
4123 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4125 /* Start up iconic or window? */
4126 x_wm_set_window_state
4127 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
4132 x_text_icon (f
, (char *) SDATA ((!NILP (f
->icon_name
)
4139 /* Make the GCs needed for this window, setting the
4140 background, border and mouse colors; also create the
4141 mouse cursor and the gray border tile. */
4143 static char cursor_bits
[] =
4145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4155 XGCValues gc_values
;
4159 /* Create the GCs of this frame.
4160 Note that many default values are used. */
4163 gc_values
.font
= f
->output_data
.x
->font
->fid
;
4164 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
4165 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4166 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
4167 f
->output_data
.x
->normal_gc
4168 = XCreateGC (FRAME_X_DISPLAY (f
),
4170 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
4173 /* Reverse video style. */
4174 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4175 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4176 f
->output_data
.x
->reverse_gc
4177 = XCreateGC (FRAME_X_DISPLAY (f
),
4179 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
4182 /* Cursor has cursor-color background, background-color foreground. */
4183 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4184 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
4185 gc_values
.fill_style
= FillOpaqueStippled
;
4187 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4188 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4189 cursor_bits
, 16, 16);
4190 f
->output_data
.x
->cursor_gc
4191 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4192 (GCFont
| GCForeground
| GCBackground
4193 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
4197 f
->output_data
.x
->white_relief
.gc
= 0;
4198 f
->output_data
.x
->black_relief
.gc
= 0;
4200 /* Create the gray border tile used when the pointer is not in
4201 the frame. Since this depends on the frame's pixel values,
4202 this must be done on a per-frame basis. */
4203 f
->output_data
.x
->border_tile
4204 = (XCreatePixmapFromBitmapData
4205 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
4206 gray_bits
, gray_width
, gray_height
,
4207 f
->output_data
.x
->foreground_pixel
,
4208 f
->output_data
.x
->background_pixel
,
4209 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4215 /* Free what was was allocated in x_make_gc. */
4221 Display
*dpy
= FRAME_X_DISPLAY (f
);
4225 if (f
->output_data
.x
->normal_gc
)
4227 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4228 f
->output_data
.x
->normal_gc
= 0;
4231 if (f
->output_data
.x
->reverse_gc
)
4233 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4234 f
->output_data
.x
->reverse_gc
= 0;
4237 if (f
->output_data
.x
->cursor_gc
)
4239 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4240 f
->output_data
.x
->cursor_gc
= 0;
4243 if (f
->output_data
.x
->border_tile
)
4245 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4246 f
->output_data
.x
->border_tile
= 0;
4253 /* Handler for signals raised during x_create_frame and
4254 x_create_top_frame. FRAME is the frame which is partially
4258 unwind_create_frame (frame
)
4261 struct frame
*f
= XFRAME (frame
);
4263 /* If frame is ``official'', nothing to do. */
4264 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4267 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4270 x_free_frame_resources (f
);
4272 /* Check that reference counts are indeed correct. */
4273 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4274 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4282 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4284 doc
: /* Make a new X window, which is called a "frame" in Emacs terms.
4285 Returns an Emacs frame object.
4286 ALIST is an alist of frame parameters.
4287 If the parameters specify that the frame should not have a minibuffer,
4288 and do not specify a specific minibuffer window to use,
4289 then `default-minibuffer-frame' must be a frame whose minibuffer can
4290 be shared by the new frame.
4292 This function is an internal primitive--use `make-frame' instead. */)
4297 Lisp_Object frame
, tem
;
4299 int minibuffer_only
= 0;
4300 long window_prompting
= 0;
4302 int count
= SPECPDL_INDEX ();
4303 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4304 Lisp_Object display
;
4305 struct x_display_info
*dpyinfo
= NULL
;
4311 /* Use this general default value to start with
4312 until we know if this frame has a specified name. */
4313 Vx_resource_name
= Vinvocation_name
;
4315 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4316 if (EQ (display
, Qunbound
))
4318 dpyinfo
= check_x_display_info (display
);
4320 kb
= dpyinfo
->kboard
;
4322 kb
= &the_only_kboard
;
4325 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4327 && ! EQ (name
, Qunbound
)
4329 error ("Invalid frame name--not a string or nil");
4332 Vx_resource_name
= name
;
4334 /* See if parent window is specified. */
4335 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4336 if (EQ (parent
, Qunbound
))
4338 if (! NILP (parent
))
4339 CHECK_NUMBER (parent
);
4341 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4342 /* No need to protect DISPLAY because that's not used after passing
4343 it to make_frame_without_minibuffer. */
4345 GCPRO4 (parms
, parent
, name
, frame
);
4346 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4348 if (EQ (tem
, Qnone
) || NILP (tem
))
4349 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4350 else if (EQ (tem
, Qonly
))
4352 f
= make_minibuffer_frame ();
4353 minibuffer_only
= 1;
4355 else if (WINDOWP (tem
))
4356 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4360 XSETFRAME (frame
, f
);
4362 /* Note that X Windows does support scroll bars. */
4363 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4365 f
->output_method
= output_x_window
;
4366 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4367 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4368 f
->output_data
.x
->icon_bitmap
= -1;
4369 f
->output_data
.x
->fontset
= -1;
4370 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4371 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4372 #ifdef USE_TOOLKIT_SCROLL_BARS
4373 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
4374 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
4375 #endif /* USE_TOOLKIT_SCROLL_BARS */
4376 record_unwind_protect (unwind_create_frame
, frame
);
4379 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4381 if (! STRINGP (f
->icon_name
))
4382 f
->icon_name
= Qnil
;
4384 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4386 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4387 dpyinfo_refcount
= dpyinfo
->reference_count
;
4388 #endif /* GLYPH_DEBUG */
4390 FRAME_KBOARD (f
) = kb
;
4393 /* These colors will be set anyway later, but it's important
4394 to get the color reference counts right, so initialize them! */
4397 struct gcpro gcpro1
;
4399 /* Function x_decode_color can signal an error. Make
4400 sure to initialize color slots so that we won't try
4401 to free colors we haven't allocated. */
4402 f
->output_data
.x
->foreground_pixel
= -1;
4403 f
->output_data
.x
->background_pixel
= -1;
4404 f
->output_data
.x
->cursor_pixel
= -1;
4405 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4406 f
->output_data
.x
->border_pixel
= -1;
4407 f
->output_data
.x
->mouse_pixel
= -1;
4409 black
= build_string ("black");
4411 f
->output_data
.x
->foreground_pixel
4412 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4413 f
->output_data
.x
->background_pixel
4414 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4415 f
->output_data
.x
->cursor_pixel
4416 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4417 f
->output_data
.x
->cursor_foreground_pixel
4418 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4419 f
->output_data
.x
->border_pixel
4420 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4421 f
->output_data
.x
->mouse_pixel
4422 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4426 /* Specify the parent under which to make this X window. */
4430 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4431 f
->output_data
.x
->explicit_parent
= 1;
4435 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4436 f
->output_data
.x
->explicit_parent
= 0;
4439 /* Set the name; the functions to which we pass f expect the name to
4441 if (EQ (name
, Qunbound
) || NILP (name
))
4443 f
->name
= build_string (dpyinfo
->x_id_name
);
4444 f
->explicit_name
= 0;
4449 f
->explicit_name
= 1;
4450 /* use the frame's title when getting resources for this frame. */
4451 specbind (Qx_resource_name
, name
);
4454 /* Extract the window parameters from the supplied values
4455 that are needed to determine window geometry. */
4459 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4462 /* First, try whatever font the caller has specified. */
4465 tem
= Fquery_fontset (font
, Qnil
);
4467 font
= x_new_fontset (f
, SDATA (tem
));
4469 font
= x_new_font (f
, SDATA (font
));
4472 /* Try out a font which we hope has bold and italic variations. */
4473 if (!STRINGP (font
))
4474 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4475 if (!STRINGP (font
))
4476 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4477 if (! STRINGP (font
))
4478 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4479 if (! STRINGP (font
))
4480 /* This was formerly the first thing tried, but it finds too many fonts
4481 and takes too long. */
4482 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4483 /* If those didn't work, look for something which will at least work. */
4484 if (! STRINGP (font
))
4485 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4487 if (! STRINGP (font
))
4488 font
= build_string ("fixed");
4490 x_default_parameter (f
, parms
, Qfont
, font
,
4491 "font", "Font", RES_TYPE_STRING
);
4495 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4496 whereby it fails to get any font. */
4497 xlwmenu_default_font
= f
->output_data
.x
->font
;
4500 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4501 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4503 /* This defaults to 1 in order to match xterm. We recognize either
4504 internalBorderWidth or internalBorder (which is what xterm calls
4506 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4510 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4511 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4512 if (! EQ (value
, Qunbound
))
4513 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4516 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4517 "internalBorderWidth", "internalBorderWidth",
4519 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4520 "verticalScrollBars", "ScrollBars",
4523 /* Also do the stuff which must be set before the window exists. */
4524 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4525 "foreground", "Foreground", RES_TYPE_STRING
);
4526 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4527 "background", "Background", RES_TYPE_STRING
);
4528 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4529 "pointerColor", "Foreground", RES_TYPE_STRING
);
4530 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4531 "cursorColor", "Foreground", RES_TYPE_STRING
);
4532 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4533 "borderColor", "BorderColor", RES_TYPE_STRING
);
4534 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4535 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4536 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4537 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4538 x_default_parameter (f
, parms
, Qleft_fringe
, Qnil
,
4539 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4540 x_default_parameter (f
, parms
, Qright_fringe
, Qnil
,
4541 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4543 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4544 "scrollBarForeground",
4545 "ScrollBarForeground", 1);
4546 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4547 "scrollBarBackground",
4548 "ScrollBarBackground", 0);
4550 /* Init faces before x_default_parameter is called for scroll-bar
4551 parameters because that function calls x_set_scroll_bar_width,
4552 which calls change_frame_size, which calls Fset_window_buffer,
4553 which runs hooks, which call Fvertical_motion. At the end, we
4554 end up in init_iterator with a null face cache, which should not
4556 init_frame_faces (f
);
4558 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4559 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4560 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4561 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4562 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4563 "bufferPredicate", "BufferPredicate",
4565 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4566 "title", "Title", RES_TYPE_STRING
);
4567 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4568 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4569 x_default_parameter (f
, parms
, Qfullscreen
, Qnil
,
4570 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4572 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4574 /* Add the tool-bar height to the initial frame height so that the
4575 user gets a text display area of the size he specified with -g or
4576 via .Xdefaults. Later changes of the tool-bar height don't
4577 change the frame size. This is done so that users can create
4578 tall Emacs frames without having to guess how tall the tool-bar
4580 if (FRAME_TOOL_BAR_LINES (f
))
4582 int margin
, relief
, bar_height
;
4584 relief
= (tool_bar_button_relief
>= 0
4585 ? tool_bar_button_relief
4586 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4588 if (INTEGERP (Vtool_bar_button_margin
)
4589 && XINT (Vtool_bar_button_margin
) > 0)
4590 margin
= XFASTINT (Vtool_bar_button_margin
);
4591 else if (CONSP (Vtool_bar_button_margin
)
4592 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4593 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4594 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4598 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4599 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4602 /* Compute the size of the X window. */
4603 window_prompting
= x_figure_window_size (f
, parms
);
4605 if (window_prompting
& XNegative
)
4607 if (window_prompting
& YNegative
)
4608 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4610 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4614 if (window_prompting
& YNegative
)
4615 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4617 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4620 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4622 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4623 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4625 /* Create the X widget or window. */
4626 #ifdef USE_X_TOOLKIT
4627 x_window (f
, window_prompting
, minibuffer_only
);
4635 /* Now consider the frame official. */
4636 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4637 Vframe_list
= Fcons (frame
, Vframe_list
);
4639 /* We need to do this after creating the X window, so that the
4640 icon-creation functions can say whose icon they're describing. */
4641 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4642 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4644 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4645 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4646 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4647 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4648 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4649 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4650 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4651 "scrollBarWidth", "ScrollBarWidth",
4654 /* Dimensions, especially f->height, must be done via change_frame_size.
4655 Change will not be effected unless different from the current
4661 SET_FRAME_WIDTH (f
, 0);
4662 change_frame_size (f
, height
, width
, 1, 0, 0);
4664 /* Set up faces after all frame parameters are known. This call
4665 also merges in face attributes specified for new frames. If we
4666 don't do this, the `menu' face for instance won't have the right
4667 colors, and the menu bar won't appear in the specified colors for
4669 call1 (Qface_set_after_frame_default
, frame
);
4671 #ifdef USE_X_TOOLKIT
4672 /* Create the menu bar. */
4673 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4675 /* If this signals an error, we haven't set size hints for the
4676 frame and we didn't make it visible. */
4677 initialize_frame_menubar (f
);
4679 /* This is a no-op, except under Motif where it arranges the
4680 main window for the widgets on it. */
4681 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4682 f
->output_data
.x
->menubar_widget
,
4683 f
->output_data
.x
->edit_widget
);
4685 #endif /* USE_X_TOOLKIT */
4687 /* Tell the server what size and position, etc, we want, and how
4688 badly we want them. This should be done after we have the menu
4689 bar so that its size can be taken into account. */
4691 x_wm_set_size_hint (f
, window_prompting
, 0);
4694 /* Make the window appear on the frame and enable display, unless
4695 the caller says not to. However, with explicit parent, Emacs
4696 cannot control visibility, so don't try. */
4697 if (! f
->output_data
.x
->explicit_parent
)
4699 Lisp_Object visibility
;
4701 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4703 if (EQ (visibility
, Qunbound
))
4706 if (EQ (visibility
, Qicon
))
4707 x_iconify_frame (f
);
4708 else if (! NILP (visibility
))
4709 x_make_frame_visible (f
);
4711 /* Must have been Qnil. */
4717 /* Make sure windows on this frame appear in calls to next-window
4718 and similar functions. */
4719 Vwindow_list
= Qnil
;
4721 return unbind_to (count
, frame
);
4725 /* FRAME is used only to get a handle on the X display. We don't pass the
4726 display info directly because we're called from frame.c, which doesn't
4727 know about that structure. */
4730 x_get_focus_frame (frame
)
4731 struct frame
*frame
;
4733 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4735 if (! dpyinfo
->x_focus_frame
)
4738 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4743 /* In certain situations, when the window manager follows a
4744 click-to-focus policy, there seems to be no way around calling
4745 XSetInputFocus to give another frame the input focus .
4747 In an ideal world, XSetInputFocus should generally be avoided so
4748 that applications don't interfere with the window manager's focus
4749 policy. But I think it's okay to use when it's clearly done
4750 following a user-command. */
4752 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4753 doc
: /* Set the input focus to FRAME.
4754 FRAME nil means use the selected frame. */)
4758 struct frame
*f
= check_x_frame (frame
);
4759 Display
*dpy
= FRAME_X_DISPLAY (f
);
4763 count
= x_catch_errors (dpy
);
4764 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4765 RevertToParent
, CurrentTime
);
4766 x_uncatch_errors (dpy
, count
);
4773 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4774 doc
: /* Internal function called by `color-defined-p', which see. */)
4776 Lisp_Object color
, frame
;
4779 FRAME_PTR f
= check_x_frame (frame
);
4781 CHECK_STRING (color
);
4783 if (x_defined_color (f
, SDATA (color
), &foo
, 0))
4789 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4790 doc
: /* Internal function called by `color-values', which see. */)
4792 Lisp_Object color
, frame
;
4795 FRAME_PTR f
= check_x_frame (frame
);
4797 CHECK_STRING (color
);
4799 if (x_defined_color (f
, SDATA (color
), &foo
, 0))
4803 rgb
[0] = make_number (foo
.red
);
4804 rgb
[1] = make_number (foo
.green
);
4805 rgb
[2] = make_number (foo
.blue
);
4806 return Flist (3, rgb
);
4812 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4813 doc
: /* Internal function called by `display-color-p', which see. */)
4815 Lisp_Object display
;
4817 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4819 if (dpyinfo
->n_planes
<= 2)
4822 switch (dpyinfo
->visual
->class)
4835 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4837 doc
: /* Return t if the X display supports shades of gray.
4838 Note that color displays do support shades of gray.
4839 The optional argument DISPLAY specifies which display to ask about.
4840 DISPLAY should be either a frame or a display name (a string).
4841 If omitted or nil, that stands for the selected frame's display. */)
4843 Lisp_Object display
;
4845 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4847 if (dpyinfo
->n_planes
<= 1)
4850 switch (dpyinfo
->visual
->class)
4865 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4867 doc
: /* Returns the width in pixels of the X display DISPLAY.
4868 The optional argument DISPLAY specifies which display to ask about.
4869 DISPLAY should be either a frame or a display name (a string).
4870 If omitted or nil, that stands for the selected frame's display. */)
4872 Lisp_Object display
;
4874 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4876 return make_number (dpyinfo
->width
);
4879 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4880 Sx_display_pixel_height
, 0, 1, 0,
4881 doc
: /* Returns the height in pixels of the X display DISPLAY.
4882 The optional argument DISPLAY specifies which display to ask about.
4883 DISPLAY should be either a frame or a display name (a string).
4884 If omitted or nil, that stands for the selected frame's display. */)
4886 Lisp_Object display
;
4888 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4890 return make_number (dpyinfo
->height
);
4893 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4895 doc
: /* Returns the number of bitplanes of the X display DISPLAY.
4896 The optional argument DISPLAY specifies which display to ask about.
4897 DISPLAY should be either a frame or a display name (a string).
4898 If omitted or nil, that stands for the selected frame's display. */)
4900 Lisp_Object display
;
4902 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4904 return make_number (dpyinfo
->n_planes
);
4907 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4909 doc
: /* Returns the number of color cells of the X display DISPLAY.
4910 The optional argument DISPLAY specifies which display to ask about.
4911 DISPLAY should be either a frame or a display name (a string).
4912 If omitted or nil, that stands for the selected frame's display. */)
4914 Lisp_Object display
;
4916 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4918 return make_number (DisplayCells (dpyinfo
->display
,
4919 XScreenNumberOfScreen (dpyinfo
->screen
)));
4922 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4923 Sx_server_max_request_size
,
4925 doc
: /* Returns the maximum request size of the X server of display DISPLAY.
4926 The optional argument DISPLAY specifies which display to ask about.
4927 DISPLAY should be either a frame or a display name (a string).
4928 If omitted or nil, that stands for the selected frame's display. */)
4930 Lisp_Object display
;
4932 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4934 return make_number (MAXREQUEST (dpyinfo
->display
));
4937 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4938 doc
: /* Returns the vendor ID string of the X server of display DISPLAY.
4939 The optional argument DISPLAY specifies which display to ask about.
4940 DISPLAY should be either a frame or a display name (a string).
4941 If omitted or nil, that stands for the selected frame's display. */)
4943 Lisp_Object display
;
4945 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4946 char *vendor
= ServerVendor (dpyinfo
->display
);
4948 if (! vendor
) vendor
= "";
4949 return build_string (vendor
);
4952 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4953 doc
: /* Returns the version numbers of the X server of display DISPLAY.
4954 The value is a list of three integers: the major and minor
4955 version numbers of the X Protocol in use, and the vendor-specific release
4956 number. See also the function `x-server-vendor'.
4958 The optional argument DISPLAY specifies which display to ask about.
4959 DISPLAY should be either a frame or a display name (a string).
4960 If omitted or nil, that stands for the selected frame's display. */)
4962 Lisp_Object display
;
4964 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4965 Display
*dpy
= dpyinfo
->display
;
4967 return Fcons (make_number (ProtocolVersion (dpy
)),
4968 Fcons (make_number (ProtocolRevision (dpy
)),
4969 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4972 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4973 doc
: /* Return the number of screens on the X server of display DISPLAY.
4974 The optional argument DISPLAY specifies which display to ask about.
4975 DISPLAY should be either a frame or a display name (a string).
4976 If omitted or nil, that stands for the selected frame's display. */)
4978 Lisp_Object display
;
4980 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4982 return make_number (ScreenCount (dpyinfo
->display
));
4985 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4986 doc
: /* Return the height in millimeters of the X display DISPLAY.
4987 The optional argument DISPLAY specifies which display to ask about.
4988 DISPLAY should be either a frame or a display name (a string).
4989 If omitted or nil, that stands for the selected frame's display. */)
4991 Lisp_Object display
;
4993 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4995 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4998 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4999 doc
: /* Return the width in millimeters of the X display DISPLAY.
5000 The optional argument DISPLAY specifies which display to ask about.
5001 DISPLAY should be either a frame or a display name (a string).
5002 If omitted or nil, that stands for the selected frame's display. */)
5004 Lisp_Object display
;
5006 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5008 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
5011 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
5012 Sx_display_backing_store
, 0, 1, 0,
5013 doc
: /* Returns an indication of whether X display DISPLAY does backing store.
5014 The value may be `always', `when-mapped', or `not-useful'.
5015 The optional argument DISPLAY specifies which display to ask about.
5016 DISPLAY should be either a frame or a display name (a string).
5017 If omitted or nil, that stands for the selected frame's display. */)
5019 Lisp_Object display
;
5021 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5024 switch (DoesBackingStore (dpyinfo
->screen
))
5027 result
= intern ("always");
5031 result
= intern ("when-mapped");
5035 result
= intern ("not-useful");
5039 error ("Strange value for BackingStore parameter of screen");
5046 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
5047 Sx_display_visual_class
, 0, 1, 0,
5048 doc
: /* Return the visual class of the X display DISPLAY.
5049 The value is one of the symbols `static-gray', `gray-scale',
5050 `static-color', `pseudo-color', `true-color', or `direct-color'.
5052 The optional argument DISPLAY specifies which display to ask about.
5053 DISPLAY should be either a frame or a display name (a string).
5054 If omitted or nil, that stands for the selected frame's display. */)
5056 Lisp_Object display
;
5058 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5061 switch (dpyinfo
->visual
->class)
5064 result
= intern ("static-gray");
5067 result
= intern ("gray-scale");
5070 result
= intern ("static-color");
5073 result
= intern ("pseudo-color");
5076 result
= intern ("true-color");
5079 result
= intern ("direct-color");
5082 error ("Display has an unknown visual class");
5089 DEFUN ("x-display-save-under", Fx_display_save_under
,
5090 Sx_display_save_under
, 0, 1, 0,
5091 doc
: /* Returns t if the X display DISPLAY supports the save-under feature.
5092 The optional argument DISPLAY specifies which display to ask about.
5093 DISPLAY should be either a frame or a display name (a string).
5094 If omitted or nil, that stands for the selected frame's display. */)
5096 Lisp_Object display
;
5098 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5100 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
5108 register struct frame
*f
;
5110 return PIXEL_WIDTH (f
);
5115 register struct frame
*f
;
5117 return PIXEL_HEIGHT (f
);
5122 register struct frame
*f
;
5124 return FONT_WIDTH (f
->output_data
.x
->font
);
5129 register struct frame
*f
;
5131 return f
->output_data
.x
->line_height
;
5136 register struct frame
*f
;
5138 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
5143 /************************************************************************
5145 ************************************************************************/
5148 /* Mapping visual names to visuals. */
5150 static struct visual_class
5157 {"StaticGray", StaticGray
},
5158 {"GrayScale", GrayScale
},
5159 {"StaticColor", StaticColor
},
5160 {"PseudoColor", PseudoColor
},
5161 {"TrueColor", TrueColor
},
5162 {"DirectColor", DirectColor
},
5167 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5169 /* Value is the screen number of screen SCR. This is a substitute for
5170 the X function with the same name when that doesn't exist. */
5173 XScreenNumberOfScreen (scr
)
5174 register Screen
*scr
;
5176 Display
*dpy
= scr
->display
;
5179 for (i
= 0; i
< dpy
->nscreens
; ++i
)
5180 if (scr
== dpy
->screens
+ i
)
5186 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5189 /* Select the visual that should be used on display DPYINFO. Set
5190 members of DPYINFO appropriately. Called from x_term_init. */
5193 select_visual (dpyinfo
)
5194 struct x_display_info
*dpyinfo
;
5196 Display
*dpy
= dpyinfo
->display
;
5197 Screen
*screen
= dpyinfo
->screen
;
5200 /* See if a visual is specified. */
5201 value
= display_x_get_resource (dpyinfo
,
5202 build_string ("visualClass"),
5203 build_string ("VisualClass"),
5205 if (STRINGP (value
))
5207 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5208 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5209 depth, a decimal number. NAME is compared with case ignored. */
5210 char *s
= (char *) alloca (SBYTES (value
) + 1);
5215 strcpy (s
, SDATA (value
));
5216 dash
= index (s
, '-');
5219 dpyinfo
->n_planes
= atoi (dash
+ 1);
5223 /* We won't find a matching visual with depth 0, so that
5224 an error will be printed below. */
5225 dpyinfo
->n_planes
= 0;
5227 /* Determine the visual class. */
5228 for (i
= 0; visual_classes
[i
].name
; ++i
)
5229 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5231 class = visual_classes
[i
].class;
5235 /* Look up a matching visual for the specified class. */
5237 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5238 dpyinfo
->n_planes
, class, &vinfo
))
5239 fatal ("Invalid visual specification `%s'", SDATA (value
));
5241 dpyinfo
->visual
= vinfo
.visual
;
5246 XVisualInfo
*vinfo
, vinfo_template
;
5248 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5251 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5253 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5255 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5256 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5257 &vinfo_template
, &n_visuals
);
5259 fatal ("Can't get proper X visual info");
5261 dpyinfo
->n_planes
= vinfo
->depth
;
5262 XFree ((char *) vinfo
);
5267 /* Return the X display structure for the display named NAME.
5268 Open a new connection if necessary. */
5270 struct x_display_info
*
5271 x_display_info_for_name (name
)
5275 struct x_display_info
*dpyinfo
;
5277 CHECK_STRING (name
);
5279 if (! EQ (Vwindow_system
, intern ("x")))
5280 error ("Not using X Windows");
5282 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5284 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5287 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5292 /* Use this general default value to start with. */
5293 Vx_resource_name
= Vinvocation_name
;
5295 validate_x_resource_name ();
5297 dpyinfo
= x_term_init (name
, (char *)0,
5298 (char *) SDATA (Vx_resource_name
));
5301 error ("Cannot connect to X server %s", SDATA (name
));
5304 XSETFASTINT (Vwindow_system_version
, 11);
5310 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5312 doc
: /* Open a connection to an X server.
5313 DISPLAY is the name of the display to connect to.
5314 Optional second arg XRM-STRING is a string of resources in xrdb format.
5315 If the optional third arg MUST-SUCCEED is non-nil,
5316 terminate Emacs if we can't open the connection. */)
5317 (display
, xrm_string
, must_succeed
)
5318 Lisp_Object display
, xrm_string
, must_succeed
;
5320 unsigned char *xrm_option
;
5321 struct x_display_info
*dpyinfo
;
5323 CHECK_STRING (display
);
5324 if (! NILP (xrm_string
))
5325 CHECK_STRING (xrm_string
);
5327 if (! EQ (Vwindow_system
, intern ("x")))
5328 error ("Not using X Windows");
5330 if (! NILP (xrm_string
))
5331 xrm_option
= (unsigned char *) SDATA (xrm_string
);
5333 xrm_option
= (unsigned char *) 0;
5335 validate_x_resource_name ();
5337 /* This is what opens the connection and sets x_current_display.
5338 This also initializes many symbols, such as those used for input. */
5339 dpyinfo
= x_term_init (display
, xrm_option
,
5340 (char *) SDATA (Vx_resource_name
));
5344 if (!NILP (must_succeed
))
5345 fatal ("Cannot connect to X server %s.\n\
5346 Check the DISPLAY environment variable or use `-d'.\n\
5347 Also use the `xhost' program to verify that it is set to permit\n\
5348 connections from your machine.\n",
5351 error ("Cannot connect to X server %s", SDATA (display
));
5356 XSETFASTINT (Vwindow_system_version
, 11);
5360 DEFUN ("x-close-connection", Fx_close_connection
,
5361 Sx_close_connection
, 1, 1, 0,
5362 doc
: /* Close the connection to DISPLAY's X server.
5363 For DISPLAY, specify either a frame or a display name (a string).
5364 If DISPLAY is nil, that stands for the selected frame's display. */)
5366 Lisp_Object display
;
5368 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5371 if (dpyinfo
->reference_count
> 0)
5372 error ("Display still has frames on it");
5375 /* Free the fonts in the font table. */
5376 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5377 if (dpyinfo
->font_table
[i
].name
)
5379 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5380 xfree (dpyinfo
->font_table
[i
].full_name
);
5381 xfree (dpyinfo
->font_table
[i
].name
);
5382 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5385 x_destroy_all_bitmaps (dpyinfo
);
5386 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5388 #ifdef USE_X_TOOLKIT
5389 XtCloseDisplay (dpyinfo
->display
);
5391 XCloseDisplay (dpyinfo
->display
);
5394 x_delete_display (dpyinfo
);
5400 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5401 doc
: /* Return the list of display names that Emacs has connections to. */)
5404 Lisp_Object tail
, result
;
5407 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5408 result
= Fcons (XCAR (XCAR (tail
)), result
);
5413 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5414 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5415 If ON is nil, allow buffering of requests.
5416 Turning on synchronization prohibits the Xlib routines from buffering
5417 requests and seriously degrades performance, but makes debugging much
5419 The optional second argument DISPLAY specifies which display to act on.
5420 DISPLAY should be either a frame or a display name (a string).
5421 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5423 Lisp_Object display
, on
;
5425 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5427 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5432 /* Wait for responses to all X commands issued so far for frame F. */
5439 XSync (FRAME_X_DISPLAY (f
), False
);
5444 /***********************************************************************
5446 ***********************************************************************/
5448 /* Value is the number of elements of vector VECTOR. */
5450 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5452 /* List of supported image types. Use define_image_type to add new
5453 types. Use lookup_image_type to find a type for a given symbol. */
5455 static struct image_type
*image_types
;
5457 /* The symbol `image' which is the car of the lists used to represent
5460 extern Lisp_Object Qimage
;
5462 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5468 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5469 extern Lisp_Object QCdata
, QCtype
;
5470 Lisp_Object QCascent
, QCmargin
, QCrelief
;
5471 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5472 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5474 /* Other symbols. */
5476 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5478 /* Time in seconds after which images should be removed from the cache
5479 if not displayed. */
5481 Lisp_Object Vimage_cache_eviction_delay
;
5483 /* Function prototypes. */
5485 static void define_image_type
P_ ((struct image_type
*type
));
5486 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5487 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5488 static void x_laplace
P_ ((struct frame
*, struct image
*));
5489 static void x_emboss
P_ ((struct frame
*, struct image
*));
5490 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5494 /* Define a new image type from TYPE. This adds a copy of TYPE to
5495 image_types and adds the symbol *TYPE->type to Vimage_types. */
5498 define_image_type (type
)
5499 struct image_type
*type
;
5501 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5502 The initialized data segment is read-only. */
5503 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5504 bcopy (type
, p
, sizeof *p
);
5505 p
->next
= image_types
;
5507 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5511 /* Look up image type SYMBOL, and return a pointer to its image_type
5512 structure. Value is null if SYMBOL is not a known image type. */
5514 static INLINE
struct image_type
*
5515 lookup_image_type (symbol
)
5518 struct image_type
*type
;
5520 for (type
= image_types
; type
; type
= type
->next
)
5521 if (EQ (symbol
, *type
->type
))
5528 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5529 valid image specification is a list whose car is the symbol
5530 `image', and whose rest is a property list. The property list must
5531 contain a value for key `:type'. That value must be the name of a
5532 supported image type. The rest of the property list depends on the
5536 valid_image_p (object
)
5541 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5545 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5546 if (EQ (XCAR (tem
), QCtype
))
5549 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5551 struct image_type
*type
;
5552 type
= lookup_image_type (XCAR (tem
));
5554 valid_p
= type
->valid_p (object
);
5565 /* Log error message with format string FORMAT and argument ARG.
5566 Signaling an error, e.g. when an image cannot be loaded, is not a
5567 good idea because this would interrupt redisplay, and the error
5568 message display would lead to another redisplay. This function
5569 therefore simply displays a message. */
5572 image_error (format
, arg1
, arg2
)
5574 Lisp_Object arg1
, arg2
;
5576 add_to_log (format
, arg1
, arg2
);
5581 /***********************************************************************
5582 Image specifications
5583 ***********************************************************************/
5585 enum image_value_type
5587 IMAGE_DONT_CHECK_VALUE_TYPE
,
5589 IMAGE_STRING_OR_NIL_VALUE
,
5591 IMAGE_POSITIVE_INTEGER_VALUE
,
5592 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5593 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5595 IMAGE_INTEGER_VALUE
,
5596 IMAGE_FUNCTION_VALUE
,
5601 /* Structure used when parsing image specifications. */
5603 struct image_keyword
5605 /* Name of keyword. */
5608 /* The type of value allowed. */
5609 enum image_value_type type
;
5611 /* Non-zero means key must be present. */
5614 /* Used to recognize duplicate keywords in a property list. */
5617 /* The value that was found. */
5622 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5624 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5627 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5628 has the format (image KEYWORD VALUE ...). One of the keyword/
5629 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5630 image_keywords structures of size NKEYWORDS describing other
5631 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5634 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5636 struct image_keyword
*keywords
;
5643 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5646 plist
= XCDR (spec
);
5647 while (CONSP (plist
))
5649 Lisp_Object key
, value
;
5651 /* First element of a pair must be a symbol. */
5653 plist
= XCDR (plist
);
5657 /* There must follow a value. */
5660 value
= XCAR (plist
);
5661 plist
= XCDR (plist
);
5663 /* Find key in KEYWORDS. Error if not found. */
5664 for (i
= 0; i
< nkeywords
; ++i
)
5665 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
5671 /* Record that we recognized the keyword. If a keywords
5672 was found more than once, it's an error. */
5673 keywords
[i
].value
= value
;
5674 ++keywords
[i
].count
;
5676 if (keywords
[i
].count
> 1)
5679 /* Check type of value against allowed type. */
5680 switch (keywords
[i
].type
)
5682 case IMAGE_STRING_VALUE
:
5683 if (!STRINGP (value
))
5687 case IMAGE_STRING_OR_NIL_VALUE
:
5688 if (!STRINGP (value
) && !NILP (value
))
5692 case IMAGE_SYMBOL_VALUE
:
5693 if (!SYMBOLP (value
))
5697 case IMAGE_POSITIVE_INTEGER_VALUE
:
5698 if (!INTEGERP (value
) || XINT (value
) <= 0)
5702 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5703 if (INTEGERP (value
) && XINT (value
) >= 0)
5706 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5707 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5711 case IMAGE_ASCENT_VALUE
:
5712 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5714 else if (INTEGERP (value
)
5715 && XINT (value
) >= 0
5716 && XINT (value
) <= 100)
5720 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5721 if (!INTEGERP (value
) || XINT (value
) < 0)
5725 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5728 case IMAGE_FUNCTION_VALUE
:
5729 value
= indirect_function (value
);
5731 || COMPILEDP (value
)
5732 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5736 case IMAGE_NUMBER_VALUE
:
5737 if (!INTEGERP (value
) && !FLOATP (value
))
5741 case IMAGE_INTEGER_VALUE
:
5742 if (!INTEGERP (value
))
5746 case IMAGE_BOOL_VALUE
:
5747 if (!NILP (value
) && !EQ (value
, Qt
))
5756 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5760 /* Check that all mandatory fields are present. */
5761 for (i
= 0; i
< nkeywords
; ++i
)
5762 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5765 return NILP (plist
);
5769 /* Return the value of KEY in image specification SPEC. Value is nil
5770 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5771 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5774 image_spec_value (spec
, key
, found
)
5775 Lisp_Object spec
, key
;
5780 xassert (valid_image_p (spec
));
5782 for (tail
= XCDR (spec
);
5783 CONSP (tail
) && CONSP (XCDR (tail
));
5784 tail
= XCDR (XCDR (tail
)))
5786 if (EQ (XCAR (tail
), key
))
5790 return XCAR (XCDR (tail
));
5800 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5801 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5802 PIXELS non-nil means return the size in pixels, otherwise return the
5803 size in canonical character units.
5804 FRAME is the frame on which the image will be displayed. FRAME nil
5805 or omitted means use the selected frame. */)
5806 (spec
, pixels
, frame
)
5807 Lisp_Object spec
, pixels
, frame
;
5812 if (valid_image_p (spec
))
5814 struct frame
*f
= check_x_frame (frame
);
5815 int id
= lookup_image (f
, spec
);
5816 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5817 int width
= img
->width
+ 2 * img
->hmargin
;
5818 int height
= img
->height
+ 2 * img
->vmargin
;
5821 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5822 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5824 size
= Fcons (make_number (width
), make_number (height
));
5827 error ("Invalid image specification");
5833 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5834 doc
: /* Return t if image SPEC has a mask bitmap.
5835 FRAME is the frame on which the image will be displayed. FRAME nil
5836 or omitted means use the selected frame. */)
5838 Lisp_Object spec
, frame
;
5843 if (valid_image_p (spec
))
5845 struct frame
*f
= check_x_frame (frame
);
5846 int id
= lookup_image (f
, spec
);
5847 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5852 error ("Invalid image specification");
5859 /***********************************************************************
5860 Image type independent image structures
5861 ***********************************************************************/
5863 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5864 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5867 /* Allocate and return a new image structure for image specification
5868 SPEC. SPEC has a hash value of HASH. */
5870 static struct image
*
5871 make_image (spec
, hash
)
5875 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5877 xassert (valid_image_p (spec
));
5878 bzero (img
, sizeof *img
);
5879 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5880 xassert (img
->type
!= NULL
);
5882 img
->data
.lisp_val
= Qnil
;
5883 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5889 /* Free image IMG which was used on frame F, including its resources. */
5898 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5900 /* Remove IMG from the hash table of its cache. */
5902 img
->prev
->next
= img
->next
;
5904 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5907 img
->next
->prev
= img
->prev
;
5909 c
->images
[img
->id
] = NULL
;
5911 /* Free resources, then free IMG. */
5912 img
->type
->free (f
, img
);
5918 /* Prepare image IMG for display on frame F. Must be called before
5919 drawing an image. */
5922 prepare_image_for_display (f
, img
)
5928 /* We're about to display IMG, so set its timestamp to `now'. */
5930 img
->timestamp
= EMACS_SECS (t
);
5932 /* If IMG doesn't have a pixmap yet, load it now, using the image
5933 type dependent loader function. */
5934 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5935 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5939 /* Value is the number of pixels for the ascent of image IMG when
5940 drawn in face FACE. */
5943 image_ascent (img
, face
)
5947 int height
= img
->height
+ img
->vmargin
;
5950 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5953 /* This expression is arranged so that if the image can't be
5954 exactly centered, it will be moved slightly up. This is
5955 because a typical font is `top-heavy' (due to the presence
5956 uppercase letters), so the image placement should err towards
5957 being top-heavy too. It also just generally looks better. */
5958 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5960 ascent
= height
/ 2;
5963 ascent
= height
* img
->ascent
/ 100.0;
5969 /* Image background colors. */
5971 static unsigned long
5972 four_corners_best (ximg
, width
, height
)
5974 unsigned long width
, height
;
5976 unsigned long corners
[4], best
;
5979 /* Get the colors at the corners of ximg. */
5980 corners
[0] = XGetPixel (ximg
, 0, 0);
5981 corners
[1] = XGetPixel (ximg
, width
- 1, 0);
5982 corners
[2] = XGetPixel (ximg
, width
- 1, height
- 1);
5983 corners
[3] = XGetPixel (ximg
, 0, height
- 1);
5985 /* Choose the most frequently found color as background. */
5986 for (i
= best_count
= 0; i
< 4; ++i
)
5990 for (j
= n
= 0; j
< 4; ++j
)
5991 if (corners
[i
] == corners
[j
])
5995 best
= corners
[i
], best_count
= n
;
6001 /* Return the `background' field of IMG. If IMG doesn't have one yet,
6002 it is guessed heuristically. If non-zero, XIMG is an existing XImage
6003 object to use for the heuristic. */
6006 image_background (img
, f
, ximg
)
6011 if (! img
->background_valid
)
6012 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6014 int free_ximg
= !ximg
;
6017 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
6018 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6020 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
6023 XDestroyImage (ximg
);
6025 img
->background_valid
= 1;
6028 return img
->background
;
6031 /* Return the `background_transparent' field of IMG. If IMG doesn't
6032 have one yet, it is guessed heuristically. If non-zero, MASK is an
6033 existing XImage object to use for the heuristic. */
6036 image_background_transparent (img
, f
, mask
)
6041 if (! img
->background_transparent_valid
)
6042 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6046 int free_mask
= !mask
;
6049 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
6050 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6052 img
->background_transparent
6053 = !four_corners_best (mask
, img
->width
, img
->height
);
6056 XDestroyImage (mask
);
6059 img
->background_transparent
= 0;
6061 img
->background_transparent_valid
= 1;
6064 return img
->background_transparent
;
6068 /***********************************************************************
6069 Helper functions for X image types
6070 ***********************************************************************/
6072 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
6074 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
6075 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
6077 Lisp_Object color_name
,
6078 unsigned long dflt
));
6081 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6082 free the pixmap if any. MASK_P non-zero means clear the mask
6083 pixmap if any. COLORS_P non-zero means free colors allocated for
6084 the image, if any. */
6087 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
6090 int pixmap_p
, mask_p
, colors_p
;
6092 if (pixmap_p
&& img
->pixmap
)
6094 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6096 img
->background_valid
= 0;
6099 if (mask_p
&& img
->mask
)
6101 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6103 img
->background_transparent_valid
= 0;
6106 if (colors_p
&& img
->ncolors
)
6108 x_free_colors (f
, img
->colors
, img
->ncolors
);
6109 xfree (img
->colors
);
6115 /* Free X resources of image IMG which is used on frame F. */
6118 x_clear_image (f
, img
)
6123 x_clear_image_1 (f
, img
, 1, 1, 1);
6128 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6129 cannot be allocated, use DFLT. Add a newly allocated color to
6130 IMG->colors, so that it can be freed again. Value is the pixel
6133 static unsigned long
6134 x_alloc_image_color (f
, img
, color_name
, dflt
)
6137 Lisp_Object color_name
;
6141 unsigned long result
;
6143 xassert (STRINGP (color_name
));
6145 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
6147 /* This isn't called frequently so we get away with simply
6148 reallocating the color vector to the needed size, here. */
6151 (unsigned long *) xrealloc (img
->colors
,
6152 img
->ncolors
* sizeof *img
->colors
);
6153 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
6154 result
= color
.pixel
;
6164 /***********************************************************************
6166 ***********************************************************************/
6168 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
6169 static void postprocess_image
P_ ((struct frame
*, struct image
*));
6172 /* Return a new, initialized image cache that is allocated from the
6173 heap. Call free_image_cache to free an image cache. */
6175 struct image_cache
*
6178 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
6181 bzero (c
, sizeof *c
);
6183 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
6184 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
6185 c
->buckets
= (struct image
**) xmalloc (size
);
6186 bzero (c
->buckets
, size
);
6191 /* Free image cache of frame F. Be aware that X frames share images
6195 free_image_cache (f
)
6198 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6203 /* Cache should not be referenced by any frame when freed. */
6204 xassert (c
->refcount
== 0);
6206 for (i
= 0; i
< c
->used
; ++i
)
6207 free_image (f
, c
->images
[i
]);
6211 FRAME_X_IMAGE_CACHE (f
) = NULL
;
6216 /* Clear image cache of frame F. FORCE_P non-zero means free all
6217 images. FORCE_P zero means clear only images that haven't been
6218 displayed for some time. Should be called from time to time to
6219 reduce the number of loaded images. If image-eviction-seconds is
6220 non-nil, this frees images in the cache which weren't displayed for
6221 at least that many seconds. */
6224 clear_image_cache (f
, force_p
)
6228 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6230 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
6237 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
6239 /* Block input so that we won't be interrupted by a SIGIO
6240 while being in an inconsistent state. */
6243 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
6245 struct image
*img
= c
->images
[i
];
6247 && (force_p
|| img
->timestamp
< old
))
6249 free_image (f
, img
);
6254 /* We may be clearing the image cache because, for example,
6255 Emacs was iconified for a longer period of time. In that
6256 case, current matrices may still contain references to
6257 images freed above. So, clear these matrices. */
6260 Lisp_Object tail
, frame
;
6262 FOR_EACH_FRAME (tail
, frame
)
6264 struct frame
*f
= XFRAME (frame
);
6266 && FRAME_X_IMAGE_CACHE (f
) == c
)
6267 clear_current_matrices (f
);
6270 ++windows_or_buffers_changed
;
6278 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
6280 doc
: /* Clear the image cache of FRAME.
6281 FRAME nil or omitted means use the selected frame.
6282 FRAME t means clear the image caches of all frames. */)
6290 FOR_EACH_FRAME (tail
, frame
)
6291 if (FRAME_X_P (XFRAME (frame
)))
6292 clear_image_cache (XFRAME (frame
), 1);
6295 clear_image_cache (check_x_frame (frame
), 1);
6301 /* Compute masks and transform image IMG on frame F, as specified
6302 by the image's specification, */
6305 postprocess_image (f
, img
)
6309 /* Manipulation of the image's mask. */
6312 Lisp_Object conversion
, spec
;
6317 /* `:heuristic-mask t'
6319 means build a mask heuristically.
6320 `:heuristic-mask (R G B)'
6321 `:mask (heuristic (R G B))'
6322 means build a mask from color (R G B) in the
6325 means remove a mask, if any. */
6327 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6329 x_build_heuristic_mask (f
, img
, mask
);
6334 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6336 if (EQ (mask
, Qheuristic
))
6337 x_build_heuristic_mask (f
, img
, Qt
);
6338 else if (CONSP (mask
)
6339 && EQ (XCAR (mask
), Qheuristic
))
6341 if (CONSP (XCDR (mask
)))
6342 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6344 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6346 else if (NILP (mask
) && found_p
&& img
->mask
)
6348 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6354 /* Should we apply an image transformation algorithm? */
6355 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6356 if (EQ (conversion
, Qdisabled
))
6357 x_disable_image (f
, img
);
6358 else if (EQ (conversion
, Qlaplace
))
6360 else if (EQ (conversion
, Qemboss
))
6362 else if (CONSP (conversion
)
6363 && EQ (XCAR (conversion
), Qedge_detection
))
6366 tem
= XCDR (conversion
);
6368 x_edge_detection (f
, img
,
6369 Fplist_get (tem
, QCmatrix
),
6370 Fplist_get (tem
, QCcolor_adjustment
));
6376 /* Return the id of image with Lisp specification SPEC on frame F.
6377 SPEC must be a valid Lisp image specification (see valid_image_p). */
6380 lookup_image (f
, spec
)
6384 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6388 struct gcpro gcpro1
;
6391 /* F must be a window-system frame, and SPEC must be a valid image
6393 xassert (FRAME_WINDOW_P (f
));
6394 xassert (valid_image_p (spec
));
6398 /* Look up SPEC in the hash table of the image cache. */
6399 hash
= sxhash (spec
, 0);
6400 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6402 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6403 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6406 /* If not found, create a new image and cache it. */
6409 extern Lisp_Object Qpostscript
;
6412 img
= make_image (spec
, hash
);
6413 cache_image (f
, img
);
6414 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6416 /* If we can't load the image, and we don't have a width and
6417 height, use some arbitrary width and height so that we can
6418 draw a rectangle for it. */
6419 if (img
->load_failed_p
)
6423 value
= image_spec_value (spec
, QCwidth
, NULL
);
6424 img
->width
= (INTEGERP (value
)
6425 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6426 value
= image_spec_value (spec
, QCheight
, NULL
);
6427 img
->height
= (INTEGERP (value
)
6428 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6432 /* Handle image type independent image attributes
6433 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6434 `:background COLOR'. */
6435 Lisp_Object ascent
, margin
, relief
, bg
;
6437 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6438 if (INTEGERP (ascent
))
6439 img
->ascent
= XFASTINT (ascent
);
6440 else if (EQ (ascent
, Qcenter
))
6441 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6443 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6444 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6445 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6446 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6447 && INTEGERP (XCDR (margin
)))
6449 if (XINT (XCAR (margin
)) > 0)
6450 img
->hmargin
= XFASTINT (XCAR (margin
));
6451 if (XINT (XCDR (margin
)) > 0)
6452 img
->vmargin
= XFASTINT (XCDR (margin
));
6455 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6456 if (INTEGERP (relief
))
6458 img
->relief
= XINT (relief
);
6459 img
->hmargin
+= abs (img
->relief
);
6460 img
->vmargin
+= abs (img
->relief
);
6463 if (! img
->background_valid
)
6465 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6469 = x_alloc_image_color (f
, img
, bg
,
6470 FRAME_BACKGROUND_PIXEL (f
));
6471 img
->background_valid
= 1;
6475 /* Do image transformations and compute masks, unless we
6476 don't have the image yet. */
6477 if (!EQ (*img
->type
->type
, Qpostscript
))
6478 postprocess_image (f
, img
);
6482 xassert (!interrupt_input_blocked
);
6485 /* We're using IMG, so set its timestamp to `now'. */
6486 EMACS_GET_TIME (now
);
6487 img
->timestamp
= EMACS_SECS (now
);
6491 /* Value is the image id. */
6496 /* Cache image IMG in the image cache of frame F. */
6499 cache_image (f
, img
)
6503 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6506 /* Find a free slot in c->images. */
6507 for (i
= 0; i
< c
->used
; ++i
)
6508 if (c
->images
[i
] == NULL
)
6511 /* If no free slot found, maybe enlarge c->images. */
6512 if (i
== c
->used
&& c
->used
== c
->size
)
6515 c
->images
= (struct image
**) xrealloc (c
->images
,
6516 c
->size
* sizeof *c
->images
);
6519 /* Add IMG to c->images, and assign IMG an id. */
6525 /* Add IMG to the cache's hash table. */
6526 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6527 img
->next
= c
->buckets
[i
];
6529 img
->next
->prev
= img
;
6531 c
->buckets
[i
] = img
;
6535 /* Call FN on every image in the image cache of frame F. Used to mark
6536 Lisp Objects in the image cache. */
6539 forall_images_in_image_cache (f
, fn
)
6541 void (*fn
) P_ ((struct image
*img
));
6543 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6545 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6549 for (i
= 0; i
< c
->used
; ++i
)
6558 /***********************************************************************
6560 ***********************************************************************/
6562 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6563 XImage
**, Pixmap
*));
6564 static void x_destroy_x_image
P_ ((XImage
*));
6565 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6568 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6569 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6570 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6571 via xmalloc. Print error messages via image_error if an error
6572 occurs. Value is non-zero if successful. */
6575 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6577 int width
, height
, depth
;
6581 Display
*display
= FRAME_X_DISPLAY (f
);
6582 Screen
*screen
= FRAME_X_SCREEN (f
);
6583 Window window
= FRAME_X_WINDOW (f
);
6585 xassert (interrupt_input_blocked
);
6588 depth
= DefaultDepthOfScreen (screen
);
6589 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6590 depth
, ZPixmap
, 0, NULL
, width
, height
,
6591 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6594 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6598 /* Allocate image raster. */
6599 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6601 /* Allocate a pixmap of the same size. */
6602 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6603 if (*pixmap
== None
)
6605 x_destroy_x_image (*ximg
);
6607 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6615 /* Destroy XImage XIMG. Free XIMG->data. */
6618 x_destroy_x_image (ximg
)
6621 xassert (interrupt_input_blocked
);
6626 XDestroyImage (ximg
);
6631 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6632 are width and height of both the image and pixmap. */
6635 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6642 xassert (interrupt_input_blocked
);
6643 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6644 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6645 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6650 /***********************************************************************
6652 ***********************************************************************/
6654 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6655 static char *slurp_file
P_ ((char *, int *));
6658 /* Find image file FILE. Look in data-directory, then
6659 x-bitmap-file-path. Value is the full name of the file found, or
6660 nil if not found. */
6663 x_find_image_file (file
)
6666 Lisp_Object file_found
, search_path
;
6667 struct gcpro gcpro1
, gcpro2
;
6671 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6672 GCPRO2 (file_found
, search_path
);
6674 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6675 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
6687 /* Read FILE into memory. Value is a pointer to a buffer allocated
6688 with xmalloc holding FILE's contents. Value is null if an error
6689 occurred. *SIZE is set to the size of the file. */
6692 slurp_file (file
, size
)
6700 if (stat (file
, &st
) == 0
6701 && (fp
= fopen (file
, "r")) != NULL
6702 && (buf
= (char *) xmalloc (st
.st_size
),
6703 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6724 /***********************************************************************
6726 ***********************************************************************/
6728 static int xbm_scan
P_ ((char **, char *, char *, int *));
6729 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6730 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6732 static int xbm_image_p
P_ ((Lisp_Object object
));
6733 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6735 static int xbm_file_p
P_ ((Lisp_Object
));
6738 /* Indices of image specification fields in xbm_format, below. */
6740 enum xbm_keyword_index
6758 /* Vector of image_keyword structures describing the format
6759 of valid XBM image specifications. */
6761 static struct image_keyword xbm_format
[XBM_LAST
] =
6763 {":type", IMAGE_SYMBOL_VALUE
, 1},
6764 {":file", IMAGE_STRING_VALUE
, 0},
6765 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6766 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6767 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6768 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6769 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6770 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6771 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6772 {":relief", IMAGE_INTEGER_VALUE
, 0},
6773 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6774 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6775 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6778 /* Structure describing the image type XBM. */
6780 static struct image_type xbm_type
=
6789 /* Tokens returned from xbm_scan. */
6798 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6799 A valid specification is a list starting with the symbol `image'
6800 The rest of the list is a property list which must contain an
6803 If the specification specifies a file to load, it must contain
6804 an entry `:file FILENAME' where FILENAME is a string.
6806 If the specification is for a bitmap loaded from memory it must
6807 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6808 WIDTH and HEIGHT are integers > 0. DATA may be:
6810 1. a string large enough to hold the bitmap data, i.e. it must
6811 have a size >= (WIDTH + 7) / 8 * HEIGHT
6813 2. a bool-vector of size >= WIDTH * HEIGHT
6815 3. a vector of strings or bool-vectors, one for each line of the
6818 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6819 may not be specified in this case because they are defined in the
6822 Both the file and data forms may contain the additional entries
6823 `:background COLOR' and `:foreground COLOR'. If not present,
6824 foreground and background of the frame on which the image is
6825 displayed is used. */
6828 xbm_image_p (object
)
6831 struct image_keyword kw
[XBM_LAST
];
6833 bcopy (xbm_format
, kw
, sizeof kw
);
6834 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6837 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6839 if (kw
[XBM_FILE
].count
)
6841 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6844 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6846 /* In-memory XBM file. */
6847 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6855 /* Entries for `:width', `:height' and `:data' must be present. */
6856 if (!kw
[XBM_WIDTH
].count
6857 || !kw
[XBM_HEIGHT
].count
6858 || !kw
[XBM_DATA
].count
)
6861 data
= kw
[XBM_DATA
].value
;
6862 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6863 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6865 /* Check type of data, and width and height against contents of
6871 /* Number of elements of the vector must be >= height. */
6872 if (XVECTOR (data
)->size
< height
)
6875 /* Each string or bool-vector in data must be large enough
6876 for one line of the image. */
6877 for (i
= 0; i
< height
; ++i
)
6879 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6884 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6887 else if (BOOL_VECTOR_P (elt
))
6889 if (XBOOL_VECTOR (elt
)->size
< width
)
6896 else if (STRINGP (data
))
6899 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6902 else if (BOOL_VECTOR_P (data
))
6904 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6915 /* Scan a bitmap file. FP is the stream to read from. Value is
6916 either an enumerator from enum xbm_token, or a character for a
6917 single-character token, or 0 at end of file. If scanning an
6918 identifier, store the lexeme of the identifier in SVAL. If
6919 scanning a number, store its value in *IVAL. */
6922 xbm_scan (s
, end
, sval
, ival
)
6931 /* Skip white space. */
6932 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6937 else if (isdigit (c
))
6939 int value
= 0, digit
;
6941 if (c
== '0' && *s
< end
)
6944 if (c
== 'x' || c
== 'X')
6951 else if (c
>= 'a' && c
<= 'f')
6952 digit
= c
- 'a' + 10;
6953 else if (c
>= 'A' && c
<= 'F')
6954 digit
= c
- 'A' + 10;
6957 value
= 16 * value
+ digit
;
6960 else if (isdigit (c
))
6964 && (c
= *(*s
)++, isdigit (c
)))
6965 value
= 8 * value
+ c
- '0';
6972 && (c
= *(*s
)++, isdigit (c
)))
6973 value
= 10 * value
+ c
- '0';
6981 else if (isalpha (c
) || c
== '_')
6985 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6992 else if (c
== '/' && **s
== '*')
6994 /* C-style comment. */
6996 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
7009 /* Replacement for XReadBitmapFileData which isn't available under old
7010 X versions. CONTENTS is a pointer to a buffer to parse; END is the
7011 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
7012 the image. Return in *DATA the bitmap data allocated with xmalloc.
7013 Value is non-zero if successful. DATA null means just test if
7014 CONTENTS looks like an in-memory XBM file. */
7017 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
7018 char *contents
, *end
;
7019 int *width
, *height
;
7020 unsigned char **data
;
7023 char buffer
[BUFSIZ
];
7026 int bytes_per_line
, i
, nbytes
;
7032 LA1 = xbm_scan (&s, end, buffer, &value)
7034 #define expect(TOKEN) \
7035 if (LA1 != (TOKEN)) \
7040 #define expect_ident(IDENT) \
7041 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
7046 *width
= *height
= -1;
7049 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
7051 /* Parse defines for width, height and hot-spots. */
7055 expect_ident ("define");
7056 expect (XBM_TK_IDENT
);
7058 if (LA1
== XBM_TK_NUMBER
);
7060 char *p
= strrchr (buffer
, '_');
7061 p
= p
? p
+ 1 : buffer
;
7062 if (strcmp (p
, "width") == 0)
7064 else if (strcmp (p
, "height") == 0)
7067 expect (XBM_TK_NUMBER
);
7070 if (*width
< 0 || *height
< 0)
7072 else if (data
== NULL
)
7075 /* Parse bits. Must start with `static'. */
7076 expect_ident ("static");
7077 if (LA1
== XBM_TK_IDENT
)
7079 if (strcmp (buffer
, "unsigned") == 0)
7082 expect_ident ("char");
7084 else if (strcmp (buffer
, "short") == 0)
7088 if (*width
% 16 && *width
% 16 < 9)
7091 else if (strcmp (buffer
, "char") == 0)
7099 expect (XBM_TK_IDENT
);
7105 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
7106 nbytes
= bytes_per_line
* *height
;
7107 p
= *data
= (char *) xmalloc (nbytes
);
7111 for (i
= 0; i
< nbytes
; i
+= 2)
7114 expect (XBM_TK_NUMBER
);
7117 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
7120 if (LA1
== ',' || LA1
== '}')
7128 for (i
= 0; i
< nbytes
; ++i
)
7131 expect (XBM_TK_NUMBER
);
7135 if (LA1
== ',' || LA1
== '}')
7160 /* Load XBM image IMG which will be displayed on frame F from buffer
7161 CONTENTS. END is the end of the buffer. Value is non-zero if
7165 xbm_load_image (f
, img
, contents
, end
)
7168 char *contents
, *end
;
7171 unsigned char *data
;
7174 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
7177 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7178 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7179 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7182 xassert (img
->width
> 0 && img
->height
> 0);
7184 /* Get foreground and background colors, maybe allocate colors. */
7185 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
7187 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
7188 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7191 background
= x_alloc_image_color (f
, img
, value
, background
);
7192 img
->background
= background
;
7193 img
->background_valid
= 1;
7197 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7200 img
->width
, img
->height
,
7201 foreground
, background
,
7205 if (img
->pixmap
== None
)
7207 x_clear_image (f
, img
);
7208 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
7214 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7220 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7227 return (STRINGP (data
)
7228 && xbm_read_bitmap_data (SDATA (data
),
7235 /* Fill image IMG which is used on frame F with pixmap data. Value is
7236 non-zero if successful. */
7244 Lisp_Object file_name
;
7246 xassert (xbm_image_p (img
->spec
));
7248 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7249 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7250 if (STRINGP (file_name
))
7255 struct gcpro gcpro1
;
7257 file
= x_find_image_file (file_name
);
7259 if (!STRINGP (file
))
7261 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7266 contents
= slurp_file (SDATA (file
), &size
);
7267 if (contents
== NULL
)
7269 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7274 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
7279 struct image_keyword fmt
[XBM_LAST
];
7282 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7283 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7286 int in_memory_file_p
= 0;
7288 /* See if data looks like an in-memory XBM file. */
7289 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7290 in_memory_file_p
= xbm_file_p (data
);
7292 /* Parse the image specification. */
7293 bcopy (xbm_format
, fmt
, sizeof fmt
);
7294 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
7297 /* Get specified width, and height. */
7298 if (!in_memory_file_p
)
7300 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
7301 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
7302 xassert (img
->width
> 0 && img
->height
> 0);
7305 /* Get foreground and background colors, maybe allocate colors. */
7306 if (fmt
[XBM_FOREGROUND
].count
7307 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
7308 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
7310 if (fmt
[XBM_BACKGROUND
].count
7311 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
7312 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7315 if (in_memory_file_p
)
7316 success_p
= xbm_load_image (f
, img
, SDATA (data
),
7325 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7327 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7328 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7330 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7332 bcopy (SDATA (line
), p
, nbytes
);
7334 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7337 else if (STRINGP (data
))
7338 bits
= SDATA (data
);
7340 bits
= XBOOL_VECTOR (data
)->data
;
7342 /* Create the pixmap. */
7343 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7345 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7348 img
->width
, img
->height
,
7349 foreground
, background
,
7355 image_error ("Unable to create pixmap for XBM image `%s'",
7357 x_clear_image (f
, img
);
7367 /***********************************************************************
7369 ***********************************************************************/
7373 static int xpm_image_p
P_ ((Lisp_Object object
));
7374 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7375 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7377 #include "X11/xpm.h"
7379 /* The symbol `xpm' identifying XPM-format images. */
7383 /* Indices of image specification fields in xpm_format, below. */
7385 enum xpm_keyword_index
7401 /* Vector of image_keyword structures describing the format
7402 of valid XPM image specifications. */
7404 static struct image_keyword xpm_format
[XPM_LAST
] =
7406 {":type", IMAGE_SYMBOL_VALUE
, 1},
7407 {":file", IMAGE_STRING_VALUE
, 0},
7408 {":data", IMAGE_STRING_VALUE
, 0},
7409 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7410 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7411 {":relief", IMAGE_INTEGER_VALUE
, 0},
7412 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7413 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7414 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7415 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7416 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7419 /* Structure describing the image type XBM. */
7421 static struct image_type xpm_type
=
7431 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7432 functions for allocating image colors. Our own functions handle
7433 color allocation failures more gracefully than the ones on the XPM
7436 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7437 #define ALLOC_XPM_COLORS
7440 #ifdef ALLOC_XPM_COLORS
7442 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7443 static void xpm_free_color_cache
P_ ((void));
7444 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7445 static int xpm_color_bucket
P_ ((char *));
7446 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7449 /* An entry in a hash table used to cache color definitions of named
7450 colors. This cache is necessary to speed up XPM image loading in
7451 case we do color allocations ourselves. Without it, we would need
7452 a call to XParseColor per pixel in the image. */
7454 struct xpm_cached_color
7456 /* Next in collision chain. */
7457 struct xpm_cached_color
*next
;
7459 /* Color definition (RGB and pixel color). */
7466 /* The hash table used for the color cache, and its bucket vector
7469 #define XPM_COLOR_CACHE_BUCKETS 1001
7470 struct xpm_cached_color
**xpm_color_cache
;
7472 /* Initialize the color cache. */
7475 xpm_init_color_cache (f
, attrs
)
7477 XpmAttributes
*attrs
;
7479 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7480 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7481 memset (xpm_color_cache
, 0, nbytes
);
7482 init_color_table ();
7484 if (attrs
->valuemask
& XpmColorSymbols
)
7489 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7490 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7491 attrs
->colorsymbols
[i
].value
, &color
))
7493 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7495 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7501 /* Free the color cache. */
7504 xpm_free_color_cache ()
7506 struct xpm_cached_color
*p
, *next
;
7509 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7510 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7516 xfree (xpm_color_cache
);
7517 xpm_color_cache
= NULL
;
7518 free_color_table ();
7522 /* Return the bucket index for color named COLOR_NAME in the color
7526 xpm_color_bucket (color_name
)
7532 for (s
= color_name
; *s
; ++s
)
7534 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7538 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7539 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7542 static struct xpm_cached_color
*
7543 xpm_cache_color (f
, color_name
, color
, bucket
)
7550 struct xpm_cached_color
*p
;
7553 bucket
= xpm_color_bucket (color_name
);
7555 nbytes
= sizeof *p
+ strlen (color_name
);
7556 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7557 strcpy (p
->name
, color_name
);
7559 p
->next
= xpm_color_cache
[bucket
];
7560 xpm_color_cache
[bucket
] = p
;
7565 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7566 return the cached definition in *COLOR. Otherwise, make a new
7567 entry in the cache and allocate the color. Value is zero if color
7568 allocation failed. */
7571 xpm_lookup_color (f
, color_name
, color
)
7576 struct xpm_cached_color
*p
;
7577 int h
= xpm_color_bucket (color_name
);
7579 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7580 if (strcmp (p
->name
, color_name
) == 0)
7585 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7588 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7590 p
= xpm_cache_color (f
, color_name
, color
, h
);
7597 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7598 CLOSURE is a pointer to the frame on which we allocate the
7599 color. Return in *COLOR the allocated color. Value is non-zero
7603 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7610 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7614 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7615 is a pointer to the frame on which we allocate the color. Value is
7616 non-zero if successful. */
7619 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7629 #endif /* ALLOC_XPM_COLORS */
7632 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7633 for XPM images. Such a list must consist of conses whose car and
7637 xpm_valid_color_symbols_p (color_symbols
)
7638 Lisp_Object color_symbols
;
7640 while (CONSP (color_symbols
))
7642 Lisp_Object sym
= XCAR (color_symbols
);
7644 || !STRINGP (XCAR (sym
))
7645 || !STRINGP (XCDR (sym
)))
7647 color_symbols
= XCDR (color_symbols
);
7650 return NILP (color_symbols
);
7654 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7657 xpm_image_p (object
)
7660 struct image_keyword fmt
[XPM_LAST
];
7661 bcopy (xpm_format
, fmt
, sizeof fmt
);
7662 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7663 /* Either `:file' or `:data' must be present. */
7664 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7665 /* Either no `:color-symbols' or it's a list of conses
7666 whose car and cdr are strings. */
7667 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7668 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7672 /* Load image IMG which will be displayed on frame F. Value is
7673 non-zero if successful. */
7681 XpmAttributes attrs
;
7682 Lisp_Object specified_file
, color_symbols
;
7684 /* Configure the XPM lib. Use the visual of frame F. Allocate
7685 close colors. Return colors allocated. */
7686 bzero (&attrs
, sizeof attrs
);
7687 attrs
.visual
= FRAME_X_VISUAL (f
);
7688 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7689 attrs
.valuemask
|= XpmVisual
;
7690 attrs
.valuemask
|= XpmColormap
;
7692 #ifdef ALLOC_XPM_COLORS
7693 /* Allocate colors with our own functions which handle
7694 failing color allocation more gracefully. */
7695 attrs
.color_closure
= f
;
7696 attrs
.alloc_color
= xpm_alloc_color
;
7697 attrs
.free_colors
= xpm_free_colors
;
7698 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7699 #else /* not ALLOC_XPM_COLORS */
7700 /* Let the XPM lib allocate colors. */
7701 attrs
.valuemask
|= XpmReturnAllocPixels
;
7702 #ifdef XpmAllocCloseColors
7703 attrs
.alloc_close_colors
= 1;
7704 attrs
.valuemask
|= XpmAllocCloseColors
;
7705 #else /* not XpmAllocCloseColors */
7706 attrs
.closeness
= 600;
7707 attrs
.valuemask
|= XpmCloseness
;
7708 #endif /* not XpmAllocCloseColors */
7709 #endif /* ALLOC_XPM_COLORS */
7711 /* If image specification contains symbolic color definitions, add
7712 these to `attrs'. */
7713 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7714 if (CONSP (color_symbols
))
7717 XpmColorSymbol
*xpm_syms
;
7720 attrs
.valuemask
|= XpmColorSymbols
;
7722 /* Count number of symbols. */
7723 attrs
.numsymbols
= 0;
7724 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7727 /* Allocate an XpmColorSymbol array. */
7728 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7729 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7730 bzero (xpm_syms
, size
);
7731 attrs
.colorsymbols
= xpm_syms
;
7733 /* Fill the color symbol array. */
7734 for (tail
= color_symbols
, i
= 0;
7736 ++i
, tail
= XCDR (tail
))
7738 Lisp_Object name
= XCAR (XCAR (tail
));
7739 Lisp_Object color
= XCDR (XCAR (tail
));
7740 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
7741 strcpy (xpm_syms
[i
].name
, SDATA (name
));
7742 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
7743 strcpy (xpm_syms
[i
].value
, SDATA (color
));
7747 /* Create a pixmap for the image, either from a file, or from a
7748 string buffer containing data in the same format as an XPM file. */
7749 #ifdef ALLOC_XPM_COLORS
7750 xpm_init_color_cache (f
, &attrs
);
7753 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7754 if (STRINGP (specified_file
))
7756 Lisp_Object file
= x_find_image_file (specified_file
);
7757 if (!STRINGP (file
))
7759 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7763 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7764 SDATA (file
), &img
->pixmap
, &img
->mask
,
7769 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7770 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7772 &img
->pixmap
, &img
->mask
,
7776 if (rc
== XpmSuccess
)
7778 #ifdef ALLOC_XPM_COLORS
7779 img
->colors
= colors_in_color_table (&img
->ncolors
);
7780 #else /* not ALLOC_XPM_COLORS */
7783 img
->ncolors
= attrs
.nalloc_pixels
;
7784 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7785 * sizeof *img
->colors
);
7786 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7788 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7789 #ifdef DEBUG_X_COLORS
7790 register_color (img
->colors
[i
]);
7793 #endif /* not ALLOC_XPM_COLORS */
7795 img
->width
= attrs
.width
;
7796 img
->height
= attrs
.height
;
7797 xassert (img
->width
> 0 && img
->height
> 0);
7799 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7800 XpmFreeAttributes (&attrs
);
7807 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7810 case XpmFileInvalid
:
7811 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7815 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7818 case XpmColorFailed
:
7819 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7823 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7828 #ifdef ALLOC_XPM_COLORS
7829 xpm_free_color_cache ();
7831 return rc
== XpmSuccess
;
7834 #endif /* HAVE_XPM != 0 */
7837 /***********************************************************************
7839 ***********************************************************************/
7841 /* An entry in the color table mapping an RGB color to a pixel color. */
7846 unsigned long pixel
;
7848 /* Next in color table collision list. */
7849 struct ct_color
*next
;
7852 /* The bucket vector size to use. Must be prime. */
7856 /* Value is a hash of the RGB color given by R, G, and B. */
7858 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7860 /* The color hash table. */
7862 struct ct_color
**ct_table
;
7864 /* Number of entries in the color table. */
7866 int ct_colors_allocated
;
7868 /* Initialize the color table. */
7873 int size
= CT_SIZE
* sizeof (*ct_table
);
7874 ct_table
= (struct ct_color
**) xmalloc (size
);
7875 bzero (ct_table
, size
);
7876 ct_colors_allocated
= 0;
7880 /* Free memory associated with the color table. */
7886 struct ct_color
*p
, *next
;
7888 for (i
= 0; i
< CT_SIZE
; ++i
)
7889 for (p
= ct_table
[i
]; p
; p
= next
)
7900 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7901 entry for that color already is in the color table, return the
7902 pixel color of that entry. Otherwise, allocate a new color for R,
7903 G, B, and make an entry in the color table. */
7905 static unsigned long
7906 lookup_rgb_color (f
, r
, g
, b
)
7910 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7911 int i
= hash
% CT_SIZE
;
7914 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7915 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7928 cmap
= FRAME_X_COLORMAP (f
);
7929 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7933 ++ct_colors_allocated
;
7935 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7939 p
->pixel
= color
.pixel
;
7940 p
->next
= ct_table
[i
];
7944 return FRAME_FOREGROUND_PIXEL (f
);
7951 /* Look up pixel color PIXEL which is used on frame F in the color
7952 table. If not already present, allocate it. Value is PIXEL. */
7954 static unsigned long
7955 lookup_pixel_color (f
, pixel
)
7957 unsigned long pixel
;
7959 int i
= pixel
% CT_SIZE
;
7962 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7963 if (p
->pixel
== pixel
)
7972 cmap
= FRAME_X_COLORMAP (f
);
7973 color
.pixel
= pixel
;
7974 x_query_color (f
, &color
);
7975 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7979 ++ct_colors_allocated
;
7981 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7986 p
->next
= ct_table
[i
];
7990 return FRAME_FOREGROUND_PIXEL (f
);
7997 /* Value is a vector of all pixel colors contained in the color table,
7998 allocated via xmalloc. Set *N to the number of colors. */
8000 static unsigned long *
8001 colors_in_color_table (n
)
8006 unsigned long *colors
;
8008 if (ct_colors_allocated
== 0)
8015 colors
= (unsigned long *) xmalloc (ct_colors_allocated
8017 *n
= ct_colors_allocated
;
8019 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
8020 for (p
= ct_table
[i
]; p
; p
= p
->next
)
8021 colors
[j
++] = p
->pixel
;
8029 /***********************************************************************
8031 ***********************************************************************/
8033 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
8034 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
8035 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
8037 /* Non-zero means draw a cross on images having `:conversion
8040 int cross_disabled_images
;
8042 /* Edge detection matrices for different edge-detection
8045 static int emboss_matrix
[9] = {
8047 2, -1, 0, /* y - 1 */
8049 0, 1, -2 /* y + 1 */
8052 static int laplace_matrix
[9] = {
8054 1, 0, 0, /* y - 1 */
8056 0, 0, -1 /* y + 1 */
8059 /* Value is the intensity of the color whose red/green/blue values
8062 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8065 /* On frame F, return an array of XColor structures describing image
8066 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8067 non-zero means also fill the red/green/blue members of the XColor
8068 structures. Value is a pointer to the array of XColors structures,
8069 allocated with xmalloc; it must be freed by the caller. */
8072 x_to_xcolors (f
, img
, rgb_p
)
8081 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
8083 /* Get the X image IMG->pixmap. */
8084 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8085 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8087 /* Fill the `pixel' members of the XColor array. I wished there
8088 were an easy and portable way to circumvent XGetPixel. */
8090 for (y
= 0; y
< img
->height
; ++y
)
8094 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8095 p
->pixel
= XGetPixel (ximg
, x
, y
);
8098 x_query_colors (f
, row
, img
->width
);
8101 XDestroyImage (ximg
);
8106 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8107 RGB members are set. F is the frame on which this all happens.
8108 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8111 x_from_xcolors (f
, img
, colors
)
8121 init_color_table ();
8123 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
8126 for (y
= 0; y
< img
->height
; ++y
)
8127 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8129 unsigned long pixel
;
8130 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
8131 XPutPixel (oimg
, x
, y
, pixel
);
8135 x_clear_image_1 (f
, img
, 1, 0, 1);
8137 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
8138 x_destroy_x_image (oimg
);
8139 img
->pixmap
= pixmap
;
8140 img
->colors
= colors_in_color_table (&img
->ncolors
);
8141 free_color_table ();
8145 /* On frame F, perform edge-detection on image IMG.
8147 MATRIX is a nine-element array specifying the transformation
8148 matrix. See emboss_matrix for an example.
8150 COLOR_ADJUST is a color adjustment added to each pixel of the
8154 x_detect_edges (f
, img
, matrix
, color_adjust
)
8157 int matrix
[9], color_adjust
;
8159 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8163 for (i
= sum
= 0; i
< 9; ++i
)
8164 sum
+= abs (matrix
[i
]);
8166 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8168 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
8170 for (y
= 0; y
< img
->height
; ++y
)
8172 p
= COLOR (new, 0, y
);
8173 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8174 p
= COLOR (new, img
->width
- 1, y
);
8175 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8178 for (x
= 1; x
< img
->width
- 1; ++x
)
8180 p
= COLOR (new, x
, 0);
8181 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8182 p
= COLOR (new, x
, img
->height
- 1);
8183 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8186 for (y
= 1; y
< img
->height
- 1; ++y
)
8188 p
= COLOR (new, 1, y
);
8190 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
8192 int r
, g
, b
, y1
, x1
;
8195 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
8196 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
8199 XColor
*t
= COLOR (colors
, x1
, y1
);
8200 r
+= matrix
[i
] * t
->red
;
8201 g
+= matrix
[i
] * t
->green
;
8202 b
+= matrix
[i
] * t
->blue
;
8205 r
= (r
/ sum
+ color_adjust
) & 0xffff;
8206 g
= (g
/ sum
+ color_adjust
) & 0xffff;
8207 b
= (b
/ sum
+ color_adjust
) & 0xffff;
8208 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
8213 x_from_xcolors (f
, img
, new);
8219 /* Perform the pre-defined `emboss' edge-detection on image IMG
8227 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
8231 /* Perform the pre-defined `laplace' edge-detection on image IMG
8239 x_detect_edges (f
, img
, laplace_matrix
, 45000);
8243 /* Perform edge-detection on image IMG on frame F, with specified
8244 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8246 MATRIX must be either
8248 - a list of at least 9 numbers in row-major form
8249 - a vector of at least 9 numbers
8251 COLOR_ADJUST nil means use a default; otherwise it must be a
8255 x_edge_detection (f
, img
, matrix
, color_adjust
)
8258 Lisp_Object matrix
, color_adjust
;
8266 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
8267 ++i
, matrix
= XCDR (matrix
))
8268 trans
[i
] = XFLOATINT (XCAR (matrix
));
8270 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
8272 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
8273 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
8276 if (NILP (color_adjust
))
8277 color_adjust
= make_number (0xffff / 2);
8279 if (i
== 9 && NUMBERP (color_adjust
))
8280 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
8284 /* Transform image IMG on frame F so that it looks disabled. */
8287 x_disable_image (f
, img
)
8291 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8293 if (dpyinfo
->n_planes
>= 2)
8295 /* Color (or grayscale). Convert to gray, and equalize. Just
8296 drawing such images with a stipple can look very odd, so
8297 we're using this method instead. */
8298 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8300 const int h
= 15000;
8301 const int l
= 30000;
8303 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
8307 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
8308 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
8309 p
->red
= p
->green
= p
->blue
= i2
;
8312 x_from_xcolors (f
, img
, colors
);
8315 /* Draw a cross over the disabled image, if we must or if we
8317 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
8319 Display
*dpy
= FRAME_X_DISPLAY (f
);
8322 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
8323 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
8324 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
8325 img
->width
- 1, img
->height
- 1);
8326 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
8332 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
8333 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8334 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8335 img
->width
- 1, img
->height
- 1);
8336 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8344 /* Build a mask for image IMG which is used on frame F. FILE is the
8345 name of an image file, for error messages. HOW determines how to
8346 determine the background color of IMG. If it is a list '(R G B)',
8347 with R, G, and B being integers >= 0, take that as the color of the
8348 background. Otherwise, determine the background color of IMG
8349 heuristically. Value is non-zero if successful. */
8352 x_build_heuristic_mask (f
, img
, how
)
8357 Display
*dpy
= FRAME_X_DISPLAY (f
);
8358 XImage
*ximg
, *mask_img
;
8359 int x
, y
, rc
, use_img_background
;
8360 unsigned long bg
= 0;
8364 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8366 img
->background_transparent_valid
= 0;
8369 /* Create an image and pixmap serving as mask. */
8370 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8371 &mask_img
, &img
->mask
);
8375 /* Get the X image of IMG->pixmap. */
8376 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8379 /* Determine the background color of ximg. If HOW is `(R G B)'
8380 take that as color. Otherwise, use the image's background color. */
8381 use_img_background
= 1;
8387 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
8389 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8393 if (i
== 3 && NILP (how
))
8395 char color_name
[30];
8396 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8397 bg
= x_alloc_image_color (f
, img
, build_string (color_name
), 0);
8398 use_img_background
= 0;
8402 if (use_img_background
)
8403 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
8405 /* Set all bits in mask_img to 1 whose color in ximg is different
8406 from the background color bg. */
8407 for (y
= 0; y
< img
->height
; ++y
)
8408 for (x
= 0; x
< img
->width
; ++x
)
8409 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8411 /* Fill in the background_transparent field while we have the mask handy. */
8412 image_background_transparent (img
, f
, mask_img
);
8414 /* Put mask_img into img->mask. */
8415 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8416 x_destroy_x_image (mask_img
);
8417 XDestroyImage (ximg
);
8424 /***********************************************************************
8425 PBM (mono, gray, color)
8426 ***********************************************************************/
8428 static int pbm_image_p
P_ ((Lisp_Object object
));
8429 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8430 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8432 /* The symbol `pbm' identifying images of this type. */
8436 /* Indices of image specification fields in gs_format, below. */
8438 enum pbm_keyword_index
8454 /* Vector of image_keyword structures describing the format
8455 of valid user-defined image specifications. */
8457 static struct image_keyword pbm_format
[PBM_LAST
] =
8459 {":type", IMAGE_SYMBOL_VALUE
, 1},
8460 {":file", IMAGE_STRING_VALUE
, 0},
8461 {":data", IMAGE_STRING_VALUE
, 0},
8462 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8463 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8464 {":relief", IMAGE_INTEGER_VALUE
, 0},
8465 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8466 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8467 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8468 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8469 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8472 /* Structure describing the image type `pbm'. */
8474 static struct image_type pbm_type
=
8484 /* Return non-zero if OBJECT is a valid PBM image specification. */
8487 pbm_image_p (object
)
8490 struct image_keyword fmt
[PBM_LAST
];
8492 bcopy (pbm_format
, fmt
, sizeof fmt
);
8494 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8497 /* Must specify either :data or :file. */
8498 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8502 /* Scan a decimal number from *S and return it. Advance *S while
8503 reading the number. END is the end of the string. Value is -1 at
8507 pbm_scan_number (s
, end
)
8508 unsigned char **s
, *end
;
8510 int c
= 0, val
= -1;
8514 /* Skip white-space. */
8515 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8520 /* Skip comment to end of line. */
8521 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8524 else if (isdigit (c
))
8526 /* Read decimal number. */
8528 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8529 val
= 10 * val
+ c
- '0';
8540 /* Load PBM image IMG for use on frame F. */
8548 int width
, height
, max_color_idx
= 0;
8550 Lisp_Object file
, specified_file
;
8551 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8552 struct gcpro gcpro1
;
8553 unsigned char *contents
= NULL
;
8554 unsigned char *end
, *p
;
8557 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8561 if (STRINGP (specified_file
))
8563 file
= x_find_image_file (specified_file
);
8564 if (!STRINGP (file
))
8566 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8571 contents
= slurp_file (SDATA (file
), &size
);
8572 if (contents
== NULL
)
8574 image_error ("Error reading `%s'", file
, Qnil
);
8580 end
= contents
+ size
;
8585 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8587 end
= p
+ SBYTES (data
);
8590 /* Check magic number. */
8591 if (end
- p
< 2 || *p
++ != 'P')
8593 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8603 raw_p
= 0, type
= PBM_MONO
;
8607 raw_p
= 0, type
= PBM_GRAY
;
8611 raw_p
= 0, type
= PBM_COLOR
;
8615 raw_p
= 1, type
= PBM_MONO
;
8619 raw_p
= 1, type
= PBM_GRAY
;
8623 raw_p
= 1, type
= PBM_COLOR
;
8627 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8631 /* Read width, height, maximum color-component. Characters
8632 starting with `#' up to the end of a line are ignored. */
8633 width
= pbm_scan_number (&p
, end
);
8634 height
= pbm_scan_number (&p
, end
);
8636 if (type
!= PBM_MONO
)
8638 max_color_idx
= pbm_scan_number (&p
, end
);
8639 if (raw_p
&& max_color_idx
> 255)
8640 max_color_idx
= 255;
8645 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8648 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8649 &ximg
, &img
->pixmap
))
8652 /* Initialize the color hash table. */
8653 init_color_table ();
8655 if (type
== PBM_MONO
)
8658 struct image_keyword fmt
[PBM_LAST
];
8659 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8660 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8662 /* Parse the image specification. */
8663 bcopy (pbm_format
, fmt
, sizeof fmt
);
8664 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8666 /* Get foreground and background colors, maybe allocate colors. */
8667 if (fmt
[PBM_FOREGROUND
].count
8668 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8669 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8670 if (fmt
[PBM_BACKGROUND
].count
8671 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8673 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8674 img
->background
= bg
;
8675 img
->background_valid
= 1;
8678 for (y
= 0; y
< height
; ++y
)
8679 for (x
= 0; x
< width
; ++x
)
8689 g
= pbm_scan_number (&p
, end
);
8691 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8696 for (y
= 0; y
< height
; ++y
)
8697 for (x
= 0; x
< width
; ++x
)
8701 if (type
== PBM_GRAY
)
8702 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8711 r
= pbm_scan_number (&p
, end
);
8712 g
= pbm_scan_number (&p
, end
);
8713 b
= pbm_scan_number (&p
, end
);
8716 if (r
< 0 || g
< 0 || b
< 0)
8720 XDestroyImage (ximg
);
8721 image_error ("Invalid pixel value in image `%s'",
8726 /* RGB values are now in the range 0..max_color_idx.
8727 Scale this to the range 0..0xffff supported by X. */
8728 r
= (double) r
* 65535 / max_color_idx
;
8729 g
= (double) g
* 65535 / max_color_idx
;
8730 b
= (double) b
* 65535 / max_color_idx
;
8731 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8735 /* Store in IMG->colors the colors allocated for the image, and
8736 free the color table. */
8737 img
->colors
= colors_in_color_table (&img
->ncolors
);
8738 free_color_table ();
8740 /* Maybe fill in the background field while we have ximg handy. */
8741 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8742 IMAGE_BACKGROUND (img
, f
, ximg
);
8744 /* Put the image into a pixmap. */
8745 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8746 x_destroy_x_image (ximg
);
8749 img
->height
= height
;
8758 /***********************************************************************
8760 ***********************************************************************/
8766 /* Function prototypes. */
8768 static int png_image_p
P_ ((Lisp_Object object
));
8769 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8771 /* The symbol `png' identifying images of this type. */
8775 /* Indices of image specification fields in png_format, below. */
8777 enum png_keyword_index
8792 /* Vector of image_keyword structures describing the format
8793 of valid user-defined image specifications. */
8795 static struct image_keyword png_format
[PNG_LAST
] =
8797 {":type", IMAGE_SYMBOL_VALUE
, 1},
8798 {":data", IMAGE_STRING_VALUE
, 0},
8799 {":file", IMAGE_STRING_VALUE
, 0},
8800 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8801 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8802 {":relief", IMAGE_INTEGER_VALUE
, 0},
8803 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8804 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8805 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8806 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8809 /* Structure describing the image type `png'. */
8811 static struct image_type png_type
=
8821 /* Return non-zero if OBJECT is a valid PNG image specification. */
8824 png_image_p (object
)
8827 struct image_keyword fmt
[PNG_LAST
];
8828 bcopy (png_format
, fmt
, sizeof fmt
);
8830 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8833 /* Must specify either the :data or :file keyword. */
8834 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8838 /* Error and warning handlers installed when the PNG library
8842 my_png_error (png_ptr
, msg
)
8843 png_struct
*png_ptr
;
8846 xassert (png_ptr
!= NULL
);
8847 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8848 longjmp (png_ptr
->jmpbuf
, 1);
8853 my_png_warning (png_ptr
, msg
)
8854 png_struct
*png_ptr
;
8857 xassert (png_ptr
!= NULL
);
8858 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8861 /* Memory source for PNG decoding. */
8863 struct png_memory_storage
8865 unsigned char *bytes
; /* The data */
8866 size_t len
; /* How big is it? */
8867 int index
; /* Where are we? */
8871 /* Function set as reader function when reading PNG image from memory.
8872 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8873 bytes from the input to DATA. */
8876 png_read_from_memory (png_ptr
, data
, length
)
8877 png_structp png_ptr
;
8881 struct png_memory_storage
*tbr
8882 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8884 if (length
> tbr
->len
- tbr
->index
)
8885 png_error (png_ptr
, "Read error");
8887 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8888 tbr
->index
= tbr
->index
+ length
;
8891 /* Load PNG image IMG for use on frame F. Value is non-zero if
8899 Lisp_Object file
, specified_file
;
8900 Lisp_Object specified_data
;
8902 XImage
*ximg
, *mask_img
= NULL
;
8903 struct gcpro gcpro1
;
8904 png_struct
*png_ptr
= NULL
;
8905 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8906 FILE *volatile fp
= NULL
;
8908 png_byte
* volatile pixels
= NULL
;
8909 png_byte
** volatile rows
= NULL
;
8910 png_uint_32 width
, height
;
8911 int bit_depth
, color_type
, interlace_type
;
8913 png_uint_32 row_bytes
;
8915 double screen_gamma
, image_gamma
;
8917 struct png_memory_storage tbr
; /* Data to be read */
8919 /* Find out what file to load. */
8920 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8921 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8925 if (NILP (specified_data
))
8927 file
= x_find_image_file (specified_file
);
8928 if (!STRINGP (file
))
8930 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8935 /* Open the image file. */
8936 fp
= fopen (SDATA (file
), "rb");
8939 image_error ("Cannot open image file `%s'", file
, Qnil
);
8945 /* Check PNG signature. */
8946 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8947 || !png_check_sig (sig
, sizeof sig
))
8949 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8957 /* Read from memory. */
8958 tbr
.bytes
= SDATA (specified_data
);
8959 tbr
.len
= SBYTES (specified_data
);
8962 /* Check PNG signature. */
8963 if (tbr
.len
< sizeof sig
8964 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8966 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8971 /* Need to skip past the signature. */
8972 tbr
.bytes
+= sizeof (sig
);
8975 /* Initialize read and info structs for PNG lib. */
8976 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8977 my_png_error
, my_png_warning
);
8980 if (fp
) fclose (fp
);
8985 info_ptr
= png_create_info_struct (png_ptr
);
8988 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8989 if (fp
) fclose (fp
);
8994 end_info
= png_create_info_struct (png_ptr
);
8997 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8998 if (fp
) fclose (fp
);
9003 /* Set error jump-back. We come back here when the PNG library
9004 detects an error. */
9005 if (setjmp (png_ptr
->jmpbuf
))
9009 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9012 if (fp
) fclose (fp
);
9017 /* Read image info. */
9018 if (!NILP (specified_data
))
9019 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
9021 png_init_io (png_ptr
, fp
);
9023 png_set_sig_bytes (png_ptr
, sizeof sig
);
9024 png_read_info (png_ptr
, info_ptr
);
9025 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
9026 &interlace_type
, NULL
, NULL
);
9028 /* If image contains simply transparency data, we prefer to
9029 construct a clipping mask. */
9030 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
9035 /* This function is easier to write if we only have to handle
9036 one data format: RGB or RGBA with 8 bits per channel. Let's
9037 transform other formats into that format. */
9039 /* Strip more than 8 bits per channel. */
9040 if (bit_depth
== 16)
9041 png_set_strip_16 (png_ptr
);
9043 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
9045 png_set_expand (png_ptr
);
9047 /* Convert grayscale images to RGB. */
9048 if (color_type
== PNG_COLOR_TYPE_GRAY
9049 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
9050 png_set_gray_to_rgb (png_ptr
);
9052 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
9054 /* Tell the PNG lib to handle gamma correction for us. */
9056 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9057 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
9058 /* The libpng documentation says this is right in this case. */
9059 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9062 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
9063 /* Image contains gamma information. */
9064 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
9066 /* Use the standard default for the image gamma. */
9067 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9069 /* Handle alpha channel by combining the image with a background
9070 color. Do this only if a real alpha channel is supplied. For
9071 simple transparency, we prefer a clipping mask. */
9074 png_color_16
*image_bg
;
9075 Lisp_Object specified_bg
9076 = image_spec_value (img
->spec
, QCbackground
, NULL
);
9078 if (STRINGP (specified_bg
))
9079 /* The user specified `:background', use that. */
9082 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
9084 png_color_16 user_bg
;
9086 bzero (&user_bg
, sizeof user_bg
);
9087 user_bg
.red
= color
.red
;
9088 user_bg
.green
= color
.green
;
9089 user_bg
.blue
= color
.blue
;
9091 png_set_background (png_ptr
, &user_bg
,
9092 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9095 else if (png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
9096 /* Image contains a background color with which to
9097 combine the image. */
9098 png_set_background (png_ptr
, image_bg
,
9099 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
9102 /* Image does not contain a background color with which
9103 to combine the image data via an alpha channel. Use
9104 the frame's background instead. */
9107 png_color_16 frame_background
;
9109 cmap
= FRAME_X_COLORMAP (f
);
9110 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
9111 x_query_color (f
, &color
);
9113 bzero (&frame_background
, sizeof frame_background
);
9114 frame_background
.red
= color
.red
;
9115 frame_background
.green
= color
.green
;
9116 frame_background
.blue
= color
.blue
;
9118 png_set_background (png_ptr
, &frame_background
,
9119 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9123 /* Update info structure. */
9124 png_read_update_info (png_ptr
, info_ptr
);
9126 /* Get number of channels. Valid values are 1 for grayscale images
9127 and images with a palette, 2 for grayscale images with transparency
9128 information (alpha channel), 3 for RGB images, and 4 for RGB
9129 images with alpha channel, i.e. RGBA. If conversions above were
9130 sufficient we should only have 3 or 4 channels here. */
9131 channels
= png_get_channels (png_ptr
, info_ptr
);
9132 xassert (channels
== 3 || channels
== 4);
9134 /* Number of bytes needed for one row of the image. */
9135 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
9137 /* Allocate memory for the image. */
9138 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
9139 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
9140 for (i
= 0; i
< height
; ++i
)
9141 rows
[i
] = pixels
+ i
* row_bytes
;
9143 /* Read the entire image. */
9144 png_read_image (png_ptr
, rows
);
9145 png_read_end (png_ptr
, info_ptr
);
9152 /* Create the X image and pixmap. */
9153 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
9157 /* Create an image and pixmap serving as mask if the PNG image
9158 contains an alpha channel. */
9161 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
9162 &mask_img
, &img
->mask
))
9164 x_destroy_x_image (ximg
);
9165 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
9170 /* Fill the X image and mask from PNG data. */
9171 init_color_table ();
9173 for (y
= 0; y
< height
; ++y
)
9175 png_byte
*p
= rows
[y
];
9177 for (x
= 0; x
< width
; ++x
)
9184 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
9186 /* An alpha channel, aka mask channel, associates variable
9187 transparency with an image. Where other image formats
9188 support binary transparency---fully transparent or fully
9189 opaque---PNG allows up to 254 levels of partial transparency.
9190 The PNG library implements partial transparency by combining
9191 the image with a specified background color.
9193 I'm not sure how to handle this here nicely: because the
9194 background on which the image is displayed may change, for
9195 real alpha channel support, it would be necessary to create
9196 a new image for each possible background.
9198 What I'm doing now is that a mask is created if we have
9199 boolean transparency information. Otherwise I'm using
9200 the frame's background color to combine the image with. */
9205 XPutPixel (mask_img
, x
, y
, *p
> 0);
9211 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9212 /* Set IMG's background color from the PNG image, unless the user
9216 if (png_get_bKGD (png_ptr
, info_ptr
, &bg
))
9218 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
9219 img
->background_valid
= 1;
9223 /* Remember colors allocated for this image. */
9224 img
->colors
= colors_in_color_table (&img
->ncolors
);
9225 free_color_table ();
9228 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9233 img
->height
= height
;
9235 /* Maybe fill in the background field while we have ximg handy. */
9236 IMAGE_BACKGROUND (img
, f
, ximg
);
9238 /* Put the image into the pixmap, then free the X image and its buffer. */
9239 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9240 x_destroy_x_image (ximg
);
9242 /* Same for the mask. */
9245 /* Fill in the background_transparent field while we have the mask
9247 image_background_transparent (img
, f
, mask_img
);
9249 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
9250 x_destroy_x_image (mask_img
);
9257 #endif /* HAVE_PNG != 0 */
9261 /***********************************************************************
9263 ***********************************************************************/
9267 /* Work around a warning about HAVE_STDLIB_H being redefined in
9269 #ifdef HAVE_STDLIB_H
9270 #define HAVE_STDLIB_H_1
9271 #undef HAVE_STDLIB_H
9272 #endif /* HAVE_STLIB_H */
9274 #include <jpeglib.h>
9278 #ifdef HAVE_STLIB_H_1
9279 #define HAVE_STDLIB_H 1
9282 static int jpeg_image_p
P_ ((Lisp_Object object
));
9283 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
9285 /* The symbol `jpeg' identifying images of this type. */
9289 /* Indices of image specification fields in gs_format, below. */
9291 enum jpeg_keyword_index
9300 JPEG_HEURISTIC_MASK
,
9306 /* Vector of image_keyword structures describing the format
9307 of valid user-defined image specifications. */
9309 static struct image_keyword jpeg_format
[JPEG_LAST
] =
9311 {":type", IMAGE_SYMBOL_VALUE
, 1},
9312 {":data", IMAGE_STRING_VALUE
, 0},
9313 {":file", IMAGE_STRING_VALUE
, 0},
9314 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9315 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9316 {":relief", IMAGE_INTEGER_VALUE
, 0},
9317 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9318 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9319 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9320 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9323 /* Structure describing the image type `jpeg'. */
9325 static struct image_type jpeg_type
=
9335 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9338 jpeg_image_p (object
)
9341 struct image_keyword fmt
[JPEG_LAST
];
9343 bcopy (jpeg_format
, fmt
, sizeof fmt
);
9345 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
9348 /* Must specify either the :data or :file keyword. */
9349 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9353 struct my_jpeg_error_mgr
9355 struct jpeg_error_mgr pub
;
9356 jmp_buf setjmp_buffer
;
9361 my_error_exit (cinfo
)
9364 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9365 longjmp (mgr
->setjmp_buffer
, 1);
9369 /* Init source method for JPEG data source manager. Called by
9370 jpeg_read_header() before any data is actually read. See
9371 libjpeg.doc from the JPEG lib distribution. */
9374 our_init_source (cinfo
)
9375 j_decompress_ptr cinfo
;
9380 /* Fill input buffer method for JPEG data source manager. Called
9381 whenever more data is needed. We read the whole image in one step,
9382 so this only adds a fake end of input marker at the end. */
9385 our_fill_input_buffer (cinfo
)
9386 j_decompress_ptr cinfo
;
9388 /* Insert a fake EOI marker. */
9389 struct jpeg_source_mgr
*src
= cinfo
->src
;
9390 static JOCTET buffer
[2];
9392 buffer
[0] = (JOCTET
) 0xFF;
9393 buffer
[1] = (JOCTET
) JPEG_EOI
;
9395 src
->next_input_byte
= buffer
;
9396 src
->bytes_in_buffer
= 2;
9401 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9402 is the JPEG data source manager. */
9405 our_skip_input_data (cinfo
, num_bytes
)
9406 j_decompress_ptr cinfo
;
9409 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9413 if (num_bytes
> src
->bytes_in_buffer
)
9414 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9416 src
->bytes_in_buffer
-= num_bytes
;
9417 src
->next_input_byte
+= num_bytes
;
9422 /* Method to terminate data source. Called by
9423 jpeg_finish_decompress() after all data has been processed. */
9426 our_term_source (cinfo
)
9427 j_decompress_ptr cinfo
;
9432 /* Set up the JPEG lib for reading an image from DATA which contains
9433 LEN bytes. CINFO is the decompression info structure created for
9434 reading the image. */
9437 jpeg_memory_src (cinfo
, data
, len
)
9438 j_decompress_ptr cinfo
;
9442 struct jpeg_source_mgr
*src
;
9444 if (cinfo
->src
== NULL
)
9446 /* First time for this JPEG object? */
9447 cinfo
->src
= (struct jpeg_source_mgr
*)
9448 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9449 sizeof (struct jpeg_source_mgr
));
9450 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9451 src
->next_input_byte
= data
;
9454 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9455 src
->init_source
= our_init_source
;
9456 src
->fill_input_buffer
= our_fill_input_buffer
;
9457 src
->skip_input_data
= our_skip_input_data
;
9458 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9459 src
->term_source
= our_term_source
;
9460 src
->bytes_in_buffer
= len
;
9461 src
->next_input_byte
= data
;
9465 /* Load image IMG for use on frame F. Patterned after example.c
9466 from the JPEG lib. */
9473 struct jpeg_decompress_struct cinfo
;
9474 struct my_jpeg_error_mgr mgr
;
9475 Lisp_Object file
, specified_file
;
9476 Lisp_Object specified_data
;
9477 FILE * volatile fp
= NULL
;
9479 int row_stride
, x
, y
;
9480 XImage
*ximg
= NULL
;
9482 unsigned long *colors
;
9484 struct gcpro gcpro1
;
9486 /* Open the JPEG file. */
9487 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9488 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9492 if (NILP (specified_data
))
9494 file
= x_find_image_file (specified_file
);
9495 if (!STRINGP (file
))
9497 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9502 fp
= fopen (SDATA (file
), "r");
9505 image_error ("Cannot open `%s'", file
, Qnil
);
9511 /* Customize libjpeg's error handling to call my_error_exit when an
9512 error is detected. This function will perform a longjmp. */
9513 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9514 mgr
.pub
.error_exit
= my_error_exit
;
9516 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9520 /* Called from my_error_exit. Display a JPEG error. */
9521 char buffer
[JMSG_LENGTH_MAX
];
9522 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9523 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9524 build_string (buffer
));
9527 /* Close the input file and destroy the JPEG object. */
9529 fclose ((FILE *) fp
);
9530 jpeg_destroy_decompress (&cinfo
);
9532 /* If we already have an XImage, free that. */
9533 x_destroy_x_image (ximg
);
9535 /* Free pixmap and colors. */
9536 x_clear_image (f
, img
);
9542 /* Create the JPEG decompression object. Let it read from fp.
9543 Read the JPEG image header. */
9544 jpeg_create_decompress (&cinfo
);
9546 if (NILP (specified_data
))
9547 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9549 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
9550 SBYTES (specified_data
));
9552 jpeg_read_header (&cinfo
, TRUE
);
9554 /* Customize decompression so that color quantization will be used.
9555 Start decompression. */
9556 cinfo
.quantize_colors
= TRUE
;
9557 jpeg_start_decompress (&cinfo
);
9558 width
= img
->width
= cinfo
.output_width
;
9559 height
= img
->height
= cinfo
.output_height
;
9561 /* Create X image and pixmap. */
9562 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9563 longjmp (mgr
.setjmp_buffer
, 2);
9565 /* Allocate colors. When color quantization is used,
9566 cinfo.actual_number_of_colors has been set with the number of
9567 colors generated, and cinfo.colormap is a two-dimensional array
9568 of color indices in the range 0..cinfo.actual_number_of_colors.
9569 No more than 255 colors will be generated. */
9573 if (cinfo
.out_color_components
> 2)
9574 ir
= 0, ig
= 1, ib
= 2;
9575 else if (cinfo
.out_color_components
> 1)
9576 ir
= 0, ig
= 1, ib
= 0;
9578 ir
= 0, ig
= 0, ib
= 0;
9580 /* Use the color table mechanism because it handles colors that
9581 cannot be allocated nicely. Such colors will be replaced with
9582 a default color, and we don't have to care about which colors
9583 can be freed safely, and which can't. */
9584 init_color_table ();
9585 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9588 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9590 /* Multiply RGB values with 255 because X expects RGB values
9591 in the range 0..0xffff. */
9592 int r
= cinfo
.colormap
[ir
][i
] << 8;
9593 int g
= cinfo
.colormap
[ig
][i
] << 8;
9594 int b
= cinfo
.colormap
[ib
][i
] << 8;
9595 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9598 /* Remember those colors actually allocated. */
9599 img
->colors
= colors_in_color_table (&img
->ncolors
);
9600 free_color_table ();
9604 row_stride
= width
* cinfo
.output_components
;
9605 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9607 for (y
= 0; y
< height
; ++y
)
9609 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9610 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9611 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9615 jpeg_finish_decompress (&cinfo
);
9616 jpeg_destroy_decompress (&cinfo
);
9618 fclose ((FILE *) fp
);
9620 /* Maybe fill in the background field while we have ximg handy. */
9621 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9622 IMAGE_BACKGROUND (img
, f
, ximg
);
9624 /* Put the image into the pixmap. */
9625 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9626 x_destroy_x_image (ximg
);
9631 #endif /* HAVE_JPEG */
9635 /***********************************************************************
9637 ***********************************************************************/
9643 static int tiff_image_p
P_ ((Lisp_Object object
));
9644 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9646 /* The symbol `tiff' identifying images of this type. */
9650 /* Indices of image specification fields in tiff_format, below. */
9652 enum tiff_keyword_index
9661 TIFF_HEURISTIC_MASK
,
9667 /* Vector of image_keyword structures describing the format
9668 of valid user-defined image specifications. */
9670 static struct image_keyword tiff_format
[TIFF_LAST
] =
9672 {":type", IMAGE_SYMBOL_VALUE
, 1},
9673 {":data", IMAGE_STRING_VALUE
, 0},
9674 {":file", IMAGE_STRING_VALUE
, 0},
9675 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9676 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9677 {":relief", IMAGE_INTEGER_VALUE
, 0},
9678 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9679 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9680 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9681 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9684 /* Structure describing the image type `tiff'. */
9686 static struct image_type tiff_type
=
9696 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9699 tiff_image_p (object
)
9702 struct image_keyword fmt
[TIFF_LAST
];
9703 bcopy (tiff_format
, fmt
, sizeof fmt
);
9705 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9708 /* Must specify either the :data or :file keyword. */
9709 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9713 /* Reading from a memory buffer for TIFF images Based on the PNG
9714 memory source, but we have to provide a lot of extra functions.
9717 We really only need to implement read and seek, but I am not
9718 convinced that the TIFF library is smart enough not to destroy
9719 itself if we only hand it the function pointers we need to
9724 unsigned char *bytes
;
9732 tiff_read_from_memory (data
, buf
, size
)
9737 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9739 if (size
> src
->len
- src
->index
)
9741 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9748 tiff_write_from_memory (data
, buf
, size
)
9758 tiff_seek_in_memory (data
, off
, whence
)
9763 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9768 case SEEK_SET
: /* Go from beginning of source. */
9772 case SEEK_END
: /* Go from end of source. */
9773 idx
= src
->len
+ off
;
9776 case SEEK_CUR
: /* Go from current position. */
9777 idx
= src
->index
+ off
;
9780 default: /* Invalid `whence'. */
9784 if (idx
> src
->len
|| idx
< 0)
9793 tiff_close_memory (data
)
9802 tiff_mmap_memory (data
, pbase
, psize
)
9807 /* It is already _IN_ memory. */
9813 tiff_unmap_memory (data
, base
, size
)
9818 /* We don't need to do this. */
9823 tiff_size_of_memory (data
)
9826 return ((tiff_memory_source
*) data
)->len
;
9831 tiff_error_handler (title
, format
, ap
)
9832 const char *title
, *format
;
9838 len
= sprintf (buf
, "TIFF error: %s ", title
);
9839 vsprintf (buf
+ len
, format
, ap
);
9840 add_to_log (buf
, Qnil
, Qnil
);
9845 tiff_warning_handler (title
, format
, ap
)
9846 const char *title
, *format
;
9852 len
= sprintf (buf
, "TIFF warning: %s ", title
);
9853 vsprintf (buf
+ len
, format
, ap
);
9854 add_to_log (buf
, Qnil
, Qnil
);
9858 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9866 Lisp_Object file
, specified_file
;
9867 Lisp_Object specified_data
;
9869 int width
, height
, x
, y
;
9873 struct gcpro gcpro1
;
9874 tiff_memory_source memsrc
;
9876 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9877 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9881 TIFFSetErrorHandler (tiff_error_handler
);
9882 TIFFSetWarningHandler (tiff_warning_handler
);
9884 if (NILP (specified_data
))
9886 /* Read from a file */
9887 file
= x_find_image_file (specified_file
);
9888 if (!STRINGP (file
))
9890 image_error ("Cannot find image file `%s'", file
, Qnil
);
9895 /* Try to open the image file. */
9896 tiff
= TIFFOpen (SDATA (file
), "r");
9899 image_error ("Cannot open `%s'", file
, Qnil
);
9906 /* Memory source! */
9907 memsrc
.bytes
= SDATA (specified_data
);
9908 memsrc
.len
= SBYTES (specified_data
);
9911 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9912 (TIFFReadWriteProc
) tiff_read_from_memory
,
9913 (TIFFReadWriteProc
) tiff_write_from_memory
,
9914 tiff_seek_in_memory
,
9916 tiff_size_of_memory
,
9922 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9928 /* Get width and height of the image, and allocate a raster buffer
9929 of width x height 32-bit values. */
9930 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9931 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9932 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9934 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9938 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9944 /* Create the X image and pixmap. */
9945 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9952 /* Initialize the color table. */
9953 init_color_table ();
9955 /* Process the pixel raster. Origin is in the lower-left corner. */
9956 for (y
= 0; y
< height
; ++y
)
9958 uint32
*row
= buf
+ y
* width
;
9960 for (x
= 0; x
< width
; ++x
)
9962 uint32 abgr
= row
[x
];
9963 int r
= TIFFGetR (abgr
) << 8;
9964 int g
= TIFFGetG (abgr
) << 8;
9965 int b
= TIFFGetB (abgr
) << 8;
9966 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9970 /* Remember the colors allocated for the image. Free the color table. */
9971 img
->colors
= colors_in_color_table (&img
->ncolors
);
9972 free_color_table ();
9975 img
->height
= height
;
9977 /* Maybe fill in the background field while we have ximg handy. */
9978 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9979 IMAGE_BACKGROUND (img
, f
, ximg
);
9981 /* Put the image into the pixmap, then free the X image and its buffer. */
9982 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9983 x_destroy_x_image (ximg
);
9990 #endif /* HAVE_TIFF != 0 */
9994 /***********************************************************************
9996 ***********************************************************************/
10000 #include <gif_lib.h>
10002 static int gif_image_p
P_ ((Lisp_Object object
));
10003 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
10005 /* The symbol `gif' identifying images of this type. */
10009 /* Indices of image specification fields in gif_format, below. */
10011 enum gif_keyword_index
10020 GIF_HEURISTIC_MASK
,
10027 /* Vector of image_keyword structures describing the format
10028 of valid user-defined image specifications. */
10030 static struct image_keyword gif_format
[GIF_LAST
] =
10032 {":type", IMAGE_SYMBOL_VALUE
, 1},
10033 {":data", IMAGE_STRING_VALUE
, 0},
10034 {":file", IMAGE_STRING_VALUE
, 0},
10035 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10036 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10037 {":relief", IMAGE_INTEGER_VALUE
, 0},
10038 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10039 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10040 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10041 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
10042 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10045 /* Structure describing the image type `gif'. */
10047 static struct image_type gif_type
=
10057 /* Return non-zero if OBJECT is a valid GIF image specification. */
10060 gif_image_p (object
)
10061 Lisp_Object object
;
10063 struct image_keyword fmt
[GIF_LAST
];
10064 bcopy (gif_format
, fmt
, sizeof fmt
);
10066 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
10069 /* Must specify either the :data or :file keyword. */
10070 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
10074 /* Reading a GIF image from memory
10075 Based on the PNG memory stuff to a certain extent. */
10079 unsigned char *bytes
;
10086 /* Make the current memory source available to gif_read_from_memory.
10087 It's done this way because not all versions of libungif support
10088 a UserData field in the GifFileType structure. */
10089 static gif_memory_source
*current_gif_memory_src
;
10092 gif_read_from_memory (file
, buf
, len
)
10097 gif_memory_source
*src
= current_gif_memory_src
;
10099 if (len
> src
->len
- src
->index
)
10102 bcopy (src
->bytes
+ src
->index
, buf
, len
);
10108 /* Load GIF image IMG for use on frame F. Value is non-zero if
10116 Lisp_Object file
, specified_file
;
10117 Lisp_Object specified_data
;
10118 int rc
, width
, height
, x
, y
, i
;
10120 ColorMapObject
*gif_color_map
;
10121 unsigned long pixel_colors
[256];
10123 struct gcpro gcpro1
;
10125 int ino
, image_left
, image_top
, image_width
, image_height
;
10126 gif_memory_source memsrc
;
10127 unsigned char *raster
;
10129 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10130 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10134 if (NILP (specified_data
))
10136 file
= x_find_image_file (specified_file
);
10137 if (!STRINGP (file
))
10139 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
10144 /* Open the GIF file. */
10145 gif
= DGifOpenFileName (SDATA (file
));
10148 image_error ("Cannot open `%s'", file
, Qnil
);
10155 /* Read from memory! */
10156 current_gif_memory_src
= &memsrc
;
10157 memsrc
.bytes
= SDATA (specified_data
);
10158 memsrc
.len
= SBYTES (specified_data
);
10161 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
10164 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
10170 /* Read entire contents. */
10171 rc
= DGifSlurp (gif
);
10172 if (rc
== GIF_ERROR
)
10174 image_error ("Error reading `%s'", img
->spec
, Qnil
);
10175 DGifCloseFile (gif
);
10180 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
10181 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
10182 if (ino
>= gif
->ImageCount
)
10184 image_error ("Invalid image number `%s' in image `%s'",
10186 DGifCloseFile (gif
);
10191 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
10192 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
10194 /* Create the X image and pixmap. */
10195 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
10197 DGifCloseFile (gif
);
10202 /* Allocate colors. */
10203 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
10204 if (!gif_color_map
)
10205 gif_color_map
= gif
->SColorMap
;
10206 init_color_table ();
10207 bzero (pixel_colors
, sizeof pixel_colors
);
10209 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
10211 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
10212 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
10213 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
10214 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
10217 img
->colors
= colors_in_color_table (&img
->ncolors
);
10218 free_color_table ();
10220 /* Clear the part of the screen image that are not covered by
10221 the image from the GIF file. Full animated GIF support
10222 requires more than can be done here (see the gif89 spec,
10223 disposal methods). Let's simply assume that the part
10224 not covered by a sub-image is in the frame's background color. */
10225 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
10226 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
10227 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
10228 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
10230 for (y
= 0; y
< image_top
; ++y
)
10231 for (x
= 0; x
< width
; ++x
)
10232 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10234 for (y
= image_top
+ image_height
; y
< height
; ++y
)
10235 for (x
= 0; x
< width
; ++x
)
10236 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10238 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
10240 for (x
= 0; x
< image_left
; ++x
)
10241 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10242 for (x
= image_left
+ image_width
; x
< width
; ++x
)
10243 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10246 /* Read the GIF image into the X image. We use a local variable
10247 `raster' here because RasterBits below is a char *, and invites
10248 problems with bytes >= 0x80. */
10249 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
10251 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
10253 static int interlace_start
[] = {0, 4, 2, 1};
10254 static int interlace_increment
[] = {8, 8, 4, 2};
10256 int row
= interlace_start
[0];
10260 for (y
= 0; y
< image_height
; y
++)
10262 if (row
>= image_height
)
10264 row
= interlace_start
[++pass
];
10265 while (row
>= image_height
)
10266 row
= interlace_start
[++pass
];
10269 for (x
= 0; x
< image_width
; x
++)
10271 int i
= raster
[(y
* image_width
) + x
];
10272 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
10276 row
+= interlace_increment
[pass
];
10281 for (y
= 0; y
< image_height
; ++y
)
10282 for (x
= 0; x
< image_width
; ++x
)
10284 int i
= raster
[y
* image_width
+ x
];
10285 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
10289 DGifCloseFile (gif
);
10291 /* Maybe fill in the background field while we have ximg handy. */
10292 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
10293 IMAGE_BACKGROUND (img
, f
, ximg
);
10295 /* Put the image into the pixmap, then free the X image and its buffer. */
10296 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10297 x_destroy_x_image (ximg
);
10303 #endif /* HAVE_GIF != 0 */
10307 /***********************************************************************
10309 ***********************************************************************/
10311 static int gs_image_p
P_ ((Lisp_Object object
));
10312 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
10313 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
10315 /* The symbol `postscript' identifying images of this type. */
10317 Lisp_Object Qpostscript
;
10319 /* Keyword symbols. */
10321 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
10323 /* Indices of image specification fields in gs_format, below. */
10325 enum gs_keyword_index
10343 /* Vector of image_keyword structures describing the format
10344 of valid user-defined image specifications. */
10346 static struct image_keyword gs_format
[GS_LAST
] =
10348 {":type", IMAGE_SYMBOL_VALUE
, 1},
10349 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10350 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10351 {":file", IMAGE_STRING_VALUE
, 1},
10352 {":loader", IMAGE_FUNCTION_VALUE
, 0},
10353 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
10354 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10355 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10356 {":relief", IMAGE_INTEGER_VALUE
, 0},
10357 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10358 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10359 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10360 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10363 /* Structure describing the image type `ghostscript'. */
10365 static struct image_type gs_type
=
10375 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10378 gs_clear_image (f
, img
)
10382 /* IMG->data.ptr_val may contain a recorded colormap. */
10383 xfree (img
->data
.ptr_val
);
10384 x_clear_image (f
, img
);
10388 /* Return non-zero if OBJECT is a valid Ghostscript image
10392 gs_image_p (object
)
10393 Lisp_Object object
;
10395 struct image_keyword fmt
[GS_LAST
];
10399 bcopy (gs_format
, fmt
, sizeof fmt
);
10401 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10404 /* Bounding box must be a list or vector containing 4 integers. */
10405 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10408 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10409 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10414 else if (VECTORP (tem
))
10416 if (XVECTOR (tem
)->size
!= 4)
10418 for (i
= 0; i
< 4; ++i
)
10419 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10429 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10438 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10439 struct gcpro gcpro1
, gcpro2
;
10441 double in_width
, in_height
;
10442 Lisp_Object pixel_colors
= Qnil
;
10444 /* Compute pixel size of pixmap needed from the given size in the
10445 image specification. Sizes in the specification are in pt. 1 pt
10446 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10448 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10449 in_width
= XFASTINT (pt_width
) / 72.0;
10450 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10451 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10452 in_height
= XFASTINT (pt_height
) / 72.0;
10453 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10455 /* Create the pixmap. */
10456 xassert (img
->pixmap
== None
);
10457 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10458 img
->width
, img
->height
,
10459 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10463 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10467 /* Call the loader to fill the pixmap. It returns a process object
10468 if successful. We do not record_unwind_protect here because
10469 other places in redisplay like calling window scroll functions
10470 don't either. Let the Lisp loader use `unwind-protect' instead. */
10471 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10473 sprintf (buffer
, "%lu %lu",
10474 (unsigned long) FRAME_X_WINDOW (f
),
10475 (unsigned long) img
->pixmap
);
10476 window_and_pixmap_id
= build_string (buffer
);
10478 sprintf (buffer
, "%lu %lu",
10479 FRAME_FOREGROUND_PIXEL (f
),
10480 FRAME_BACKGROUND_PIXEL (f
));
10481 pixel_colors
= build_string (buffer
);
10483 XSETFRAME (frame
, f
);
10484 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10486 loader
= intern ("gs-load-image");
10488 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10489 make_number (img
->width
),
10490 make_number (img
->height
),
10491 window_and_pixmap_id
,
10494 return PROCESSP (img
->data
.lisp_val
);
10498 /* Kill the Ghostscript process that was started to fill PIXMAP on
10499 frame F. Called from XTread_socket when receiving an event
10500 telling Emacs that Ghostscript has finished drawing. */
10503 x_kill_gs_process (pixmap
, f
)
10507 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10511 /* Find the image containing PIXMAP. */
10512 for (i
= 0; i
< c
->used
; ++i
)
10513 if (c
->images
[i
]->pixmap
== pixmap
)
10516 /* Should someone in between have cleared the image cache, for
10517 instance, give up. */
10521 /* Kill the GS process. We should have found PIXMAP in the image
10522 cache and its image should contain a process object. */
10523 img
= c
->images
[i
];
10524 xassert (PROCESSP (img
->data
.lisp_val
));
10525 Fkill_process (img
->data
.lisp_val
, Qnil
);
10526 img
->data
.lisp_val
= Qnil
;
10528 /* On displays with a mutable colormap, figure out the colors
10529 allocated for the image by looking at the pixels of an XImage for
10531 class = FRAME_X_VISUAL (f
)->class;
10532 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10538 /* Try to get an XImage for img->pixmep. */
10539 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10540 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10545 /* Initialize the color table. */
10546 init_color_table ();
10548 /* For each pixel of the image, look its color up in the
10549 color table. After having done so, the color table will
10550 contain an entry for each color used by the image. */
10551 for (y
= 0; y
< img
->height
; ++y
)
10552 for (x
= 0; x
< img
->width
; ++x
)
10554 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10555 lookup_pixel_color (f
, pixel
);
10558 /* Record colors in the image. Free color table and XImage. */
10559 img
->colors
= colors_in_color_table (&img
->ncolors
);
10560 free_color_table ();
10561 XDestroyImage (ximg
);
10563 #if 0 /* This doesn't seem to be the case. If we free the colors
10564 here, we get a BadAccess later in x_clear_image when
10565 freeing the colors. */
10566 /* We have allocated colors once, but Ghostscript has also
10567 allocated colors on behalf of us. So, to get the
10568 reference counts right, free them once. */
10570 x_free_colors (f
, img
->colors
, img
->ncolors
);
10574 image_error ("Cannot get X image of `%s'; colors will not be freed",
10580 /* Now that we have the pixmap, compute mask and transform the
10581 image if requested. */
10583 postprocess_image (f
, img
);
10589 /***********************************************************************
10591 ***********************************************************************/
10593 DEFUN ("x-change-window-property", Fx_change_window_property
,
10594 Sx_change_window_property
, 2, 3, 0,
10595 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
10596 PROP and VALUE must be strings. FRAME nil or omitted means use the
10597 selected frame. Value is VALUE. */)
10598 (prop
, value
, frame
)
10599 Lisp_Object frame
, prop
, value
;
10601 struct frame
*f
= check_x_frame (frame
);
10604 CHECK_STRING (prop
);
10605 CHECK_STRING (value
);
10608 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10609 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10610 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10611 SDATA (value
), SCHARS (value
));
10613 /* Make sure the property is set when we return. */
10614 XFlush (FRAME_X_DISPLAY (f
));
10621 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10622 Sx_delete_window_property
, 1, 2, 0,
10623 doc
: /* Remove window property PROP from X window of FRAME.
10624 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10626 Lisp_Object prop
, frame
;
10628 struct frame
*f
= check_x_frame (frame
);
10631 CHECK_STRING (prop
);
10633 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10634 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10636 /* Make sure the property is removed when we return. */
10637 XFlush (FRAME_X_DISPLAY (f
));
10644 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10646 doc
: /* Value is the value of window property PROP on FRAME.
10647 If FRAME is nil or omitted, use the selected frame. Value is nil
10648 if FRAME hasn't a property with name PROP or if PROP has no string
10651 Lisp_Object prop
, frame
;
10653 struct frame
*f
= check_x_frame (frame
);
10656 Lisp_Object prop_value
= Qnil
;
10657 char *tmp_data
= NULL
;
10660 unsigned long actual_size
, bytes_remaining
;
10662 CHECK_STRING (prop
);
10664 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), SDATA (prop
), False
);
10665 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10666 prop_atom
, 0, 0, False
, XA_STRING
,
10667 &actual_type
, &actual_format
, &actual_size
,
10668 &bytes_remaining
, (unsigned char **) &tmp_data
);
10671 int size
= bytes_remaining
;
10676 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10677 prop_atom
, 0, bytes_remaining
,
10679 &actual_type
, &actual_format
,
10680 &actual_size
, &bytes_remaining
,
10681 (unsigned char **) &tmp_data
);
10682 if (rc
== Success
&& tmp_data
)
10683 prop_value
= make_string (tmp_data
, size
);
10694 /***********************************************************************
10696 ***********************************************************************/
10698 /* If non-null, an asynchronous timer that, when it expires, displays
10699 an hourglass cursor on all frames. */
10701 static struct atimer
*hourglass_atimer
;
10703 /* Non-zero means an hourglass cursor is currently shown. */
10705 static int hourglass_shown_p
;
10707 /* Number of seconds to wait before displaying an hourglass cursor. */
10709 static Lisp_Object Vhourglass_delay
;
10711 /* Default number of seconds to wait before displaying an hourglass
10714 #define DEFAULT_HOURGLASS_DELAY 1
10716 /* Function prototypes. */
10718 static void show_hourglass
P_ ((struct atimer
*));
10719 static void hide_hourglass
P_ ((void));
10722 /* Cancel a currently active hourglass timer, and start a new one. */
10728 int secs
, usecs
= 0;
10730 cancel_hourglass ();
10732 if (INTEGERP (Vhourglass_delay
)
10733 && XINT (Vhourglass_delay
) > 0)
10734 secs
= XFASTINT (Vhourglass_delay
);
10735 else if (FLOATP (Vhourglass_delay
)
10736 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10739 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10740 secs
= XFASTINT (tem
);
10741 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10744 secs
= DEFAULT_HOURGLASS_DELAY
;
10746 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10747 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10748 show_hourglass
, NULL
);
10752 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10756 cancel_hourglass ()
10758 if (hourglass_atimer
)
10760 cancel_atimer (hourglass_atimer
);
10761 hourglass_atimer
= NULL
;
10764 if (hourglass_shown_p
)
10769 /* Timer function of hourglass_atimer. TIMER is equal to
10772 Display an hourglass pointer on all frames by mapping the frames'
10773 hourglass_window. Set the hourglass_p flag in the frames'
10774 output_data.x structure to indicate that an hourglass cursor is
10775 shown on the frames. */
10778 show_hourglass (timer
)
10779 struct atimer
*timer
;
10781 /* The timer implementation will cancel this timer automatically
10782 after this function has run. Set hourglass_atimer to null
10783 so that we know the timer doesn't have to be canceled. */
10784 hourglass_atimer
= NULL
;
10786 if (!hourglass_shown_p
)
10788 Lisp_Object rest
, frame
;
10792 FOR_EACH_FRAME (rest
, frame
)
10794 struct frame
*f
= XFRAME (frame
);
10796 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10798 Display
*dpy
= FRAME_X_DISPLAY (f
);
10800 #ifdef USE_X_TOOLKIT
10801 if (f
->output_data
.x
->widget
)
10803 if (FRAME_OUTER_WINDOW (f
))
10806 f
->output_data
.x
->hourglass_p
= 1;
10808 if (!f
->output_data
.x
->hourglass_window
)
10810 unsigned long mask
= CWCursor
;
10811 XSetWindowAttributes attrs
;
10813 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10815 f
->output_data
.x
->hourglass_window
10816 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10817 0, 0, 32000, 32000, 0, 0,
10823 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10829 hourglass_shown_p
= 1;
10835 /* Hide the hourglass pointer on all frames, if it is currently
10841 if (hourglass_shown_p
)
10843 Lisp_Object rest
, frame
;
10846 FOR_EACH_FRAME (rest
, frame
)
10848 struct frame
*f
= XFRAME (frame
);
10851 /* Watch out for newly created frames. */
10852 && f
->output_data
.x
->hourglass_window
)
10854 XUnmapWindow (FRAME_X_DISPLAY (f
),
10855 f
->output_data
.x
->hourglass_window
);
10856 /* Sync here because XTread_socket looks at the
10857 hourglass_p flag that is reset to zero below. */
10858 XSync (FRAME_X_DISPLAY (f
), False
);
10859 f
->output_data
.x
->hourglass_p
= 0;
10863 hourglass_shown_p
= 0;
10870 /***********************************************************************
10872 ***********************************************************************/
10874 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10875 Lisp_Object
, Lisp_Object
));
10876 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10877 Lisp_Object
, int, int, int *, int *));
10879 /* The frame of a currently visible tooltip. */
10881 Lisp_Object tip_frame
;
10883 /* If non-nil, a timer started that hides the last tooltip when it
10886 Lisp_Object tip_timer
;
10889 /* If non-nil, a vector of 3 elements containing the last args
10890 with which x-show-tip was called. See there. */
10892 Lisp_Object last_show_tip_args
;
10894 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10896 Lisp_Object Vx_max_tooltip_size
;
10900 unwind_create_tip_frame (frame
)
10903 Lisp_Object deleted
;
10905 deleted
= unwind_create_frame (frame
);
10906 if (EQ (deleted
, Qt
))
10916 /* Create a frame for a tooltip on the display described by DPYINFO.
10917 PARMS is a list of frame parameters. TEXT is the string to
10918 display in the tip frame. Value is the frame.
10920 Note that functions called here, esp. x_default_parameter can
10921 signal errors, for instance when a specified color name is
10922 undefined. We have to make sure that we're in a consistent state
10923 when this happens. */
10926 x_create_tip_frame (dpyinfo
, parms
, text
)
10927 struct x_display_info
*dpyinfo
;
10928 Lisp_Object parms
, text
;
10931 Lisp_Object frame
, tem
;
10933 long window_prompting
= 0;
10935 int count
= SPECPDL_INDEX ();
10936 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10938 int face_change_count_before
= face_change_count
;
10939 Lisp_Object buffer
;
10940 struct buffer
*old_buffer
;
10944 /* Use this general default value to start with until we know if
10945 this frame has a specified name. */
10946 Vx_resource_name
= Vinvocation_name
;
10948 #ifdef MULTI_KBOARD
10949 kb
= dpyinfo
->kboard
;
10951 kb
= &the_only_kboard
;
10954 /* Get the name of the frame to use for resource lookup. */
10955 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10956 if (!STRINGP (name
)
10957 && !EQ (name
, Qunbound
)
10959 error ("Invalid frame name--not a string or nil");
10960 Vx_resource_name
= name
;
10963 GCPRO3 (parms
, name
, frame
);
10964 f
= make_frame (1);
10965 XSETFRAME (frame
, f
);
10967 buffer
= Fget_buffer_create (build_string (" *tip*"));
10968 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10969 old_buffer
= current_buffer
;
10970 set_buffer_internal_1 (XBUFFER (buffer
));
10971 current_buffer
->truncate_lines
= Qnil
;
10973 Finsert (1, &text
);
10974 set_buffer_internal_1 (old_buffer
);
10976 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10977 record_unwind_protect (unwind_create_tip_frame
, frame
);
10979 /* By setting the output method, we're essentially saying that
10980 the frame is live, as per FRAME_LIVE_P. If we get a signal
10981 from this point on, x_destroy_window might screw up reference
10983 f
->output_method
= output_x_window
;
10984 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10985 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10986 f
->output_data
.x
->icon_bitmap
= -1;
10987 f
->output_data
.x
->fontset
= -1;
10988 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10989 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10990 #ifdef USE_TOOLKIT_SCROLL_BARS
10991 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
10992 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
10993 #endif /* USE_TOOLKIT_SCROLL_BARS */
10994 f
->icon_name
= Qnil
;
10995 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10997 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
10998 dpyinfo_refcount
= dpyinfo
->reference_count
;
10999 #endif /* GLYPH_DEBUG */
11000 #ifdef MULTI_KBOARD
11001 FRAME_KBOARD (f
) = kb
;
11003 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
11004 f
->output_data
.x
->explicit_parent
= 0;
11006 /* These colors will be set anyway later, but it's important
11007 to get the color reference counts right, so initialize them! */
11010 struct gcpro gcpro1
;
11012 black
= build_string ("black");
11014 f
->output_data
.x
->foreground_pixel
11015 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11016 f
->output_data
.x
->background_pixel
11017 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11018 f
->output_data
.x
->cursor_pixel
11019 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11020 f
->output_data
.x
->cursor_foreground_pixel
11021 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11022 f
->output_data
.x
->border_pixel
11023 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11024 f
->output_data
.x
->mouse_pixel
11025 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11029 /* Set the name; the functions to which we pass f expect the name to
11031 if (EQ (name
, Qunbound
) || NILP (name
))
11033 f
->name
= build_string (dpyinfo
->x_id_name
);
11034 f
->explicit_name
= 0;
11039 f
->explicit_name
= 1;
11040 /* use the frame's title when getting resources for this frame. */
11041 specbind (Qx_resource_name
, name
);
11044 /* Extract the window parameters from the supplied values that are
11045 needed to determine window geometry. */
11049 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
11052 /* First, try whatever font the caller has specified. */
11053 if (STRINGP (font
))
11055 tem
= Fquery_fontset (font
, Qnil
);
11057 font
= x_new_fontset (f
, SDATA (tem
));
11059 font
= x_new_font (f
, SDATA (font
));
11062 /* Try out a font which we hope has bold and italic variations. */
11063 if (!STRINGP (font
))
11064 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
11065 if (!STRINGP (font
))
11066 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11067 if (! STRINGP (font
))
11068 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11069 if (! STRINGP (font
))
11070 /* This was formerly the first thing tried, but it finds too many fonts
11071 and takes too long. */
11072 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
11073 /* If those didn't work, look for something which will at least work. */
11074 if (! STRINGP (font
))
11075 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
11077 if (! STRINGP (font
))
11078 font
= build_string ("fixed");
11080 x_default_parameter (f
, parms
, Qfont
, font
,
11081 "font", "Font", RES_TYPE_STRING
);
11084 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
11085 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
11087 /* This defaults to 2 in order to match xterm. We recognize either
11088 internalBorderWidth or internalBorder (which is what xterm calls
11090 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11094 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
11095 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
11096 if (! EQ (value
, Qunbound
))
11097 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
11101 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
11102 "internalBorderWidth", "internalBorderWidth",
11105 /* Also do the stuff which must be set before the window exists. */
11106 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
11107 "foreground", "Foreground", RES_TYPE_STRING
);
11108 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
11109 "background", "Background", RES_TYPE_STRING
);
11110 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
11111 "pointerColor", "Foreground", RES_TYPE_STRING
);
11112 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
11113 "cursorColor", "Foreground", RES_TYPE_STRING
);
11114 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
11115 "borderColor", "BorderColor", RES_TYPE_STRING
);
11117 /* Init faces before x_default_parameter is called for scroll-bar
11118 parameters because that function calls x_set_scroll_bar_width,
11119 which calls change_frame_size, which calls Fset_window_buffer,
11120 which runs hooks, which call Fvertical_motion. At the end, we
11121 end up in init_iterator with a null face cache, which should not
11123 init_frame_faces (f
);
11125 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
11126 window_prompting
= x_figure_window_size (f
, parms
);
11128 if (window_prompting
& XNegative
)
11130 if (window_prompting
& YNegative
)
11131 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
11133 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
11137 if (window_prompting
& YNegative
)
11138 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
11140 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11143 f
->output_data
.x
->size_hint_flags
= window_prompting
;
11145 XSetWindowAttributes attrs
;
11146 unsigned long mask
;
11149 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
11150 if (DoesSaveUnders (dpyinfo
->screen
))
11151 mask
|= CWSaveUnder
;
11153 /* Window managers look at the override-redirect flag to determine
11154 whether or net to give windows a decoration (Xlib spec, chapter
11156 attrs
.override_redirect
= True
;
11157 attrs
.save_under
= True
;
11158 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
11159 /* Arrange for getting MapNotify and UnmapNotify events. */
11160 attrs
.event_mask
= StructureNotifyMask
;
11162 = FRAME_X_WINDOW (f
)
11163 = XCreateWindow (FRAME_X_DISPLAY (f
),
11164 FRAME_X_DISPLAY_INFO (f
)->root_window
,
11165 /* x, y, width, height */
11169 CopyFromParent
, InputOutput
, CopyFromParent
,
11176 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
11177 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11178 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
11179 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11180 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
11181 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
11183 /* Dimensions, especially f->height, must be done via change_frame_size.
11184 Change will not be effected unless different from the current
11187 height
= f
->height
;
11189 SET_FRAME_WIDTH (f
, 0);
11190 change_frame_size (f
, height
, width
, 1, 0, 0);
11192 /* Set up faces after all frame parameters are known. This call
11193 also merges in face attributes specified for new frames.
11195 Frame parameters may be changed if .Xdefaults contains
11196 specifications for the default font. For example, if there is an
11197 `Emacs.default.attributeBackground: pink', the `background-color'
11198 attribute of the frame get's set, which let's the internal border
11199 of the tooltip frame appear in pink. Prevent this. */
11201 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
11203 /* Set tip_frame here, so that */
11205 call1 (Qface_set_after_frame_default
, frame
);
11207 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
11208 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
11216 /* It is now ok to make the frame official even if we get an error
11217 below. And the frame needs to be on Vframe_list or making it
11218 visible won't work. */
11219 Vframe_list
= Fcons (frame
, Vframe_list
);
11221 /* Now that the frame is official, it counts as a reference to
11223 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
11225 /* Setting attributes of faces of the tooltip frame from resources
11226 and similar will increment face_change_count, which leads to the
11227 clearing of all current matrices. Since this isn't necessary
11228 here, avoid it by resetting face_change_count to the value it
11229 had before we created the tip frame. */
11230 face_change_count
= face_change_count_before
;
11232 /* Discard the unwind_protect. */
11233 return unbind_to (count
, frame
);
11237 /* Compute where to display tip frame F. PARMS is the list of frame
11238 parameters for F. DX and DY are specified offsets from the current
11239 location of the mouse. WIDTH and HEIGHT are the width and height
11240 of the tooltip. Return coordinates relative to the root window of
11241 the display in *ROOT_X, and *ROOT_Y. */
11244 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
11246 Lisp_Object parms
, dx
, dy
;
11248 int *root_x
, *root_y
;
11250 Lisp_Object left
, top
;
11252 Window root
, child
;
11255 /* User-specified position? */
11256 left
= Fcdr (Fassq (Qleft
, parms
));
11257 top
= Fcdr (Fassq (Qtop
, parms
));
11259 /* Move the tooltip window where the mouse pointer is. Resize and
11261 if (!INTEGERP (left
) || !INTEGERP (top
))
11264 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
11265 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
11269 if (INTEGERP (top
))
11270 *root_y
= XINT (top
);
11271 else if (*root_y
+ XINT (dy
) - height
< 0)
11272 *root_y
-= XINT (dy
);
11276 *root_y
+= XINT (dy
);
11279 if (INTEGERP (left
))
11280 *root_x
= XINT (left
);
11281 else if (*root_x
+ XINT (dx
) + width
<= FRAME_X_DISPLAY_INFO (f
)->width
)
11282 /* It fits to the right of the pointer. */
11283 *root_x
+= XINT (dx
);
11284 else if (width
+ XINT (dx
) <= *root_x
)
11285 /* It fits to the left of the pointer. */
11286 *root_x
-= width
+ XINT (dx
);
11288 /* Put it left-justified on the screen--it ought to fit that way. */
11293 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
11294 doc
: /* Show STRING in a "tooltip" window on frame FRAME.
11295 A tooltip window is a small X window displaying a string.
11297 FRAME nil or omitted means use the selected frame.
11299 PARMS is an optional list of frame parameters which can be used to
11300 change the tooltip's appearance.
11302 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11303 means use the default timeout of 5 seconds.
11305 If the list of frame parameters PARAMS contains a `left' parameters,
11306 the tooltip is displayed at that x-position. Otherwise it is
11307 displayed at the mouse position, with offset DX added (default is 5 if
11308 DX isn't specified). Likewise for the y-position; if a `top' frame
11309 parameter is specified, it determines the y-position of the tooltip
11310 window, otherwise it is displayed at the mouse position, with offset
11311 DY added (default is -10).
11313 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11314 Text larger than the specified size is clipped. */)
11315 (string
, frame
, parms
, timeout
, dx
, dy
)
11316 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
11320 int root_x
, root_y
;
11321 struct buffer
*old_buffer
;
11322 struct text_pos pos
;
11323 int i
, width
, height
;
11324 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
11325 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
11326 int count
= SPECPDL_INDEX ();
11328 specbind (Qinhibit_redisplay
, Qt
);
11330 GCPRO4 (string
, parms
, frame
, timeout
);
11332 CHECK_STRING (string
);
11333 f
= check_x_frame (frame
);
11334 if (NILP (timeout
))
11335 timeout
= make_number (5);
11337 CHECK_NATNUM (timeout
);
11340 dx
= make_number (5);
11345 dy
= make_number (-10);
11349 if (NILP (last_show_tip_args
))
11350 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
11352 if (!NILP (tip_frame
))
11354 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
11355 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
11356 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
11358 if (EQ (frame
, last_frame
)
11359 && !NILP (Fequal (last_string
, string
))
11360 && !NILP (Fequal (last_parms
, parms
)))
11362 struct frame
*f
= XFRAME (tip_frame
);
11364 /* Only DX and DY have changed. */
11365 if (!NILP (tip_timer
))
11367 Lisp_Object timer
= tip_timer
;
11369 call1 (Qcancel_timer
, timer
);
11373 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
11374 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
11375 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11382 /* Hide a previous tip, if any. */
11385 ASET (last_show_tip_args
, 0, string
);
11386 ASET (last_show_tip_args
, 1, frame
);
11387 ASET (last_show_tip_args
, 2, parms
);
11389 /* Add default values to frame parameters. */
11390 if (NILP (Fassq (Qname
, parms
)))
11391 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
11392 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11393 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
11394 if (NILP (Fassq (Qborder_width
, parms
)))
11395 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
11396 if (NILP (Fassq (Qborder_color
, parms
)))
11397 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
11398 if (NILP (Fassq (Qbackground_color
, parms
)))
11399 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
11402 /* Create a frame for the tooltip, and record it in the global
11403 variable tip_frame. */
11404 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
11405 f
= XFRAME (frame
);
11407 /* Set up the frame's root window. */
11408 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
11409 w
->left
= w
->top
= make_number (0);
11411 if (CONSP (Vx_max_tooltip_size
)
11412 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11413 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11414 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11415 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11417 w
->width
= XCAR (Vx_max_tooltip_size
);
11418 w
->height
= XCDR (Vx_max_tooltip_size
);
11422 w
->width
= make_number (80);
11423 w
->height
= make_number (40);
11426 f
->window_width
= XINT (w
->width
);
11428 w
->pseudo_window_p
= 1;
11430 /* Display the tooltip text in a temporary buffer. */
11431 old_buffer
= current_buffer
;
11432 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11433 current_buffer
->truncate_lines
= Qnil
;
11434 clear_glyph_matrix (w
->desired_matrix
);
11435 clear_glyph_matrix (w
->current_matrix
);
11436 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11437 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11439 /* Compute width and height of the tooltip. */
11440 width
= height
= 0;
11441 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11443 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11444 struct glyph
*last
;
11447 /* Stop at the first empty row at the end. */
11448 if (!row
->enabled_p
|| !row
->displays_text_p
)
11451 /* Let the row go over the full width of the frame. */
11452 row
->full_width_p
= 1;
11454 /* There's a glyph at the end of rows that is used to place
11455 the cursor there. Don't include the width of this glyph. */
11456 if (row
->used
[TEXT_AREA
])
11458 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11459 row_width
= row
->pixel_width
- last
->pixel_width
;
11462 row_width
= row
->pixel_width
;
11464 height
+= row
->height
;
11465 width
= max (width
, row_width
);
11468 /* Add the frame's internal border to the width and height the X
11469 window should have. */
11470 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11471 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11473 /* Move the tooltip window where the mouse pointer is. Resize and
11475 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11478 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11479 root_x
, root_y
, width
, height
);
11480 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11483 /* Draw into the window. */
11484 w
->must_be_updated_p
= 1;
11485 update_single_window (w
, 1);
11487 /* Restore original current buffer. */
11488 set_buffer_internal_1 (old_buffer
);
11489 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11492 /* Let the tip disappear after timeout seconds. */
11493 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11494 intern ("x-hide-tip"));
11497 return unbind_to (count
, Qnil
);
11501 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11502 doc
: /* Hide the current tooltip window, if there is any.
11503 Value is t if tooltip was open, nil otherwise. */)
11507 Lisp_Object deleted
, frame
, timer
;
11508 struct gcpro gcpro1
, gcpro2
;
11510 /* Return quickly if nothing to do. */
11511 if (NILP (tip_timer
) && NILP (tip_frame
))
11516 GCPRO2 (frame
, timer
);
11517 tip_frame
= tip_timer
= deleted
= Qnil
;
11519 count
= SPECPDL_INDEX ();
11520 specbind (Qinhibit_redisplay
, Qt
);
11521 specbind (Qinhibit_quit
, Qt
);
11524 call1 (Qcancel_timer
, timer
);
11526 if (FRAMEP (frame
))
11528 Fdelete_frame (frame
, Qnil
);
11532 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11533 redisplay procedure is not called when a tip frame over menu
11534 items is unmapped. Redisplay the menu manually... */
11536 struct frame
*f
= SELECTED_FRAME ();
11537 Widget w
= f
->output_data
.x
->menubar_widget
;
11538 extern void xlwmenu_redisplay
P_ ((Widget
));
11540 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11544 xlwmenu_redisplay (w
);
11548 #endif /* USE_LUCID */
11552 return unbind_to (count
, deleted
);
11557 /***********************************************************************
11558 File selection dialog
11559 ***********************************************************************/
11563 /* Callback for "OK" and "Cancel" on file selection dialog. */
11566 file_dialog_cb (widget
, client_data
, call_data
)
11568 XtPointer call_data
, client_data
;
11570 int *result
= (int *) client_data
;
11571 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11572 *result
= cb
->reason
;
11576 /* Callback for unmapping a file selection dialog. This is used to
11577 capture the case where a dialog is closed via a window manager's
11578 closer button, for example. Using a XmNdestroyCallback didn't work
11582 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11584 XtPointer call_data
, client_data
;
11586 int *result
= (int *) client_data
;
11587 *result
= XmCR_CANCEL
;
11591 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11592 doc
: /* Read file name, prompting with PROMPT in directory DIR.
11593 Use a file selection dialog.
11594 Select DEFAULT-FILENAME in the dialog's file selection box, if
11595 specified. Don't let the user enter a file name in the file
11596 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11597 (prompt
, dir
, default_filename
, mustmatch
)
11598 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11601 struct frame
*f
= SELECTED_FRAME ();
11602 Lisp_Object file
= Qnil
;
11603 Widget dialog
, text
, list
, help
;
11606 extern XtAppContext Xt_app_con
;
11607 XmString dir_xmstring
, pattern_xmstring
;
11608 int count
= SPECPDL_INDEX ();
11609 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11611 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11612 CHECK_STRING (prompt
);
11613 CHECK_STRING (dir
);
11615 /* Prevent redisplay. */
11616 specbind (Qinhibit_redisplay
, Qt
);
11620 /* Create the dialog with PROMPT as title, using DIR as initial
11621 directory and using "*" as pattern. */
11622 dir
= Fexpand_file_name (dir
, Qnil
);
11623 dir_xmstring
= XmStringCreateLocalized (SDATA (dir
));
11624 pattern_xmstring
= XmStringCreateLocalized ("*");
11626 XtSetArg (al
[ac
], XmNtitle
, SDATA (prompt
)); ++ac
;
11627 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11628 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11629 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11630 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11631 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11633 XmStringFree (dir_xmstring
);
11634 XmStringFree (pattern_xmstring
);
11636 /* Add callbacks for OK and Cancel. */
11637 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11638 (XtPointer
) &result
);
11639 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11640 (XtPointer
) &result
);
11641 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11642 (XtPointer
) &result
);
11644 /* Disable the help button since we can't display help. */
11645 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11646 XtSetSensitive (help
, False
);
11648 /* Mark OK button as default. */
11649 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11650 XmNshowAsDefault
, True
, NULL
);
11652 /* If MUSTMATCH is non-nil, disable the file entry field of the
11653 dialog, so that the user must select a file from the files list
11654 box. We can't remove it because we wouldn't have a way to get at
11655 the result file name, then. */
11656 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11657 if (!NILP (mustmatch
))
11660 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11661 XtSetSensitive (text
, False
);
11662 XtSetSensitive (label
, False
);
11665 /* Manage the dialog, so that list boxes get filled. */
11666 XtManageChild (dialog
);
11668 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11669 must include the path for this to work. */
11670 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11671 if (STRINGP (default_filename
))
11673 XmString default_xmstring
;
11677 = XmStringCreateLocalized (SDATA (default_filename
));
11679 if (!XmListItemExists (list
, default_xmstring
))
11681 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11682 XmListAddItem (list
, default_xmstring
, 0);
11686 item_pos
= XmListItemPos (list
, default_xmstring
);
11687 XmStringFree (default_xmstring
);
11689 /* Select the item and scroll it into view. */
11690 XmListSelectPos (list
, item_pos
, True
);
11691 XmListSetPos (list
, item_pos
);
11694 /* Process events until the user presses Cancel or OK. Block
11695 and unblock input here so that we get a chance of processing
11699 while (result
== 0)
11702 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11707 /* Get the result. */
11708 if (result
== XmCR_OK
)
11713 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11714 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11715 XmStringFree (text
);
11716 file
= build_string (data
);
11723 XtUnmanageChild (dialog
);
11724 XtDestroyWidget (dialog
);
11728 /* Make "Cancel" equivalent to C-g. */
11730 Fsignal (Qquit
, Qnil
);
11732 return unbind_to (count
, file
);
11735 #endif /* USE_MOTIF */
11739 /***********************************************************************
11741 ***********************************************************************/
11743 #ifdef HAVE_XKBGETKEYBOARD
11744 #include <X11/XKBlib.h>
11745 #include <X11/keysym.h>
11748 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11749 Sx_backspace_delete_keys_p
, 0, 1, 0,
11750 doc
: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11751 FRAME nil means use the selected frame.
11752 Value is t if we know that both keys are present, and are mapped to the
11753 usual X keysyms. */)
11757 #ifdef HAVE_XKBGETKEYBOARD
11759 struct frame
*f
= check_x_frame (frame
);
11760 Display
*dpy
= FRAME_X_DISPLAY (f
);
11761 Lisp_Object have_keys
;
11762 int major
, minor
, op
, event
, error
;
11766 /* Check library version in case we're dynamically linked. */
11767 major
= XkbMajorVersion
;
11768 minor
= XkbMinorVersion
;
11769 if (!XkbLibraryVersion (&major
, &minor
))
11775 /* Check that the server supports XKB. */
11776 major
= XkbMajorVersion
;
11777 minor
= XkbMinorVersion
;
11778 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11785 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11788 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11790 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11792 for (i
= kb
->min_key_code
;
11793 (i
< kb
->max_key_code
11794 && (delete_keycode
== 0 || backspace_keycode
== 0));
11797 /* The XKB symbolic key names can be seen most easily in
11798 the PS file generated by `xkbprint -label name
11800 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11801 delete_keycode
= i
;
11802 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11803 backspace_keycode
= i
;
11806 XkbFreeNames (kb
, 0, True
);
11809 XkbFreeClientMap (kb
, 0, True
);
11812 && backspace_keycode
11813 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11814 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11819 #else /* not HAVE_XKBGETKEYBOARD */
11821 #endif /* not HAVE_XKBGETKEYBOARD */
11826 /***********************************************************************
11828 ***********************************************************************/
11833 /* This is zero if not using X windows. */
11836 /* The section below is built by the lisp expression at the top of the file,
11837 just above where these variables are declared. */
11838 /*&&& init symbols here &&&*/
11839 Qauto_raise
= intern ("auto-raise");
11840 staticpro (&Qauto_raise
);
11841 Qauto_lower
= intern ("auto-lower");
11842 staticpro (&Qauto_lower
);
11843 Qbar
= intern ("bar");
11845 Qhbar
= intern ("hbar");
11846 staticpro (&Qhbar
);
11847 Qborder_color
= intern ("border-color");
11848 staticpro (&Qborder_color
);
11849 Qborder_width
= intern ("border-width");
11850 staticpro (&Qborder_width
);
11851 Qbox
= intern ("box");
11853 Qcursor_color
= intern ("cursor-color");
11854 staticpro (&Qcursor_color
);
11855 Qcursor_type
= intern ("cursor-type");
11856 staticpro (&Qcursor_type
);
11857 Qgeometry
= intern ("geometry");
11858 staticpro (&Qgeometry
);
11859 Qicon_left
= intern ("icon-left");
11860 staticpro (&Qicon_left
);
11861 Qicon_top
= intern ("icon-top");
11862 staticpro (&Qicon_top
);
11863 Qicon_type
= intern ("icon-type");
11864 staticpro (&Qicon_type
);
11865 Qicon_name
= intern ("icon-name");
11866 staticpro (&Qicon_name
);
11867 Qinternal_border_width
= intern ("internal-border-width");
11868 staticpro (&Qinternal_border_width
);
11869 Qleft
= intern ("left");
11870 staticpro (&Qleft
);
11871 Qright
= intern ("right");
11872 staticpro (&Qright
);
11873 Qmouse_color
= intern ("mouse-color");
11874 staticpro (&Qmouse_color
);
11875 Qnone
= intern ("none");
11876 staticpro (&Qnone
);
11877 Qparent_id
= intern ("parent-id");
11878 staticpro (&Qparent_id
);
11879 Qscroll_bar_width
= intern ("scroll-bar-width");
11880 staticpro (&Qscroll_bar_width
);
11881 Qsuppress_icon
= intern ("suppress-icon");
11882 staticpro (&Qsuppress_icon
);
11883 Qundefined_color
= intern ("undefined-color");
11884 staticpro (&Qundefined_color
);
11885 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11886 staticpro (&Qvertical_scroll_bars
);
11887 Qvisibility
= intern ("visibility");
11888 staticpro (&Qvisibility
);
11889 Qwindow_id
= intern ("window-id");
11890 staticpro (&Qwindow_id
);
11891 Qouter_window_id
= intern ("outer-window-id");
11892 staticpro (&Qouter_window_id
);
11893 Qx_frame_parameter
= intern ("x-frame-parameter");
11894 staticpro (&Qx_frame_parameter
);
11895 Qx_resource_name
= intern ("x-resource-name");
11896 staticpro (&Qx_resource_name
);
11897 Quser_position
= intern ("user-position");
11898 staticpro (&Quser_position
);
11899 Quser_size
= intern ("user-size");
11900 staticpro (&Quser_size
);
11901 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11902 staticpro (&Qscroll_bar_foreground
);
11903 Qscroll_bar_background
= intern ("scroll-bar-background");
11904 staticpro (&Qscroll_bar_background
);
11905 Qscreen_gamma
= intern ("screen-gamma");
11906 staticpro (&Qscreen_gamma
);
11907 Qline_spacing
= intern ("line-spacing");
11908 staticpro (&Qline_spacing
);
11909 Qcenter
= intern ("center");
11910 staticpro (&Qcenter
);
11911 Qcompound_text
= intern ("compound-text");
11912 staticpro (&Qcompound_text
);
11913 Qcancel_timer
= intern ("cancel-timer");
11914 staticpro (&Qcancel_timer
);
11915 Qwait_for_wm
= intern ("wait-for-wm");
11916 staticpro (&Qwait_for_wm
);
11917 Qfullscreen
= intern ("fullscreen");
11918 staticpro (&Qfullscreen
);
11919 Qfullwidth
= intern ("fullwidth");
11920 staticpro (&Qfullwidth
);
11921 Qfullheight
= intern ("fullheight");
11922 staticpro (&Qfullheight
);
11923 Qfullboth
= intern ("fullboth");
11924 staticpro (&Qfullboth
);
11925 /* This is the end of symbol initialization. */
11927 /* Text property `display' should be nonsticky by default. */
11928 Vtext_property_default_nonsticky
11929 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11932 Qlaplace
= intern ("laplace");
11933 staticpro (&Qlaplace
);
11934 Qemboss
= intern ("emboss");
11935 staticpro (&Qemboss
);
11936 Qedge_detection
= intern ("edge-detection");
11937 staticpro (&Qedge_detection
);
11938 Qheuristic
= intern ("heuristic");
11939 staticpro (&Qheuristic
);
11940 QCmatrix
= intern (":matrix");
11941 staticpro (&QCmatrix
);
11942 QCcolor_adjustment
= intern (":color-adjustment");
11943 staticpro (&QCcolor_adjustment
);
11944 QCmask
= intern (":mask");
11945 staticpro (&QCmask
);
11947 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11948 staticpro (&Qface_set_after_frame_default
);
11950 Fput (Qundefined_color
, Qerror_conditions
,
11951 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11952 Fput (Qundefined_color
, Qerror_message
,
11953 build_string ("Undefined color"));
11955 init_x_parm_symbols ();
11957 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11958 doc
: /* Non-nil means always draw a cross over disabled images.
11959 Disabled images are those having an `:conversion disabled' property.
11960 A cross is always drawn on black & white displays. */);
11961 cross_disabled_images
= 0;
11963 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11964 doc
: /* List of directories to search for bitmap files for X. */);
11965 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11967 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11968 doc
: /* The shape of the pointer when over text.
11969 Changing the value does not affect existing frames
11970 unless you set the mouse color. */);
11971 Vx_pointer_shape
= Qnil
;
11973 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11974 doc
: /* The name Emacs uses to look up X resources.
11975 `x-get-resource' uses this as the first component of the instance name
11976 when requesting resource values.
11977 Emacs initially sets `x-resource-name' to the name under which Emacs
11978 was invoked, or to the value specified with the `-name' or `-rn'
11979 switches, if present.
11981 It may be useful to bind this variable locally around a call
11982 to `x-get-resource'. See also the variable `x-resource-class'. */);
11983 Vx_resource_name
= Qnil
;
11985 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11986 doc
: /* The class Emacs uses to look up X resources.
11987 `x-get-resource' uses this as the first component of the instance class
11988 when requesting resource values.
11990 Emacs initially sets `x-resource-class' to "Emacs".
11992 Setting this variable permanently is not a reasonable thing to do,
11993 but binding this variable locally around a call to `x-get-resource'
11994 is a reasonable practice. See also the variable `x-resource-name'. */);
11995 Vx_resource_class
= build_string (EMACS_CLASS
);
11997 #if 0 /* This doesn't really do anything. */
11998 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11999 doc
: /* The shape of the pointer when not over text.
12000 This variable takes effect when you create a new frame
12001 or when you set the mouse color. */);
12003 Vx_nontext_pointer_shape
= Qnil
;
12005 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
12006 doc
: /* The shape of the pointer when Emacs is busy.
12007 This variable takes effect when you create a new frame
12008 or when you set the mouse color. */);
12009 Vx_hourglass_pointer_shape
= Qnil
;
12011 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
12012 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
12013 display_hourglass_p
= 1;
12015 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
12016 doc
: /* *Seconds to wait before displaying an hourglass pointer.
12017 Value must be an integer or float. */);
12018 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
12020 #if 0 /* This doesn't really do anything. */
12021 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
12022 doc
: /* The shape of the pointer when over the mode line.
12023 This variable takes effect when you create a new frame
12024 or when you set the mouse color. */);
12026 Vx_mode_pointer_shape
= Qnil
;
12028 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
12029 &Vx_sensitive_text_pointer_shape
,
12030 doc
: /* The shape of the pointer when over mouse-sensitive text.
12031 This variable takes effect when you create a new frame
12032 or when you set the mouse color. */);
12033 Vx_sensitive_text_pointer_shape
= Qnil
;
12035 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
12036 &Vx_window_horizontal_drag_shape
,
12037 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
12038 This variable takes effect when you create a new frame
12039 or when you set the mouse color. */);
12040 Vx_window_horizontal_drag_shape
= Qnil
;
12042 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
12043 doc
: /* A string indicating the foreground color of the cursor box. */);
12044 Vx_cursor_fore_pixel
= Qnil
;
12046 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
12047 doc
: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
12048 Text larger than this is clipped. */);
12049 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
12051 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
12052 doc
: /* Non-nil if no X window manager is in use.
12053 Emacs doesn't try to figure this out; this is always nil
12054 unless you set it to something else. */);
12055 /* We don't have any way to find this out, so set it to nil
12056 and maybe the user would like to set it to t. */
12057 Vx_no_window_manager
= Qnil
;
12059 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
12060 &Vx_pixel_size_width_font_regexp
,
12061 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
12063 Since Emacs gets width of a font matching with this regexp from
12064 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12065 such a font. This is especially effective for such large fonts as
12066 Chinese, Japanese, and Korean. */);
12067 Vx_pixel_size_width_font_regexp
= Qnil
;
12069 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
12070 doc
: /* Time after which cached images are removed from the cache.
12071 When an image has not been displayed this many seconds, remove it
12072 from the image cache. Value must be an integer or nil with nil
12073 meaning don't clear the cache. */);
12074 Vimage_cache_eviction_delay
= make_number (30 * 60);
12076 #ifdef USE_X_TOOLKIT
12077 Fprovide (intern ("x-toolkit"), Qnil
);
12079 Fprovide (intern ("motif"), Qnil
);
12081 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
12082 doc
: /* Version info for LessTif/Motif. */);
12083 Vmotif_version_string
= build_string (XmVERSION_STRING
);
12084 #endif /* USE_MOTIF */
12085 #endif /* USE_X_TOOLKIT */
12087 defsubr (&Sx_get_resource
);
12089 /* X window properties. */
12090 defsubr (&Sx_change_window_property
);
12091 defsubr (&Sx_delete_window_property
);
12092 defsubr (&Sx_window_property
);
12094 defsubr (&Sxw_display_color_p
);
12095 defsubr (&Sx_display_grayscale_p
);
12096 defsubr (&Sxw_color_defined_p
);
12097 defsubr (&Sxw_color_values
);
12098 defsubr (&Sx_server_max_request_size
);
12099 defsubr (&Sx_server_vendor
);
12100 defsubr (&Sx_server_version
);
12101 defsubr (&Sx_display_pixel_width
);
12102 defsubr (&Sx_display_pixel_height
);
12103 defsubr (&Sx_display_mm_width
);
12104 defsubr (&Sx_display_mm_height
);
12105 defsubr (&Sx_display_screens
);
12106 defsubr (&Sx_display_planes
);
12107 defsubr (&Sx_display_color_cells
);
12108 defsubr (&Sx_display_visual_class
);
12109 defsubr (&Sx_display_backing_store
);
12110 defsubr (&Sx_display_save_under
);
12111 defsubr (&Sx_parse_geometry
);
12112 defsubr (&Sx_create_frame
);
12113 defsubr (&Sx_open_connection
);
12114 defsubr (&Sx_close_connection
);
12115 defsubr (&Sx_display_list
);
12116 defsubr (&Sx_synchronize
);
12117 defsubr (&Sx_focus_frame
);
12118 defsubr (&Sx_backspace_delete_keys_p
);
12120 /* Setting callback functions for fontset handler. */
12121 get_font_info_func
= x_get_font_info
;
12123 #if 0 /* This function pointer doesn't seem to be used anywhere.
12124 And the pointer assigned has the wrong type, anyway. */
12125 list_fonts_func
= x_list_fonts
;
12128 load_font_func
= x_load_font
;
12129 find_ccl_program_func
= x_find_ccl_program
;
12130 query_font_func
= x_query_font
;
12131 set_frame_fontset_func
= x_set_font
;
12132 check_window_system_func
= check_x
;
12135 Qxbm
= intern ("xbm");
12137 QCconversion
= intern (":conversion");
12138 staticpro (&QCconversion
);
12139 QCheuristic_mask
= intern (":heuristic-mask");
12140 staticpro (&QCheuristic_mask
);
12141 QCcolor_symbols
= intern (":color-symbols");
12142 staticpro (&QCcolor_symbols
);
12143 QCascent
= intern (":ascent");
12144 staticpro (&QCascent
);
12145 QCmargin
= intern (":margin");
12146 staticpro (&QCmargin
);
12147 QCrelief
= intern (":relief");
12148 staticpro (&QCrelief
);
12149 Qpostscript
= intern ("postscript");
12150 staticpro (&Qpostscript
);
12151 QCloader
= intern (":loader");
12152 staticpro (&QCloader
);
12153 QCbounding_box
= intern (":bounding-box");
12154 staticpro (&QCbounding_box
);
12155 QCpt_width
= intern (":pt-width");
12156 staticpro (&QCpt_width
);
12157 QCpt_height
= intern (":pt-height");
12158 staticpro (&QCpt_height
);
12159 QCindex
= intern (":index");
12160 staticpro (&QCindex
);
12161 Qpbm
= intern ("pbm");
12165 Qxpm
= intern ("xpm");
12170 Qjpeg
= intern ("jpeg");
12171 staticpro (&Qjpeg
);
12175 Qtiff
= intern ("tiff");
12176 staticpro (&Qtiff
);
12180 Qgif
= intern ("gif");
12185 Qpng
= intern ("png");
12189 defsubr (&Sclear_image_cache
);
12190 defsubr (&Simage_size
);
12191 defsubr (&Simage_mask_p
);
12193 hourglass_atimer
= NULL
;
12194 hourglass_shown_p
= 0;
12196 defsubr (&Sx_show_tip
);
12197 defsubr (&Sx_hide_tip
);
12199 staticpro (&tip_timer
);
12201 staticpro (&tip_frame
);
12203 last_show_tip_args
= Qnil
;
12204 staticpro (&last_show_tip_args
);
12207 defsubr (&Sx_file_dialog
);
12215 image_types
= NULL
;
12216 Vimage_types
= Qnil
;
12218 define_image_type (&xbm_type
);
12219 define_image_type (&gs_type
);
12220 define_image_type (&pbm_type
);
12223 define_image_type (&xpm_type
);
12227 define_image_type (&jpeg_type
);
12231 define_image_type (&tiff_type
);
12235 define_image_type (&gif_type
);
12239 define_image_type (&png_type
);
12243 #endif /* HAVE_X_WINDOWS */