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
);
306 CHECK_LIVE_FRAME (frame
);
309 error ("Non-X frame used");
310 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
317 /* Return the Emacs frame-object corresponding to an X window.
318 It could be the frame's main window or an icon window. */
320 /* This function can be called during GC, so use GC_xxx type test macros. */
323 x_window_to_frame (dpyinfo
, wdesc
)
324 struct x_display_info
*dpyinfo
;
327 Lisp_Object tail
, frame
;
330 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
333 if (!GC_FRAMEP (frame
))
336 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
338 if (f
->output_data
.x
->hourglass_window
== wdesc
)
341 if ((f
->output_data
.x
->edit_widget
342 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
343 /* A tooltip frame? */
344 || (!f
->output_data
.x
->edit_widget
345 && FRAME_X_WINDOW (f
) == wdesc
)
346 || f
->output_data
.x
->icon_desc
== wdesc
)
348 #else /* not USE_X_TOOLKIT */
349 if (FRAME_X_WINDOW (f
) == wdesc
350 || f
->output_data
.x
->icon_desc
== wdesc
)
352 #endif /* not USE_X_TOOLKIT */
358 /* Like x_window_to_frame but also compares the window with the widget's
362 x_any_window_to_frame (dpyinfo
, wdesc
)
363 struct x_display_info
*dpyinfo
;
366 Lisp_Object tail
, frame
;
367 struct frame
*f
, *found
;
371 for (tail
= Vframe_list
; GC_CONSP (tail
) && !found
; tail
= XCDR (tail
))
374 if (!GC_FRAMEP (frame
))
378 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
380 /* This frame matches if the window is any of its widgets. */
381 x
= f
->output_data
.x
;
382 if (x
->hourglass_window
== wdesc
)
386 if (wdesc
== XtWindow (x
->widget
)
387 || wdesc
== XtWindow (x
->column_widget
)
388 || wdesc
== XtWindow (x
->edit_widget
))
390 /* Match if the window is this frame's menubar. */
391 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
394 else if (FRAME_X_WINDOW (f
) == wdesc
)
395 /* A tooltip frame. */
403 /* Likewise, but exclude the menu bar widget. */
406 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
407 struct x_display_info
*dpyinfo
;
410 Lisp_Object tail
, frame
;
414 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
417 if (!GC_FRAMEP (frame
))
420 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
422 x
= f
->output_data
.x
;
423 /* This frame matches if the window is any of its widgets. */
424 if (x
->hourglass_window
== wdesc
)
428 if (wdesc
== XtWindow (x
->widget
)
429 || wdesc
== XtWindow (x
->column_widget
)
430 || wdesc
== XtWindow (x
->edit_widget
))
433 else if (FRAME_X_WINDOW (f
) == wdesc
)
434 /* A tooltip frame. */
440 /* Likewise, but consider only the menu bar widget. */
443 x_menubar_window_to_frame (dpyinfo
, wdesc
)
444 struct x_display_info
*dpyinfo
;
447 Lisp_Object tail
, frame
;
451 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
454 if (!GC_FRAMEP (frame
))
457 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
459 x
= f
->output_data
.x
;
460 /* Match if the window is this frame's menubar. */
461 if (x
->menubar_widget
462 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
468 /* Return the frame whose principal (outermost) window is WDESC.
469 If WDESC is some other (smaller) window, we return 0. */
472 x_top_window_to_frame (dpyinfo
, wdesc
)
473 struct x_display_info
*dpyinfo
;
476 Lisp_Object tail
, frame
;
480 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
483 if (!GC_FRAMEP (frame
))
486 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
488 x
= f
->output_data
.x
;
492 /* This frame matches if the window is its topmost widget. */
493 if (wdesc
== XtWindow (x
->widget
))
495 #if 0 /* I don't know why it did this,
496 but it seems logically wrong,
497 and it causes trouble for MapNotify events. */
498 /* Match if the window is this frame's menubar. */
499 if (x
->menubar_widget
500 && wdesc
== XtWindow (x
->menubar_widget
))
504 else if (FRAME_X_WINDOW (f
) == wdesc
)
510 #endif /* USE_X_TOOLKIT */
514 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
515 id, which is just an int that this section returns. Bitmaps are
516 reference counted so they can be shared among frames.
518 Bitmap indices are guaranteed to be > 0, so a negative number can
519 be used to indicate no bitmap.
521 If you use x_create_bitmap_from_data, then you must keep track of
522 the bitmaps yourself. That is, creating a bitmap from the same
523 data more than once will not be caught. */
526 /* Functions to access the contents of a bitmap, given an id. */
529 x_bitmap_height (f
, id
)
533 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
537 x_bitmap_width (f
, id
)
541 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
545 x_bitmap_pixmap (f
, id
)
549 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
553 /* Allocate a new bitmap record. Returns index of new record. */
556 x_allocate_bitmap_record (f
)
559 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
562 if (dpyinfo
->bitmaps
== NULL
)
564 dpyinfo
->bitmaps_size
= 10;
566 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
567 dpyinfo
->bitmaps_last
= 1;
571 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
572 return ++dpyinfo
->bitmaps_last
;
574 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
575 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
578 dpyinfo
->bitmaps_size
*= 2;
580 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
581 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
582 return ++dpyinfo
->bitmaps_last
;
585 /* Add one reference to the reference count of the bitmap with id ID. */
588 x_reference_bitmap (f
, id
)
592 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
595 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
598 x_create_bitmap_from_data (f
, bits
, width
, height
)
601 unsigned int width
, height
;
603 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
607 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
608 bits
, width
, height
);
613 id
= x_allocate_bitmap_record (f
);
614 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
615 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
616 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
617 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
618 dpyinfo
->bitmaps
[id
- 1].height
= height
;
619 dpyinfo
->bitmaps
[id
- 1].width
= width
;
624 /* Create bitmap from file FILE for frame F. */
627 x_create_bitmap_from_file (f
, file
)
631 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
632 unsigned int width
, height
;
634 int xhot
, yhot
, result
, id
;
639 /* Look for an existing bitmap with the same name. */
640 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
642 if (dpyinfo
->bitmaps
[id
].refcount
643 && dpyinfo
->bitmaps
[id
].file
644 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
646 ++dpyinfo
->bitmaps
[id
].refcount
;
651 /* Search bitmap-file-path for the file, if appropriate. */
652 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, 0);
657 filename
= (char *) XSTRING (found
)->data
;
659 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
660 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
661 if (result
!= BitmapSuccess
)
664 id
= x_allocate_bitmap_record (f
);
665 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
666 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
667 dpyinfo
->bitmaps
[id
- 1].file
668 = (char *) xmalloc (STRING_BYTES (XSTRING (file
)) + 1);
669 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
670 dpyinfo
->bitmaps
[id
- 1].height
= height
;
671 dpyinfo
->bitmaps
[id
- 1].width
= width
;
672 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
677 /* Remove reference to bitmap with id number ID. */
680 x_destroy_bitmap (f
, id
)
684 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
688 --dpyinfo
->bitmaps
[id
- 1].refcount
;
689 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
692 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
693 if (dpyinfo
->bitmaps
[id
- 1].file
)
695 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
696 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
703 /* Free all the bitmaps for the display specified by DPYINFO. */
706 x_destroy_all_bitmaps (dpyinfo
)
707 struct x_display_info
*dpyinfo
;
710 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
711 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
713 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
714 if (dpyinfo
->bitmaps
[i
].file
)
715 xfree (dpyinfo
->bitmaps
[i
].file
);
717 dpyinfo
->bitmaps_last
= 0;
720 /* Connect the frame-parameter names for X frames
721 to the ways of passing the parameter values to the window system.
723 The name of a parameter, as a Lisp symbol,
724 has an `x-frame-parameter' property which is an integer in Lisp
725 that is an index in this table. */
727 struct x_frame_parm_table
730 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
733 static Lisp_Object unwind_create_frame
P_ ((Lisp_Object
));
734 static Lisp_Object unwind_create_tip_frame
P_ ((Lisp_Object
));
735 static void x_change_window_heights
P_ ((Lisp_Object
, int));
736 static void x_disable_image
P_ ((struct frame
*, struct image
*));
737 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
738 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
739 static void x_set_wait_for_wm
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
740 static void x_set_fullscreen
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
741 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
742 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
743 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
744 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
745 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
746 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
747 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
748 static void x_set_fringe_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
749 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
750 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
751 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
753 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
754 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
755 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
756 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
758 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
759 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
760 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
761 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
762 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
763 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
764 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
766 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
768 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
773 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
774 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
776 static void init_color_table
P_ ((void));
777 static void free_color_table
P_ ((void));
778 static unsigned long *colors_in_color_table
P_ ((int *n
));
779 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
780 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
784 static struct x_frame_parm_table x_frame_parms
[] =
786 {"auto-raise", x_set_autoraise
},
787 {"auto-lower", x_set_autolower
},
788 {"background-color", x_set_background_color
},
789 {"border-color", x_set_border_color
},
790 {"border-width", x_set_border_width
},
791 {"cursor-color", x_set_cursor_color
},
792 {"cursor-type", x_set_cursor_type
},
793 {"font", x_set_font
},
794 {"foreground-color", x_set_foreground_color
},
795 {"icon-name", x_set_icon_name
},
796 {"icon-type", x_set_icon_type
},
797 {"internal-border-width", x_set_internal_border_width
},
798 {"menu-bar-lines", x_set_menu_bar_lines
},
799 {"mouse-color", x_set_mouse_color
},
800 {"name", x_explicitly_set_name
},
801 {"scroll-bar-width", x_set_scroll_bar_width
},
802 {"title", x_set_title
},
803 {"unsplittable", x_set_unsplittable
},
804 {"vertical-scroll-bars", x_set_vertical_scroll_bars
},
805 {"visibility", x_set_visibility
},
806 {"tool-bar-lines", x_set_tool_bar_lines
},
807 {"scroll-bar-foreground", x_set_scroll_bar_foreground
},
808 {"scroll-bar-background", x_set_scroll_bar_background
},
809 {"screen-gamma", x_set_screen_gamma
},
810 {"line-spacing", x_set_line_spacing
},
811 {"left-fringe", x_set_fringe_width
},
812 {"right-fringe", x_set_fringe_width
},
813 {"wait-for-wm", x_set_wait_for_wm
},
814 {"fullscreen", x_set_fullscreen
},
818 /* Attach the `x-frame-parameter' properties to
819 the Lisp symbol names of parameters relevant to X. */
822 init_x_parm_symbols ()
826 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
827 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
832 /* Really try to move where we want to be in case of fullscreen. Some WMs
833 moves the window where we tell them. Some (mwm, twm) moves the outer
834 window manager window there instead.
835 Try to compensate for those WM here. */
837 x_fullscreen_move (f
, new_top
, new_left
)
842 if (new_top
!= f
->output_data
.x
->top_pos
843 || new_left
!= f
->output_data
.x
->left_pos
)
845 int move_x
= new_left
+ f
->output_data
.x
->x_pixels_outer_diff
;
846 int move_y
= new_top
+ f
->output_data
.x
->y_pixels_outer_diff
;
848 f
->output_data
.x
->want_fullscreen
|= FULLSCREEN_MOVE_WAIT
;
849 x_set_offset (f
, move_x
, move_y
, 1);
853 /* Change the parameters of frame F as specified by ALIST.
854 If a parameter is not specially recognized, do nothing special;
855 otherwise call the `x_set_...' function for that parameter.
856 Except for certain geometry properties, always call store_frame_param
857 to store the new value in the parameter alist. */
860 x_set_frame_parameters (f
, alist
)
866 /* If both of these parameters are present, it's more efficient to
867 set them both at once. So we wait until we've looked at the
868 entire list before we set them. */
872 Lisp_Object left
, top
;
874 /* Same with these. */
875 Lisp_Object icon_left
, icon_top
;
877 /* Record in these vectors all the parms specified. */
881 int left_no_change
= 0, top_no_change
= 0;
882 int icon_left_no_change
= 0, icon_top_no_change
= 0;
883 int fullscreen_is_being_set
= 0;
885 struct gcpro gcpro1
, gcpro2
;
888 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
891 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
892 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
894 /* Extract parm names and values into those vectors. */
897 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
902 parms
[i
] = Fcar (elt
);
903 values
[i
] = Fcdr (elt
);
906 /* TAIL and ALIST are not used again below here. */
909 GCPRO2 (*parms
, *values
);
913 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
914 because their values appear in VALUES and strings are not valid. */
915 top
= left
= Qunbound
;
916 icon_left
= icon_top
= Qunbound
;
918 /* Provide default values for HEIGHT and WIDTH. */
919 if (FRAME_NEW_WIDTH (f
))
920 width
= FRAME_NEW_WIDTH (f
);
922 width
= FRAME_WIDTH (f
);
924 if (FRAME_NEW_HEIGHT (f
))
925 height
= FRAME_NEW_HEIGHT (f
);
927 height
= FRAME_HEIGHT (f
);
929 /* Process foreground_color and background_color before anything else.
930 They are independent of other properties, but other properties (e.g.,
931 cursor_color) are dependent upon them. */
932 /* Process default font as well, since fringe widths depends on it. */
933 /* Also, process fullscreen, width and height depend upon that */
934 for (p
= 0; p
< i
; p
++)
936 Lisp_Object prop
, val
;
940 if (EQ (prop
, Qforeground_color
)
941 || EQ (prop
, Qbackground_color
)
943 || EQ (prop
, Qfullscreen
))
945 register Lisp_Object param_index
, old_value
;
947 old_value
= get_frame_param (f
, prop
);
948 fullscreen_is_being_set
|= EQ (prop
, Qfullscreen
);
950 if (NILP (Fequal (val
, old_value
)))
952 store_frame_param (f
, prop
, val
);
954 param_index
= Fget (prop
, Qx_frame_parameter
);
955 if (NATNUMP (param_index
)
956 && (XFASTINT (param_index
)
957 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
958 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
963 /* Now process them in reverse of specified order. */
964 for (i
--; i
>= 0; i
--)
966 Lisp_Object prop
, val
;
971 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
972 width
= XFASTINT (val
);
973 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
974 height
= XFASTINT (val
);
975 else if (EQ (prop
, Qtop
))
977 else if (EQ (prop
, Qleft
))
979 else if (EQ (prop
, Qicon_top
))
981 else if (EQ (prop
, Qicon_left
))
983 else if (EQ (prop
, Qforeground_color
)
984 || EQ (prop
, Qbackground_color
)
986 || EQ (prop
, Qfullscreen
))
987 /* Processed above. */
991 register Lisp_Object param_index
, old_value
;
993 old_value
= get_frame_param (f
, prop
);
995 store_frame_param (f
, prop
, val
);
997 param_index
= Fget (prop
, Qx_frame_parameter
);
998 if (NATNUMP (param_index
)
999 && (XFASTINT (param_index
)
1000 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
1001 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
1005 /* Don't die if just one of these was set. */
1006 if (EQ (left
, Qunbound
))
1009 if (f
->output_data
.x
->left_pos
< 0)
1010 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
1012 XSETINT (left
, f
->output_data
.x
->left_pos
);
1014 if (EQ (top
, Qunbound
))
1017 if (f
->output_data
.x
->top_pos
< 0)
1018 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
1020 XSETINT (top
, f
->output_data
.x
->top_pos
);
1023 /* If one of the icon positions was not set, preserve or default it. */
1024 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
1026 icon_left_no_change
= 1;
1027 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
1028 if (NILP (icon_left
))
1029 XSETINT (icon_left
, 0);
1031 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
1033 icon_top_no_change
= 1;
1034 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
1035 if (NILP (icon_top
))
1036 XSETINT (icon_top
, 0);
1039 if (FRAME_VISIBLE_P (f
) && fullscreen_is_being_set
)
1041 /* If the frame is visible already and the fullscreen parameter is
1042 being set, it is too late to set WM manager hints to specify
1044 Here we first get the width, height and position that applies to
1045 fullscreen. We then move the frame to the appropriate
1046 position. Resize of the frame is taken care of in the code after
1047 this if-statement. */
1048 int new_left
, new_top
;
1050 x_fullscreen_adjust (f
, &width
, &height
, &new_top
, &new_left
);
1051 x_fullscreen_move (f
, new_top
, new_left
);
1054 /* Don't set these parameters unless they've been explicitly
1055 specified. The window might be mapped or resized while we're in
1056 this function, and we don't want to override that unless the lisp
1057 code has asked for it.
1059 Don't set these parameters unless they actually differ from the
1060 window's current parameters; the window may not actually exist
1065 check_frame_size (f
, &height
, &width
);
1067 XSETFRAME (frame
, f
);
1069 if (width
!= FRAME_WIDTH (f
)
1070 || height
!= FRAME_HEIGHT (f
)
1071 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
1072 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1074 if ((!NILP (left
) || !NILP (top
))
1075 && ! (left_no_change
&& top_no_change
)
1076 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1077 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1082 /* Record the signs. */
1083 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1084 if (EQ (left
, Qminus
))
1085 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1086 else if (INTEGERP (left
))
1088 leftpos
= XINT (left
);
1090 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1092 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1093 && CONSP (XCDR (left
))
1094 && INTEGERP (XCAR (XCDR (left
))))
1096 leftpos
= - XINT (XCAR (XCDR (left
)));
1097 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1099 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1100 && CONSP (XCDR (left
))
1101 && INTEGERP (XCAR (XCDR (left
))))
1103 leftpos
= XINT (XCAR (XCDR (left
)));
1106 if (EQ (top
, Qminus
))
1107 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1108 else if (INTEGERP (top
))
1110 toppos
= XINT (top
);
1112 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1114 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1115 && CONSP (XCDR (top
))
1116 && INTEGERP (XCAR (XCDR (top
))))
1118 toppos
= - XINT (XCAR (XCDR (top
)));
1119 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1121 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1122 && CONSP (XCDR (top
))
1123 && INTEGERP (XCAR (XCDR (top
))))
1125 toppos
= XINT (XCAR (XCDR (top
)));
1129 /* Store the numeric value of the position. */
1130 f
->output_data
.x
->top_pos
= toppos
;
1131 f
->output_data
.x
->left_pos
= leftpos
;
1133 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1135 /* Actually set that position, and convert to absolute. */
1136 x_set_offset (f
, leftpos
, toppos
, -1);
1139 if ((!NILP (icon_left
) || !NILP (icon_top
))
1140 && ! (icon_left_no_change
&& icon_top_no_change
))
1141 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1147 /* Store the screen positions of frame F into XPTR and YPTR.
1148 These are the positions of the containing window manager window,
1149 not Emacs's own window. */
1152 x_real_positions (f
, xptr
, yptr
)
1156 int win_x
, win_y
, outer_x
, outer_y
;
1157 int real_x
= 0, real_y
= 0;
1159 Window win
= f
->output_data
.x
->parent_desc
;
1165 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1167 if (win
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1168 win
= FRAME_OUTER_WINDOW (f
);
1170 /* This loop traverses up the containment tree until we hit the root
1171 window. Window managers may intersect many windows between our window
1172 and the root window. The window we find just before the root window
1173 should be the outer WM window. */
1176 Window wm_window
, rootw
;
1177 Window
*tmp_children
;
1178 unsigned int tmp_nchildren
;
1181 success
= XQueryTree (FRAME_X_DISPLAY (f
), win
, &rootw
,
1182 &wm_window
, &tmp_children
, &tmp_nchildren
);
1184 had_errors
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1186 /* Don't free tmp_children if XQueryTree failed. */
1190 XFree ((char *) tmp_children
);
1192 if (wm_window
== rootw
|| had_errors
)
1201 Window child
, rootw
;
1203 /* Get the real coordinates for the WM window upper left corner */
1204 XGetGeometry (FRAME_X_DISPLAY (f
), win
,
1205 &rootw
, &real_x
, &real_y
, &ign
, &ign
, &ign
, &ign
);
1207 /* Translate real coordinates to coordinates relative to our
1208 window. For our window, the upper left corner is 0, 0.
1209 Since the upper left corner of the WM window is outside
1210 our window, win_x and win_y will be negative:
1212 ------------------ ---> x
1214 | ----------------- v y
1217 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1219 /* From-window, to-window. */
1220 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1223 /* From-position, to-position. */
1224 real_x
, real_y
, &win_x
, &win_y
,
1229 if (FRAME_X_WINDOW (f
) == FRAME_OUTER_WINDOW (f
))
1236 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1238 /* From-window, to-window. */
1239 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1240 FRAME_OUTER_WINDOW (f
),
1242 /* From-position, to-position. */
1243 real_x
, real_y
, &outer_x
, &outer_y
,
1249 had_errors
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1252 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1256 if (had_errors
) return;
1258 f
->output_data
.x
->x_pixels_diff
= -win_x
;
1259 f
->output_data
.x
->y_pixels_diff
= -win_y
;
1260 f
->output_data
.x
->x_pixels_outer_diff
= -outer_x
;
1261 f
->output_data
.x
->y_pixels_outer_diff
= -outer_y
;
1267 /* Insert a description of internally-recorded parameters of frame X
1268 into the parameter alist *ALISTPTR that is to be given to the user.
1269 Only parameters that are specific to the X window system
1270 and whose values are not correctly recorded in the frame's
1271 param_alist need to be considered here. */
1274 x_report_frame_params (f
, alistptr
)
1276 Lisp_Object
*alistptr
;
1281 /* Represent negative positions (off the top or left screen edge)
1282 in a way that Fmodify_frame_parameters will understand correctly. */
1283 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1284 if (f
->output_data
.x
->left_pos
>= 0)
1285 store_in_alist (alistptr
, Qleft
, tem
);
1287 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1289 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1290 if (f
->output_data
.x
->top_pos
>= 0)
1291 store_in_alist (alistptr
, Qtop
, tem
);
1293 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1295 store_in_alist (alistptr
, Qborder_width
,
1296 make_number (f
->output_data
.x
->border_width
));
1297 store_in_alist (alistptr
, Qinternal_border_width
,
1298 make_number (f
->output_data
.x
->internal_border_width
));
1299 store_in_alist (alistptr
, Qleft_fringe
,
1300 make_number (f
->output_data
.x
->left_fringe_width
));
1301 store_in_alist (alistptr
, Qright_fringe
,
1302 make_number (f
->output_data
.x
->right_fringe_width
));
1303 store_in_alist (alistptr
, Qscroll_bar_width
,
1304 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
1305 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f
)
1307 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1308 store_in_alist (alistptr
, Qwindow_id
,
1309 build_string (buf
));
1310 #ifdef USE_X_TOOLKIT
1311 /* Tooltip frame may not have this widget. */
1312 if (f
->output_data
.x
->widget
)
1314 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1315 store_in_alist (alistptr
, Qouter_window_id
,
1316 build_string (buf
));
1317 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1318 FRAME_SAMPLE_VISIBILITY (f
);
1319 store_in_alist (alistptr
, Qvisibility
,
1320 (FRAME_VISIBLE_P (f
) ? Qt
1321 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1322 store_in_alist (alistptr
, Qdisplay
,
1323 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1325 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1328 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1329 store_in_alist (alistptr
, Qparent_id
, tem
);
1334 /* Gamma-correct COLOR on frame F. */
1337 gamma_correct (f
, color
)
1343 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1344 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1345 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1350 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1351 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1352 allocate the color. Value is zero if COLOR_NAME is invalid, or
1353 no color could be allocated. */
1356 x_defined_color (f
, color_name
, color
, alloc_p
)
1363 Display
*dpy
= FRAME_X_DISPLAY (f
);
1364 Colormap cmap
= FRAME_X_COLORMAP (f
);
1367 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1368 if (success_p
&& alloc_p
)
1369 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1376 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1377 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1378 Signal an error if color can't be allocated. */
1381 x_decode_color (f
, color_name
, mono_color
)
1383 Lisp_Object color_name
;
1388 CHECK_STRING (color_name
);
1390 #if 0 /* Don't do this. It's wrong when we're not using the default
1391 colormap, it makes freeing difficult, and it's probably not
1392 an important optimization. */
1393 if (strcmp (XSTRING (color_name
)->data
, "black") == 0)
1394 return BLACK_PIX_DEFAULT (f
);
1395 else if (strcmp (XSTRING (color_name
)->data
, "white") == 0)
1396 return WHITE_PIX_DEFAULT (f
);
1399 /* Return MONO_COLOR for monochrome frames. */
1400 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1403 /* x_defined_color is responsible for coping with failures
1404 by looking for a near-miss. */
1405 if (x_defined_color (f
, XSTRING (color_name
)->data
, &cdef
, 1))
1408 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1409 Fcons (color_name
, Qnil
)));
1415 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1416 the previous value of that parameter, NEW_VALUE is the new value. */
1419 x_set_line_spacing (f
, new_value
, old_value
)
1421 Lisp_Object new_value
, old_value
;
1423 if (NILP (new_value
))
1424 f
->extra_line_spacing
= 0;
1425 else if (NATNUMP (new_value
))
1426 f
->extra_line_spacing
= XFASTINT (new_value
);
1428 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1429 Fcons (new_value
, Qnil
)));
1430 if (FRAME_VISIBLE_P (f
))
1435 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1436 the previous value of that parameter, NEW_VALUE is the new value.
1437 See also the comment of wait_for_wm in struct x_output. */
1440 x_set_wait_for_wm (f
, new_value
, old_value
)
1442 Lisp_Object new_value
, old_value
;
1444 f
->output_data
.x
->wait_for_wm
= !NILP (new_value
);
1448 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
1449 the previous value of that parameter, NEW_VALUE is the new value. */
1452 x_set_fullscreen (f
, new_value
, old_value
)
1454 Lisp_Object new_value
, old_value
;
1456 if (NILP (new_value
))
1457 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_NONE
;
1458 else if (EQ (new_value
, Qfullboth
))
1459 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_BOTH
;
1460 else if (EQ (new_value
, Qfullwidth
))
1461 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_WIDTH
;
1462 else if (EQ (new_value
, Qfullheight
))
1463 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_HEIGHT
;
1467 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1468 the previous value of that parameter, NEW_VALUE is the new
1472 x_set_screen_gamma (f
, new_value
, old_value
)
1474 Lisp_Object new_value
, old_value
;
1476 if (NILP (new_value
))
1478 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1479 /* The value 0.4545 is the normal viewing gamma. */
1480 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1482 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1483 Fcons (new_value
, Qnil
)));
1485 clear_face_cache (0);
1489 /* Functions called only from `x_set_frame_param'
1490 to set individual parameters.
1492 If FRAME_X_WINDOW (f) is 0,
1493 the frame is being created and its X-window does not exist yet.
1494 In that case, just record the parameter's new value
1495 in the standard place; do not attempt to change the window. */
1498 x_set_foreground_color (f
, arg
, oldval
)
1500 Lisp_Object arg
, oldval
;
1502 struct x_output
*x
= f
->output_data
.x
;
1503 unsigned long fg
, old_fg
;
1505 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1506 old_fg
= x
->foreground_pixel
;
1507 x
->foreground_pixel
= fg
;
1509 if (FRAME_X_WINDOW (f
) != 0)
1511 Display
*dpy
= FRAME_X_DISPLAY (f
);
1514 XSetForeground (dpy
, x
->normal_gc
, fg
);
1515 XSetBackground (dpy
, x
->reverse_gc
, fg
);
1517 if (x
->cursor_pixel
== old_fg
)
1519 unload_color (f
, x
->cursor_pixel
);
1520 x
->cursor_pixel
= x_copy_color (f
, fg
);
1521 XSetBackground (dpy
, x
->cursor_gc
, x
->cursor_pixel
);
1526 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1528 if (FRAME_VISIBLE_P (f
))
1532 unload_color (f
, old_fg
);
1536 x_set_background_color (f
, arg
, oldval
)
1538 Lisp_Object arg
, oldval
;
1540 struct x_output
*x
= f
->output_data
.x
;
1543 bg
= x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1544 unload_color (f
, x
->background_pixel
);
1545 x
->background_pixel
= bg
;
1547 if (FRAME_X_WINDOW (f
) != 0)
1549 Display
*dpy
= FRAME_X_DISPLAY (f
);
1552 XSetBackground (dpy
, x
->normal_gc
, bg
);
1553 XSetForeground (dpy
, x
->reverse_gc
, bg
);
1554 XSetWindowBackground (dpy
, FRAME_X_WINDOW (f
), bg
);
1555 XSetForeground (dpy
, x
->cursor_gc
, bg
);
1557 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1558 toolkit scroll bars. */
1561 for (bar
= FRAME_SCROLL_BARS (f
);
1563 bar
= XSCROLL_BAR (bar
)->next
)
1565 Window window
= SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
));
1566 XSetWindowBackground (dpy
, window
, bg
);
1569 #endif /* USE_TOOLKIT_SCROLL_BARS */
1572 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1574 if (FRAME_VISIBLE_P (f
))
1580 x_set_mouse_color (f
, arg
, oldval
)
1582 Lisp_Object arg
, oldval
;
1584 struct x_output
*x
= f
->output_data
.x
;
1585 Display
*dpy
= FRAME_X_DISPLAY (f
);
1586 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1587 Cursor hourglass_cursor
, horizontal_drag_cursor
;
1589 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1590 unsigned long mask_color
= x
->background_pixel
;
1592 /* Don't let pointers be invisible. */
1593 if (mask_color
== pixel
)
1595 x_free_colors (f
, &pixel
, 1);
1596 pixel
= x_copy_color (f
, x
->foreground_pixel
);
1599 unload_color (f
, x
->mouse_pixel
);
1600 x
->mouse_pixel
= pixel
;
1604 /* It's not okay to crash if the user selects a screwy cursor. */
1605 count
= x_catch_errors (dpy
);
1607 if (!NILP (Vx_pointer_shape
))
1609 CHECK_NUMBER (Vx_pointer_shape
);
1610 cursor
= XCreateFontCursor (dpy
, XINT (Vx_pointer_shape
));
1613 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1614 x_check_errors (dpy
, "bad text pointer cursor: %s");
1616 if (!NILP (Vx_nontext_pointer_shape
))
1618 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1620 = XCreateFontCursor (dpy
, XINT (Vx_nontext_pointer_shape
));
1623 nontext_cursor
= XCreateFontCursor (dpy
, XC_left_ptr
);
1624 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1626 if (!NILP (Vx_hourglass_pointer_shape
))
1628 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1630 = XCreateFontCursor (dpy
, XINT (Vx_hourglass_pointer_shape
));
1633 hourglass_cursor
= XCreateFontCursor (dpy
, XC_watch
);
1634 x_check_errors (dpy
, "bad hourglass pointer cursor: %s");
1636 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1637 if (!NILP (Vx_mode_pointer_shape
))
1639 CHECK_NUMBER (Vx_mode_pointer_shape
);
1640 mode_cursor
= XCreateFontCursor (dpy
, XINT (Vx_mode_pointer_shape
));
1643 mode_cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1644 x_check_errors (dpy
, "bad modeline pointer cursor: %s");
1646 if (!NILP (Vx_sensitive_text_pointer_shape
))
1648 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1650 = XCreateFontCursor (dpy
, XINT (Vx_sensitive_text_pointer_shape
));
1653 cross_cursor
= XCreateFontCursor (dpy
, XC_hand2
);
1655 if (!NILP (Vx_window_horizontal_drag_shape
))
1657 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1658 horizontal_drag_cursor
1659 = XCreateFontCursor (dpy
, XINT (Vx_window_horizontal_drag_shape
));
1662 horizontal_drag_cursor
1663 = XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
1665 /* Check and report errors with the above calls. */
1666 x_check_errors (dpy
, "can't set cursor shape: %s");
1667 x_uncatch_errors (dpy
, count
);
1670 XColor fore_color
, back_color
;
1672 fore_color
.pixel
= x
->mouse_pixel
;
1673 x_query_color (f
, &fore_color
);
1674 back_color
.pixel
= mask_color
;
1675 x_query_color (f
, &back_color
);
1677 XRecolorCursor (dpy
, cursor
, &fore_color
, &back_color
);
1678 XRecolorCursor (dpy
, nontext_cursor
, &fore_color
, &back_color
);
1679 XRecolorCursor (dpy
, mode_cursor
, &fore_color
, &back_color
);
1680 XRecolorCursor (dpy
, cross_cursor
, &fore_color
, &back_color
);
1681 XRecolorCursor (dpy
, hourglass_cursor
, &fore_color
, &back_color
);
1682 XRecolorCursor (dpy
, horizontal_drag_cursor
, &fore_color
, &back_color
);
1685 if (FRAME_X_WINDOW (f
) != 0)
1686 XDefineCursor (dpy
, FRAME_X_WINDOW (f
), cursor
);
1688 if (cursor
!= x
->text_cursor
1689 && x
->text_cursor
!= 0)
1690 XFreeCursor (dpy
, x
->text_cursor
);
1691 x
->text_cursor
= cursor
;
1693 if (nontext_cursor
!= x
->nontext_cursor
1694 && x
->nontext_cursor
!= 0)
1695 XFreeCursor (dpy
, x
->nontext_cursor
);
1696 x
->nontext_cursor
= nontext_cursor
;
1698 if (hourglass_cursor
!= x
->hourglass_cursor
1699 && x
->hourglass_cursor
!= 0)
1700 XFreeCursor (dpy
, x
->hourglass_cursor
);
1701 x
->hourglass_cursor
= hourglass_cursor
;
1703 if (mode_cursor
!= x
->modeline_cursor
1704 && x
->modeline_cursor
!= 0)
1705 XFreeCursor (dpy
, f
->output_data
.x
->modeline_cursor
);
1706 x
->modeline_cursor
= mode_cursor
;
1708 if (cross_cursor
!= x
->cross_cursor
1709 && x
->cross_cursor
!= 0)
1710 XFreeCursor (dpy
, x
->cross_cursor
);
1711 x
->cross_cursor
= cross_cursor
;
1713 if (horizontal_drag_cursor
!= x
->horizontal_drag_cursor
1714 && x
->horizontal_drag_cursor
!= 0)
1715 XFreeCursor (dpy
, x
->horizontal_drag_cursor
);
1716 x
->horizontal_drag_cursor
= horizontal_drag_cursor
;
1721 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1725 x_set_cursor_color (f
, arg
, oldval
)
1727 Lisp_Object arg
, oldval
;
1729 unsigned long fore_pixel
, pixel
;
1730 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1731 struct x_output
*x
= f
->output_data
.x
;
1733 if (!NILP (Vx_cursor_fore_pixel
))
1735 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1736 WHITE_PIX_DEFAULT (f
));
1737 fore_pixel_allocated_p
= 1;
1740 fore_pixel
= x
->background_pixel
;
1742 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1743 pixel_allocated_p
= 1;
1745 /* Make sure that the cursor color differs from the background color. */
1746 if (pixel
== x
->background_pixel
)
1748 if (pixel_allocated_p
)
1750 x_free_colors (f
, &pixel
, 1);
1751 pixel_allocated_p
= 0;
1754 pixel
= x
->mouse_pixel
;
1755 if (pixel
== fore_pixel
)
1757 if (fore_pixel_allocated_p
)
1759 x_free_colors (f
, &fore_pixel
, 1);
1760 fore_pixel_allocated_p
= 0;
1762 fore_pixel
= x
->background_pixel
;
1766 unload_color (f
, x
->cursor_foreground_pixel
);
1767 if (!fore_pixel_allocated_p
)
1768 fore_pixel
= x_copy_color (f
, fore_pixel
);
1769 x
->cursor_foreground_pixel
= fore_pixel
;
1771 unload_color (f
, x
->cursor_pixel
);
1772 if (!pixel_allocated_p
)
1773 pixel
= x_copy_color (f
, pixel
);
1774 x
->cursor_pixel
= pixel
;
1776 if (FRAME_X_WINDOW (f
) != 0)
1779 XSetBackground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, x
->cursor_pixel
);
1780 XSetForeground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, fore_pixel
);
1783 if (FRAME_VISIBLE_P (f
))
1785 x_update_cursor (f
, 0);
1786 x_update_cursor (f
, 1);
1790 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1793 /* Set the border-color of frame F to value described by ARG.
1794 ARG can be a string naming a color.
1795 The border-color is used for the border that is drawn by the X server.
1796 Note that this does not fully take effect if done before
1797 F has an x-window; it must be redone when the window is created.
1799 Note: this is done in two routines because of the way X10 works.
1801 Note: under X11, this is normally the province of the window manager,
1802 and so emacs' border colors may be overridden. */
1805 x_set_border_color (f
, arg
, oldval
)
1807 Lisp_Object arg
, oldval
;
1812 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1813 x_set_border_pixel (f
, pix
);
1814 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1817 /* Set the border-color of frame F to pixel value PIX.
1818 Note that this does not fully take effect if done before
1819 F has an x-window. */
1822 x_set_border_pixel (f
, pix
)
1826 unload_color (f
, f
->output_data
.x
->border_pixel
);
1827 f
->output_data
.x
->border_pixel
= pix
;
1829 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1832 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1833 (unsigned long)pix
);
1836 if (FRAME_VISIBLE_P (f
))
1842 /* Value is the internal representation of the specified cursor type
1843 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1844 of the bar cursor. */
1846 enum text_cursor_kinds
1847 x_specified_cursor_type (arg
, width
)
1851 enum text_cursor_kinds type
;
1858 else if (CONSP (arg
)
1859 && EQ (XCAR (arg
), Qbar
)
1860 && INTEGERP (XCDR (arg
))
1861 && XINT (XCDR (arg
)) >= 0)
1864 *width
= XINT (XCDR (arg
));
1866 else if (EQ (arg
, Qhbar
))
1871 else if (CONSP (arg
)
1872 && EQ (XCAR (arg
), Qhbar
)
1873 && INTEGERP (XCDR (arg
))
1874 && XINT (XCDR (arg
)) >= 0)
1877 *width
= XINT (XCDR (arg
));
1879 else if (NILP (arg
))
1882 /* Treat anything unknown as "box cursor".
1883 It was bad to signal an error; people have trouble fixing
1884 .Xdefaults with Emacs, when it has something bad in it. */
1885 type
= FILLED_BOX_CURSOR
;
1891 x_set_cursor_type (f
, arg
, oldval
)
1893 Lisp_Object arg
, oldval
;
1897 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1898 f
->output_data
.x
->cursor_width
= width
;
1900 /* Make sure the cursor gets redrawn. */
1901 cursor_type_changed
= 1;
1905 x_set_icon_type (f
, arg
, oldval
)
1907 Lisp_Object arg
, oldval
;
1913 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1916 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1921 result
= x_text_icon (f
,
1922 (char *) XSTRING ((!NILP (f
->icon_name
)
1926 result
= x_bitmap_icon (f
, arg
);
1931 error ("No icon window available");
1934 XFlush (FRAME_X_DISPLAY (f
));
1938 /* Return non-nil if frame F wants a bitmap icon. */
1946 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1954 x_set_icon_name (f
, arg
, oldval
)
1956 Lisp_Object arg
, oldval
;
1962 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1965 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1970 if (f
->output_data
.x
->icon_bitmap
!= 0)
1975 result
= x_text_icon (f
,
1976 (char *) XSTRING ((!NILP (f
->icon_name
)
1985 error ("No icon window available");
1988 XFlush (FRAME_X_DISPLAY (f
));
1993 x_set_font (f
, arg
, oldval
)
1995 Lisp_Object arg
, oldval
;
1998 Lisp_Object fontset_name
;
2000 int old_fontset
= f
->output_data
.x
->fontset
;
2004 fontset_name
= Fquery_fontset (arg
, Qnil
);
2007 result
= (STRINGP (fontset_name
)
2008 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
2009 : x_new_font (f
, XSTRING (arg
)->data
));
2012 if (EQ (result
, Qnil
))
2013 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
2014 else if (EQ (result
, Qt
))
2015 error ("The characters of the given font have varying widths");
2016 else if (STRINGP (result
))
2018 if (STRINGP (fontset_name
))
2020 /* Fontset names are built from ASCII font names, so the
2021 names may be equal despite there was a change. */
2022 if (old_fontset
== f
->output_data
.x
->fontset
)
2025 else if (!NILP (Fequal (result
, oldval
)))
2028 store_frame_param (f
, Qfont
, result
);
2029 recompute_basic_faces (f
);
2034 do_pending_window_change (0);
2036 /* Don't call `face-set-after-frame-default' when faces haven't been
2037 initialized yet. This is the case when called from
2038 Fx_create_frame. In that case, the X widget or window doesn't
2039 exist either, and we can end up in x_report_frame_params with a
2040 null widget which gives a segfault. */
2041 if (FRAME_FACE_CACHE (f
))
2043 XSETFRAME (frame
, f
);
2044 call1 (Qface_set_after_frame_default
, frame
);
2049 x_set_fringe_width (f
, new_value
, old_value
)
2051 Lisp_Object new_value
, old_value
;
2053 x_compute_fringe_widths (f
, 1);
2057 x_set_border_width (f
, arg
, oldval
)
2059 Lisp_Object arg
, oldval
;
2063 if (XINT (arg
) == f
->output_data
.x
->border_width
)
2066 if (FRAME_X_WINDOW (f
) != 0)
2067 error ("Cannot change the border width of a window");
2069 f
->output_data
.x
->border_width
= XINT (arg
);
2073 x_set_internal_border_width (f
, arg
, oldval
)
2075 Lisp_Object arg
, oldval
;
2077 int old
= f
->output_data
.x
->internal_border_width
;
2080 f
->output_data
.x
->internal_border_width
= XINT (arg
);
2081 if (f
->output_data
.x
->internal_border_width
< 0)
2082 f
->output_data
.x
->internal_border_width
= 0;
2084 #ifdef USE_X_TOOLKIT
2085 if (f
->output_data
.x
->edit_widget
)
2086 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
2089 if (f
->output_data
.x
->internal_border_width
== old
)
2092 if (FRAME_X_WINDOW (f
) != 0)
2094 x_set_window_size (f
, 0, f
->width
, f
->height
);
2095 SET_FRAME_GARBAGED (f
);
2096 do_pending_window_change (0);
2099 SET_FRAME_GARBAGED (f
);
2103 x_set_visibility (f
, value
, oldval
)
2105 Lisp_Object value
, oldval
;
2108 XSETFRAME (frame
, f
);
2111 Fmake_frame_invisible (frame
, Qt
);
2112 else if (EQ (value
, Qicon
))
2113 Ficonify_frame (frame
);
2115 Fmake_frame_visible (frame
);
2119 /* Change window heights in windows rooted in WINDOW by N lines. */
2122 x_change_window_heights (window
, n
)
2126 struct window
*w
= XWINDOW (window
);
2128 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
2129 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
2131 if (INTEGERP (w
->orig_top
))
2132 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
2133 if (INTEGERP (w
->orig_height
))
2134 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
2136 /* Handle just the top child in a vertical split. */
2137 if (!NILP (w
->vchild
))
2138 x_change_window_heights (w
->vchild
, n
);
2140 /* Adjust all children in a horizontal split. */
2141 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
2143 w
= XWINDOW (window
);
2144 x_change_window_heights (window
, n
);
2149 x_set_menu_bar_lines (f
, value
, oldval
)
2151 Lisp_Object value
, oldval
;
2154 #ifndef USE_X_TOOLKIT
2155 int olines
= FRAME_MENU_BAR_LINES (f
);
2158 /* Right now, menu bars don't work properly in minibuf-only frames;
2159 most of the commands try to apply themselves to the minibuffer
2160 frame itself, and get an error because you can't switch buffers
2161 in or split the minibuffer window. */
2162 if (FRAME_MINIBUF_ONLY_P (f
))
2165 if (INTEGERP (value
))
2166 nlines
= XINT (value
);
2170 /* Make sure we redisplay all windows in this frame. */
2171 windows_or_buffers_changed
++;
2173 #ifdef USE_X_TOOLKIT
2174 FRAME_MENU_BAR_LINES (f
) = 0;
2177 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2178 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2179 /* Make sure next redisplay shows the menu bar. */
2180 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2184 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2185 free_frame_menubar (f
);
2186 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2188 f
->output_data
.x
->menubar_widget
= 0;
2190 #else /* not USE_X_TOOLKIT */
2191 FRAME_MENU_BAR_LINES (f
) = nlines
;
2192 x_change_window_heights (f
->root_window
, nlines
- olines
);
2193 #endif /* not USE_X_TOOLKIT */
2198 /* Set the number of lines used for the tool bar of frame F to VALUE.
2199 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2200 is the old number of tool bar lines. This function changes the
2201 height of all windows on frame F to match the new tool bar height.
2202 The frame's height doesn't change. */
2205 x_set_tool_bar_lines (f
, value
, oldval
)
2207 Lisp_Object value
, oldval
;
2209 int delta
, nlines
, root_height
;
2210 Lisp_Object root_window
;
2212 /* Treat tool bars like menu bars. */
2213 if (FRAME_MINIBUF_ONLY_P (f
))
2216 /* Use VALUE only if an integer >= 0. */
2217 if (INTEGERP (value
) && XINT (value
) >= 0)
2218 nlines
= XFASTINT (value
);
2222 /* Make sure we redisplay all windows in this frame. */
2223 ++windows_or_buffers_changed
;
2225 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2227 /* Don't resize the tool-bar to more than we have room for. */
2228 root_window
= FRAME_ROOT_WINDOW (f
);
2229 root_height
= XINT (XWINDOW (root_window
)->height
);
2230 if (root_height
- delta
< 1)
2232 delta
= root_height
- 1;
2233 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2236 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2237 x_change_window_heights (root_window
, delta
);
2240 /* We also have to make sure that the internal border at the top of
2241 the frame, below the menu bar or tool bar, is redrawn when the
2242 tool bar disappears. This is so because the internal border is
2243 below the tool bar if one is displayed, but is below the menu bar
2244 if there isn't a tool bar. The tool bar draws into the area
2245 below the menu bar. */
2246 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2250 clear_current_matrices (f
);
2251 updating_frame
= NULL
;
2254 /* If the tool bar gets smaller, the internal border below it
2255 has to be cleared. It was formerly part of the display
2256 of the larger tool bar, and updating windows won't clear it. */
2259 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2260 int width
= PIXEL_WIDTH (f
);
2261 int y
= nlines
* CANON_Y_UNIT (f
);
2264 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2265 0, y
, width
, height
, False
);
2268 if (WINDOWP (f
->tool_bar_window
))
2269 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2274 /* Set the foreground color for scroll bars on frame F to VALUE.
2275 VALUE should be a string, a color name. If it isn't a string or
2276 isn't a valid color name, do nothing. OLDVAL is the old value of
2277 the frame parameter. */
2280 x_set_scroll_bar_foreground (f
, value
, oldval
)
2282 Lisp_Object value
, oldval
;
2284 unsigned long pixel
;
2286 if (STRINGP (value
))
2287 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2291 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2292 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2294 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2295 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2297 /* Remove all scroll bars because they have wrong colors. */
2298 if (condemn_scroll_bars_hook
)
2299 (*condemn_scroll_bars_hook
) (f
);
2300 if (judge_scroll_bars_hook
)
2301 (*judge_scroll_bars_hook
) (f
);
2303 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2309 /* Set the background color for scroll bars on frame F to VALUE VALUE
2310 should be a string, a color name. If it isn't a string or isn't a
2311 valid color name, do nothing. OLDVAL is the old value of the frame
2315 x_set_scroll_bar_background (f
, value
, oldval
)
2317 Lisp_Object value
, oldval
;
2319 unsigned long pixel
;
2321 if (STRINGP (value
))
2322 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2326 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2327 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2329 #ifdef USE_TOOLKIT_SCROLL_BARS
2330 /* Scrollbar shadow colors. */
2331 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
2333 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
2334 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
2336 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
2338 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
2339 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
2341 #endif /* USE_TOOLKIT_SCROLL_BARS */
2343 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2344 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2346 /* Remove all scroll bars because they have wrong colors. */
2347 if (condemn_scroll_bars_hook
)
2348 (*condemn_scroll_bars_hook
) (f
);
2349 if (judge_scroll_bars_hook
)
2350 (*judge_scroll_bars_hook
) (f
);
2352 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2358 /* Encode Lisp string STRING as a text in a format appropriate for
2359 XICCC (X Inter Client Communication Conventions).
2361 If STRING contains only ASCII characters, do no conversion and
2362 return the string data of STRING. Otherwise, encode the text by
2363 CODING_SYSTEM, and return a newly allocated memory area which
2364 should be freed by `xfree' by a caller.
2366 SELECTIONP non-zero means the string is being encoded for an X
2367 selection, so it is safe to run pre-write conversions (which
2370 Store the byte length of resulting text in *TEXT_BYTES.
2372 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2373 which means that the `encoding' of the result can be `STRING'.
2374 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2375 the result should be `COMPOUND_TEXT'. */
2378 x_encode_text (string
, coding_system
, selectionp
, text_bytes
, stringp
)
2379 Lisp_Object string
, coding_system
;
2380 int *text_bytes
, *stringp
;
2383 unsigned char *str
= XSTRING (string
)->data
;
2384 int chars
= XSTRING (string
)->size
;
2385 int bytes
= STRING_BYTES (XSTRING (string
));
2389 struct coding_system coding
;
2391 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2392 if (charset_info
== 0)
2394 /* No multibyte character in OBJ. We need not encode it. */
2395 *text_bytes
= bytes
;
2400 setup_coding_system (coding_system
, &coding
);
2402 && SYMBOLP (coding
.pre_write_conversion
)
2403 && !NILP (Ffboundp (coding
.pre_write_conversion
)))
2405 string
= run_pre_post_conversion_on_str (string
, &coding
, 1);
2406 str
= XSTRING (string
)->data
;
2407 chars
= XSTRING (string
)->size
;
2408 bytes
= STRING_BYTES (XSTRING (string
));
2410 coding
.src_multibyte
= 1;
2411 coding
.dst_multibyte
= 0;
2412 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2413 if (coding
.type
== coding_type_iso2022
)
2414 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2415 /* We suppress producing escape sequences for composition. */
2416 coding
.composing
= COMPOSITION_DISABLED
;
2417 bufsize
= encoding_buffer_size (&coding
, bytes
);
2418 buf
= (unsigned char *) xmalloc (bufsize
);
2419 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2420 *text_bytes
= coding
.produced
;
2421 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2426 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2429 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2430 name; if NAME is a string, set F's name to NAME and set
2431 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2433 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2434 suggesting a new name, which lisp code should override; if
2435 F->explicit_name is set, ignore the new name; otherwise, set it. */
2438 x_set_name (f
, name
, explicit)
2443 /* Make sure that requests from lisp code override requests from
2444 Emacs redisplay code. */
2447 /* If we're switching from explicit to implicit, we had better
2448 update the mode lines and thereby update the title. */
2449 if (f
->explicit_name
&& NILP (name
))
2450 update_mode_lines
= 1;
2452 f
->explicit_name
= ! NILP (name
);
2454 else if (f
->explicit_name
)
2457 /* If NAME is nil, set the name to the x_id_name. */
2460 /* Check for no change needed in this very common case
2461 before we do any consing. */
2462 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2463 XSTRING (f
->name
)->data
))
2465 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2468 CHECK_STRING (name
);
2470 /* Don't change the name if it's already NAME. */
2471 if (! NILP (Fstring_equal (name
, f
->name
)))
2476 /* For setting the frame title, the title parameter should override
2477 the name parameter. */
2478 if (! NILP (f
->title
))
2481 if (FRAME_X_WINDOW (f
))
2486 XTextProperty text
, icon
;
2488 Lisp_Object coding_system
;
2490 coding_system
= Vlocale_coding_system
;
2491 if (NILP (coding_system
))
2492 coding_system
= Qcompound_text
;
2493 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2494 text
.encoding
= (stringp
? XA_STRING
2495 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2497 text
.nitems
= bytes
;
2499 if (NILP (f
->icon_name
))
2505 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2507 icon
.encoding
= (stringp
? XA_STRING
2508 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2510 icon
.nitems
= bytes
;
2512 #ifdef USE_X_TOOLKIT
2513 XSetWMName (FRAME_X_DISPLAY (f
),
2514 XtWindow (f
->output_data
.x
->widget
), &text
);
2515 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2517 #else /* not USE_X_TOOLKIT */
2518 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2519 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2520 #endif /* not USE_X_TOOLKIT */
2521 if (!NILP (f
->icon_name
)
2522 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2524 if (text
.value
!= XSTRING (name
)->data
)
2527 #else /* not HAVE_X11R4 */
2528 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2529 XSTRING (name
)->data
);
2530 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2531 XSTRING (name
)->data
);
2532 #endif /* not HAVE_X11R4 */
2537 /* This function should be called when the user's lisp code has
2538 specified a name for the frame; the name will override any set by the
2541 x_explicitly_set_name (f
, arg
, oldval
)
2543 Lisp_Object arg
, oldval
;
2545 x_set_name (f
, arg
, 1);
2548 /* This function should be called by Emacs redisplay code to set the
2549 name; names set this way will never override names set by the user's
2552 x_implicitly_set_name (f
, arg
, oldval
)
2554 Lisp_Object arg
, oldval
;
2556 x_set_name (f
, arg
, 0);
2559 /* Change the title of frame F to NAME.
2560 If NAME is nil, use the frame name as the title.
2562 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2563 name; if NAME is a string, set F's name to NAME and set
2564 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2566 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2567 suggesting a new name, which lisp code should override; if
2568 F->explicit_name is set, ignore the new name; otherwise, set it. */
2571 x_set_title (f
, name
, old_name
)
2573 Lisp_Object name
, old_name
;
2575 /* Don't change the title if it's already NAME. */
2576 if (EQ (name
, f
->title
))
2579 update_mode_lines
= 1;
2586 CHECK_STRING (name
);
2588 if (FRAME_X_WINDOW (f
))
2593 XTextProperty text
, icon
;
2595 Lisp_Object coding_system
;
2597 coding_system
= Vlocale_coding_system
;
2598 if (NILP (coding_system
))
2599 coding_system
= Qcompound_text
;
2600 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2601 text
.encoding
= (stringp
? XA_STRING
2602 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2604 text
.nitems
= bytes
;
2606 if (NILP (f
->icon_name
))
2612 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2614 icon
.encoding
= (stringp
? XA_STRING
2615 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2617 icon
.nitems
= bytes
;
2619 #ifdef USE_X_TOOLKIT
2620 XSetWMName (FRAME_X_DISPLAY (f
),
2621 XtWindow (f
->output_data
.x
->widget
), &text
);
2622 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2624 #else /* not USE_X_TOOLKIT */
2625 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2626 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2627 #endif /* not USE_X_TOOLKIT */
2628 if (!NILP (f
->icon_name
)
2629 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2631 if (text
.value
!= XSTRING (name
)->data
)
2634 #else /* not HAVE_X11R4 */
2635 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2636 XSTRING (name
)->data
);
2637 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2638 XSTRING (name
)->data
);
2639 #endif /* not HAVE_X11R4 */
2645 x_set_autoraise (f
, arg
, oldval
)
2647 Lisp_Object arg
, oldval
;
2649 f
->auto_raise
= !EQ (Qnil
, arg
);
2653 x_set_autolower (f
, arg
, oldval
)
2655 Lisp_Object arg
, oldval
;
2657 f
->auto_lower
= !EQ (Qnil
, arg
);
2661 x_set_unsplittable (f
, arg
, oldval
)
2663 Lisp_Object arg
, oldval
;
2665 f
->no_split
= !NILP (arg
);
2669 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2671 Lisp_Object arg
, oldval
;
2673 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2674 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2675 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2676 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2678 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2680 ? vertical_scroll_bar_none
2682 ? vertical_scroll_bar_right
2683 : vertical_scroll_bar_left
);
2685 /* We set this parameter before creating the X window for the
2686 frame, so we can get the geometry right from the start.
2687 However, if the window hasn't been created yet, we shouldn't
2688 call x_set_window_size. */
2689 if (FRAME_X_WINDOW (f
))
2690 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2691 do_pending_window_change (0);
2696 x_set_scroll_bar_width (f
, arg
, oldval
)
2698 Lisp_Object arg
, oldval
;
2700 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2704 #ifdef USE_TOOLKIT_SCROLL_BARS
2705 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2706 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2707 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2708 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2710 /* Make the actual width at least 14 pixels and a multiple of a
2712 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2714 /* Use all of that space (aside from required margins) for the
2716 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2719 if (FRAME_X_WINDOW (f
))
2720 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2721 do_pending_window_change (0);
2723 else if (INTEGERP (arg
) && XINT (arg
) > 0
2724 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2726 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2727 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2729 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2730 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2731 if (FRAME_X_WINDOW (f
))
2732 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2735 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2736 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2737 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2742 /* Subroutines of creating an X frame. */
2744 /* Make sure that Vx_resource_name is set to a reasonable value.
2745 Fix it up, or set it to `emacs' if it is too hopeless. */
2748 validate_x_resource_name ()
2751 /* Number of valid characters in the resource name. */
2753 /* Number of invalid characters in the resource name. */
2758 if (!STRINGP (Vx_resource_class
))
2759 Vx_resource_class
= build_string (EMACS_CLASS
);
2761 if (STRINGP (Vx_resource_name
))
2763 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2766 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2768 /* Only letters, digits, - and _ are valid in resource names.
2769 Count the valid characters and count the invalid ones. */
2770 for (i
= 0; i
< len
; i
++)
2773 if (! ((c
>= 'a' && c
<= 'z')
2774 || (c
>= 'A' && c
<= 'Z')
2775 || (c
>= '0' && c
<= '9')
2776 || c
== '-' || c
== '_'))
2783 /* Not a string => completely invalid. */
2784 bad_count
= 5, good_count
= 0;
2786 /* If name is valid already, return. */
2790 /* If name is entirely invalid, or nearly so, use `emacs'. */
2792 || (good_count
== 1 && bad_count
> 0))
2794 Vx_resource_name
= build_string ("emacs");
2798 /* Name is partly valid. Copy it and replace the invalid characters
2799 with underscores. */
2801 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2803 for (i
= 0; i
< len
; i
++)
2805 int c
= XSTRING (new)->data
[i
];
2806 if (! ((c
>= 'a' && c
<= 'z')
2807 || (c
>= 'A' && c
<= 'Z')
2808 || (c
>= '0' && c
<= '9')
2809 || c
== '-' || c
== '_'))
2810 XSTRING (new)->data
[i
] = '_';
2815 extern char *x_get_string_resource ();
2817 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2818 doc
: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2819 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2820 class, where INSTANCE is the name under which Emacs was invoked, or
2821 the name specified by the `-name' or `-rn' command-line arguments.
2823 The optional arguments COMPONENT and SUBCLASS add to the key and the
2824 class, respectively. You must specify both of them or neither.
2825 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2826 and the class is `Emacs.CLASS.SUBCLASS'. */)
2827 (attribute
, class, component
, subclass
)
2828 Lisp_Object attribute
, class, component
, subclass
;
2830 register char *value
;
2836 CHECK_STRING (attribute
);
2837 CHECK_STRING (class);
2839 if (!NILP (component
))
2840 CHECK_STRING (component
);
2841 if (!NILP (subclass
))
2842 CHECK_STRING (subclass
);
2843 if (NILP (component
) != NILP (subclass
))
2844 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2846 validate_x_resource_name ();
2848 /* Allocate space for the components, the dots which separate them,
2849 and the final '\0'. Make them big enough for the worst case. */
2850 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2851 + (STRINGP (component
)
2852 ? STRING_BYTES (XSTRING (component
)) : 0)
2853 + STRING_BYTES (XSTRING (attribute
))
2856 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2857 + STRING_BYTES (XSTRING (class))
2858 + (STRINGP (subclass
)
2859 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2862 /* Start with emacs.FRAMENAME for the name (the specific one)
2863 and with `Emacs' for the class key (the general one). */
2864 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2865 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2867 strcat (class_key
, ".");
2868 strcat (class_key
, XSTRING (class)->data
);
2870 if (!NILP (component
))
2872 strcat (class_key
, ".");
2873 strcat (class_key
, XSTRING (subclass
)->data
);
2875 strcat (name_key
, ".");
2876 strcat (name_key
, XSTRING (component
)->data
);
2879 strcat (name_key
, ".");
2880 strcat (name_key
, XSTRING (attribute
)->data
);
2882 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2883 name_key
, class_key
);
2885 if (value
!= (char *) 0)
2886 return build_string (value
);
2891 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2894 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2895 struct x_display_info
*dpyinfo
;
2896 Lisp_Object attribute
, class, component
, subclass
;
2898 register char *value
;
2902 CHECK_STRING (attribute
);
2903 CHECK_STRING (class);
2905 if (!NILP (component
))
2906 CHECK_STRING (component
);
2907 if (!NILP (subclass
))
2908 CHECK_STRING (subclass
);
2909 if (NILP (component
) != NILP (subclass
))
2910 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2912 validate_x_resource_name ();
2914 /* Allocate space for the components, the dots which separate them,
2915 and the final '\0'. Make them big enough for the worst case. */
2916 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2917 + (STRINGP (component
)
2918 ? STRING_BYTES (XSTRING (component
)) : 0)
2919 + STRING_BYTES (XSTRING (attribute
))
2922 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2923 + STRING_BYTES (XSTRING (class))
2924 + (STRINGP (subclass
)
2925 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2928 /* Start with emacs.FRAMENAME for the name (the specific one)
2929 and with `Emacs' for the class key (the general one). */
2930 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2931 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2933 strcat (class_key
, ".");
2934 strcat (class_key
, XSTRING (class)->data
);
2936 if (!NILP (component
))
2938 strcat (class_key
, ".");
2939 strcat (class_key
, XSTRING (subclass
)->data
);
2941 strcat (name_key
, ".");
2942 strcat (name_key
, XSTRING (component
)->data
);
2945 strcat (name_key
, ".");
2946 strcat (name_key
, XSTRING (attribute
)->data
);
2948 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2950 if (value
!= (char *) 0)
2951 return build_string (value
);
2956 /* Used when C code wants a resource value. */
2959 x_get_resource_string (attribute
, class)
2960 char *attribute
, *class;
2964 struct frame
*sf
= SELECTED_FRAME ();
2966 /* Allocate space for the components, the dots which separate them,
2967 and the final '\0'. */
2968 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2969 + strlen (attribute
) + 2);
2970 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2971 + strlen (class) + 2);
2973 sprintf (name_key
, "%s.%s",
2974 XSTRING (Vinvocation_name
)->data
,
2976 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2978 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2979 name_key
, class_key
);
2982 /* Types we might convert a resource string into. */
2992 /* Return the value of parameter PARAM.
2994 First search ALIST, then Vdefault_frame_alist, then the X defaults
2995 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2997 Convert the resource to the type specified by desired_type.
2999 If no default is specified, return Qunbound. If you call
3000 x_get_arg, make sure you deal with Qunbound in a reasonable way,
3001 and don't let it get stored in any Lisp-visible variables! */
3004 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
3005 struct x_display_info
*dpyinfo
;
3006 Lisp_Object alist
, param
;
3009 enum resource_types type
;
3011 register Lisp_Object tem
;
3013 tem
= Fassq (param
, alist
);
3015 tem
= Fassq (param
, Vdefault_frame_alist
);
3021 tem
= display_x_get_resource (dpyinfo
,
3022 build_string (attribute
),
3023 build_string (class),
3031 case RES_TYPE_NUMBER
:
3032 return make_number (atoi (XSTRING (tem
)->data
));
3034 case RES_TYPE_FLOAT
:
3035 return make_float (atof (XSTRING (tem
)->data
));
3037 case RES_TYPE_BOOLEAN
:
3038 tem
= Fdowncase (tem
);
3039 if (!strcmp (XSTRING (tem
)->data
, "on")
3040 || !strcmp (XSTRING (tem
)->data
, "true"))
3045 case RES_TYPE_STRING
:
3048 case RES_TYPE_SYMBOL
:
3049 /* As a special case, we map the values `true' and `on'
3050 to Qt, and `false' and `off' to Qnil. */
3053 lower
= Fdowncase (tem
);
3054 if (!strcmp (XSTRING (lower
)->data
, "on")
3055 || !strcmp (XSTRING (lower
)->data
, "true"))
3057 else if (!strcmp (XSTRING (lower
)->data
, "off")
3058 || !strcmp (XSTRING (lower
)->data
, "false"))
3061 return Fintern (tem
, Qnil
);
3074 /* Like x_get_arg, but also record the value in f->param_alist. */
3077 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
3079 Lisp_Object alist
, param
;
3082 enum resource_types type
;
3086 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
3087 attribute
, class, type
);
3089 store_frame_param (f
, param
, value
);
3094 /* Record in frame F the specified or default value according to ALIST
3095 of the parameter named PROP (a Lisp symbol).
3096 If no value is specified for PROP, look for an X default for XPROP
3097 on the frame named NAME.
3098 If that is not found either, use the value DEFLT. */
3101 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
3108 enum resource_types type
;
3112 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
3113 if (EQ (tem
, Qunbound
))
3115 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3120 /* Record in frame F the specified or default value according to ALIST
3121 of the parameter named PROP (a Lisp symbol). If no value is
3122 specified for PROP, look for an X default for XPROP on the frame
3123 named NAME. If that is not found either, use the value DEFLT. */
3126 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
3135 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3138 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
3139 if (EQ (tem
, Qunbound
))
3141 #ifdef USE_TOOLKIT_SCROLL_BARS
3143 /* See if an X resource for the scroll bar color has been
3145 tem
= display_x_get_resource (dpyinfo
,
3146 build_string (foreground_p
3150 build_string ("verticalScrollBar"),
3154 /* If nothing has been specified, scroll bars will use a
3155 toolkit-dependent default. Because these defaults are
3156 difficult to get at without actually creating a scroll
3157 bar, use nil to indicate that no color has been
3162 #else /* not USE_TOOLKIT_SCROLL_BARS */
3166 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3169 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3175 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3176 doc
: /* Parse an X-style geometry string STRING.
3177 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3178 The properties returned may include `top', `left', `height', and `width'.
3179 The value of `left' or `top' may be an integer,
3180 or a list (+ N) meaning N pixels relative to top/left corner,
3181 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3186 unsigned int width
, height
;
3189 CHECK_STRING (string
);
3191 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
3192 &x
, &y
, &width
, &height
);
3195 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3196 error ("Must specify both x and y position, or neither");
3200 if (geometry
& XValue
)
3202 Lisp_Object element
;
3204 if (x
>= 0 && (geometry
& XNegative
))
3205 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3206 else if (x
< 0 && ! (geometry
& XNegative
))
3207 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3209 element
= Fcons (Qleft
, make_number (x
));
3210 result
= Fcons (element
, result
);
3213 if (geometry
& YValue
)
3215 Lisp_Object element
;
3217 if (y
>= 0 && (geometry
& YNegative
))
3218 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3219 else if (y
< 0 && ! (geometry
& YNegative
))
3220 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3222 element
= Fcons (Qtop
, make_number (y
));
3223 result
= Fcons (element
, result
);
3226 if (geometry
& WidthValue
)
3227 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3228 if (geometry
& HeightValue
)
3229 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3234 /* Calculate the desired size and position of this window,
3235 and return the flags saying which aspects were specified.
3237 This function does not make the coordinates positive. */
3239 #define DEFAULT_ROWS 40
3240 #define DEFAULT_COLS 80
3243 x_figure_window_size (f
, parms
)
3247 register Lisp_Object tem0
, tem1
, tem2
;
3248 long window_prompting
= 0;
3249 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3251 /* Default values if we fall through.
3252 Actually, if that happens we should get
3253 window manager prompting. */
3254 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3255 f
->height
= DEFAULT_ROWS
;
3256 /* Window managers expect that if program-specified
3257 positions are not (0,0), they're intentional, not defaults. */
3258 f
->output_data
.x
->top_pos
= 0;
3259 f
->output_data
.x
->left_pos
= 0;
3261 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3262 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3263 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3264 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3266 if (!EQ (tem0
, Qunbound
))
3268 CHECK_NUMBER (tem0
);
3269 f
->height
= XINT (tem0
);
3271 if (!EQ (tem1
, Qunbound
))
3273 CHECK_NUMBER (tem1
);
3274 SET_FRAME_WIDTH (f
, XINT (tem1
));
3276 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3277 window_prompting
|= USSize
;
3279 window_prompting
|= PSize
;
3282 f
->output_data
.x
->vertical_scroll_bar_extra
3283 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3285 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3287 x_compute_fringe_widths (f
, 0);
3289 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3290 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3292 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3293 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3294 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3295 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3297 if (EQ (tem0
, Qminus
))
3299 f
->output_data
.x
->top_pos
= 0;
3300 window_prompting
|= YNegative
;
3302 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3303 && CONSP (XCDR (tem0
))
3304 && INTEGERP (XCAR (XCDR (tem0
))))
3306 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3307 window_prompting
|= YNegative
;
3309 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3310 && CONSP (XCDR (tem0
))
3311 && INTEGERP (XCAR (XCDR (tem0
))))
3313 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3315 else if (EQ (tem0
, Qunbound
))
3316 f
->output_data
.x
->top_pos
= 0;
3319 CHECK_NUMBER (tem0
);
3320 f
->output_data
.x
->top_pos
= XINT (tem0
);
3321 if (f
->output_data
.x
->top_pos
< 0)
3322 window_prompting
|= YNegative
;
3325 if (EQ (tem1
, Qminus
))
3327 f
->output_data
.x
->left_pos
= 0;
3328 window_prompting
|= XNegative
;
3330 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3331 && CONSP (XCDR (tem1
))
3332 && INTEGERP (XCAR (XCDR (tem1
))))
3334 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3335 window_prompting
|= XNegative
;
3337 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3338 && CONSP (XCDR (tem1
))
3339 && INTEGERP (XCAR (XCDR (tem1
))))
3341 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3343 else if (EQ (tem1
, Qunbound
))
3344 f
->output_data
.x
->left_pos
= 0;
3347 CHECK_NUMBER (tem1
);
3348 f
->output_data
.x
->left_pos
= XINT (tem1
);
3349 if (f
->output_data
.x
->left_pos
< 0)
3350 window_prompting
|= XNegative
;
3353 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3354 window_prompting
|= USPosition
;
3356 window_prompting
|= PPosition
;
3359 if (f
->output_data
.x
->want_fullscreen
!= FULLSCREEN_NONE
)
3364 /* It takes both for some WM:s to place it where we want */
3365 window_prompting
= USPosition
| PPosition
;
3366 x_fullscreen_adjust (f
, &width
, &height
, &top
, &left
);
3369 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3370 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3371 f
->output_data
.x
->left_pos
= left
;
3372 f
->output_data
.x
->top_pos
= top
;
3375 return window_prompting
;
3378 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3381 XSetWMProtocols (dpy
, w
, protocols
, count
)
3388 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3389 if (prop
== None
) return False
;
3390 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3391 (unsigned char *) protocols
, count
);
3394 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3396 #ifdef USE_X_TOOLKIT
3398 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3399 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3400 already be present because of the toolkit (Motif adds some of them,
3401 for example, but Xt doesn't). */
3404 hack_wm_protocols (f
, widget
)
3408 Display
*dpy
= XtDisplay (widget
);
3409 Window w
= XtWindow (widget
);
3410 int need_delete
= 1;
3416 Atom type
, *atoms
= 0;
3418 unsigned long nitems
= 0;
3419 unsigned long bytes_after
;
3421 if ((XGetWindowProperty (dpy
, w
,
3422 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3423 (long)0, (long)100, False
, XA_ATOM
,
3424 &type
, &format
, &nitems
, &bytes_after
,
3425 (unsigned char **) &atoms
)
3427 && format
== 32 && type
== XA_ATOM
)
3431 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3433 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3435 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3438 if (atoms
) XFree ((char *) atoms
);
3444 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3446 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3448 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3450 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3451 XA_ATOM
, 32, PropModeAppend
,
3452 (unsigned char *) props
, count
);
3460 /* Support routines for XIC (X Input Context). */
3464 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3465 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3468 /* Supported XIM styles, ordered by preferenc. */
3470 static XIMStyle supported_xim_styles
[] =
3472 XIMPreeditPosition
| XIMStatusArea
,
3473 XIMPreeditPosition
| XIMStatusNothing
,
3474 XIMPreeditPosition
| XIMStatusNone
,
3475 XIMPreeditNothing
| XIMStatusArea
,
3476 XIMPreeditNothing
| XIMStatusNothing
,
3477 XIMPreeditNothing
| XIMStatusNone
,
3478 XIMPreeditNone
| XIMStatusArea
,
3479 XIMPreeditNone
| XIMStatusNothing
,
3480 XIMPreeditNone
| XIMStatusNone
,
3485 /* Create an X fontset on frame F with base font name
3489 xic_create_xfontset (f
, base_fontname
)
3491 char *base_fontname
;
3494 char **missing_list
;
3498 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3499 base_fontname
, &missing_list
,
3500 &missing_count
, &def_string
);
3502 XFreeStringList (missing_list
);
3504 /* No need to free def_string. */
3509 /* Value is the best input style, given user preferences USER (already
3510 checked to be supported by Emacs), and styles supported by the
3511 input method XIM. */
3514 best_xim_style (user
, xim
)
3520 for (i
= 0; i
< user
->count_styles
; ++i
)
3521 for (j
= 0; j
< xim
->count_styles
; ++j
)
3522 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3523 return user
->supported_styles
[i
];
3525 /* Return the default style. */
3526 return XIMPreeditNothing
| XIMStatusNothing
;
3529 /* Create XIC for frame F. */
3531 static XIMStyle xic_style
;
3534 create_frame_xic (f
)
3539 XFontSet xfs
= NULL
;
3544 xim
= FRAME_X_XIM (f
);
3549 XVaNestedList preedit_attr
;
3550 XVaNestedList status_attr
;
3551 char *base_fontname
;
3554 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3555 spot
.x
= 0; spot
.y
= 1;
3556 /* Create X fontset. */
3557 fontset
= FRAME_FONTSET (f
);
3559 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3562 /* Determine the base fontname from the ASCII font name of
3564 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3565 char *p
= ascii_font
;
3568 for (i
= 0; *p
; p
++)
3571 /* As the font name doesn't conform to XLFD, we can't
3572 modify it to get a suitable base fontname for the
3574 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3577 int len
= strlen (ascii_font
) + 1;
3580 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3589 base_fontname
= (char *) alloca (len
);
3590 bzero (base_fontname
, len
);
3591 strcpy (base_fontname
, "-*-*-");
3592 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3593 strcat (base_fontname
, "*-*-*-*-*-*-*");
3596 xfs
= xic_create_xfontset (f
, base_fontname
);
3598 /* Determine XIC style. */
3601 XIMStyles supported_list
;
3602 supported_list
.count_styles
= (sizeof supported_xim_styles
3603 / sizeof supported_xim_styles
[0]);
3604 supported_list
.supported_styles
= supported_xim_styles
;
3605 xic_style
= best_xim_style (&supported_list
,
3606 FRAME_X_XIM_STYLES (f
));
3609 preedit_attr
= XVaCreateNestedList (0,
3612 FRAME_FOREGROUND_PIXEL (f
),
3614 FRAME_BACKGROUND_PIXEL (f
),
3615 (xic_style
& XIMPreeditPosition
3620 status_attr
= XVaCreateNestedList (0,
3626 FRAME_FOREGROUND_PIXEL (f
),
3628 FRAME_BACKGROUND_PIXEL (f
),
3631 xic
= XCreateIC (xim
,
3632 XNInputStyle
, xic_style
,
3633 XNClientWindow
, FRAME_X_WINDOW(f
),
3634 XNFocusWindow
, FRAME_X_WINDOW(f
),
3635 XNStatusAttributes
, status_attr
,
3636 XNPreeditAttributes
, preedit_attr
,
3638 XFree (preedit_attr
);
3639 XFree (status_attr
);
3642 FRAME_XIC (f
) = xic
;
3643 FRAME_XIC_STYLE (f
) = xic_style
;
3644 FRAME_XIC_FONTSET (f
) = xfs
;
3648 /* Destroy XIC and free XIC fontset of frame F, if any. */
3654 if (FRAME_XIC (f
) == NULL
)
3657 XDestroyIC (FRAME_XIC (f
));
3658 if (FRAME_XIC_FONTSET (f
))
3659 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3661 FRAME_XIC (f
) = NULL
;
3662 FRAME_XIC_FONTSET (f
) = NULL
;
3666 /* Place preedit area for XIC of window W's frame to specified
3667 pixel position X/Y. X and Y are relative to window W. */
3670 xic_set_preeditarea (w
, x
, y
)
3674 struct frame
*f
= XFRAME (w
->frame
);
3678 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3679 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3680 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3681 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3686 /* Place status area for XIC in bottom right corner of frame F.. */
3689 xic_set_statusarea (f
)
3692 XIC xic
= FRAME_XIC (f
);
3697 /* Negotiate geometry of status area. If input method has existing
3698 status area, use its current size. */
3699 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3700 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3701 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3704 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3705 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3708 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3710 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3711 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3715 area
.width
= needed
->width
;
3716 area
.height
= needed
->height
;
3717 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3718 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3719 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3722 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3723 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3728 /* Set X fontset for XIC of frame F, using base font name
3729 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3732 xic_set_xfontset (f
, base_fontname
)
3734 char *base_fontname
;
3739 xfs
= xic_create_xfontset (f
, base_fontname
);
3741 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3742 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3743 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3744 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3745 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3748 if (FRAME_XIC_FONTSET (f
))
3749 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3750 FRAME_XIC_FONTSET (f
) = xfs
;
3753 #endif /* HAVE_X_I18N */
3757 #ifdef USE_X_TOOLKIT
3759 /* Create and set up the X widget for frame F. */
3762 x_window (f
, window_prompting
, minibuffer_only
)
3764 long window_prompting
;
3765 int minibuffer_only
;
3767 XClassHint class_hints
;
3768 XSetWindowAttributes attributes
;
3769 unsigned long attribute_mask
;
3770 Widget shell_widget
;
3772 Widget frame_widget
;
3778 /* Use the resource name as the top-level widget name
3779 for looking up resources. Make a non-Lisp copy
3780 for the window manager, so GC relocation won't bother it.
3782 Elsewhere we specify the window name for the window manager. */
3785 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3786 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3787 strcpy (f
->namebuf
, str
);
3791 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3792 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3793 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3794 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3795 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3796 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3797 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3798 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3799 applicationShellWidgetClass
,
3800 FRAME_X_DISPLAY (f
), al
, ac
);
3802 f
->output_data
.x
->widget
= shell_widget
;
3803 /* maybe_set_screen_title_format (shell_widget); */
3805 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3806 (widget_value
*) NULL
,
3807 shell_widget
, False
,
3811 (lw_callback
) NULL
);
3814 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3815 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3816 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3817 XtSetValues (pane_widget
, al
, ac
);
3818 f
->output_data
.x
->column_widget
= pane_widget
;
3820 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3821 the emacs screen when changing menubar. This reduces flickering. */
3824 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3825 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3826 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3827 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3828 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3829 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3830 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3831 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3832 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3835 f
->output_data
.x
->edit_widget
= frame_widget
;
3837 XtManageChild (frame_widget
);
3839 /* Do some needed geometry management. */
3842 char *tem
, shell_position
[32];
3845 int extra_borders
= 0;
3847 = (f
->output_data
.x
->menubar_widget
3848 ? (f
->output_data
.x
->menubar_widget
->core
.height
3849 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3852 #if 0 /* Experimentally, we now get the right results
3853 for -geometry -0-0 without this. 24 Aug 96, rms. */
3854 if (FRAME_EXTERNAL_MENU_BAR (f
))
3857 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3858 menubar_size
+= ibw
;
3862 f
->output_data
.x
->menubar_height
= menubar_size
;
3865 /* Motif seems to need this amount added to the sizes
3866 specified for the shell widget. The Athena/Lucid widgets don't.
3867 Both conclusions reached experimentally. -- rms. */
3868 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3869 &extra_borders
, NULL
);
3873 /* Convert our geometry parameters into a geometry string
3875 Note that we do not specify here whether the position
3876 is a user-specified or program-specified one.
3877 We pass that information later, in x_wm_set_size_hints. */
3879 int left
= f
->output_data
.x
->left_pos
;
3880 int xneg
= window_prompting
& XNegative
;
3881 int top
= f
->output_data
.x
->top_pos
;
3882 int yneg
= window_prompting
& YNegative
;
3888 if (window_prompting
& USPosition
)
3889 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3890 PIXEL_WIDTH (f
) + extra_borders
,
3891 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3892 (xneg
? '-' : '+'), left
,
3893 (yneg
? '-' : '+'), top
);
3895 sprintf (shell_position
, "=%dx%d",
3896 PIXEL_WIDTH (f
) + extra_borders
,
3897 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3900 len
= strlen (shell_position
) + 1;
3901 /* We don't free this because we don't know whether
3902 it is safe to free it while the frame exists.
3903 It isn't worth the trouble of arranging to free it
3904 when the frame is deleted. */
3905 tem
= (char *) xmalloc (len
);
3906 strncpy (tem
, shell_position
, len
);
3907 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3908 XtSetValues (shell_widget
, al
, ac
);
3911 XtManageChild (pane_widget
);
3912 XtRealizeWidget (shell_widget
);
3914 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3916 validate_x_resource_name ();
3918 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3919 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3920 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3923 FRAME_XIC (f
) = NULL
;
3925 create_frame_xic (f
);
3929 f
->output_data
.x
->wm_hints
.input
= True
;
3930 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3931 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3932 &f
->output_data
.x
->wm_hints
);
3934 hack_wm_protocols (f
, shell_widget
);
3937 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3940 /* Do a stupid property change to force the server to generate a
3941 PropertyNotify event so that the event_stream server timestamp will
3942 be initialized to something relevant to the time we created the window.
3944 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3945 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3946 XA_ATOM
, 32, PropModeAppend
,
3947 (unsigned char*) NULL
, 0);
3949 /* Make all the standard events reach the Emacs frame. */
3950 attributes
.event_mask
= STANDARD_EVENT_SET
;
3955 /* XIM server might require some X events. */
3956 unsigned long fevent
= NoEventMask
;
3957 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3958 attributes
.event_mask
|= fevent
;
3960 #endif /* HAVE_X_I18N */
3962 attribute_mask
= CWEventMask
;
3963 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3964 attribute_mask
, &attributes
);
3966 XtMapWidget (frame_widget
);
3968 /* x_set_name normally ignores requests to set the name if the
3969 requested name is the same as the current name. This is the one
3970 place where that assumption isn't correct; f->name is set, but
3971 the X server hasn't been told. */
3974 int explicit = f
->explicit_name
;
3976 f
->explicit_name
= 0;
3979 x_set_name (f
, name
, explicit);
3982 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3983 f
->output_data
.x
->text_cursor
);
3987 /* This is a no-op, except under Motif. Make sure main areas are
3988 set to something reasonable, in case we get an error later. */
3989 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3992 #else /* not USE_X_TOOLKIT */
3994 /* Create and set up the X window for frame F. */
4001 XClassHint class_hints
;
4002 XSetWindowAttributes attributes
;
4003 unsigned long attribute_mask
;
4005 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
4006 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
4007 attributes
.bit_gravity
= StaticGravity
;
4008 attributes
.backing_store
= NotUseful
;
4009 attributes
.save_under
= True
;
4010 attributes
.event_mask
= STANDARD_EVENT_SET
;
4011 attributes
.colormap
= FRAME_X_COLORMAP (f
);
4012 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
4017 = XCreateWindow (FRAME_X_DISPLAY (f
),
4018 f
->output_data
.x
->parent_desc
,
4019 f
->output_data
.x
->left_pos
,
4020 f
->output_data
.x
->top_pos
,
4021 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
4022 f
->output_data
.x
->border_width
,
4023 CopyFromParent
, /* depth */
4024 InputOutput
, /* class */
4026 attribute_mask
, &attributes
);
4030 create_frame_xic (f
);
4033 /* XIM server might require some X events. */
4034 unsigned long fevent
= NoEventMask
;
4035 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
4036 attributes
.event_mask
|= fevent
;
4037 attribute_mask
= CWEventMask
;
4038 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4039 attribute_mask
, &attributes
);
4042 #endif /* HAVE_X_I18N */
4044 validate_x_resource_name ();
4046 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
4047 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
4048 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
4050 /* The menubar is part of the ordinary display;
4051 it does not count in addition to the height of the window. */
4052 f
->output_data
.x
->menubar_height
= 0;
4054 /* This indicates that we use the "Passive Input" input model.
4055 Unless we do this, we don't get the Focus{In,Out} events that we
4056 need to draw the cursor correctly. Accursed bureaucrats.
4057 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
4059 f
->output_data
.x
->wm_hints
.input
= True
;
4060 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
4061 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4062 &f
->output_data
.x
->wm_hints
);
4063 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
4065 /* Request "save yourself" and "delete window" commands from wm. */
4068 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
4069 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
4070 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
4073 /* x_set_name normally ignores requests to set the name if the
4074 requested name is the same as the current name. This is the one
4075 place where that assumption isn't correct; f->name is set, but
4076 the X server hasn't been told. */
4079 int explicit = f
->explicit_name
;
4081 f
->explicit_name
= 0;
4084 x_set_name (f
, name
, explicit);
4087 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4088 f
->output_data
.x
->text_cursor
);
4092 if (FRAME_X_WINDOW (f
) == 0)
4093 error ("Unable to create window");
4096 #endif /* not USE_X_TOOLKIT */
4098 /* Handle the icon stuff for this window. Perhaps later we might
4099 want an x_set_icon_position which can be called interactively as
4107 Lisp_Object icon_x
, icon_y
;
4108 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4110 /* Set the position of the icon. Note that twm groups all
4111 icons in an icon window. */
4112 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4113 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4114 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4116 CHECK_NUMBER (icon_x
);
4117 CHECK_NUMBER (icon_y
);
4119 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4120 error ("Both left and top icon corners of icon must be specified");
4124 if (! EQ (icon_x
, Qunbound
))
4125 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4127 /* Start up iconic or window? */
4128 x_wm_set_window_state
4129 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
4134 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
4141 /* Make the GCs needed for this window, setting the
4142 background, border and mouse colors; also create the
4143 mouse cursor and the gray border tile. */
4145 static char cursor_bits
[] =
4147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4157 XGCValues gc_values
;
4161 /* Create the GCs of this frame.
4162 Note that many default values are used. */
4165 gc_values
.font
= f
->output_data
.x
->font
->fid
;
4166 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
4167 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4168 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
4169 f
->output_data
.x
->normal_gc
4170 = XCreateGC (FRAME_X_DISPLAY (f
),
4172 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
4175 /* Reverse video style. */
4176 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4177 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4178 f
->output_data
.x
->reverse_gc
4179 = XCreateGC (FRAME_X_DISPLAY (f
),
4181 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
4184 /* Cursor has cursor-color background, background-color foreground. */
4185 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4186 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
4187 gc_values
.fill_style
= FillOpaqueStippled
;
4189 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4190 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4191 cursor_bits
, 16, 16);
4192 f
->output_data
.x
->cursor_gc
4193 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4194 (GCFont
| GCForeground
| GCBackground
4195 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
4199 f
->output_data
.x
->white_relief
.gc
= 0;
4200 f
->output_data
.x
->black_relief
.gc
= 0;
4202 /* Create the gray border tile used when the pointer is not in
4203 the frame. Since this depends on the frame's pixel values,
4204 this must be done on a per-frame basis. */
4205 f
->output_data
.x
->border_tile
4206 = (XCreatePixmapFromBitmapData
4207 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
4208 gray_bits
, gray_width
, gray_height
,
4209 f
->output_data
.x
->foreground_pixel
,
4210 f
->output_data
.x
->background_pixel
,
4211 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4217 /* Free what was was allocated in x_make_gc. */
4223 Display
*dpy
= FRAME_X_DISPLAY (f
);
4227 if (f
->output_data
.x
->normal_gc
)
4229 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4230 f
->output_data
.x
->normal_gc
= 0;
4233 if (f
->output_data
.x
->reverse_gc
)
4235 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4236 f
->output_data
.x
->reverse_gc
= 0;
4239 if (f
->output_data
.x
->cursor_gc
)
4241 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4242 f
->output_data
.x
->cursor_gc
= 0;
4245 if (f
->output_data
.x
->border_tile
)
4247 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4248 f
->output_data
.x
->border_tile
= 0;
4255 /* Handler for signals raised during x_create_frame and
4256 x_create_top_frame. FRAME is the frame which is partially
4260 unwind_create_frame (frame
)
4263 struct frame
*f
= XFRAME (frame
);
4265 /* If frame is ``official'', nothing to do. */
4266 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4269 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4272 x_free_frame_resources (f
);
4274 /* Check that reference counts are indeed correct. */
4275 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4276 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4284 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4286 doc
: /* Make a new X window, which is called a "frame" in Emacs terms.
4287 Returns an Emacs frame object.
4288 ALIST is an alist of frame parameters.
4289 If the parameters specify that the frame should not have a minibuffer,
4290 and do not specify a specific minibuffer window to use,
4291 then `default-minibuffer-frame' must be a frame whose minibuffer can
4292 be shared by the new frame.
4294 This function is an internal primitive--use `make-frame' instead. */)
4299 Lisp_Object frame
, tem
;
4301 int minibuffer_only
= 0;
4302 long window_prompting
= 0;
4304 int count
= BINDING_STACK_SIZE ();
4305 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4306 Lisp_Object display
;
4307 struct x_display_info
*dpyinfo
= NULL
;
4313 /* Use this general default value to start with
4314 until we know if this frame has a specified name. */
4315 Vx_resource_name
= Vinvocation_name
;
4317 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4318 if (EQ (display
, Qunbound
))
4320 dpyinfo
= check_x_display_info (display
);
4322 kb
= dpyinfo
->kboard
;
4324 kb
= &the_only_kboard
;
4327 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4329 && ! EQ (name
, Qunbound
)
4331 error ("Invalid frame name--not a string or nil");
4334 Vx_resource_name
= name
;
4336 /* See if parent window is specified. */
4337 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4338 if (EQ (parent
, Qunbound
))
4340 if (! NILP (parent
))
4341 CHECK_NUMBER (parent
);
4343 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4344 /* No need to protect DISPLAY because that's not used after passing
4345 it to make_frame_without_minibuffer. */
4347 GCPRO4 (parms
, parent
, name
, frame
);
4348 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4350 if (EQ (tem
, Qnone
) || NILP (tem
))
4351 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4352 else if (EQ (tem
, Qonly
))
4354 f
= make_minibuffer_frame ();
4355 minibuffer_only
= 1;
4357 else if (WINDOWP (tem
))
4358 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4362 XSETFRAME (frame
, f
);
4364 /* Note that X Windows does support scroll bars. */
4365 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4367 f
->output_method
= output_x_window
;
4368 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4369 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4370 f
->output_data
.x
->icon_bitmap
= -1;
4371 f
->output_data
.x
->fontset
= -1;
4372 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4373 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4374 #ifdef USE_TOOLKIT_SCROLL_BARS
4375 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
4376 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
4377 #endif /* USE_TOOLKIT_SCROLL_BARS */
4378 record_unwind_protect (unwind_create_frame
, frame
);
4381 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4383 if (! STRINGP (f
->icon_name
))
4384 f
->icon_name
= Qnil
;
4386 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4388 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4389 dpyinfo_refcount
= dpyinfo
->reference_count
;
4390 #endif /* GLYPH_DEBUG */
4392 FRAME_KBOARD (f
) = kb
;
4395 /* These colors will be set anyway later, but it's important
4396 to get the color reference counts right, so initialize them! */
4399 struct gcpro gcpro1
;
4401 /* Function x_decode_color can signal an error. Make
4402 sure to initialize color slots so that we won't try
4403 to free colors we haven't allocated. */
4404 f
->output_data
.x
->foreground_pixel
= -1;
4405 f
->output_data
.x
->background_pixel
= -1;
4406 f
->output_data
.x
->cursor_pixel
= -1;
4407 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4408 f
->output_data
.x
->border_pixel
= -1;
4409 f
->output_data
.x
->mouse_pixel
= -1;
4411 black
= build_string ("black");
4413 f
->output_data
.x
->foreground_pixel
4414 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4415 f
->output_data
.x
->background_pixel
4416 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4417 f
->output_data
.x
->cursor_pixel
4418 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4419 f
->output_data
.x
->cursor_foreground_pixel
4420 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4421 f
->output_data
.x
->border_pixel
4422 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4423 f
->output_data
.x
->mouse_pixel
4424 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4428 /* Specify the parent under which to make this X window. */
4432 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4433 f
->output_data
.x
->explicit_parent
= 1;
4437 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4438 f
->output_data
.x
->explicit_parent
= 0;
4441 /* Set the name; the functions to which we pass f expect the name to
4443 if (EQ (name
, Qunbound
) || NILP (name
))
4445 f
->name
= build_string (dpyinfo
->x_id_name
);
4446 f
->explicit_name
= 0;
4451 f
->explicit_name
= 1;
4452 /* use the frame's title when getting resources for this frame. */
4453 specbind (Qx_resource_name
, name
);
4456 /* Extract the window parameters from the supplied values
4457 that are needed to determine window geometry. */
4461 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4464 /* First, try whatever font the caller has specified. */
4467 tem
= Fquery_fontset (font
, Qnil
);
4469 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4471 font
= x_new_font (f
, XSTRING (font
)->data
);
4474 /* Try out a font which we hope has bold and italic variations. */
4475 if (!STRINGP (font
))
4476 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4477 if (!STRINGP (font
))
4478 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4479 if (! STRINGP (font
))
4480 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4481 if (! STRINGP (font
))
4482 /* This was formerly the first thing tried, but it finds too many fonts
4483 and takes too long. */
4484 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4485 /* If those didn't work, look for something which will at least work. */
4486 if (! STRINGP (font
))
4487 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4489 if (! STRINGP (font
))
4490 font
= build_string ("fixed");
4492 x_default_parameter (f
, parms
, Qfont
, font
,
4493 "font", "Font", RES_TYPE_STRING
);
4497 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4498 whereby it fails to get any font. */
4499 xlwmenu_default_font
= f
->output_data
.x
->font
;
4502 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4503 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4505 /* This defaults to 1 in order to match xterm. We recognize either
4506 internalBorderWidth or internalBorder (which is what xterm calls
4508 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4512 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4513 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4514 if (! EQ (value
, Qunbound
))
4515 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4518 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4519 "internalBorderWidth", "internalBorderWidth",
4521 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4522 "verticalScrollBars", "ScrollBars",
4525 /* Also do the stuff which must be set before the window exists. */
4526 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4527 "foreground", "Foreground", RES_TYPE_STRING
);
4528 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4529 "background", "Background", RES_TYPE_STRING
);
4530 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4531 "pointerColor", "Foreground", RES_TYPE_STRING
);
4532 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4533 "cursorColor", "Foreground", RES_TYPE_STRING
);
4534 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4535 "borderColor", "BorderColor", RES_TYPE_STRING
);
4536 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4537 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4538 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4539 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4540 x_default_parameter (f
, parms
, Qleft_fringe
, Qnil
,
4541 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4542 x_default_parameter (f
, parms
, Qright_fringe
, Qnil
,
4543 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4545 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4546 "scrollBarForeground",
4547 "ScrollBarForeground", 1);
4548 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4549 "scrollBarBackground",
4550 "ScrollBarBackground", 0);
4552 /* Init faces before x_default_parameter is called for scroll-bar
4553 parameters because that function calls x_set_scroll_bar_width,
4554 which calls change_frame_size, which calls Fset_window_buffer,
4555 which runs hooks, which call Fvertical_motion. At the end, we
4556 end up in init_iterator with a null face cache, which should not
4558 init_frame_faces (f
);
4560 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4561 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4562 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4563 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4564 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4565 "bufferPredicate", "BufferPredicate",
4567 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4568 "title", "Title", RES_TYPE_STRING
);
4569 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4570 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4571 x_default_parameter (f
, parms
, Qfullscreen
, Qnil
,
4572 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4574 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4576 /* Add the tool-bar height to the initial frame height so that the
4577 user gets a text display area of the size he specified with -g or
4578 via .Xdefaults. Later changes of the tool-bar height don't
4579 change the frame size. This is done so that users can create
4580 tall Emacs frames without having to guess how tall the tool-bar
4582 if (FRAME_TOOL_BAR_LINES (f
))
4584 int margin
, relief
, bar_height
;
4586 relief
= (tool_bar_button_relief
>= 0
4587 ? tool_bar_button_relief
4588 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4590 if (INTEGERP (Vtool_bar_button_margin
)
4591 && XINT (Vtool_bar_button_margin
) > 0)
4592 margin
= XFASTINT (Vtool_bar_button_margin
);
4593 else if (CONSP (Vtool_bar_button_margin
)
4594 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4595 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4596 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4600 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4601 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4604 /* Compute the size of the X window. */
4605 window_prompting
= x_figure_window_size (f
, parms
);
4607 if (window_prompting
& XNegative
)
4609 if (window_prompting
& YNegative
)
4610 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4612 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4616 if (window_prompting
& YNegative
)
4617 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4619 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4622 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4624 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4625 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4627 /* Create the X widget or window. */
4628 #ifdef USE_X_TOOLKIT
4629 x_window (f
, window_prompting
, minibuffer_only
);
4637 /* Now consider the frame official. */
4638 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4639 Vframe_list
= Fcons (frame
, Vframe_list
);
4641 /* We need to do this after creating the X window, so that the
4642 icon-creation functions can say whose icon they're describing. */
4643 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4644 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4646 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4647 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4648 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4649 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4650 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4651 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4652 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4653 "scrollBarWidth", "ScrollBarWidth",
4656 /* Dimensions, especially f->height, must be done via change_frame_size.
4657 Change will not be effected unless different from the current
4663 SET_FRAME_WIDTH (f
, 0);
4664 change_frame_size (f
, height
, width
, 1, 0, 0);
4666 /* Set up faces after all frame parameters are known. This call
4667 also merges in face attributes specified for new frames. If we
4668 don't do this, the `menu' face for instance won't have the right
4669 colors, and the menu bar won't appear in the specified colors for
4671 call1 (Qface_set_after_frame_default
, frame
);
4673 #ifdef USE_X_TOOLKIT
4674 /* Create the menu bar. */
4675 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4677 /* If this signals an error, we haven't set size hints for the
4678 frame and we didn't make it visible. */
4679 initialize_frame_menubar (f
);
4681 /* This is a no-op, except under Motif where it arranges the
4682 main window for the widgets on it. */
4683 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4684 f
->output_data
.x
->menubar_widget
,
4685 f
->output_data
.x
->edit_widget
);
4687 #endif /* USE_X_TOOLKIT */
4689 /* Tell the server what size and position, etc, we want, and how
4690 badly we want them. This should be done after we have the menu
4691 bar so that its size can be taken into account. */
4693 x_wm_set_size_hint (f
, window_prompting
, 0);
4696 /* Make the window appear on the frame and enable display, unless
4697 the caller says not to. However, with explicit parent, Emacs
4698 cannot control visibility, so don't try. */
4699 if (! f
->output_data
.x
->explicit_parent
)
4701 Lisp_Object visibility
;
4703 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4705 if (EQ (visibility
, Qunbound
))
4708 if (EQ (visibility
, Qicon
))
4709 x_iconify_frame (f
);
4710 else if (! NILP (visibility
))
4711 x_make_frame_visible (f
);
4713 /* Must have been Qnil. */
4719 /* Make sure windows on this frame appear in calls to next-window
4720 and similar functions. */
4721 Vwindow_list
= Qnil
;
4723 return unbind_to (count
, frame
);
4727 /* FRAME is used only to get a handle on the X display. We don't pass the
4728 display info directly because we're called from frame.c, which doesn't
4729 know about that structure. */
4732 x_get_focus_frame (frame
)
4733 struct frame
*frame
;
4735 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4737 if (! dpyinfo
->x_focus_frame
)
4740 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4745 /* In certain situations, when the window manager follows a
4746 click-to-focus policy, there seems to be no way around calling
4747 XSetInputFocus to give another frame the input focus .
4749 In an ideal world, XSetInputFocus should generally be avoided so
4750 that applications don't interfere with the window manager's focus
4751 policy. But I think it's okay to use when it's clearly done
4752 following a user-command. */
4754 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4755 doc
: /* Set the input focus to FRAME.
4756 FRAME nil means use the selected frame. */)
4760 struct frame
*f
= check_x_frame (frame
);
4761 Display
*dpy
= FRAME_X_DISPLAY (f
);
4765 count
= x_catch_errors (dpy
);
4766 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4767 RevertToParent
, CurrentTime
);
4768 x_uncatch_errors (dpy
, count
);
4775 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4776 doc
: /* Internal function called by `color-defined-p', which see. */)
4778 Lisp_Object color
, frame
;
4781 FRAME_PTR f
= check_x_frame (frame
);
4783 CHECK_STRING (color
);
4785 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4791 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4792 doc
: /* Internal function called by `color-values', which see. */)
4794 Lisp_Object color
, frame
;
4797 FRAME_PTR f
= check_x_frame (frame
);
4799 CHECK_STRING (color
);
4801 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4805 rgb
[0] = make_number (foo
.red
);
4806 rgb
[1] = make_number (foo
.green
);
4807 rgb
[2] = make_number (foo
.blue
);
4808 return Flist (3, rgb
);
4814 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4815 doc
: /* Internal function called by `display-color-p', which see. */)
4817 Lisp_Object display
;
4819 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4821 if (dpyinfo
->n_planes
<= 2)
4824 switch (dpyinfo
->visual
->class)
4837 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4839 doc
: /* Return t if the X display supports shades of gray.
4840 Note that color displays do support shades of gray.
4841 The optional argument DISPLAY specifies which display to ask about.
4842 DISPLAY should be either a frame or a display name (a string).
4843 If omitted or nil, that stands for the selected frame's display. */)
4845 Lisp_Object display
;
4847 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4849 if (dpyinfo
->n_planes
<= 1)
4852 switch (dpyinfo
->visual
->class)
4867 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4869 doc
: /* Returns the width in pixels of the X display DISPLAY.
4870 The optional argument DISPLAY specifies which display to ask about.
4871 DISPLAY should be either a frame or a display name (a string).
4872 If omitted or nil, that stands for the selected frame's display. */)
4874 Lisp_Object display
;
4876 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4878 return make_number (dpyinfo
->width
);
4881 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4882 Sx_display_pixel_height
, 0, 1, 0,
4883 doc
: /* Returns the height in pixels of the X display DISPLAY.
4884 The optional argument DISPLAY specifies which display to ask about.
4885 DISPLAY should be either a frame or a display name (a string).
4886 If omitted or nil, that stands for the selected frame's display. */)
4888 Lisp_Object display
;
4890 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4892 return make_number (dpyinfo
->height
);
4895 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4897 doc
: /* Returns the number of bitplanes of the X display DISPLAY.
4898 The optional argument DISPLAY specifies which display to ask about.
4899 DISPLAY should be either a frame or a display name (a string).
4900 If omitted or nil, that stands for the selected frame's display. */)
4902 Lisp_Object display
;
4904 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4906 return make_number (dpyinfo
->n_planes
);
4909 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4911 doc
: /* Returns the number of color cells of the X display DISPLAY.
4912 The optional argument DISPLAY specifies which display to ask about.
4913 DISPLAY should be either a frame or a display name (a string).
4914 If omitted or nil, that stands for the selected frame's display. */)
4916 Lisp_Object display
;
4918 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4920 return make_number (DisplayCells (dpyinfo
->display
,
4921 XScreenNumberOfScreen (dpyinfo
->screen
)));
4924 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4925 Sx_server_max_request_size
,
4927 doc
: /* Returns the maximum request size of the X server of display DISPLAY.
4928 The optional argument DISPLAY specifies which display to ask about.
4929 DISPLAY should be either a frame or a display name (a string).
4930 If omitted or nil, that stands for the selected frame's display. */)
4932 Lisp_Object display
;
4934 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4936 return make_number (MAXREQUEST (dpyinfo
->display
));
4939 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4940 doc
: /* Returns the vendor ID string of the X server of display DISPLAY.
4941 The optional argument DISPLAY specifies which display to ask about.
4942 DISPLAY should be either a frame or a display name (a string).
4943 If omitted or nil, that stands for the selected frame's display. */)
4945 Lisp_Object display
;
4947 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4948 char *vendor
= ServerVendor (dpyinfo
->display
);
4950 if (! vendor
) vendor
= "";
4951 return build_string (vendor
);
4954 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4955 doc
: /* Returns the version numbers of the X server of display DISPLAY.
4956 The value is a list of three integers: the major and minor
4957 version numbers of the X Protocol in use, and the vendor-specific release
4958 number. See also the function `x-server-vendor'.
4960 The optional argument DISPLAY specifies which display to ask about.
4961 DISPLAY should be either a frame or a display name (a string).
4962 If omitted or nil, that stands for the selected frame's display. */)
4964 Lisp_Object display
;
4966 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4967 Display
*dpy
= dpyinfo
->display
;
4969 return Fcons (make_number (ProtocolVersion (dpy
)),
4970 Fcons (make_number (ProtocolRevision (dpy
)),
4971 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4974 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4975 doc
: /* Return the number of screens on the X server of display DISPLAY.
4976 The optional argument DISPLAY specifies which display to ask about.
4977 DISPLAY should be either a frame or a display name (a string).
4978 If omitted or nil, that stands for the selected frame's display. */)
4980 Lisp_Object display
;
4982 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4984 return make_number (ScreenCount (dpyinfo
->display
));
4987 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4988 doc
: /* Return the height in millimeters of the X display DISPLAY.
4989 The optional argument DISPLAY specifies which display to ask about.
4990 DISPLAY should be either a frame or a display name (a string).
4991 If omitted or nil, that stands for the selected frame's display. */)
4993 Lisp_Object display
;
4995 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4997 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
5000 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
5001 doc
: /* Return the width in millimeters of the X display DISPLAY.
5002 The optional argument DISPLAY specifies which display to ask about.
5003 DISPLAY should be either a frame or a display name (a string).
5004 If omitted or nil, that stands for the selected frame's display. */)
5006 Lisp_Object display
;
5008 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5010 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
5013 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
5014 Sx_display_backing_store
, 0, 1, 0,
5015 doc
: /* Returns an indication of whether X display DISPLAY does backing store.
5016 The value may be `always', `when-mapped', or `not-useful'.
5017 The optional argument DISPLAY specifies which display to ask about.
5018 DISPLAY should be either a frame or a display name (a string).
5019 If omitted or nil, that stands for the selected frame's display. */)
5021 Lisp_Object display
;
5023 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5026 switch (DoesBackingStore (dpyinfo
->screen
))
5029 result
= intern ("always");
5033 result
= intern ("when-mapped");
5037 result
= intern ("not-useful");
5041 error ("Strange value for BackingStore parameter of screen");
5048 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
5049 Sx_display_visual_class
, 0, 1, 0,
5050 doc
: /* Return the visual class of the X display DISPLAY.
5051 The value is one of the symbols `static-gray', `gray-scale',
5052 `static-color', `pseudo-color', `true-color', or `direct-color'.
5054 The optional argument DISPLAY specifies which display to ask about.
5055 DISPLAY should be either a frame or a display name (a string).
5056 If omitted or nil, that stands for the selected frame's display. */)
5058 Lisp_Object display
;
5060 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5063 switch (dpyinfo
->visual
->class)
5066 result
= intern ("static-gray");
5069 result
= intern ("gray-scale");
5072 result
= intern ("static-color");
5075 result
= intern ("pseudo-color");
5078 result
= intern ("true-color");
5081 result
= intern ("direct-color");
5084 error ("Display has an unknown visual class");
5091 DEFUN ("x-display-save-under", Fx_display_save_under
,
5092 Sx_display_save_under
, 0, 1, 0,
5093 doc
: /* Returns t if the X display DISPLAY supports the save-under feature.
5094 The optional argument DISPLAY specifies which display to ask about.
5095 DISPLAY should be either a frame or a display name (a string).
5096 If omitted or nil, that stands for the selected frame's display. */)
5098 Lisp_Object display
;
5100 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5102 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
5110 register struct frame
*f
;
5112 return PIXEL_WIDTH (f
);
5117 register struct frame
*f
;
5119 return PIXEL_HEIGHT (f
);
5124 register struct frame
*f
;
5126 return FONT_WIDTH (f
->output_data
.x
->font
);
5131 register struct frame
*f
;
5133 return f
->output_data
.x
->line_height
;
5138 register struct frame
*f
;
5140 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
5145 /************************************************************************
5147 ************************************************************************/
5150 /* Mapping visual names to visuals. */
5152 static struct visual_class
5159 {"StaticGray", StaticGray
},
5160 {"GrayScale", GrayScale
},
5161 {"StaticColor", StaticColor
},
5162 {"PseudoColor", PseudoColor
},
5163 {"TrueColor", TrueColor
},
5164 {"DirectColor", DirectColor
},
5169 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5171 /* Value is the screen number of screen SCR. This is a substitute for
5172 the X function with the same name when that doesn't exist. */
5175 XScreenNumberOfScreen (scr
)
5176 register Screen
*scr
;
5178 Display
*dpy
= scr
->display
;
5181 for (i
= 0; i
< dpy
->nscreens
; ++i
)
5182 if (scr
== dpy
->screens
+ i
)
5188 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5191 /* Select the visual that should be used on display DPYINFO. Set
5192 members of DPYINFO appropriately. Called from x_term_init. */
5195 select_visual (dpyinfo
)
5196 struct x_display_info
*dpyinfo
;
5198 Display
*dpy
= dpyinfo
->display
;
5199 Screen
*screen
= dpyinfo
->screen
;
5202 /* See if a visual is specified. */
5203 value
= display_x_get_resource (dpyinfo
,
5204 build_string ("visualClass"),
5205 build_string ("VisualClass"),
5207 if (STRINGP (value
))
5209 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5210 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5211 depth, a decimal number. NAME is compared with case ignored. */
5212 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
5217 strcpy (s
, XSTRING (value
)->data
);
5218 dash
= index (s
, '-');
5221 dpyinfo
->n_planes
= atoi (dash
+ 1);
5225 /* We won't find a matching visual with depth 0, so that
5226 an error will be printed below. */
5227 dpyinfo
->n_planes
= 0;
5229 /* Determine the visual class. */
5230 for (i
= 0; visual_classes
[i
].name
; ++i
)
5231 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5233 class = visual_classes
[i
].class;
5237 /* Look up a matching visual for the specified class. */
5239 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5240 dpyinfo
->n_planes
, class, &vinfo
))
5241 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
5243 dpyinfo
->visual
= vinfo
.visual
;
5248 XVisualInfo
*vinfo
, vinfo_template
;
5250 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5253 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5255 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5257 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5258 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5259 &vinfo_template
, &n_visuals
);
5261 fatal ("Can't get proper X visual info");
5263 dpyinfo
->n_planes
= vinfo
->depth
;
5264 XFree ((char *) vinfo
);
5269 /* Return the X display structure for the display named NAME.
5270 Open a new connection if necessary. */
5272 struct x_display_info
*
5273 x_display_info_for_name (name
)
5277 struct x_display_info
*dpyinfo
;
5279 CHECK_STRING (name
);
5281 if (! EQ (Vwindow_system
, intern ("x")))
5282 error ("Not using X Windows");
5284 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5286 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5289 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5294 /* Use this general default value to start with. */
5295 Vx_resource_name
= Vinvocation_name
;
5297 validate_x_resource_name ();
5299 dpyinfo
= x_term_init (name
, (char *)0,
5300 (char *) XSTRING (Vx_resource_name
)->data
);
5303 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5306 XSETFASTINT (Vwindow_system_version
, 11);
5312 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5314 doc
: /* Open a connection to an X server.
5315 DISPLAY is the name of the display to connect to.
5316 Optional second arg XRM-STRING is a string of resources in xrdb format.
5317 If the optional third arg MUST-SUCCEED is non-nil,
5318 terminate Emacs if we can't open the connection. */)
5319 (display
, xrm_string
, must_succeed
)
5320 Lisp_Object display
, xrm_string
, must_succeed
;
5322 unsigned char *xrm_option
;
5323 struct x_display_info
*dpyinfo
;
5325 CHECK_STRING (display
);
5326 if (! NILP (xrm_string
))
5327 CHECK_STRING (xrm_string
);
5329 if (! EQ (Vwindow_system
, intern ("x")))
5330 error ("Not using X Windows");
5332 if (! NILP (xrm_string
))
5333 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5335 xrm_option
= (unsigned char *) 0;
5337 validate_x_resource_name ();
5339 /* This is what opens the connection and sets x_current_display.
5340 This also initializes many symbols, such as those used for input. */
5341 dpyinfo
= x_term_init (display
, xrm_option
,
5342 (char *) XSTRING (Vx_resource_name
)->data
);
5346 if (!NILP (must_succeed
))
5347 fatal ("Cannot connect to X server %s.\n\
5348 Check the DISPLAY environment variable or use `-d'.\n\
5349 Also use the `xhost' program to verify that it is set to permit\n\
5350 connections from your machine.\n",
5351 XSTRING (display
)->data
);
5353 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5358 XSETFASTINT (Vwindow_system_version
, 11);
5362 DEFUN ("x-close-connection", Fx_close_connection
,
5363 Sx_close_connection
, 1, 1, 0,
5364 doc
: /* Close the connection to DISPLAY's X server.
5365 For DISPLAY, specify either a frame or a display name (a string).
5366 If DISPLAY is nil, that stands for the selected frame's display. */)
5368 Lisp_Object display
;
5370 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5373 if (dpyinfo
->reference_count
> 0)
5374 error ("Display still has frames on it");
5377 /* Free the fonts in the font table. */
5378 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5379 if (dpyinfo
->font_table
[i
].name
)
5381 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5382 xfree (dpyinfo
->font_table
[i
].full_name
);
5383 xfree (dpyinfo
->font_table
[i
].name
);
5384 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5387 x_destroy_all_bitmaps (dpyinfo
);
5388 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5390 #ifdef USE_X_TOOLKIT
5391 XtCloseDisplay (dpyinfo
->display
);
5393 XCloseDisplay (dpyinfo
->display
);
5396 x_delete_display (dpyinfo
);
5402 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5403 doc
: /* Return the list of display names that Emacs has connections to. */)
5406 Lisp_Object tail
, result
;
5409 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5410 result
= Fcons (XCAR (XCAR (tail
)), result
);
5415 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5416 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5417 If ON is nil, allow buffering of requests.
5418 Turning on synchronization prohibits the Xlib routines from buffering
5419 requests and seriously degrades performance, but makes debugging much
5421 The optional second argument DISPLAY specifies which display to act on.
5422 DISPLAY should be either a frame or a display name (a string).
5423 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5425 Lisp_Object display
, on
;
5427 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5429 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5434 /* Wait for responses to all X commands issued so far for frame F. */
5441 XSync (FRAME_X_DISPLAY (f
), False
);
5446 /***********************************************************************
5448 ***********************************************************************/
5450 /* Value is the number of elements of vector VECTOR. */
5452 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5454 /* List of supported image types. Use define_image_type to add new
5455 types. Use lookup_image_type to find a type for a given symbol. */
5457 static struct image_type
*image_types
;
5459 /* The symbol `image' which is the car of the lists used to represent
5462 extern Lisp_Object Qimage
;
5464 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5470 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5471 extern Lisp_Object QCdata
, QCtype
;
5472 Lisp_Object QCascent
, QCmargin
, QCrelief
;
5473 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5474 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5476 /* Other symbols. */
5478 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5480 /* Time in seconds after which images should be removed from the cache
5481 if not displayed. */
5483 Lisp_Object Vimage_cache_eviction_delay
;
5485 /* Function prototypes. */
5487 static void define_image_type
P_ ((struct image_type
*type
));
5488 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5489 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5490 static void x_laplace
P_ ((struct frame
*, struct image
*));
5491 static void x_emboss
P_ ((struct frame
*, struct image
*));
5492 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5496 /* Define a new image type from TYPE. This adds a copy of TYPE to
5497 image_types and adds the symbol *TYPE->type to Vimage_types. */
5500 define_image_type (type
)
5501 struct image_type
*type
;
5503 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5504 The initialized data segment is read-only. */
5505 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5506 bcopy (type
, p
, sizeof *p
);
5507 p
->next
= image_types
;
5509 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5513 /* Look up image type SYMBOL, and return a pointer to its image_type
5514 structure. Value is null if SYMBOL is not a known image type. */
5516 static INLINE
struct image_type
*
5517 lookup_image_type (symbol
)
5520 struct image_type
*type
;
5522 for (type
= image_types
; type
; type
= type
->next
)
5523 if (EQ (symbol
, *type
->type
))
5530 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5531 valid image specification is a list whose car is the symbol
5532 `image', and whose rest is a property list. The property list must
5533 contain a value for key `:type'. That value must be the name of a
5534 supported image type. The rest of the property list depends on the
5538 valid_image_p (object
)
5543 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5547 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5548 if (EQ (XCAR (tem
), QCtype
))
5551 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5553 struct image_type
*type
;
5554 type
= lookup_image_type (XCAR (tem
));
5556 valid_p
= type
->valid_p (object
);
5567 /* Log error message with format string FORMAT and argument ARG.
5568 Signaling an error, e.g. when an image cannot be loaded, is not a
5569 good idea because this would interrupt redisplay, and the error
5570 message display would lead to another redisplay. This function
5571 therefore simply displays a message. */
5574 image_error (format
, arg1
, arg2
)
5576 Lisp_Object arg1
, arg2
;
5578 add_to_log (format
, arg1
, arg2
);
5583 /***********************************************************************
5584 Image specifications
5585 ***********************************************************************/
5587 enum image_value_type
5589 IMAGE_DONT_CHECK_VALUE_TYPE
,
5591 IMAGE_STRING_OR_NIL_VALUE
,
5593 IMAGE_POSITIVE_INTEGER_VALUE
,
5594 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5595 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5597 IMAGE_INTEGER_VALUE
,
5598 IMAGE_FUNCTION_VALUE
,
5603 /* Structure used when parsing image specifications. */
5605 struct image_keyword
5607 /* Name of keyword. */
5610 /* The type of value allowed. */
5611 enum image_value_type type
;
5613 /* Non-zero means key must be present. */
5616 /* Used to recognize duplicate keywords in a property list. */
5619 /* The value that was found. */
5624 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5626 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5629 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5630 has the format (image KEYWORD VALUE ...). One of the keyword/
5631 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5632 image_keywords structures of size NKEYWORDS describing other
5633 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5636 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5638 struct image_keyword
*keywords
;
5645 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5648 plist
= XCDR (spec
);
5649 while (CONSP (plist
))
5651 Lisp_Object key
, value
;
5653 /* First element of a pair must be a symbol. */
5655 plist
= XCDR (plist
);
5659 /* There must follow a value. */
5662 value
= XCAR (plist
);
5663 plist
= XCDR (plist
);
5665 /* Find key in KEYWORDS. Error if not found. */
5666 for (i
= 0; i
< nkeywords
; ++i
)
5667 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5673 /* Record that we recognized the keyword. If a keywords
5674 was found more than once, it's an error. */
5675 keywords
[i
].value
= value
;
5676 ++keywords
[i
].count
;
5678 if (keywords
[i
].count
> 1)
5681 /* Check type of value against allowed type. */
5682 switch (keywords
[i
].type
)
5684 case IMAGE_STRING_VALUE
:
5685 if (!STRINGP (value
))
5689 case IMAGE_STRING_OR_NIL_VALUE
:
5690 if (!STRINGP (value
) && !NILP (value
))
5694 case IMAGE_SYMBOL_VALUE
:
5695 if (!SYMBOLP (value
))
5699 case IMAGE_POSITIVE_INTEGER_VALUE
:
5700 if (!INTEGERP (value
) || XINT (value
) <= 0)
5704 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5705 if (INTEGERP (value
) && XINT (value
) >= 0)
5708 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5709 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5713 case IMAGE_ASCENT_VALUE
:
5714 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5716 else if (INTEGERP (value
)
5717 && XINT (value
) >= 0
5718 && XINT (value
) <= 100)
5722 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5723 if (!INTEGERP (value
) || XINT (value
) < 0)
5727 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5730 case IMAGE_FUNCTION_VALUE
:
5731 value
= indirect_function (value
);
5733 || COMPILEDP (value
)
5734 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5738 case IMAGE_NUMBER_VALUE
:
5739 if (!INTEGERP (value
) && !FLOATP (value
))
5743 case IMAGE_INTEGER_VALUE
:
5744 if (!INTEGERP (value
))
5748 case IMAGE_BOOL_VALUE
:
5749 if (!NILP (value
) && !EQ (value
, Qt
))
5758 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5762 /* Check that all mandatory fields are present. */
5763 for (i
= 0; i
< nkeywords
; ++i
)
5764 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5767 return NILP (plist
);
5771 /* Return the value of KEY in image specification SPEC. Value is nil
5772 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5773 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5776 image_spec_value (spec
, key
, found
)
5777 Lisp_Object spec
, key
;
5782 xassert (valid_image_p (spec
));
5784 for (tail
= XCDR (spec
);
5785 CONSP (tail
) && CONSP (XCDR (tail
));
5786 tail
= XCDR (XCDR (tail
)))
5788 if (EQ (XCAR (tail
), key
))
5792 return XCAR (XCDR (tail
));
5802 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5803 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5804 PIXELS non-nil means return the size in pixels, otherwise return the
5805 size in canonical character units.
5806 FRAME is the frame on which the image will be displayed. FRAME nil
5807 or omitted means use the selected frame. */)
5808 (spec
, pixels
, frame
)
5809 Lisp_Object spec
, pixels
, frame
;
5814 if (valid_image_p (spec
))
5816 struct frame
*f
= check_x_frame (frame
);
5817 int id
= lookup_image (f
, spec
);
5818 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5819 int width
= img
->width
+ 2 * img
->hmargin
;
5820 int height
= img
->height
+ 2 * img
->vmargin
;
5823 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5824 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5826 size
= Fcons (make_number (width
), make_number (height
));
5829 error ("Invalid image specification");
5835 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5836 doc
: /* Return t if image SPEC has a mask bitmap.
5837 FRAME is the frame on which the image will be displayed. FRAME nil
5838 or omitted means use the selected frame. */)
5840 Lisp_Object spec
, frame
;
5845 if (valid_image_p (spec
))
5847 struct frame
*f
= check_x_frame (frame
);
5848 int id
= lookup_image (f
, spec
);
5849 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5854 error ("Invalid image specification");
5861 /***********************************************************************
5862 Image type independent image structures
5863 ***********************************************************************/
5865 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5866 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5869 /* Allocate and return a new image structure for image specification
5870 SPEC. SPEC has a hash value of HASH. */
5872 static struct image
*
5873 make_image (spec
, hash
)
5877 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5879 xassert (valid_image_p (spec
));
5880 bzero (img
, sizeof *img
);
5881 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5882 xassert (img
->type
!= NULL
);
5884 img
->data
.lisp_val
= Qnil
;
5885 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5891 /* Free image IMG which was used on frame F, including its resources. */
5900 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5902 /* Remove IMG from the hash table of its cache. */
5904 img
->prev
->next
= img
->next
;
5906 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5909 img
->next
->prev
= img
->prev
;
5911 c
->images
[img
->id
] = NULL
;
5913 /* Free resources, then free IMG. */
5914 img
->type
->free (f
, img
);
5920 /* Prepare image IMG for display on frame F. Must be called before
5921 drawing an image. */
5924 prepare_image_for_display (f
, img
)
5930 /* We're about to display IMG, so set its timestamp to `now'. */
5932 img
->timestamp
= EMACS_SECS (t
);
5934 /* If IMG doesn't have a pixmap yet, load it now, using the image
5935 type dependent loader function. */
5936 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5937 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5941 /* Value is the number of pixels for the ascent of image IMG when
5942 drawn in face FACE. */
5945 image_ascent (img
, face
)
5949 int height
= img
->height
+ img
->vmargin
;
5952 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5955 /* This expression is arranged so that if the image can't be
5956 exactly centered, it will be moved slightly up. This is
5957 because a typical font is `top-heavy' (due to the presence
5958 uppercase letters), so the image placement should err towards
5959 being top-heavy too. It also just generally looks better. */
5960 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5962 ascent
= height
/ 2;
5965 ascent
= height
* img
->ascent
/ 100.0;
5971 /* Image background colors. */
5973 static unsigned long
5974 four_corners_best (ximg
, width
, height
)
5976 unsigned long width
, height
;
5978 unsigned long corners
[4], best
;
5981 /* Get the colors at the corners of ximg. */
5982 corners
[0] = XGetPixel (ximg
, 0, 0);
5983 corners
[1] = XGetPixel (ximg
, width
- 1, 0);
5984 corners
[2] = XGetPixel (ximg
, width
- 1, height
- 1);
5985 corners
[3] = XGetPixel (ximg
, 0, height
- 1);
5987 /* Choose the most frequently found color as background. */
5988 for (i
= best_count
= 0; i
< 4; ++i
)
5992 for (j
= n
= 0; j
< 4; ++j
)
5993 if (corners
[i
] == corners
[j
])
5997 best
= corners
[i
], best_count
= n
;
6003 /* Return the `background' field of IMG. If IMG doesn't have one yet,
6004 it is guessed heuristically. If non-zero, XIMG is an existing XImage
6005 object to use for the heuristic. */
6008 image_background (img
, f
, ximg
)
6013 if (! img
->background_valid
)
6014 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6016 int free_ximg
= !ximg
;
6019 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
6020 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6022 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
6025 XDestroyImage (ximg
);
6027 img
->background_valid
= 1;
6030 return img
->background
;
6033 /* Return the `background_transparent' field of IMG. If IMG doesn't
6034 have one yet, it is guessed heuristically. If non-zero, MASK is an
6035 existing XImage object to use for the heuristic. */
6038 image_background_transparent (img
, f
, mask
)
6043 if (! img
->background_transparent_valid
)
6044 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6048 int free_mask
= !mask
;
6051 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
6052 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6054 img
->background_transparent
6055 = !four_corners_best (mask
, img
->width
, img
->height
);
6058 XDestroyImage (mask
);
6061 img
->background_transparent
= 0;
6063 img
->background_transparent_valid
= 1;
6066 return img
->background_transparent
;
6070 /***********************************************************************
6071 Helper functions for X image types
6072 ***********************************************************************/
6074 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
6076 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
6077 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
6079 Lisp_Object color_name
,
6080 unsigned long dflt
));
6083 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6084 free the pixmap if any. MASK_P non-zero means clear the mask
6085 pixmap if any. COLORS_P non-zero means free colors allocated for
6086 the image, if any. */
6089 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
6092 int pixmap_p
, mask_p
, colors_p
;
6094 if (pixmap_p
&& img
->pixmap
)
6096 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6098 img
->background_valid
= 0;
6101 if (mask_p
&& img
->mask
)
6103 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6105 img
->background_transparent_valid
= 0;
6108 if (colors_p
&& img
->ncolors
)
6110 x_free_colors (f
, img
->colors
, img
->ncolors
);
6111 xfree (img
->colors
);
6117 /* Free X resources of image IMG which is used on frame F. */
6120 x_clear_image (f
, img
)
6125 x_clear_image_1 (f
, img
, 1, 1, 1);
6130 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6131 cannot be allocated, use DFLT. Add a newly allocated color to
6132 IMG->colors, so that it can be freed again. Value is the pixel
6135 static unsigned long
6136 x_alloc_image_color (f
, img
, color_name
, dflt
)
6139 Lisp_Object color_name
;
6143 unsigned long result
;
6145 xassert (STRINGP (color_name
));
6147 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
6149 /* This isn't called frequently so we get away with simply
6150 reallocating the color vector to the needed size, here. */
6153 (unsigned long *) xrealloc (img
->colors
,
6154 img
->ncolors
* sizeof *img
->colors
);
6155 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
6156 result
= color
.pixel
;
6166 /***********************************************************************
6168 ***********************************************************************/
6170 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
6171 static void postprocess_image
P_ ((struct frame
*, struct image
*));
6174 /* Return a new, initialized image cache that is allocated from the
6175 heap. Call free_image_cache to free an image cache. */
6177 struct image_cache
*
6180 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
6183 bzero (c
, sizeof *c
);
6185 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
6186 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
6187 c
->buckets
= (struct image
**) xmalloc (size
);
6188 bzero (c
->buckets
, size
);
6193 /* Free image cache of frame F. Be aware that X frames share images
6197 free_image_cache (f
)
6200 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6205 /* Cache should not be referenced by any frame when freed. */
6206 xassert (c
->refcount
== 0);
6208 for (i
= 0; i
< c
->used
; ++i
)
6209 free_image (f
, c
->images
[i
]);
6213 FRAME_X_IMAGE_CACHE (f
) = NULL
;
6218 /* Clear image cache of frame F. FORCE_P non-zero means free all
6219 images. FORCE_P zero means clear only images that haven't been
6220 displayed for some time. Should be called from time to time to
6221 reduce the number of loaded images. If image-eviction-seconds is
6222 non-nil, this frees images in the cache which weren't displayed for
6223 at least that many seconds. */
6226 clear_image_cache (f
, force_p
)
6230 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6232 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
6239 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
6241 /* Block input so that we won't be interrupted by a SIGIO
6242 while being in an inconsistent state. */
6245 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
6247 struct image
*img
= c
->images
[i
];
6249 && (force_p
|| img
->timestamp
< old
))
6251 free_image (f
, img
);
6256 /* We may be clearing the image cache because, for example,
6257 Emacs was iconified for a longer period of time. In that
6258 case, current matrices may still contain references to
6259 images freed above. So, clear these matrices. */
6262 Lisp_Object tail
, frame
;
6264 FOR_EACH_FRAME (tail
, frame
)
6266 struct frame
*f
= XFRAME (frame
);
6268 && FRAME_X_IMAGE_CACHE (f
) == c
)
6269 clear_current_matrices (f
);
6272 ++windows_or_buffers_changed
;
6280 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
6282 doc
: /* Clear the image cache of FRAME.
6283 FRAME nil or omitted means use the selected frame.
6284 FRAME t means clear the image caches of all frames. */)
6292 FOR_EACH_FRAME (tail
, frame
)
6293 if (FRAME_X_P (XFRAME (frame
)))
6294 clear_image_cache (XFRAME (frame
), 1);
6297 clear_image_cache (check_x_frame (frame
), 1);
6303 /* Compute masks and transform image IMG on frame F, as specified
6304 by the image's specification, */
6307 postprocess_image (f
, img
)
6311 /* Manipulation of the image's mask. */
6314 Lisp_Object conversion
, spec
;
6319 /* `:heuristic-mask t'
6321 means build a mask heuristically.
6322 `:heuristic-mask (R G B)'
6323 `:mask (heuristic (R G B))'
6324 means build a mask from color (R G B) in the
6327 means remove a mask, if any. */
6329 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6331 x_build_heuristic_mask (f
, img
, mask
);
6336 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6338 if (EQ (mask
, Qheuristic
))
6339 x_build_heuristic_mask (f
, img
, Qt
);
6340 else if (CONSP (mask
)
6341 && EQ (XCAR (mask
), Qheuristic
))
6343 if (CONSP (XCDR (mask
)))
6344 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6346 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6348 else if (NILP (mask
) && found_p
&& img
->mask
)
6350 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6356 /* Should we apply an image transformation algorithm? */
6357 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6358 if (EQ (conversion
, Qdisabled
))
6359 x_disable_image (f
, img
);
6360 else if (EQ (conversion
, Qlaplace
))
6362 else if (EQ (conversion
, Qemboss
))
6364 else if (CONSP (conversion
)
6365 && EQ (XCAR (conversion
), Qedge_detection
))
6368 tem
= XCDR (conversion
);
6370 x_edge_detection (f
, img
,
6371 Fplist_get (tem
, QCmatrix
),
6372 Fplist_get (tem
, QCcolor_adjustment
));
6378 /* Return the id of image with Lisp specification SPEC on frame F.
6379 SPEC must be a valid Lisp image specification (see valid_image_p). */
6382 lookup_image (f
, spec
)
6386 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6390 struct gcpro gcpro1
;
6393 /* F must be a window-system frame, and SPEC must be a valid image
6395 xassert (FRAME_WINDOW_P (f
));
6396 xassert (valid_image_p (spec
));
6400 /* Look up SPEC in the hash table of the image cache. */
6401 hash
= sxhash (spec
, 0);
6402 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6404 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6405 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6408 /* If not found, create a new image and cache it. */
6411 extern Lisp_Object Qpostscript
;
6414 img
= make_image (spec
, hash
);
6415 cache_image (f
, img
);
6416 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6418 /* If we can't load the image, and we don't have a width and
6419 height, use some arbitrary width and height so that we can
6420 draw a rectangle for it. */
6421 if (img
->load_failed_p
)
6425 value
= image_spec_value (spec
, QCwidth
, NULL
);
6426 img
->width
= (INTEGERP (value
)
6427 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6428 value
= image_spec_value (spec
, QCheight
, NULL
);
6429 img
->height
= (INTEGERP (value
)
6430 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6434 /* Handle image type independent image attributes
6435 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6436 `:background COLOR'. */
6437 Lisp_Object ascent
, margin
, relief
, bg
;
6439 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6440 if (INTEGERP (ascent
))
6441 img
->ascent
= XFASTINT (ascent
);
6442 else if (EQ (ascent
, Qcenter
))
6443 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6445 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6446 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6447 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6448 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6449 && INTEGERP (XCDR (margin
)))
6451 if (XINT (XCAR (margin
)) > 0)
6452 img
->hmargin
= XFASTINT (XCAR (margin
));
6453 if (XINT (XCDR (margin
)) > 0)
6454 img
->vmargin
= XFASTINT (XCDR (margin
));
6457 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6458 if (INTEGERP (relief
))
6460 img
->relief
= XINT (relief
);
6461 img
->hmargin
+= abs (img
->relief
);
6462 img
->vmargin
+= abs (img
->relief
);
6465 if (! img
->background_valid
)
6467 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6471 = x_alloc_image_color (f
, img
, bg
,
6472 FRAME_BACKGROUND_PIXEL (f
));
6473 img
->background_valid
= 1;
6477 /* Do image transformations and compute masks, unless we
6478 don't have the image yet. */
6479 if (!EQ (*img
->type
->type
, Qpostscript
))
6480 postprocess_image (f
, img
);
6484 xassert (!interrupt_input_blocked
);
6487 /* We're using IMG, so set its timestamp to `now'. */
6488 EMACS_GET_TIME (now
);
6489 img
->timestamp
= EMACS_SECS (now
);
6493 /* Value is the image id. */
6498 /* Cache image IMG in the image cache of frame F. */
6501 cache_image (f
, img
)
6505 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6508 /* Find a free slot in c->images. */
6509 for (i
= 0; i
< c
->used
; ++i
)
6510 if (c
->images
[i
] == NULL
)
6513 /* If no free slot found, maybe enlarge c->images. */
6514 if (i
== c
->used
&& c
->used
== c
->size
)
6517 c
->images
= (struct image
**) xrealloc (c
->images
,
6518 c
->size
* sizeof *c
->images
);
6521 /* Add IMG to c->images, and assign IMG an id. */
6527 /* Add IMG to the cache's hash table. */
6528 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6529 img
->next
= c
->buckets
[i
];
6531 img
->next
->prev
= img
;
6533 c
->buckets
[i
] = img
;
6537 /* Call FN on every image in the image cache of frame F. Used to mark
6538 Lisp Objects in the image cache. */
6541 forall_images_in_image_cache (f
, fn
)
6543 void (*fn
) P_ ((struct image
*img
));
6545 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6547 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6551 for (i
= 0; i
< c
->used
; ++i
)
6560 /***********************************************************************
6562 ***********************************************************************/
6564 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6565 XImage
**, Pixmap
*));
6566 static void x_destroy_x_image
P_ ((XImage
*));
6567 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6570 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6571 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6572 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6573 via xmalloc. Print error messages via image_error if an error
6574 occurs. Value is non-zero if successful. */
6577 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6579 int width
, height
, depth
;
6583 Display
*display
= FRAME_X_DISPLAY (f
);
6584 Screen
*screen
= FRAME_X_SCREEN (f
);
6585 Window window
= FRAME_X_WINDOW (f
);
6587 xassert (interrupt_input_blocked
);
6590 depth
= DefaultDepthOfScreen (screen
);
6591 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6592 depth
, ZPixmap
, 0, NULL
, width
, height
,
6593 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6596 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6600 /* Allocate image raster. */
6601 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6603 /* Allocate a pixmap of the same size. */
6604 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6605 if (*pixmap
== None
)
6607 x_destroy_x_image (*ximg
);
6609 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6617 /* Destroy XImage XIMG. Free XIMG->data. */
6620 x_destroy_x_image (ximg
)
6623 xassert (interrupt_input_blocked
);
6628 XDestroyImage (ximg
);
6633 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6634 are width and height of both the image and pixmap. */
6637 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6644 xassert (interrupt_input_blocked
);
6645 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6646 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6647 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6652 /***********************************************************************
6654 ***********************************************************************/
6656 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6657 static char *slurp_file
P_ ((char *, int *));
6660 /* Find image file FILE. Look in data-directory, then
6661 x-bitmap-file-path. Value is the full name of the file found, or
6662 nil if not found. */
6665 x_find_image_file (file
)
6668 Lisp_Object file_found
, search_path
;
6669 struct gcpro gcpro1
, gcpro2
;
6673 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6674 GCPRO2 (file_found
, search_path
);
6676 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6677 fd
= openp (search_path
, file
, Qnil
, &file_found
, 0);
6689 /* Read FILE into memory. Value is a pointer to a buffer allocated
6690 with xmalloc holding FILE's contents. Value is null if an error
6691 occurred. *SIZE is set to the size of the file. */
6694 slurp_file (file
, size
)
6702 if (stat (file
, &st
) == 0
6703 && (fp
= fopen (file
, "r")) != NULL
6704 && (buf
= (char *) xmalloc (st
.st_size
),
6705 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6726 /***********************************************************************
6728 ***********************************************************************/
6730 static int xbm_scan
P_ ((char **, char *, char *, int *));
6731 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6732 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6734 static int xbm_image_p
P_ ((Lisp_Object object
));
6735 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6737 static int xbm_file_p
P_ ((Lisp_Object
));
6740 /* Indices of image specification fields in xbm_format, below. */
6742 enum xbm_keyword_index
6760 /* Vector of image_keyword structures describing the format
6761 of valid XBM image specifications. */
6763 static struct image_keyword xbm_format
[XBM_LAST
] =
6765 {":type", IMAGE_SYMBOL_VALUE
, 1},
6766 {":file", IMAGE_STRING_VALUE
, 0},
6767 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6768 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6769 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6770 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6771 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6772 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6773 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6774 {":relief", IMAGE_INTEGER_VALUE
, 0},
6775 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6776 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6777 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6780 /* Structure describing the image type XBM. */
6782 static struct image_type xbm_type
=
6791 /* Tokens returned from xbm_scan. */
6800 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6801 A valid specification is a list starting with the symbol `image'
6802 The rest of the list is a property list which must contain an
6805 If the specification specifies a file to load, it must contain
6806 an entry `:file FILENAME' where FILENAME is a string.
6808 If the specification is for a bitmap loaded from memory it must
6809 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6810 WIDTH and HEIGHT are integers > 0. DATA may be:
6812 1. a string large enough to hold the bitmap data, i.e. it must
6813 have a size >= (WIDTH + 7) / 8 * HEIGHT
6815 2. a bool-vector of size >= WIDTH * HEIGHT
6817 3. a vector of strings or bool-vectors, one for each line of the
6820 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6821 may not be specified in this case because they are defined in the
6824 Both the file and data forms may contain the additional entries
6825 `:background COLOR' and `:foreground COLOR'. If not present,
6826 foreground and background of the frame on which the image is
6827 displayed is used. */
6830 xbm_image_p (object
)
6833 struct image_keyword kw
[XBM_LAST
];
6835 bcopy (xbm_format
, kw
, sizeof kw
);
6836 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6839 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6841 if (kw
[XBM_FILE
].count
)
6843 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6846 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6848 /* In-memory XBM file. */
6849 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6857 /* Entries for `:width', `:height' and `:data' must be present. */
6858 if (!kw
[XBM_WIDTH
].count
6859 || !kw
[XBM_HEIGHT
].count
6860 || !kw
[XBM_DATA
].count
)
6863 data
= kw
[XBM_DATA
].value
;
6864 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6865 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6867 /* Check type of data, and width and height against contents of
6873 /* Number of elements of the vector must be >= height. */
6874 if (XVECTOR (data
)->size
< height
)
6877 /* Each string or bool-vector in data must be large enough
6878 for one line of the image. */
6879 for (i
= 0; i
< height
; ++i
)
6881 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6885 if (XSTRING (elt
)->size
6886 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6889 else if (BOOL_VECTOR_P (elt
))
6891 if (XBOOL_VECTOR (elt
)->size
< width
)
6898 else if (STRINGP (data
))
6900 if (XSTRING (data
)->size
6901 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6904 else if (BOOL_VECTOR_P (data
))
6906 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6917 /* Scan a bitmap file. FP is the stream to read from. Value is
6918 either an enumerator from enum xbm_token, or a character for a
6919 single-character token, or 0 at end of file. If scanning an
6920 identifier, store the lexeme of the identifier in SVAL. If
6921 scanning a number, store its value in *IVAL. */
6924 xbm_scan (s
, end
, sval
, ival
)
6933 /* Skip white space. */
6934 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6939 else if (isdigit (c
))
6941 int value
= 0, digit
;
6943 if (c
== '0' && *s
< end
)
6946 if (c
== 'x' || c
== 'X')
6953 else if (c
>= 'a' && c
<= 'f')
6954 digit
= c
- 'a' + 10;
6955 else if (c
>= 'A' && c
<= 'F')
6956 digit
= c
- 'A' + 10;
6959 value
= 16 * value
+ digit
;
6962 else if (isdigit (c
))
6966 && (c
= *(*s
)++, isdigit (c
)))
6967 value
= 8 * value
+ c
- '0';
6974 && (c
= *(*s
)++, isdigit (c
)))
6975 value
= 10 * value
+ c
- '0';
6983 else if (isalpha (c
) || c
== '_')
6987 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6994 else if (c
== '/' && **s
== '*')
6996 /* C-style comment. */
6998 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
7011 /* Replacement for XReadBitmapFileData which isn't available under old
7012 X versions. CONTENTS is a pointer to a buffer to parse; END is the
7013 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
7014 the image. Return in *DATA the bitmap data allocated with xmalloc.
7015 Value is non-zero if successful. DATA null means just test if
7016 CONTENTS looks like an in-memory XBM file. */
7019 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
7020 char *contents
, *end
;
7021 int *width
, *height
;
7022 unsigned char **data
;
7025 char buffer
[BUFSIZ
];
7028 int bytes_per_line
, i
, nbytes
;
7034 LA1 = xbm_scan (&s, end, buffer, &value)
7036 #define expect(TOKEN) \
7037 if (LA1 != (TOKEN)) \
7042 #define expect_ident(IDENT) \
7043 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
7048 *width
= *height
= -1;
7051 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
7053 /* Parse defines for width, height and hot-spots. */
7057 expect_ident ("define");
7058 expect (XBM_TK_IDENT
);
7060 if (LA1
== XBM_TK_NUMBER
);
7062 char *p
= strrchr (buffer
, '_');
7063 p
= p
? p
+ 1 : buffer
;
7064 if (strcmp (p
, "width") == 0)
7066 else if (strcmp (p
, "height") == 0)
7069 expect (XBM_TK_NUMBER
);
7072 if (*width
< 0 || *height
< 0)
7074 else if (data
== NULL
)
7077 /* Parse bits. Must start with `static'. */
7078 expect_ident ("static");
7079 if (LA1
== XBM_TK_IDENT
)
7081 if (strcmp (buffer
, "unsigned") == 0)
7084 expect_ident ("char");
7086 else if (strcmp (buffer
, "short") == 0)
7090 if (*width
% 16 && *width
% 16 < 9)
7093 else if (strcmp (buffer
, "char") == 0)
7101 expect (XBM_TK_IDENT
);
7107 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
7108 nbytes
= bytes_per_line
* *height
;
7109 p
= *data
= (char *) xmalloc (nbytes
);
7113 for (i
= 0; i
< nbytes
; i
+= 2)
7116 expect (XBM_TK_NUMBER
);
7119 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
7122 if (LA1
== ',' || LA1
== '}')
7130 for (i
= 0; i
< nbytes
; ++i
)
7133 expect (XBM_TK_NUMBER
);
7137 if (LA1
== ',' || LA1
== '}')
7162 /* Load XBM image IMG which will be displayed on frame F from buffer
7163 CONTENTS. END is the end of the buffer. Value is non-zero if
7167 xbm_load_image (f
, img
, contents
, end
)
7170 char *contents
, *end
;
7173 unsigned char *data
;
7176 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
7179 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7180 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7181 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7184 xassert (img
->width
> 0 && img
->height
> 0);
7186 /* Get foreground and background colors, maybe allocate colors. */
7187 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
7189 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
7190 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7193 background
= x_alloc_image_color (f
, img
, value
, background
);
7194 img
->background
= background
;
7195 img
->background_valid
= 1;
7199 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7202 img
->width
, img
->height
,
7203 foreground
, background
,
7207 if (img
->pixmap
== None
)
7209 x_clear_image (f
, img
);
7210 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
7216 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7222 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7229 return (STRINGP (data
)
7230 && xbm_read_bitmap_data (XSTRING (data
)->data
,
7231 (XSTRING (data
)->data
7232 + STRING_BYTES (XSTRING (data
))),
7237 /* Fill image IMG which is used on frame F with pixmap data. Value is
7238 non-zero if successful. */
7246 Lisp_Object file_name
;
7248 xassert (xbm_image_p (img
->spec
));
7250 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7251 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7252 if (STRINGP (file_name
))
7257 struct gcpro gcpro1
;
7259 file
= x_find_image_file (file_name
);
7261 if (!STRINGP (file
))
7263 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7268 contents
= slurp_file (XSTRING (file
)->data
, &size
);
7269 if (contents
== NULL
)
7271 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7276 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
7281 struct image_keyword fmt
[XBM_LAST
];
7284 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7285 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7288 int in_memory_file_p
= 0;
7290 /* See if data looks like an in-memory XBM file. */
7291 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7292 in_memory_file_p
= xbm_file_p (data
);
7294 /* Parse the image specification. */
7295 bcopy (xbm_format
, fmt
, sizeof fmt
);
7296 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
7299 /* Get specified width, and height. */
7300 if (!in_memory_file_p
)
7302 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
7303 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
7304 xassert (img
->width
> 0 && img
->height
> 0);
7307 /* Get foreground and background colors, maybe allocate colors. */
7308 if (fmt
[XBM_FOREGROUND
].count
7309 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
7310 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
7312 if (fmt
[XBM_BACKGROUND
].count
7313 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
7314 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7317 if (in_memory_file_p
)
7318 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
7319 (XSTRING (data
)->data
7320 + STRING_BYTES (XSTRING (data
))));
7327 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7329 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7330 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7332 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7334 bcopy (XSTRING (line
)->data
, p
, nbytes
);
7336 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7339 else if (STRINGP (data
))
7340 bits
= XSTRING (data
)->data
;
7342 bits
= XBOOL_VECTOR (data
)->data
;
7344 /* Create the pixmap. */
7345 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7347 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7350 img
->width
, img
->height
,
7351 foreground
, background
,
7357 image_error ("Unable to create pixmap for XBM image `%s'",
7359 x_clear_image (f
, img
);
7369 /***********************************************************************
7371 ***********************************************************************/
7375 static int xpm_image_p
P_ ((Lisp_Object object
));
7376 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7377 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7379 #include "X11/xpm.h"
7381 /* The symbol `xpm' identifying XPM-format images. */
7385 /* Indices of image specification fields in xpm_format, below. */
7387 enum xpm_keyword_index
7403 /* Vector of image_keyword structures describing the format
7404 of valid XPM image specifications. */
7406 static struct image_keyword xpm_format
[XPM_LAST
] =
7408 {":type", IMAGE_SYMBOL_VALUE
, 1},
7409 {":file", IMAGE_STRING_VALUE
, 0},
7410 {":data", IMAGE_STRING_VALUE
, 0},
7411 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7412 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7413 {":relief", IMAGE_INTEGER_VALUE
, 0},
7414 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7415 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7416 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7417 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7418 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7421 /* Structure describing the image type XBM. */
7423 static struct image_type xpm_type
=
7433 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7434 functions for allocating image colors. Our own functions handle
7435 color allocation failures more gracefully than the ones on the XPM
7438 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7439 #define ALLOC_XPM_COLORS
7442 #ifdef ALLOC_XPM_COLORS
7444 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7445 static void xpm_free_color_cache
P_ ((void));
7446 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7447 static int xpm_color_bucket
P_ ((char *));
7448 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7451 /* An entry in a hash table used to cache color definitions of named
7452 colors. This cache is necessary to speed up XPM image loading in
7453 case we do color allocations ourselves. Without it, we would need
7454 a call to XParseColor per pixel in the image. */
7456 struct xpm_cached_color
7458 /* Next in collision chain. */
7459 struct xpm_cached_color
*next
;
7461 /* Color definition (RGB and pixel color). */
7468 /* The hash table used for the color cache, and its bucket vector
7471 #define XPM_COLOR_CACHE_BUCKETS 1001
7472 struct xpm_cached_color
**xpm_color_cache
;
7474 /* Initialize the color cache. */
7477 xpm_init_color_cache (f
, attrs
)
7479 XpmAttributes
*attrs
;
7481 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7482 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7483 memset (xpm_color_cache
, 0, nbytes
);
7484 init_color_table ();
7486 if (attrs
->valuemask
& XpmColorSymbols
)
7491 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7492 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7493 attrs
->colorsymbols
[i
].value
, &color
))
7495 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7497 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7503 /* Free the color cache. */
7506 xpm_free_color_cache ()
7508 struct xpm_cached_color
*p
, *next
;
7511 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7512 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7518 xfree (xpm_color_cache
);
7519 xpm_color_cache
= NULL
;
7520 free_color_table ();
7524 /* Return the bucket index for color named COLOR_NAME in the color
7528 xpm_color_bucket (color_name
)
7534 for (s
= color_name
; *s
; ++s
)
7536 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7540 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7541 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7544 static struct xpm_cached_color
*
7545 xpm_cache_color (f
, color_name
, color
, bucket
)
7552 struct xpm_cached_color
*p
;
7555 bucket
= xpm_color_bucket (color_name
);
7557 nbytes
= sizeof *p
+ strlen (color_name
);
7558 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7559 strcpy (p
->name
, color_name
);
7561 p
->next
= xpm_color_cache
[bucket
];
7562 xpm_color_cache
[bucket
] = p
;
7567 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7568 return the cached definition in *COLOR. Otherwise, make a new
7569 entry in the cache and allocate the color. Value is zero if color
7570 allocation failed. */
7573 xpm_lookup_color (f
, color_name
, color
)
7578 struct xpm_cached_color
*p
;
7579 int h
= xpm_color_bucket (color_name
);
7581 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7582 if (strcmp (p
->name
, color_name
) == 0)
7587 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7590 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7592 p
= xpm_cache_color (f
, color_name
, color
, h
);
7599 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7600 CLOSURE is a pointer to the frame on which we allocate the
7601 color. Return in *COLOR the allocated color. Value is non-zero
7605 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7612 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7616 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7617 is a pointer to the frame on which we allocate the color. Value is
7618 non-zero if successful. */
7621 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7631 #endif /* ALLOC_XPM_COLORS */
7634 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7635 for XPM images. Such a list must consist of conses whose car and
7639 xpm_valid_color_symbols_p (color_symbols
)
7640 Lisp_Object color_symbols
;
7642 while (CONSP (color_symbols
))
7644 Lisp_Object sym
= XCAR (color_symbols
);
7646 || !STRINGP (XCAR (sym
))
7647 || !STRINGP (XCDR (sym
)))
7649 color_symbols
= XCDR (color_symbols
);
7652 return NILP (color_symbols
);
7656 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7659 xpm_image_p (object
)
7662 struct image_keyword fmt
[XPM_LAST
];
7663 bcopy (xpm_format
, fmt
, sizeof fmt
);
7664 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7665 /* Either `:file' or `:data' must be present. */
7666 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7667 /* Either no `:color-symbols' or it's a list of conses
7668 whose car and cdr are strings. */
7669 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7670 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7674 /* Load image IMG which will be displayed on frame F. Value is
7675 non-zero if successful. */
7683 XpmAttributes attrs
;
7684 Lisp_Object specified_file
, color_symbols
;
7686 /* Configure the XPM lib. Use the visual of frame F. Allocate
7687 close colors. Return colors allocated. */
7688 bzero (&attrs
, sizeof attrs
);
7689 attrs
.visual
= FRAME_X_VISUAL (f
);
7690 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7691 attrs
.valuemask
|= XpmVisual
;
7692 attrs
.valuemask
|= XpmColormap
;
7694 #ifdef ALLOC_XPM_COLORS
7695 /* Allocate colors with our own functions which handle
7696 failing color allocation more gracefully. */
7697 attrs
.color_closure
= f
;
7698 attrs
.alloc_color
= xpm_alloc_color
;
7699 attrs
.free_colors
= xpm_free_colors
;
7700 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7701 #else /* not ALLOC_XPM_COLORS */
7702 /* Let the XPM lib allocate colors. */
7703 attrs
.valuemask
|= XpmReturnAllocPixels
;
7704 #ifdef XpmAllocCloseColors
7705 attrs
.alloc_close_colors
= 1;
7706 attrs
.valuemask
|= XpmAllocCloseColors
;
7707 #else /* not XpmAllocCloseColors */
7708 attrs
.closeness
= 600;
7709 attrs
.valuemask
|= XpmCloseness
;
7710 #endif /* not XpmAllocCloseColors */
7711 #endif /* ALLOC_XPM_COLORS */
7713 /* If image specification contains symbolic color definitions, add
7714 these to `attrs'. */
7715 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7716 if (CONSP (color_symbols
))
7719 XpmColorSymbol
*xpm_syms
;
7722 attrs
.valuemask
|= XpmColorSymbols
;
7724 /* Count number of symbols. */
7725 attrs
.numsymbols
= 0;
7726 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7729 /* Allocate an XpmColorSymbol array. */
7730 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7731 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7732 bzero (xpm_syms
, size
);
7733 attrs
.colorsymbols
= xpm_syms
;
7735 /* Fill the color symbol array. */
7736 for (tail
= color_symbols
, i
= 0;
7738 ++i
, tail
= XCDR (tail
))
7740 Lisp_Object name
= XCAR (XCAR (tail
));
7741 Lisp_Object color
= XCDR (XCAR (tail
));
7742 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7743 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7744 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7745 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7749 /* Create a pixmap for the image, either from a file, or from a
7750 string buffer containing data in the same format as an XPM file. */
7751 #ifdef ALLOC_XPM_COLORS
7752 xpm_init_color_cache (f
, &attrs
);
7755 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7756 if (STRINGP (specified_file
))
7758 Lisp_Object file
= x_find_image_file (specified_file
);
7759 if (!STRINGP (file
))
7761 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7765 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7766 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7771 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7772 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7773 XSTRING (buffer
)->data
,
7774 &img
->pixmap
, &img
->mask
,
7778 if (rc
== XpmSuccess
)
7780 #ifdef ALLOC_XPM_COLORS
7781 img
->colors
= colors_in_color_table (&img
->ncolors
);
7782 #else /* not ALLOC_XPM_COLORS */
7785 img
->ncolors
= attrs
.nalloc_pixels
;
7786 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7787 * sizeof *img
->colors
);
7788 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7790 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7791 #ifdef DEBUG_X_COLORS
7792 register_color (img
->colors
[i
]);
7795 #endif /* not ALLOC_XPM_COLORS */
7797 img
->width
= attrs
.width
;
7798 img
->height
= attrs
.height
;
7799 xassert (img
->width
> 0 && img
->height
> 0);
7801 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7802 XpmFreeAttributes (&attrs
);
7809 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7812 case XpmFileInvalid
:
7813 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7817 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7820 case XpmColorFailed
:
7821 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7825 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7830 #ifdef ALLOC_XPM_COLORS
7831 xpm_free_color_cache ();
7833 return rc
== XpmSuccess
;
7836 #endif /* HAVE_XPM != 0 */
7839 /***********************************************************************
7841 ***********************************************************************/
7843 /* An entry in the color table mapping an RGB color to a pixel color. */
7848 unsigned long pixel
;
7850 /* Next in color table collision list. */
7851 struct ct_color
*next
;
7854 /* The bucket vector size to use. Must be prime. */
7858 /* Value is a hash of the RGB color given by R, G, and B. */
7860 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7862 /* The color hash table. */
7864 struct ct_color
**ct_table
;
7866 /* Number of entries in the color table. */
7868 int ct_colors_allocated
;
7870 /* Initialize the color table. */
7875 int size
= CT_SIZE
* sizeof (*ct_table
);
7876 ct_table
= (struct ct_color
**) xmalloc (size
);
7877 bzero (ct_table
, size
);
7878 ct_colors_allocated
= 0;
7882 /* Free memory associated with the color table. */
7888 struct ct_color
*p
, *next
;
7890 for (i
= 0; i
< CT_SIZE
; ++i
)
7891 for (p
= ct_table
[i
]; p
; p
= next
)
7902 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7903 entry for that color already is in the color table, return the
7904 pixel color of that entry. Otherwise, allocate a new color for R,
7905 G, B, and make an entry in the color table. */
7907 static unsigned long
7908 lookup_rgb_color (f
, r
, g
, b
)
7912 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7913 int i
= hash
% CT_SIZE
;
7916 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7917 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7930 cmap
= FRAME_X_COLORMAP (f
);
7931 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7935 ++ct_colors_allocated
;
7937 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7941 p
->pixel
= color
.pixel
;
7942 p
->next
= ct_table
[i
];
7946 return FRAME_FOREGROUND_PIXEL (f
);
7953 /* Look up pixel color PIXEL which is used on frame F in the color
7954 table. If not already present, allocate it. Value is PIXEL. */
7956 static unsigned long
7957 lookup_pixel_color (f
, pixel
)
7959 unsigned long pixel
;
7961 int i
= pixel
% CT_SIZE
;
7964 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7965 if (p
->pixel
== pixel
)
7974 cmap
= FRAME_X_COLORMAP (f
);
7975 color
.pixel
= pixel
;
7976 x_query_color (f
, &color
);
7977 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7981 ++ct_colors_allocated
;
7983 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7988 p
->next
= ct_table
[i
];
7992 return FRAME_FOREGROUND_PIXEL (f
);
7999 /* Value is a vector of all pixel colors contained in the color table,
8000 allocated via xmalloc. Set *N to the number of colors. */
8002 static unsigned long *
8003 colors_in_color_table (n
)
8008 unsigned long *colors
;
8010 if (ct_colors_allocated
== 0)
8017 colors
= (unsigned long *) xmalloc (ct_colors_allocated
8019 *n
= ct_colors_allocated
;
8021 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
8022 for (p
= ct_table
[i
]; p
; p
= p
->next
)
8023 colors
[j
++] = p
->pixel
;
8031 /***********************************************************************
8033 ***********************************************************************/
8035 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
8036 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
8037 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
8039 /* Non-zero means draw a cross on images having `:conversion
8042 int cross_disabled_images
;
8044 /* Edge detection matrices for different edge-detection
8047 static int emboss_matrix
[9] = {
8049 2, -1, 0, /* y - 1 */
8051 0, 1, -2 /* y + 1 */
8054 static int laplace_matrix
[9] = {
8056 1, 0, 0, /* y - 1 */
8058 0, 0, -1 /* y + 1 */
8061 /* Value is the intensity of the color whose red/green/blue values
8064 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8067 /* On frame F, return an array of XColor structures describing image
8068 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8069 non-zero means also fill the red/green/blue members of the XColor
8070 structures. Value is a pointer to the array of XColors structures,
8071 allocated with xmalloc; it must be freed by the caller. */
8074 x_to_xcolors (f
, img
, rgb_p
)
8083 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
8085 /* Get the X image IMG->pixmap. */
8086 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8087 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8089 /* Fill the `pixel' members of the XColor array. I wished there
8090 were an easy and portable way to circumvent XGetPixel. */
8092 for (y
= 0; y
< img
->height
; ++y
)
8096 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8097 p
->pixel
= XGetPixel (ximg
, x
, y
);
8100 x_query_colors (f
, row
, img
->width
);
8103 XDestroyImage (ximg
);
8108 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8109 RGB members are set. F is the frame on which this all happens.
8110 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8113 x_from_xcolors (f
, img
, colors
)
8123 init_color_table ();
8125 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
8128 for (y
= 0; y
< img
->height
; ++y
)
8129 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8131 unsigned long pixel
;
8132 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
8133 XPutPixel (oimg
, x
, y
, pixel
);
8137 x_clear_image_1 (f
, img
, 1, 0, 1);
8139 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
8140 x_destroy_x_image (oimg
);
8141 img
->pixmap
= pixmap
;
8142 img
->colors
= colors_in_color_table (&img
->ncolors
);
8143 free_color_table ();
8147 /* On frame F, perform edge-detection on image IMG.
8149 MATRIX is a nine-element array specifying the transformation
8150 matrix. See emboss_matrix for an example.
8152 COLOR_ADJUST is a color adjustment added to each pixel of the
8156 x_detect_edges (f
, img
, matrix
, color_adjust
)
8159 int matrix
[9], color_adjust
;
8161 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8165 for (i
= sum
= 0; i
< 9; ++i
)
8166 sum
+= abs (matrix
[i
]);
8168 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8170 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
8172 for (y
= 0; y
< img
->height
; ++y
)
8174 p
= COLOR (new, 0, y
);
8175 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8176 p
= COLOR (new, img
->width
- 1, y
);
8177 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8180 for (x
= 1; x
< img
->width
- 1; ++x
)
8182 p
= COLOR (new, x
, 0);
8183 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8184 p
= COLOR (new, x
, img
->height
- 1);
8185 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8188 for (y
= 1; y
< img
->height
- 1; ++y
)
8190 p
= COLOR (new, 1, y
);
8192 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
8194 int r
, g
, b
, y1
, x1
;
8197 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
8198 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
8201 XColor
*t
= COLOR (colors
, x1
, y1
);
8202 r
+= matrix
[i
] * t
->red
;
8203 g
+= matrix
[i
] * t
->green
;
8204 b
+= matrix
[i
] * t
->blue
;
8207 r
= (r
/ sum
+ color_adjust
) & 0xffff;
8208 g
= (g
/ sum
+ color_adjust
) & 0xffff;
8209 b
= (b
/ sum
+ color_adjust
) & 0xffff;
8210 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
8215 x_from_xcolors (f
, img
, new);
8221 /* Perform the pre-defined `emboss' edge-detection on image IMG
8229 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
8233 /* Perform the pre-defined `laplace' edge-detection on image IMG
8241 x_detect_edges (f
, img
, laplace_matrix
, 45000);
8245 /* Perform edge-detection on image IMG on frame F, with specified
8246 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8248 MATRIX must be either
8250 - a list of at least 9 numbers in row-major form
8251 - a vector of at least 9 numbers
8253 COLOR_ADJUST nil means use a default; otherwise it must be a
8257 x_edge_detection (f
, img
, matrix
, color_adjust
)
8260 Lisp_Object matrix
, color_adjust
;
8268 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
8269 ++i
, matrix
= XCDR (matrix
))
8270 trans
[i
] = XFLOATINT (XCAR (matrix
));
8272 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
8274 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
8275 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
8278 if (NILP (color_adjust
))
8279 color_adjust
= make_number (0xffff / 2);
8281 if (i
== 9 && NUMBERP (color_adjust
))
8282 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
8286 /* Transform image IMG on frame F so that it looks disabled. */
8289 x_disable_image (f
, img
)
8293 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8295 if (dpyinfo
->n_planes
>= 2)
8297 /* Color (or grayscale). Convert to gray, and equalize. Just
8298 drawing such images with a stipple can look very odd, so
8299 we're using this method instead. */
8300 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8302 const int h
= 15000;
8303 const int l
= 30000;
8305 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
8309 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
8310 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
8311 p
->red
= p
->green
= p
->blue
= i2
;
8314 x_from_xcolors (f
, img
, colors
);
8317 /* Draw a cross over the disabled image, if we must or if we
8319 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
8321 Display
*dpy
= FRAME_X_DISPLAY (f
);
8324 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
8325 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
8326 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
8327 img
->width
- 1, img
->height
- 1);
8328 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
8334 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
8335 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8336 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8337 img
->width
- 1, img
->height
- 1);
8338 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8346 /* Build a mask for image IMG which is used on frame F. FILE is the
8347 name of an image file, for error messages. HOW determines how to
8348 determine the background color of IMG. If it is a list '(R G B)',
8349 with R, G, and B being integers >= 0, take that as the color of the
8350 background. Otherwise, determine the background color of IMG
8351 heuristically. Value is non-zero if successful. */
8354 x_build_heuristic_mask (f
, img
, how
)
8359 Display
*dpy
= FRAME_X_DISPLAY (f
);
8360 XImage
*ximg
, *mask_img
;
8361 int x
, y
, rc
, use_img_background
;
8362 unsigned long bg
= 0;
8366 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8368 img
->background_transparent_valid
= 0;
8371 /* Create an image and pixmap serving as mask. */
8372 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8373 &mask_img
, &img
->mask
);
8377 /* Get the X image of IMG->pixmap. */
8378 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8381 /* Determine the background color of ximg. If HOW is `(R G B)'
8382 take that as color. Otherwise, use the image's background color. */
8383 use_img_background
= 1;
8389 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
8391 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8395 if (i
== 3 && NILP (how
))
8397 char color_name
[30];
8398 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8399 bg
= x_alloc_image_color (f
, img
, build_string (color_name
), 0);
8400 use_img_background
= 0;
8404 if (use_img_background
)
8405 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
8407 /* Set all bits in mask_img to 1 whose color in ximg is different
8408 from the background color bg. */
8409 for (y
= 0; y
< img
->height
; ++y
)
8410 for (x
= 0; x
< img
->width
; ++x
)
8411 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8413 /* Fill in the background_transparent field while we have the mask handy. */
8414 image_background_transparent (img
, f
, mask_img
);
8416 /* Put mask_img into img->mask. */
8417 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8418 x_destroy_x_image (mask_img
);
8419 XDestroyImage (ximg
);
8426 /***********************************************************************
8427 PBM (mono, gray, color)
8428 ***********************************************************************/
8430 static int pbm_image_p
P_ ((Lisp_Object object
));
8431 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8432 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8434 /* The symbol `pbm' identifying images of this type. */
8438 /* Indices of image specification fields in gs_format, below. */
8440 enum pbm_keyword_index
8456 /* Vector of image_keyword structures describing the format
8457 of valid user-defined image specifications. */
8459 static struct image_keyword pbm_format
[PBM_LAST
] =
8461 {":type", IMAGE_SYMBOL_VALUE
, 1},
8462 {":file", IMAGE_STRING_VALUE
, 0},
8463 {":data", IMAGE_STRING_VALUE
, 0},
8464 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8465 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8466 {":relief", IMAGE_INTEGER_VALUE
, 0},
8467 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8468 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8469 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8470 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8471 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8474 /* Structure describing the image type `pbm'. */
8476 static struct image_type pbm_type
=
8486 /* Return non-zero if OBJECT is a valid PBM image specification. */
8489 pbm_image_p (object
)
8492 struct image_keyword fmt
[PBM_LAST
];
8494 bcopy (pbm_format
, fmt
, sizeof fmt
);
8496 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8499 /* Must specify either :data or :file. */
8500 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8504 /* Scan a decimal number from *S and return it. Advance *S while
8505 reading the number. END is the end of the string. Value is -1 at
8509 pbm_scan_number (s
, end
)
8510 unsigned char **s
, *end
;
8512 int c
= 0, val
= -1;
8516 /* Skip white-space. */
8517 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8522 /* Skip comment to end of line. */
8523 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8526 else if (isdigit (c
))
8528 /* Read decimal number. */
8530 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8531 val
= 10 * val
+ c
- '0';
8542 /* Load PBM image IMG for use on frame F. */
8550 int width
, height
, max_color_idx
= 0;
8552 Lisp_Object file
, specified_file
;
8553 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8554 struct gcpro gcpro1
;
8555 unsigned char *contents
= NULL
;
8556 unsigned char *end
, *p
;
8559 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8563 if (STRINGP (specified_file
))
8565 file
= x_find_image_file (specified_file
);
8566 if (!STRINGP (file
))
8568 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8573 contents
= slurp_file (XSTRING (file
)->data
, &size
);
8574 if (contents
== NULL
)
8576 image_error ("Error reading `%s'", file
, Qnil
);
8582 end
= contents
+ size
;
8587 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8588 p
= XSTRING (data
)->data
;
8589 end
= p
+ STRING_BYTES (XSTRING (data
));
8592 /* Check magic number. */
8593 if (end
- p
< 2 || *p
++ != 'P')
8595 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8605 raw_p
= 0, type
= PBM_MONO
;
8609 raw_p
= 0, type
= PBM_GRAY
;
8613 raw_p
= 0, type
= PBM_COLOR
;
8617 raw_p
= 1, type
= PBM_MONO
;
8621 raw_p
= 1, type
= PBM_GRAY
;
8625 raw_p
= 1, type
= PBM_COLOR
;
8629 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8633 /* Read width, height, maximum color-component. Characters
8634 starting with `#' up to the end of a line are ignored. */
8635 width
= pbm_scan_number (&p
, end
);
8636 height
= pbm_scan_number (&p
, end
);
8638 if (type
!= PBM_MONO
)
8640 max_color_idx
= pbm_scan_number (&p
, end
);
8641 if (raw_p
&& max_color_idx
> 255)
8642 max_color_idx
= 255;
8647 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8650 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8651 &ximg
, &img
->pixmap
))
8654 /* Initialize the color hash table. */
8655 init_color_table ();
8657 if (type
== PBM_MONO
)
8660 struct image_keyword fmt
[PBM_LAST
];
8661 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8662 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8664 /* Parse the image specification. */
8665 bcopy (pbm_format
, fmt
, sizeof fmt
);
8666 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8668 /* Get foreground and background colors, maybe allocate colors. */
8669 if (fmt
[PBM_FOREGROUND
].count
8670 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8671 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8672 if (fmt
[PBM_BACKGROUND
].count
8673 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8675 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8676 img
->background
= bg
;
8677 img
->background_valid
= 1;
8680 for (y
= 0; y
< height
; ++y
)
8681 for (x
= 0; x
< width
; ++x
)
8691 g
= pbm_scan_number (&p
, end
);
8693 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8698 for (y
= 0; y
< height
; ++y
)
8699 for (x
= 0; x
< width
; ++x
)
8703 if (type
== PBM_GRAY
)
8704 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8713 r
= pbm_scan_number (&p
, end
);
8714 g
= pbm_scan_number (&p
, end
);
8715 b
= pbm_scan_number (&p
, end
);
8718 if (r
< 0 || g
< 0 || b
< 0)
8722 XDestroyImage (ximg
);
8723 image_error ("Invalid pixel value in image `%s'",
8728 /* RGB values are now in the range 0..max_color_idx.
8729 Scale this to the range 0..0xffff supported by X. */
8730 r
= (double) r
* 65535 / max_color_idx
;
8731 g
= (double) g
* 65535 / max_color_idx
;
8732 b
= (double) b
* 65535 / max_color_idx
;
8733 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8737 /* Store in IMG->colors the colors allocated for the image, and
8738 free the color table. */
8739 img
->colors
= colors_in_color_table (&img
->ncolors
);
8740 free_color_table ();
8742 /* Maybe fill in the background field while we have ximg handy. */
8743 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8744 IMAGE_BACKGROUND (img
, f
, ximg
);
8746 /* Put the image into a pixmap. */
8747 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8748 x_destroy_x_image (ximg
);
8751 img
->height
= height
;
8760 /***********************************************************************
8762 ***********************************************************************/
8768 /* Function prototypes. */
8770 static int png_image_p
P_ ((Lisp_Object object
));
8771 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8773 /* The symbol `png' identifying images of this type. */
8777 /* Indices of image specification fields in png_format, below. */
8779 enum png_keyword_index
8794 /* Vector of image_keyword structures describing the format
8795 of valid user-defined image specifications. */
8797 static struct image_keyword png_format
[PNG_LAST
] =
8799 {":type", IMAGE_SYMBOL_VALUE
, 1},
8800 {":data", IMAGE_STRING_VALUE
, 0},
8801 {":file", IMAGE_STRING_VALUE
, 0},
8802 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8803 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8804 {":relief", IMAGE_INTEGER_VALUE
, 0},
8805 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8806 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8807 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8808 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8811 /* Structure describing the image type `png'. */
8813 static struct image_type png_type
=
8823 /* Return non-zero if OBJECT is a valid PNG image specification. */
8826 png_image_p (object
)
8829 struct image_keyword fmt
[PNG_LAST
];
8830 bcopy (png_format
, fmt
, sizeof fmt
);
8832 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8835 /* Must specify either the :data or :file keyword. */
8836 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8840 /* Error and warning handlers installed when the PNG library
8844 my_png_error (png_ptr
, msg
)
8845 png_struct
*png_ptr
;
8848 xassert (png_ptr
!= NULL
);
8849 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8850 longjmp (png_ptr
->jmpbuf
, 1);
8855 my_png_warning (png_ptr
, msg
)
8856 png_struct
*png_ptr
;
8859 xassert (png_ptr
!= NULL
);
8860 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8863 /* Memory source for PNG decoding. */
8865 struct png_memory_storage
8867 unsigned char *bytes
; /* The data */
8868 size_t len
; /* How big is it? */
8869 int index
; /* Where are we? */
8873 /* Function set as reader function when reading PNG image from memory.
8874 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8875 bytes from the input to DATA. */
8878 png_read_from_memory (png_ptr
, data
, length
)
8879 png_structp png_ptr
;
8883 struct png_memory_storage
*tbr
8884 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8886 if (length
> tbr
->len
- tbr
->index
)
8887 png_error (png_ptr
, "Read error");
8889 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8890 tbr
->index
= tbr
->index
+ length
;
8893 /* Load PNG image IMG for use on frame F. Value is non-zero if
8901 Lisp_Object file
, specified_file
;
8902 Lisp_Object specified_data
;
8904 XImage
*ximg
, *mask_img
= NULL
;
8905 struct gcpro gcpro1
;
8906 png_struct
*png_ptr
= NULL
;
8907 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8908 FILE *volatile fp
= NULL
;
8910 png_byte
* volatile pixels
= NULL
;
8911 png_byte
** volatile rows
= NULL
;
8912 png_uint_32 width
, height
;
8913 int bit_depth
, color_type
, interlace_type
;
8915 png_uint_32 row_bytes
;
8917 double screen_gamma
, image_gamma
;
8919 struct png_memory_storage tbr
; /* Data to be read */
8921 /* Find out what file to load. */
8922 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8923 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8927 if (NILP (specified_data
))
8929 file
= x_find_image_file (specified_file
);
8930 if (!STRINGP (file
))
8932 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8937 /* Open the image file. */
8938 fp
= fopen (XSTRING (file
)->data
, "rb");
8941 image_error ("Cannot open image file `%s'", file
, Qnil
);
8947 /* Check PNG signature. */
8948 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8949 || !png_check_sig (sig
, sizeof sig
))
8951 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8959 /* Read from memory. */
8960 tbr
.bytes
= XSTRING (specified_data
)->data
;
8961 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8964 /* Check PNG signature. */
8965 if (tbr
.len
< sizeof sig
8966 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8968 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8973 /* Need to skip past the signature. */
8974 tbr
.bytes
+= sizeof (sig
);
8977 /* Initialize read and info structs for PNG lib. */
8978 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8979 my_png_error
, my_png_warning
);
8982 if (fp
) fclose (fp
);
8987 info_ptr
= png_create_info_struct (png_ptr
);
8990 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8991 if (fp
) fclose (fp
);
8996 end_info
= png_create_info_struct (png_ptr
);
8999 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
9000 if (fp
) fclose (fp
);
9005 /* Set error jump-back. We come back here when the PNG library
9006 detects an error. */
9007 if (setjmp (png_ptr
->jmpbuf
))
9011 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9014 if (fp
) fclose (fp
);
9019 /* Read image info. */
9020 if (!NILP (specified_data
))
9021 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
9023 png_init_io (png_ptr
, fp
);
9025 png_set_sig_bytes (png_ptr
, sizeof sig
);
9026 png_read_info (png_ptr
, info_ptr
);
9027 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
9028 &interlace_type
, NULL
, NULL
);
9030 /* If image contains simply transparency data, we prefer to
9031 construct a clipping mask. */
9032 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
9037 /* This function is easier to write if we only have to handle
9038 one data format: RGB or RGBA with 8 bits per channel. Let's
9039 transform other formats into that format. */
9041 /* Strip more than 8 bits per channel. */
9042 if (bit_depth
== 16)
9043 png_set_strip_16 (png_ptr
);
9045 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
9047 png_set_expand (png_ptr
);
9049 /* Convert grayscale images to RGB. */
9050 if (color_type
== PNG_COLOR_TYPE_GRAY
9051 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
9052 png_set_gray_to_rgb (png_ptr
);
9054 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
9056 /* Tell the PNG lib to handle gamma correction for us. */
9058 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9059 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
9060 /* The libpng documentation says this is right in this case. */
9061 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9064 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
9065 /* Image contains gamma information. */
9066 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
9068 /* Use the standard default for the image gamma. */
9069 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9071 /* Handle alpha channel by combining the image with a background
9072 color. Do this only if a real alpha channel is supplied. For
9073 simple transparency, we prefer a clipping mask. */
9076 png_color_16
*image_bg
;
9077 Lisp_Object specified_bg
9078 = image_spec_value (img
->spec
, QCbackground
, NULL
);
9080 if (STRINGP (specified_bg
))
9081 /* The user specified `:background', use that. */
9084 if (x_defined_color (f
, XSTRING (specified_bg
)->data
, &color
, 0))
9086 png_color_16 user_bg
;
9088 bzero (&user_bg
, sizeof user_bg
);
9089 user_bg
.red
= color
.red
;
9090 user_bg
.green
= color
.green
;
9091 user_bg
.blue
= color
.blue
;
9093 png_set_background (png_ptr
, &user_bg
,
9094 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9097 else if (png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
9098 /* Image contains a background color with which to
9099 combine the image. */
9100 png_set_background (png_ptr
, image_bg
,
9101 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
9104 /* Image does not contain a background color with which
9105 to combine the image data via an alpha channel. Use
9106 the frame's background instead. */
9109 png_color_16 frame_background
;
9111 cmap
= FRAME_X_COLORMAP (f
);
9112 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
9113 x_query_color (f
, &color
);
9115 bzero (&frame_background
, sizeof frame_background
);
9116 frame_background
.red
= color
.red
;
9117 frame_background
.green
= color
.green
;
9118 frame_background
.blue
= color
.blue
;
9120 png_set_background (png_ptr
, &frame_background
,
9121 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9125 /* Update info structure. */
9126 png_read_update_info (png_ptr
, info_ptr
);
9128 /* Get number of channels. Valid values are 1 for grayscale images
9129 and images with a palette, 2 for grayscale images with transparency
9130 information (alpha channel), 3 for RGB images, and 4 for RGB
9131 images with alpha channel, i.e. RGBA. If conversions above were
9132 sufficient we should only have 3 or 4 channels here. */
9133 channels
= png_get_channels (png_ptr
, info_ptr
);
9134 xassert (channels
== 3 || channels
== 4);
9136 /* Number of bytes needed for one row of the image. */
9137 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
9139 /* Allocate memory for the image. */
9140 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
9141 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
9142 for (i
= 0; i
< height
; ++i
)
9143 rows
[i
] = pixels
+ i
* row_bytes
;
9145 /* Read the entire image. */
9146 png_read_image (png_ptr
, rows
);
9147 png_read_end (png_ptr
, info_ptr
);
9154 /* Create the X image and pixmap. */
9155 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
9159 /* Create an image and pixmap serving as mask if the PNG image
9160 contains an alpha channel. */
9163 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
9164 &mask_img
, &img
->mask
))
9166 x_destroy_x_image (ximg
);
9167 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
9172 /* Fill the X image and mask from PNG data. */
9173 init_color_table ();
9175 for (y
= 0; y
< height
; ++y
)
9177 png_byte
*p
= rows
[y
];
9179 for (x
= 0; x
< width
; ++x
)
9186 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
9188 /* An alpha channel, aka mask channel, associates variable
9189 transparency with an image. Where other image formats
9190 support binary transparency---fully transparent or fully
9191 opaque---PNG allows up to 254 levels of partial transparency.
9192 The PNG library implements partial transparency by combining
9193 the image with a specified background color.
9195 I'm not sure how to handle this here nicely: because the
9196 background on which the image is displayed may change, for
9197 real alpha channel support, it would be necessary to create
9198 a new image for each possible background.
9200 What I'm doing now is that a mask is created if we have
9201 boolean transparency information. Otherwise I'm using
9202 the frame's background color to combine the image with. */
9207 XPutPixel (mask_img
, x
, y
, *p
> 0);
9213 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9214 /* Set IMG's background color from the PNG image, unless the user
9218 if (png_get_bKGD (png_ptr
, info_ptr
, &bg
))
9220 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
9221 img
->background_valid
= 1;
9225 /* Remember colors allocated for this image. */
9226 img
->colors
= colors_in_color_table (&img
->ncolors
);
9227 free_color_table ();
9230 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9235 img
->height
= height
;
9237 /* Maybe fill in the background field while we have ximg handy. */
9238 IMAGE_BACKGROUND (img
, f
, ximg
);
9240 /* Put the image into the pixmap, then free the X image and its buffer. */
9241 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9242 x_destroy_x_image (ximg
);
9244 /* Same for the mask. */
9247 /* Fill in the background_transparent field while we have the mask
9249 image_background_transparent (img
, f
, mask_img
);
9251 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
9252 x_destroy_x_image (mask_img
);
9259 #endif /* HAVE_PNG != 0 */
9263 /***********************************************************************
9265 ***********************************************************************/
9269 /* Work around a warning about HAVE_STDLIB_H being redefined in
9271 #ifdef HAVE_STDLIB_H
9272 #define HAVE_STDLIB_H_1
9273 #undef HAVE_STDLIB_H
9274 #endif /* HAVE_STLIB_H */
9276 #include <jpeglib.h>
9280 #ifdef HAVE_STLIB_H_1
9281 #define HAVE_STDLIB_H 1
9284 static int jpeg_image_p
P_ ((Lisp_Object object
));
9285 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
9287 /* The symbol `jpeg' identifying images of this type. */
9291 /* Indices of image specification fields in gs_format, below. */
9293 enum jpeg_keyword_index
9302 JPEG_HEURISTIC_MASK
,
9308 /* Vector of image_keyword structures describing the format
9309 of valid user-defined image specifications. */
9311 static struct image_keyword jpeg_format
[JPEG_LAST
] =
9313 {":type", IMAGE_SYMBOL_VALUE
, 1},
9314 {":data", IMAGE_STRING_VALUE
, 0},
9315 {":file", IMAGE_STRING_VALUE
, 0},
9316 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9317 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9318 {":relief", IMAGE_INTEGER_VALUE
, 0},
9319 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9320 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9321 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9322 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9325 /* Structure describing the image type `jpeg'. */
9327 static struct image_type jpeg_type
=
9337 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9340 jpeg_image_p (object
)
9343 struct image_keyword fmt
[JPEG_LAST
];
9345 bcopy (jpeg_format
, fmt
, sizeof fmt
);
9347 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
9350 /* Must specify either the :data or :file keyword. */
9351 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9355 struct my_jpeg_error_mgr
9357 struct jpeg_error_mgr pub
;
9358 jmp_buf setjmp_buffer
;
9363 my_error_exit (cinfo
)
9366 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9367 longjmp (mgr
->setjmp_buffer
, 1);
9371 /* Init source method for JPEG data source manager. Called by
9372 jpeg_read_header() before any data is actually read. See
9373 libjpeg.doc from the JPEG lib distribution. */
9376 our_init_source (cinfo
)
9377 j_decompress_ptr cinfo
;
9382 /* Fill input buffer method for JPEG data source manager. Called
9383 whenever more data is needed. We read the whole image in one step,
9384 so this only adds a fake end of input marker at the end. */
9387 our_fill_input_buffer (cinfo
)
9388 j_decompress_ptr cinfo
;
9390 /* Insert a fake EOI marker. */
9391 struct jpeg_source_mgr
*src
= cinfo
->src
;
9392 static JOCTET buffer
[2];
9394 buffer
[0] = (JOCTET
) 0xFF;
9395 buffer
[1] = (JOCTET
) JPEG_EOI
;
9397 src
->next_input_byte
= buffer
;
9398 src
->bytes_in_buffer
= 2;
9403 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9404 is the JPEG data source manager. */
9407 our_skip_input_data (cinfo
, num_bytes
)
9408 j_decompress_ptr cinfo
;
9411 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9415 if (num_bytes
> src
->bytes_in_buffer
)
9416 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9418 src
->bytes_in_buffer
-= num_bytes
;
9419 src
->next_input_byte
+= num_bytes
;
9424 /* Method to terminate data source. Called by
9425 jpeg_finish_decompress() after all data has been processed. */
9428 our_term_source (cinfo
)
9429 j_decompress_ptr cinfo
;
9434 /* Set up the JPEG lib for reading an image from DATA which contains
9435 LEN bytes. CINFO is the decompression info structure created for
9436 reading the image. */
9439 jpeg_memory_src (cinfo
, data
, len
)
9440 j_decompress_ptr cinfo
;
9444 struct jpeg_source_mgr
*src
;
9446 if (cinfo
->src
== NULL
)
9448 /* First time for this JPEG object? */
9449 cinfo
->src
= (struct jpeg_source_mgr
*)
9450 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9451 sizeof (struct jpeg_source_mgr
));
9452 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9453 src
->next_input_byte
= data
;
9456 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9457 src
->init_source
= our_init_source
;
9458 src
->fill_input_buffer
= our_fill_input_buffer
;
9459 src
->skip_input_data
= our_skip_input_data
;
9460 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9461 src
->term_source
= our_term_source
;
9462 src
->bytes_in_buffer
= len
;
9463 src
->next_input_byte
= data
;
9467 /* Load image IMG for use on frame F. Patterned after example.c
9468 from the JPEG lib. */
9475 struct jpeg_decompress_struct cinfo
;
9476 struct my_jpeg_error_mgr mgr
;
9477 Lisp_Object file
, specified_file
;
9478 Lisp_Object specified_data
;
9479 FILE * volatile fp
= NULL
;
9481 int row_stride
, x
, y
;
9482 XImage
*ximg
= NULL
;
9484 unsigned long *colors
;
9486 struct gcpro gcpro1
;
9488 /* Open the JPEG file. */
9489 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9490 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9494 if (NILP (specified_data
))
9496 file
= x_find_image_file (specified_file
);
9497 if (!STRINGP (file
))
9499 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9504 fp
= fopen (XSTRING (file
)->data
, "r");
9507 image_error ("Cannot open `%s'", file
, Qnil
);
9513 /* Customize libjpeg's error handling to call my_error_exit when an
9514 error is detected. This function will perform a longjmp. */
9515 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9516 mgr
.pub
.error_exit
= my_error_exit
;
9518 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9522 /* Called from my_error_exit. Display a JPEG error. */
9523 char buffer
[JMSG_LENGTH_MAX
];
9524 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9525 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9526 build_string (buffer
));
9529 /* Close the input file and destroy the JPEG object. */
9531 fclose ((FILE *) fp
);
9532 jpeg_destroy_decompress (&cinfo
);
9534 /* If we already have an XImage, free that. */
9535 x_destroy_x_image (ximg
);
9537 /* Free pixmap and colors. */
9538 x_clear_image (f
, img
);
9544 /* Create the JPEG decompression object. Let it read from fp.
9545 Read the JPEG image header. */
9546 jpeg_create_decompress (&cinfo
);
9548 if (NILP (specified_data
))
9549 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9551 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
9552 STRING_BYTES (XSTRING (specified_data
)));
9554 jpeg_read_header (&cinfo
, TRUE
);
9556 /* Customize decompression so that color quantization will be used.
9557 Start decompression. */
9558 cinfo
.quantize_colors
= TRUE
;
9559 jpeg_start_decompress (&cinfo
);
9560 width
= img
->width
= cinfo
.output_width
;
9561 height
= img
->height
= cinfo
.output_height
;
9563 /* Create X image and pixmap. */
9564 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9565 longjmp (mgr
.setjmp_buffer
, 2);
9567 /* Allocate colors. When color quantization is used,
9568 cinfo.actual_number_of_colors has been set with the number of
9569 colors generated, and cinfo.colormap is a two-dimensional array
9570 of color indices in the range 0..cinfo.actual_number_of_colors.
9571 No more than 255 colors will be generated. */
9575 if (cinfo
.out_color_components
> 2)
9576 ir
= 0, ig
= 1, ib
= 2;
9577 else if (cinfo
.out_color_components
> 1)
9578 ir
= 0, ig
= 1, ib
= 0;
9580 ir
= 0, ig
= 0, ib
= 0;
9582 /* Use the color table mechanism because it handles colors that
9583 cannot be allocated nicely. Such colors will be replaced with
9584 a default color, and we don't have to care about which colors
9585 can be freed safely, and which can't. */
9586 init_color_table ();
9587 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9590 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9592 /* Multiply RGB values with 255 because X expects RGB values
9593 in the range 0..0xffff. */
9594 int r
= cinfo
.colormap
[ir
][i
] << 8;
9595 int g
= cinfo
.colormap
[ig
][i
] << 8;
9596 int b
= cinfo
.colormap
[ib
][i
] << 8;
9597 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9600 /* Remember those colors actually allocated. */
9601 img
->colors
= colors_in_color_table (&img
->ncolors
);
9602 free_color_table ();
9606 row_stride
= width
* cinfo
.output_components
;
9607 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9609 for (y
= 0; y
< height
; ++y
)
9611 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9612 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9613 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9617 jpeg_finish_decompress (&cinfo
);
9618 jpeg_destroy_decompress (&cinfo
);
9620 fclose ((FILE *) fp
);
9622 /* Maybe fill in the background field while we have ximg handy. */
9623 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9624 IMAGE_BACKGROUND (img
, f
, ximg
);
9626 /* Put the image into the pixmap. */
9627 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9628 x_destroy_x_image (ximg
);
9633 #endif /* HAVE_JPEG */
9637 /***********************************************************************
9639 ***********************************************************************/
9645 static int tiff_image_p
P_ ((Lisp_Object object
));
9646 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9648 /* The symbol `tiff' identifying images of this type. */
9652 /* Indices of image specification fields in tiff_format, below. */
9654 enum tiff_keyword_index
9663 TIFF_HEURISTIC_MASK
,
9669 /* Vector of image_keyword structures describing the format
9670 of valid user-defined image specifications. */
9672 static struct image_keyword tiff_format
[TIFF_LAST
] =
9674 {":type", IMAGE_SYMBOL_VALUE
, 1},
9675 {":data", IMAGE_STRING_VALUE
, 0},
9676 {":file", IMAGE_STRING_VALUE
, 0},
9677 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9678 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9679 {":relief", IMAGE_INTEGER_VALUE
, 0},
9680 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9681 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9682 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9683 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9686 /* Structure describing the image type `tiff'. */
9688 static struct image_type tiff_type
=
9698 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9701 tiff_image_p (object
)
9704 struct image_keyword fmt
[TIFF_LAST
];
9705 bcopy (tiff_format
, fmt
, sizeof fmt
);
9707 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9710 /* Must specify either the :data or :file keyword. */
9711 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9715 /* Reading from a memory buffer for TIFF images Based on the PNG
9716 memory source, but we have to provide a lot of extra functions.
9719 We really only need to implement read and seek, but I am not
9720 convinced that the TIFF library is smart enough not to destroy
9721 itself if we only hand it the function pointers we need to
9726 unsigned char *bytes
;
9734 tiff_read_from_memory (data
, buf
, size
)
9739 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9741 if (size
> src
->len
- src
->index
)
9743 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9750 tiff_write_from_memory (data
, buf
, size
)
9760 tiff_seek_in_memory (data
, off
, whence
)
9765 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9770 case SEEK_SET
: /* Go from beginning of source. */
9774 case SEEK_END
: /* Go from end of source. */
9775 idx
= src
->len
+ off
;
9778 case SEEK_CUR
: /* Go from current position. */
9779 idx
= src
->index
+ off
;
9782 default: /* Invalid `whence'. */
9786 if (idx
> src
->len
|| idx
< 0)
9795 tiff_close_memory (data
)
9804 tiff_mmap_memory (data
, pbase
, psize
)
9809 /* It is already _IN_ memory. */
9815 tiff_unmap_memory (data
, base
, size
)
9820 /* We don't need to do this. */
9825 tiff_size_of_memory (data
)
9828 return ((tiff_memory_source
*) data
)->len
;
9833 tiff_error_handler (title
, format
, ap
)
9834 const char *title
, *format
;
9840 len
= sprintf (buf
, "TIFF error: %s ", title
);
9841 vsprintf (buf
+ len
, format
, ap
);
9842 add_to_log (buf
, Qnil
, Qnil
);
9847 tiff_warning_handler (title
, format
, ap
)
9848 const char *title
, *format
;
9854 len
= sprintf (buf
, "TIFF warning: %s ", title
);
9855 vsprintf (buf
+ len
, format
, ap
);
9856 add_to_log (buf
, Qnil
, Qnil
);
9860 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9868 Lisp_Object file
, specified_file
;
9869 Lisp_Object specified_data
;
9871 int width
, height
, x
, y
;
9875 struct gcpro gcpro1
;
9876 tiff_memory_source memsrc
;
9878 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9879 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9883 TIFFSetErrorHandler (tiff_error_handler
);
9884 TIFFSetWarningHandler (tiff_warning_handler
);
9886 if (NILP (specified_data
))
9888 /* Read from a file */
9889 file
= x_find_image_file (specified_file
);
9890 if (!STRINGP (file
))
9892 image_error ("Cannot find image file `%s'", file
, Qnil
);
9897 /* Try to open the image file. */
9898 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9901 image_error ("Cannot open `%s'", file
, Qnil
);
9908 /* Memory source! */
9909 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9910 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9913 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9914 (TIFFReadWriteProc
) tiff_read_from_memory
,
9915 (TIFFReadWriteProc
) tiff_write_from_memory
,
9916 tiff_seek_in_memory
,
9918 tiff_size_of_memory
,
9924 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9930 /* Get width and height of the image, and allocate a raster buffer
9931 of width x height 32-bit values. */
9932 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9933 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9934 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9936 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9940 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9946 /* Create the X image and pixmap. */
9947 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9954 /* Initialize the color table. */
9955 init_color_table ();
9957 /* Process the pixel raster. Origin is in the lower-left corner. */
9958 for (y
= 0; y
< height
; ++y
)
9960 uint32
*row
= buf
+ y
* width
;
9962 for (x
= 0; x
< width
; ++x
)
9964 uint32 abgr
= row
[x
];
9965 int r
= TIFFGetR (abgr
) << 8;
9966 int g
= TIFFGetG (abgr
) << 8;
9967 int b
= TIFFGetB (abgr
) << 8;
9968 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9972 /* Remember the colors allocated for the image. Free the color table. */
9973 img
->colors
= colors_in_color_table (&img
->ncolors
);
9974 free_color_table ();
9977 img
->height
= height
;
9979 /* Maybe fill in the background field while we have ximg handy. */
9980 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9981 IMAGE_BACKGROUND (img
, f
, ximg
);
9983 /* Put the image into the pixmap, then free the X image and its buffer. */
9984 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9985 x_destroy_x_image (ximg
);
9992 #endif /* HAVE_TIFF != 0 */
9996 /***********************************************************************
9998 ***********************************************************************/
10002 #include <gif_lib.h>
10004 static int gif_image_p
P_ ((Lisp_Object object
));
10005 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
10007 /* The symbol `gif' identifying images of this type. */
10011 /* Indices of image specification fields in gif_format, below. */
10013 enum gif_keyword_index
10022 GIF_HEURISTIC_MASK
,
10029 /* Vector of image_keyword structures describing the format
10030 of valid user-defined image specifications. */
10032 static struct image_keyword gif_format
[GIF_LAST
] =
10034 {":type", IMAGE_SYMBOL_VALUE
, 1},
10035 {":data", IMAGE_STRING_VALUE
, 0},
10036 {":file", IMAGE_STRING_VALUE
, 0},
10037 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10038 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10039 {":relief", IMAGE_INTEGER_VALUE
, 0},
10040 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10041 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10042 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10043 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
10044 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10047 /* Structure describing the image type `gif'. */
10049 static struct image_type gif_type
=
10059 /* Return non-zero if OBJECT is a valid GIF image specification. */
10062 gif_image_p (object
)
10063 Lisp_Object object
;
10065 struct image_keyword fmt
[GIF_LAST
];
10066 bcopy (gif_format
, fmt
, sizeof fmt
);
10068 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
10071 /* Must specify either the :data or :file keyword. */
10072 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
10076 /* Reading a GIF image from memory
10077 Based on the PNG memory stuff to a certain extent. */
10081 unsigned char *bytes
;
10088 /* Make the current memory source available to gif_read_from_memory.
10089 It's done this way because not all versions of libungif support
10090 a UserData field in the GifFileType structure. */
10091 static gif_memory_source
*current_gif_memory_src
;
10094 gif_read_from_memory (file
, buf
, len
)
10099 gif_memory_source
*src
= current_gif_memory_src
;
10101 if (len
> src
->len
- src
->index
)
10104 bcopy (src
->bytes
+ src
->index
, buf
, len
);
10110 /* Load GIF image IMG for use on frame F. Value is non-zero if
10118 Lisp_Object file
, specified_file
;
10119 Lisp_Object specified_data
;
10120 int rc
, width
, height
, x
, y
, i
;
10122 ColorMapObject
*gif_color_map
;
10123 unsigned long pixel_colors
[256];
10125 struct gcpro gcpro1
;
10127 int ino
, image_left
, image_top
, image_width
, image_height
;
10128 gif_memory_source memsrc
;
10129 unsigned char *raster
;
10131 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10132 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10136 if (NILP (specified_data
))
10138 file
= x_find_image_file (specified_file
);
10139 if (!STRINGP (file
))
10141 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
10146 /* Open the GIF file. */
10147 gif
= DGifOpenFileName (XSTRING (file
)->data
);
10150 image_error ("Cannot open `%s'", file
, Qnil
);
10157 /* Read from memory! */
10158 current_gif_memory_src
= &memsrc
;
10159 memsrc
.bytes
= XSTRING (specified_data
)->data
;
10160 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
10163 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
10166 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
10172 /* Read entire contents. */
10173 rc
= DGifSlurp (gif
);
10174 if (rc
== GIF_ERROR
)
10176 image_error ("Error reading `%s'", img
->spec
, Qnil
);
10177 DGifCloseFile (gif
);
10182 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
10183 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
10184 if (ino
>= gif
->ImageCount
)
10186 image_error ("Invalid image number `%s' in image `%s'",
10188 DGifCloseFile (gif
);
10193 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
10194 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
10196 /* Create the X image and pixmap. */
10197 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
10199 DGifCloseFile (gif
);
10204 /* Allocate colors. */
10205 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
10206 if (!gif_color_map
)
10207 gif_color_map
= gif
->SColorMap
;
10208 init_color_table ();
10209 bzero (pixel_colors
, sizeof pixel_colors
);
10211 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
10213 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
10214 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
10215 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
10216 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
10219 img
->colors
= colors_in_color_table (&img
->ncolors
);
10220 free_color_table ();
10222 /* Clear the part of the screen image that are not covered by
10223 the image from the GIF file. Full animated GIF support
10224 requires more than can be done here (see the gif89 spec,
10225 disposal methods). Let's simply assume that the part
10226 not covered by a sub-image is in the frame's background color. */
10227 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
10228 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
10229 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
10230 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
10232 for (y
= 0; y
< image_top
; ++y
)
10233 for (x
= 0; x
< width
; ++x
)
10234 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10236 for (y
= image_top
+ image_height
; y
< height
; ++y
)
10237 for (x
= 0; x
< width
; ++x
)
10238 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10240 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
10242 for (x
= 0; x
< image_left
; ++x
)
10243 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10244 for (x
= image_left
+ image_width
; x
< width
; ++x
)
10245 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10248 /* Read the GIF image into the X image. We use a local variable
10249 `raster' here because RasterBits below is a char *, and invites
10250 problems with bytes >= 0x80. */
10251 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
10253 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
10255 static int interlace_start
[] = {0, 4, 2, 1};
10256 static int interlace_increment
[] = {8, 8, 4, 2};
10258 int row
= interlace_start
[0];
10262 for (y
= 0; y
< image_height
; y
++)
10264 if (row
>= image_height
)
10266 row
= interlace_start
[++pass
];
10267 while (row
>= image_height
)
10268 row
= interlace_start
[++pass
];
10271 for (x
= 0; x
< image_width
; x
++)
10273 int i
= raster
[(y
* image_width
) + x
];
10274 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
10278 row
+= interlace_increment
[pass
];
10283 for (y
= 0; y
< image_height
; ++y
)
10284 for (x
= 0; x
< image_width
; ++x
)
10286 int i
= raster
[y
* image_width
+ x
];
10287 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
10291 DGifCloseFile (gif
);
10293 /* Maybe fill in the background field while we have ximg handy. */
10294 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
10295 IMAGE_BACKGROUND (img
, f
, ximg
);
10297 /* Put the image into the pixmap, then free the X image and its buffer. */
10298 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10299 x_destroy_x_image (ximg
);
10305 #endif /* HAVE_GIF != 0 */
10309 /***********************************************************************
10311 ***********************************************************************/
10313 static int gs_image_p
P_ ((Lisp_Object object
));
10314 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
10315 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
10317 /* The symbol `postscript' identifying images of this type. */
10319 Lisp_Object Qpostscript
;
10321 /* Keyword symbols. */
10323 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
10325 /* Indices of image specification fields in gs_format, below. */
10327 enum gs_keyword_index
10345 /* Vector of image_keyword structures describing the format
10346 of valid user-defined image specifications. */
10348 static struct image_keyword gs_format
[GS_LAST
] =
10350 {":type", IMAGE_SYMBOL_VALUE
, 1},
10351 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10352 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10353 {":file", IMAGE_STRING_VALUE
, 1},
10354 {":loader", IMAGE_FUNCTION_VALUE
, 0},
10355 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
10356 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10357 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10358 {":relief", IMAGE_INTEGER_VALUE
, 0},
10359 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10360 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10361 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10362 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10365 /* Structure describing the image type `ghostscript'. */
10367 static struct image_type gs_type
=
10377 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10380 gs_clear_image (f
, img
)
10384 /* IMG->data.ptr_val may contain a recorded colormap. */
10385 xfree (img
->data
.ptr_val
);
10386 x_clear_image (f
, img
);
10390 /* Return non-zero if OBJECT is a valid Ghostscript image
10394 gs_image_p (object
)
10395 Lisp_Object object
;
10397 struct image_keyword fmt
[GS_LAST
];
10401 bcopy (gs_format
, fmt
, sizeof fmt
);
10403 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10406 /* Bounding box must be a list or vector containing 4 integers. */
10407 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10410 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10411 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10416 else if (VECTORP (tem
))
10418 if (XVECTOR (tem
)->size
!= 4)
10420 for (i
= 0; i
< 4; ++i
)
10421 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10431 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10440 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10441 struct gcpro gcpro1
, gcpro2
;
10443 double in_width
, in_height
;
10444 Lisp_Object pixel_colors
= Qnil
;
10446 /* Compute pixel size of pixmap needed from the given size in the
10447 image specification. Sizes in the specification are in pt. 1 pt
10448 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10450 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10451 in_width
= XFASTINT (pt_width
) / 72.0;
10452 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10453 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10454 in_height
= XFASTINT (pt_height
) / 72.0;
10455 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10457 /* Create the pixmap. */
10458 xassert (img
->pixmap
== None
);
10459 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10460 img
->width
, img
->height
,
10461 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10465 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10469 /* Call the loader to fill the pixmap. It returns a process object
10470 if successful. We do not record_unwind_protect here because
10471 other places in redisplay like calling window scroll functions
10472 don't either. Let the Lisp loader use `unwind-protect' instead. */
10473 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10475 sprintf (buffer
, "%lu %lu",
10476 (unsigned long) FRAME_X_WINDOW (f
),
10477 (unsigned long) img
->pixmap
);
10478 window_and_pixmap_id
= build_string (buffer
);
10480 sprintf (buffer
, "%lu %lu",
10481 FRAME_FOREGROUND_PIXEL (f
),
10482 FRAME_BACKGROUND_PIXEL (f
));
10483 pixel_colors
= build_string (buffer
);
10485 XSETFRAME (frame
, f
);
10486 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10488 loader
= intern ("gs-load-image");
10490 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10491 make_number (img
->width
),
10492 make_number (img
->height
),
10493 window_and_pixmap_id
,
10496 return PROCESSP (img
->data
.lisp_val
);
10500 /* Kill the Ghostscript process that was started to fill PIXMAP on
10501 frame F. Called from XTread_socket when receiving an event
10502 telling Emacs that Ghostscript has finished drawing. */
10505 x_kill_gs_process (pixmap
, f
)
10509 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10513 /* Find the image containing PIXMAP. */
10514 for (i
= 0; i
< c
->used
; ++i
)
10515 if (c
->images
[i
]->pixmap
== pixmap
)
10518 /* Should someone in between have cleared the image cache, for
10519 instance, give up. */
10523 /* Kill the GS process. We should have found PIXMAP in the image
10524 cache and its image should contain a process object. */
10525 img
= c
->images
[i
];
10526 xassert (PROCESSP (img
->data
.lisp_val
));
10527 Fkill_process (img
->data
.lisp_val
, Qnil
);
10528 img
->data
.lisp_val
= Qnil
;
10530 /* On displays with a mutable colormap, figure out the colors
10531 allocated for the image by looking at the pixels of an XImage for
10533 class = FRAME_X_VISUAL (f
)->class;
10534 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10540 /* Try to get an XImage for img->pixmep. */
10541 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10542 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10547 /* Initialize the color table. */
10548 init_color_table ();
10550 /* For each pixel of the image, look its color up in the
10551 color table. After having done so, the color table will
10552 contain an entry for each color used by the image. */
10553 for (y
= 0; y
< img
->height
; ++y
)
10554 for (x
= 0; x
< img
->width
; ++x
)
10556 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10557 lookup_pixel_color (f
, pixel
);
10560 /* Record colors in the image. Free color table and XImage. */
10561 img
->colors
= colors_in_color_table (&img
->ncolors
);
10562 free_color_table ();
10563 XDestroyImage (ximg
);
10565 #if 0 /* This doesn't seem to be the case. If we free the colors
10566 here, we get a BadAccess later in x_clear_image when
10567 freeing the colors. */
10568 /* We have allocated colors once, but Ghostscript has also
10569 allocated colors on behalf of us. So, to get the
10570 reference counts right, free them once. */
10572 x_free_colors (f
, img
->colors
, img
->ncolors
);
10576 image_error ("Cannot get X image of `%s'; colors will not be freed",
10582 /* Now that we have the pixmap, compute mask and transform the
10583 image if requested. */
10585 postprocess_image (f
, img
);
10591 /***********************************************************************
10593 ***********************************************************************/
10595 DEFUN ("x-change-window-property", Fx_change_window_property
,
10596 Sx_change_window_property
, 2, 3, 0,
10597 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
10598 PROP and VALUE must be strings. FRAME nil or omitted means use the
10599 selected frame. Value is VALUE. */)
10600 (prop
, value
, frame
)
10601 Lisp_Object frame
, prop
, value
;
10603 struct frame
*f
= check_x_frame (frame
);
10606 CHECK_STRING (prop
);
10607 CHECK_STRING (value
);
10610 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10611 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10612 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10613 XSTRING (value
)->data
, XSTRING (value
)->size
);
10615 /* Make sure the property is set when we return. */
10616 XFlush (FRAME_X_DISPLAY (f
));
10623 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10624 Sx_delete_window_property
, 1, 2, 0,
10625 doc
: /* Remove window property PROP from X window of FRAME.
10626 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10628 Lisp_Object prop
, frame
;
10630 struct frame
*f
= check_x_frame (frame
);
10633 CHECK_STRING (prop
);
10635 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10636 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10638 /* Make sure the property is removed when we return. */
10639 XFlush (FRAME_X_DISPLAY (f
));
10646 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10648 doc
: /* Value is the value of window property PROP on FRAME.
10649 If FRAME is nil or omitted, use the selected frame. Value is nil
10650 if FRAME hasn't a property with name PROP or if PROP has no string
10653 Lisp_Object prop
, frame
;
10655 struct frame
*f
= check_x_frame (frame
);
10658 Lisp_Object prop_value
= Qnil
;
10659 char *tmp_data
= NULL
;
10662 unsigned long actual_size
, bytes_remaining
;
10664 CHECK_STRING (prop
);
10666 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10667 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10668 prop_atom
, 0, 0, False
, XA_STRING
,
10669 &actual_type
, &actual_format
, &actual_size
,
10670 &bytes_remaining
, (unsigned char **) &tmp_data
);
10673 int size
= bytes_remaining
;
10678 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10679 prop_atom
, 0, bytes_remaining
,
10681 &actual_type
, &actual_format
,
10682 &actual_size
, &bytes_remaining
,
10683 (unsigned char **) &tmp_data
);
10684 if (rc
== Success
&& tmp_data
)
10685 prop_value
= make_string (tmp_data
, size
);
10696 /***********************************************************************
10698 ***********************************************************************/
10700 /* If non-null, an asynchronous timer that, when it expires, displays
10701 an hourglass cursor on all frames. */
10703 static struct atimer
*hourglass_atimer
;
10705 /* Non-zero means an hourglass cursor is currently shown. */
10707 static int hourglass_shown_p
;
10709 /* Number of seconds to wait before displaying an hourglass cursor. */
10711 static Lisp_Object Vhourglass_delay
;
10713 /* Default number of seconds to wait before displaying an hourglass
10716 #define DEFAULT_HOURGLASS_DELAY 1
10718 /* Function prototypes. */
10720 static void show_hourglass
P_ ((struct atimer
*));
10721 static void hide_hourglass
P_ ((void));
10724 /* Cancel a currently active hourglass timer, and start a new one. */
10730 int secs
, usecs
= 0;
10732 cancel_hourglass ();
10734 if (INTEGERP (Vhourglass_delay
)
10735 && XINT (Vhourglass_delay
) > 0)
10736 secs
= XFASTINT (Vhourglass_delay
);
10737 else if (FLOATP (Vhourglass_delay
)
10738 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10741 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10742 secs
= XFASTINT (tem
);
10743 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10746 secs
= DEFAULT_HOURGLASS_DELAY
;
10748 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10749 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10750 show_hourglass
, NULL
);
10754 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10758 cancel_hourglass ()
10760 if (hourglass_atimer
)
10762 cancel_atimer (hourglass_atimer
);
10763 hourglass_atimer
= NULL
;
10766 if (hourglass_shown_p
)
10771 /* Timer function of hourglass_atimer. TIMER is equal to
10774 Display an hourglass pointer on all frames by mapping the frames'
10775 hourglass_window. Set the hourglass_p flag in the frames'
10776 output_data.x structure to indicate that an hourglass cursor is
10777 shown on the frames. */
10780 show_hourglass (timer
)
10781 struct atimer
*timer
;
10783 /* The timer implementation will cancel this timer automatically
10784 after this function has run. Set hourglass_atimer to null
10785 so that we know the timer doesn't have to be canceled. */
10786 hourglass_atimer
= NULL
;
10788 if (!hourglass_shown_p
)
10790 Lisp_Object rest
, frame
;
10794 FOR_EACH_FRAME (rest
, frame
)
10796 struct frame
*f
= XFRAME (frame
);
10798 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10800 Display
*dpy
= FRAME_X_DISPLAY (f
);
10802 #ifdef USE_X_TOOLKIT
10803 if (f
->output_data
.x
->widget
)
10805 if (FRAME_OUTER_WINDOW (f
))
10808 f
->output_data
.x
->hourglass_p
= 1;
10810 if (!f
->output_data
.x
->hourglass_window
)
10812 unsigned long mask
= CWCursor
;
10813 XSetWindowAttributes attrs
;
10815 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10817 f
->output_data
.x
->hourglass_window
10818 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10819 0, 0, 32000, 32000, 0, 0,
10825 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10831 hourglass_shown_p
= 1;
10837 /* Hide the hourglass pointer on all frames, if it is currently
10843 if (hourglass_shown_p
)
10845 Lisp_Object rest
, frame
;
10848 FOR_EACH_FRAME (rest
, frame
)
10850 struct frame
*f
= XFRAME (frame
);
10853 /* Watch out for newly created frames. */
10854 && f
->output_data
.x
->hourglass_window
)
10856 XUnmapWindow (FRAME_X_DISPLAY (f
),
10857 f
->output_data
.x
->hourglass_window
);
10858 /* Sync here because XTread_socket looks at the
10859 hourglass_p flag that is reset to zero below. */
10860 XSync (FRAME_X_DISPLAY (f
), False
);
10861 f
->output_data
.x
->hourglass_p
= 0;
10865 hourglass_shown_p
= 0;
10872 /***********************************************************************
10874 ***********************************************************************/
10876 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10877 Lisp_Object
, Lisp_Object
));
10878 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10879 Lisp_Object
, int, int, int *, int *));
10881 /* The frame of a currently visible tooltip. */
10883 Lisp_Object tip_frame
;
10885 /* If non-nil, a timer started that hides the last tooltip when it
10888 Lisp_Object tip_timer
;
10891 /* If non-nil, a vector of 3 elements containing the last args
10892 with which x-show-tip was called. See there. */
10894 Lisp_Object last_show_tip_args
;
10896 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10898 Lisp_Object Vx_max_tooltip_size
;
10902 unwind_create_tip_frame (frame
)
10905 Lisp_Object deleted
;
10907 deleted
= unwind_create_frame (frame
);
10908 if (EQ (deleted
, Qt
))
10918 /* Create a frame for a tooltip on the display described by DPYINFO.
10919 PARMS is a list of frame parameters. TEXT is the string to
10920 display in the tip frame. Value is the frame.
10922 Note that functions called here, esp. x_default_parameter can
10923 signal errors, for instance when a specified color name is
10924 undefined. We have to make sure that we're in a consistent state
10925 when this happens. */
10928 x_create_tip_frame (dpyinfo
, parms
, text
)
10929 struct x_display_info
*dpyinfo
;
10930 Lisp_Object parms
, text
;
10933 Lisp_Object frame
, tem
;
10935 long window_prompting
= 0;
10937 int count
= BINDING_STACK_SIZE ();
10938 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10940 int face_change_count_before
= face_change_count
;
10941 Lisp_Object buffer
;
10942 struct buffer
*old_buffer
;
10946 /* Use this general default value to start with until we know if
10947 this frame has a specified name. */
10948 Vx_resource_name
= Vinvocation_name
;
10950 #ifdef MULTI_KBOARD
10951 kb
= dpyinfo
->kboard
;
10953 kb
= &the_only_kboard
;
10956 /* Get the name of the frame to use for resource lookup. */
10957 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10958 if (!STRINGP (name
)
10959 && !EQ (name
, Qunbound
)
10961 error ("Invalid frame name--not a string or nil");
10962 Vx_resource_name
= name
;
10965 GCPRO3 (parms
, name
, frame
);
10966 f
= make_frame (1);
10967 XSETFRAME (frame
, f
);
10969 buffer
= Fget_buffer_create (build_string (" *tip*"));
10970 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10971 old_buffer
= current_buffer
;
10972 set_buffer_internal_1 (XBUFFER (buffer
));
10973 current_buffer
->truncate_lines
= Qnil
;
10975 Finsert (1, &text
);
10976 set_buffer_internal_1 (old_buffer
);
10978 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10979 record_unwind_protect (unwind_create_tip_frame
, frame
);
10981 /* By setting the output method, we're essentially saying that
10982 the frame is live, as per FRAME_LIVE_P. If we get a signal
10983 from this point on, x_destroy_window might screw up reference
10985 f
->output_method
= output_x_window
;
10986 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10987 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10988 f
->output_data
.x
->icon_bitmap
= -1;
10989 f
->output_data
.x
->fontset
= -1;
10990 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10991 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10992 #ifdef USE_TOOLKIT_SCROLL_BARS
10993 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
10994 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
10995 #endif /* USE_TOOLKIT_SCROLL_BARS */
10996 f
->icon_name
= Qnil
;
10997 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10999 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
11000 dpyinfo_refcount
= dpyinfo
->reference_count
;
11001 #endif /* GLYPH_DEBUG */
11002 #ifdef MULTI_KBOARD
11003 FRAME_KBOARD (f
) = kb
;
11005 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
11006 f
->output_data
.x
->explicit_parent
= 0;
11008 /* These colors will be set anyway later, but it's important
11009 to get the color reference counts right, so initialize them! */
11012 struct gcpro gcpro1
;
11014 black
= build_string ("black");
11016 f
->output_data
.x
->foreground_pixel
11017 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11018 f
->output_data
.x
->background_pixel
11019 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11020 f
->output_data
.x
->cursor_pixel
11021 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11022 f
->output_data
.x
->cursor_foreground_pixel
11023 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11024 f
->output_data
.x
->border_pixel
11025 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11026 f
->output_data
.x
->mouse_pixel
11027 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11031 /* Set the name; the functions to which we pass f expect the name to
11033 if (EQ (name
, Qunbound
) || NILP (name
))
11035 f
->name
= build_string (dpyinfo
->x_id_name
);
11036 f
->explicit_name
= 0;
11041 f
->explicit_name
= 1;
11042 /* use the frame's title when getting resources for this frame. */
11043 specbind (Qx_resource_name
, name
);
11046 /* Extract the window parameters from the supplied values that are
11047 needed to determine window geometry. */
11051 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
11054 /* First, try whatever font the caller has specified. */
11055 if (STRINGP (font
))
11057 tem
= Fquery_fontset (font
, Qnil
);
11059 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
11061 font
= x_new_font (f
, XSTRING (font
)->data
);
11064 /* Try out a font which we hope has bold and italic variations. */
11065 if (!STRINGP (font
))
11066 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
11067 if (!STRINGP (font
))
11068 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11069 if (! STRINGP (font
))
11070 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11071 if (! STRINGP (font
))
11072 /* This was formerly the first thing tried, but it finds too many fonts
11073 and takes too long. */
11074 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
11075 /* If those didn't work, look for something which will at least work. */
11076 if (! STRINGP (font
))
11077 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
11079 if (! STRINGP (font
))
11080 font
= build_string ("fixed");
11082 x_default_parameter (f
, parms
, Qfont
, font
,
11083 "font", "Font", RES_TYPE_STRING
);
11086 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
11087 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
11089 /* This defaults to 2 in order to match xterm. We recognize either
11090 internalBorderWidth or internalBorder (which is what xterm calls
11092 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11096 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
11097 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
11098 if (! EQ (value
, Qunbound
))
11099 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
11103 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
11104 "internalBorderWidth", "internalBorderWidth",
11107 /* Also do the stuff which must be set before the window exists. */
11108 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
11109 "foreground", "Foreground", RES_TYPE_STRING
);
11110 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
11111 "background", "Background", RES_TYPE_STRING
);
11112 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
11113 "pointerColor", "Foreground", RES_TYPE_STRING
);
11114 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
11115 "cursorColor", "Foreground", RES_TYPE_STRING
);
11116 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
11117 "borderColor", "BorderColor", RES_TYPE_STRING
);
11119 /* Init faces before x_default_parameter is called for scroll-bar
11120 parameters because that function calls x_set_scroll_bar_width,
11121 which calls change_frame_size, which calls Fset_window_buffer,
11122 which runs hooks, which call Fvertical_motion. At the end, we
11123 end up in init_iterator with a null face cache, which should not
11125 init_frame_faces (f
);
11127 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
11128 window_prompting
= x_figure_window_size (f
, parms
);
11130 if (window_prompting
& XNegative
)
11132 if (window_prompting
& YNegative
)
11133 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
11135 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
11139 if (window_prompting
& YNegative
)
11140 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
11142 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11145 f
->output_data
.x
->size_hint_flags
= window_prompting
;
11147 XSetWindowAttributes attrs
;
11148 unsigned long mask
;
11151 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
11152 if (DoesSaveUnders (dpyinfo
->screen
))
11153 mask
|= CWSaveUnder
;
11155 /* Window managers look at the override-redirect flag to determine
11156 whether or net to give windows a decoration (Xlib spec, chapter
11158 attrs
.override_redirect
= True
;
11159 attrs
.save_under
= True
;
11160 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
11161 /* Arrange for getting MapNotify and UnmapNotify events. */
11162 attrs
.event_mask
= StructureNotifyMask
;
11164 = FRAME_X_WINDOW (f
)
11165 = XCreateWindow (FRAME_X_DISPLAY (f
),
11166 FRAME_X_DISPLAY_INFO (f
)->root_window
,
11167 /* x, y, width, height */
11171 CopyFromParent
, InputOutput
, CopyFromParent
,
11178 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
11179 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11180 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
11181 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11182 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
11183 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
11185 /* Dimensions, especially f->height, must be done via change_frame_size.
11186 Change will not be effected unless different from the current
11189 height
= f
->height
;
11191 SET_FRAME_WIDTH (f
, 0);
11192 change_frame_size (f
, height
, width
, 1, 0, 0);
11194 /* Set up faces after all frame parameters are known. This call
11195 also merges in face attributes specified for new frames.
11197 Frame parameters may be changed if .Xdefaults contains
11198 specifications for the default font. For example, if there is an
11199 `Emacs.default.attributeBackground: pink', the `background-color'
11200 attribute of the frame get's set, which let's the internal border
11201 of the tooltip frame appear in pink. Prevent this. */
11203 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
11205 /* Set tip_frame here, so that */
11207 call1 (Qface_set_after_frame_default
, frame
);
11209 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
11210 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
11218 /* It is now ok to make the frame official even if we get an error
11219 below. And the frame needs to be on Vframe_list or making it
11220 visible won't work. */
11221 Vframe_list
= Fcons (frame
, Vframe_list
);
11223 /* Now that the frame is official, it counts as a reference to
11225 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
11227 /* Setting attributes of faces of the tooltip frame from resources
11228 and similar will increment face_change_count, which leads to the
11229 clearing of all current matrices. Since this isn't necessary
11230 here, avoid it by resetting face_change_count to the value it
11231 had before we created the tip frame. */
11232 face_change_count
= face_change_count_before
;
11234 /* Discard the unwind_protect. */
11235 return unbind_to (count
, frame
);
11239 /* Compute where to display tip frame F. PARMS is the list of frame
11240 parameters for F. DX and DY are specified offsets from the current
11241 location of the mouse. WIDTH and HEIGHT are the width and height
11242 of the tooltip. Return coordinates relative to the root window of
11243 the display in *ROOT_X, and *ROOT_Y. */
11246 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
11248 Lisp_Object parms
, dx
, dy
;
11250 int *root_x
, *root_y
;
11252 Lisp_Object left
, top
;
11254 Window root
, child
;
11257 /* User-specified position? */
11258 left
= Fcdr (Fassq (Qleft
, parms
));
11259 top
= Fcdr (Fassq (Qtop
, parms
));
11261 /* Move the tooltip window where the mouse pointer is. Resize and
11263 if (!INTEGERP (left
) || !INTEGERP (top
))
11266 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
11267 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
11271 if (INTEGERP (top
))
11272 *root_y
= XINT (top
);
11273 else if (*root_y
+ XINT (dy
) - height
< 0)
11274 *root_y
-= XINT (dy
);
11278 *root_y
+= XINT (dy
);
11281 if (INTEGERP (left
))
11282 *root_x
= XINT (left
);
11283 else if (*root_x
+ XINT (dx
) + width
<= FRAME_X_DISPLAY_INFO (f
)->width
)
11284 /* It fits to the right of the pointer. */
11285 *root_x
+= XINT (dx
);
11286 else if (width
+ XINT (dx
) <= *root_x
)
11287 /* It fits to the left of the pointer. */
11288 *root_x
-= width
+ XINT (dx
);
11290 /* Put it left-justified on the screen--it ought to fit that way. */
11295 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
11296 doc
: /* Show STRING in a "tooltip" window on frame FRAME.
11297 A tooltip window is a small X window displaying a string.
11299 FRAME nil or omitted means use the selected frame.
11301 PARMS is an optional list of frame parameters which can be used to
11302 change the tooltip's appearance.
11304 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11305 means use the default timeout of 5 seconds.
11307 If the list of frame parameters PARAMS contains a `left' parameters,
11308 the tooltip is displayed at that x-position. Otherwise it is
11309 displayed at the mouse position, with offset DX added (default is 5 if
11310 DX isn't specified). Likewise for the y-position; if a `top' frame
11311 parameter is specified, it determines the y-position of the tooltip
11312 window, otherwise it is displayed at the mouse position, with offset
11313 DY added (default is -10).
11315 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11316 Text larger than the specified size is clipped. */)
11317 (string
, frame
, parms
, timeout
, dx
, dy
)
11318 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
11322 int root_x
, root_y
;
11323 struct buffer
*old_buffer
;
11324 struct text_pos pos
;
11325 int i
, width
, height
;
11326 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
11327 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
11328 int count
= BINDING_STACK_SIZE ();
11330 specbind (Qinhibit_redisplay
, Qt
);
11332 GCPRO4 (string
, parms
, frame
, timeout
);
11334 CHECK_STRING (string
);
11335 f
= check_x_frame (frame
);
11336 if (NILP (timeout
))
11337 timeout
= make_number (5);
11339 CHECK_NATNUM (timeout
);
11342 dx
= make_number (5);
11347 dy
= make_number (-10);
11351 if (NILP (last_show_tip_args
))
11352 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
11354 if (!NILP (tip_frame
))
11356 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
11357 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
11358 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
11360 if (EQ (frame
, last_frame
)
11361 && !NILP (Fequal (last_string
, string
))
11362 && !NILP (Fequal (last_parms
, parms
)))
11364 struct frame
*f
= XFRAME (tip_frame
);
11366 /* Only DX and DY have changed. */
11367 if (!NILP (tip_timer
))
11369 Lisp_Object timer
= tip_timer
;
11371 call1 (Qcancel_timer
, timer
);
11375 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
11376 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
11377 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11384 /* Hide a previous tip, if any. */
11387 ASET (last_show_tip_args
, 0, string
);
11388 ASET (last_show_tip_args
, 1, frame
);
11389 ASET (last_show_tip_args
, 2, parms
);
11391 /* Add default values to frame parameters. */
11392 if (NILP (Fassq (Qname
, parms
)))
11393 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
11394 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11395 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
11396 if (NILP (Fassq (Qborder_width
, parms
)))
11397 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
11398 if (NILP (Fassq (Qborder_color
, parms
)))
11399 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
11400 if (NILP (Fassq (Qbackground_color
, parms
)))
11401 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
11404 /* Create a frame for the tooltip, and record it in the global
11405 variable tip_frame. */
11406 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
11407 f
= XFRAME (frame
);
11409 /* Set up the frame's root window. */
11410 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
11411 w
->left
= w
->top
= make_number (0);
11413 if (CONSP (Vx_max_tooltip_size
)
11414 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11415 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11416 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11417 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11419 w
->width
= XCAR (Vx_max_tooltip_size
);
11420 w
->height
= XCDR (Vx_max_tooltip_size
);
11424 w
->width
= make_number (80);
11425 w
->height
= make_number (40);
11428 f
->window_width
= XINT (w
->width
);
11430 w
->pseudo_window_p
= 1;
11432 /* Display the tooltip text in a temporary buffer. */
11433 old_buffer
= current_buffer
;
11434 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11435 current_buffer
->truncate_lines
= Qnil
;
11436 clear_glyph_matrix (w
->desired_matrix
);
11437 clear_glyph_matrix (w
->current_matrix
);
11438 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11439 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11441 /* Compute width and height of the tooltip. */
11442 width
= height
= 0;
11443 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11445 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11446 struct glyph
*last
;
11449 /* Stop at the first empty row at the end. */
11450 if (!row
->enabled_p
|| !row
->displays_text_p
)
11453 /* Let the row go over the full width of the frame. */
11454 row
->full_width_p
= 1;
11456 /* There's a glyph at the end of rows that is used to place
11457 the cursor there. Don't include the width of this glyph. */
11458 if (row
->used
[TEXT_AREA
])
11460 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11461 row_width
= row
->pixel_width
- last
->pixel_width
;
11464 row_width
= row
->pixel_width
;
11466 height
+= row
->height
;
11467 width
= max (width
, row_width
);
11470 /* Add the frame's internal border to the width and height the X
11471 window should have. */
11472 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11473 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11475 /* Move the tooltip window where the mouse pointer is. Resize and
11477 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11480 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11481 root_x
, root_y
, width
, height
);
11482 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11485 /* Draw into the window. */
11486 w
->must_be_updated_p
= 1;
11487 update_single_window (w
, 1);
11489 /* Restore original current buffer. */
11490 set_buffer_internal_1 (old_buffer
);
11491 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11494 /* Let the tip disappear after timeout seconds. */
11495 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11496 intern ("x-hide-tip"));
11499 return unbind_to (count
, Qnil
);
11503 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11504 doc
: /* Hide the current tooltip window, if there is any.
11505 Value is t if tooltip was open, nil otherwise. */)
11509 Lisp_Object deleted
, frame
, timer
;
11510 struct gcpro gcpro1
, gcpro2
;
11512 /* Return quickly if nothing to do. */
11513 if (NILP (tip_timer
) && NILP (tip_frame
))
11518 GCPRO2 (frame
, timer
);
11519 tip_frame
= tip_timer
= deleted
= Qnil
;
11521 count
= BINDING_STACK_SIZE ();
11522 specbind (Qinhibit_redisplay
, Qt
);
11523 specbind (Qinhibit_quit
, Qt
);
11526 call1 (Qcancel_timer
, timer
);
11528 if (FRAMEP (frame
))
11530 Fdelete_frame (frame
, Qnil
);
11534 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11535 redisplay procedure is not called when a tip frame over menu
11536 items is unmapped. Redisplay the menu manually... */
11538 struct frame
*f
= SELECTED_FRAME ();
11539 Widget w
= f
->output_data
.x
->menubar_widget
;
11540 extern void xlwmenu_redisplay
P_ ((Widget
));
11542 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11546 xlwmenu_redisplay (w
);
11550 #endif /* USE_LUCID */
11554 return unbind_to (count
, deleted
);
11559 /***********************************************************************
11560 File selection dialog
11561 ***********************************************************************/
11565 /* Callback for "OK" and "Cancel" on file selection dialog. */
11568 file_dialog_cb (widget
, client_data
, call_data
)
11570 XtPointer call_data
, client_data
;
11572 int *result
= (int *) client_data
;
11573 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11574 *result
= cb
->reason
;
11578 /* Callback for unmapping a file selection dialog. This is used to
11579 capture the case where a dialog is closed via a window manager's
11580 closer button, for example. Using a XmNdestroyCallback didn't work
11584 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11586 XtPointer call_data
, client_data
;
11588 int *result
= (int *) client_data
;
11589 *result
= XmCR_CANCEL
;
11593 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11594 doc
: /* Read file name, prompting with PROMPT in directory DIR.
11595 Use a file selection dialog.
11596 Select DEFAULT-FILENAME in the dialog's file selection box, if
11597 specified. Don't let the user enter a file name in the file
11598 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11599 (prompt
, dir
, default_filename
, mustmatch
)
11600 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11603 struct frame
*f
= SELECTED_FRAME ();
11604 Lisp_Object file
= Qnil
;
11605 Widget dialog
, text
, list
, help
;
11608 extern XtAppContext Xt_app_con
;
11609 XmString dir_xmstring
, pattern_xmstring
;
11610 int count
= specpdl_ptr
- specpdl
;
11611 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11613 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11614 CHECK_STRING (prompt
);
11615 CHECK_STRING (dir
);
11617 /* Prevent redisplay. */
11618 specbind (Qinhibit_redisplay
, Qt
);
11622 /* Create the dialog with PROMPT as title, using DIR as initial
11623 directory and using "*" as pattern. */
11624 dir
= Fexpand_file_name (dir
, Qnil
);
11625 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
11626 pattern_xmstring
= XmStringCreateLocalized ("*");
11628 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
11629 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11630 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11631 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11632 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11633 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11635 XmStringFree (dir_xmstring
);
11636 XmStringFree (pattern_xmstring
);
11638 /* Add callbacks for OK and Cancel. */
11639 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11640 (XtPointer
) &result
);
11641 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11642 (XtPointer
) &result
);
11643 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11644 (XtPointer
) &result
);
11646 /* Disable the help button since we can't display help. */
11647 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11648 XtSetSensitive (help
, False
);
11650 /* Mark OK button as default. */
11651 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11652 XmNshowAsDefault
, True
, NULL
);
11654 /* If MUSTMATCH is non-nil, disable the file entry field of the
11655 dialog, so that the user must select a file from the files list
11656 box. We can't remove it because we wouldn't have a way to get at
11657 the result file name, then. */
11658 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11659 if (!NILP (mustmatch
))
11662 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11663 XtSetSensitive (text
, False
);
11664 XtSetSensitive (label
, False
);
11667 /* Manage the dialog, so that list boxes get filled. */
11668 XtManageChild (dialog
);
11670 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11671 must include the path for this to work. */
11672 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11673 if (STRINGP (default_filename
))
11675 XmString default_xmstring
;
11679 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
11681 if (!XmListItemExists (list
, default_xmstring
))
11683 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11684 XmListAddItem (list
, default_xmstring
, 0);
11688 item_pos
= XmListItemPos (list
, default_xmstring
);
11689 XmStringFree (default_xmstring
);
11691 /* Select the item and scroll it into view. */
11692 XmListSelectPos (list
, item_pos
, True
);
11693 XmListSetPos (list
, item_pos
);
11696 /* Process events until the user presses Cancel or OK. Block
11697 and unblock input here so that we get a chance of processing
11701 while (result
== 0)
11704 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11709 /* Get the result. */
11710 if (result
== XmCR_OK
)
11715 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11716 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11717 XmStringFree (text
);
11718 file
= build_string (data
);
11725 XtUnmanageChild (dialog
);
11726 XtDestroyWidget (dialog
);
11730 /* Make "Cancel" equivalent to C-g. */
11732 Fsignal (Qquit
, Qnil
);
11734 return unbind_to (count
, file
);
11737 #endif /* USE_MOTIF */
11741 /***********************************************************************
11743 ***********************************************************************/
11745 #ifdef HAVE_XKBGETKEYBOARD
11746 #include <X11/XKBlib.h>
11747 #include <X11/keysym.h>
11750 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11751 Sx_backspace_delete_keys_p
, 0, 1, 0,
11752 doc
: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11753 FRAME nil means use the selected frame.
11754 Value is t if we know that both keys are present, and are mapped to the
11755 usual X keysyms. */)
11759 #ifdef HAVE_XKBGETKEYBOARD
11761 struct frame
*f
= check_x_frame (frame
);
11762 Display
*dpy
= FRAME_X_DISPLAY (f
);
11763 Lisp_Object have_keys
;
11764 int major
, minor
, op
, event
, error
;
11768 /* Check library version in case we're dynamically linked. */
11769 major
= XkbMajorVersion
;
11770 minor
= XkbMinorVersion
;
11771 if (!XkbLibraryVersion (&major
, &minor
))
11777 /* Check that the server supports XKB. */
11778 major
= XkbMajorVersion
;
11779 minor
= XkbMinorVersion
;
11780 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11787 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11790 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11792 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11794 for (i
= kb
->min_key_code
;
11795 (i
< kb
->max_key_code
11796 && (delete_keycode
== 0 || backspace_keycode
== 0));
11799 /* The XKB symbolic key names can be seen most easily in
11800 the PS file generated by `xkbprint -label name
11802 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11803 delete_keycode
= i
;
11804 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11805 backspace_keycode
= i
;
11808 XkbFreeNames (kb
, 0, True
);
11811 XkbFreeClientMap (kb
, 0, True
);
11814 && backspace_keycode
11815 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11816 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11821 #else /* not HAVE_XKBGETKEYBOARD */
11823 #endif /* not HAVE_XKBGETKEYBOARD */
11828 /***********************************************************************
11830 ***********************************************************************/
11835 /* This is zero if not using X windows. */
11838 /* The section below is built by the lisp expression at the top of the file,
11839 just above where these variables are declared. */
11840 /*&&& init symbols here &&&*/
11841 Qauto_raise
= intern ("auto-raise");
11842 staticpro (&Qauto_raise
);
11843 Qauto_lower
= intern ("auto-lower");
11844 staticpro (&Qauto_lower
);
11845 Qbar
= intern ("bar");
11847 Qhbar
= intern ("hbar");
11848 staticpro (&Qhbar
);
11849 Qborder_color
= intern ("border-color");
11850 staticpro (&Qborder_color
);
11851 Qborder_width
= intern ("border-width");
11852 staticpro (&Qborder_width
);
11853 Qbox
= intern ("box");
11855 Qcursor_color
= intern ("cursor-color");
11856 staticpro (&Qcursor_color
);
11857 Qcursor_type
= intern ("cursor-type");
11858 staticpro (&Qcursor_type
);
11859 Qgeometry
= intern ("geometry");
11860 staticpro (&Qgeometry
);
11861 Qicon_left
= intern ("icon-left");
11862 staticpro (&Qicon_left
);
11863 Qicon_top
= intern ("icon-top");
11864 staticpro (&Qicon_top
);
11865 Qicon_type
= intern ("icon-type");
11866 staticpro (&Qicon_type
);
11867 Qicon_name
= intern ("icon-name");
11868 staticpro (&Qicon_name
);
11869 Qinternal_border_width
= intern ("internal-border-width");
11870 staticpro (&Qinternal_border_width
);
11871 Qleft
= intern ("left");
11872 staticpro (&Qleft
);
11873 Qright
= intern ("right");
11874 staticpro (&Qright
);
11875 Qmouse_color
= intern ("mouse-color");
11876 staticpro (&Qmouse_color
);
11877 Qnone
= intern ("none");
11878 staticpro (&Qnone
);
11879 Qparent_id
= intern ("parent-id");
11880 staticpro (&Qparent_id
);
11881 Qscroll_bar_width
= intern ("scroll-bar-width");
11882 staticpro (&Qscroll_bar_width
);
11883 Qsuppress_icon
= intern ("suppress-icon");
11884 staticpro (&Qsuppress_icon
);
11885 Qundefined_color
= intern ("undefined-color");
11886 staticpro (&Qundefined_color
);
11887 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11888 staticpro (&Qvertical_scroll_bars
);
11889 Qvisibility
= intern ("visibility");
11890 staticpro (&Qvisibility
);
11891 Qwindow_id
= intern ("window-id");
11892 staticpro (&Qwindow_id
);
11893 Qouter_window_id
= intern ("outer-window-id");
11894 staticpro (&Qouter_window_id
);
11895 Qx_frame_parameter
= intern ("x-frame-parameter");
11896 staticpro (&Qx_frame_parameter
);
11897 Qx_resource_name
= intern ("x-resource-name");
11898 staticpro (&Qx_resource_name
);
11899 Quser_position
= intern ("user-position");
11900 staticpro (&Quser_position
);
11901 Quser_size
= intern ("user-size");
11902 staticpro (&Quser_size
);
11903 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11904 staticpro (&Qscroll_bar_foreground
);
11905 Qscroll_bar_background
= intern ("scroll-bar-background");
11906 staticpro (&Qscroll_bar_background
);
11907 Qscreen_gamma
= intern ("screen-gamma");
11908 staticpro (&Qscreen_gamma
);
11909 Qline_spacing
= intern ("line-spacing");
11910 staticpro (&Qline_spacing
);
11911 Qcenter
= intern ("center");
11912 staticpro (&Qcenter
);
11913 Qcompound_text
= intern ("compound-text");
11914 staticpro (&Qcompound_text
);
11915 Qcancel_timer
= intern ("cancel-timer");
11916 staticpro (&Qcancel_timer
);
11917 Qwait_for_wm
= intern ("wait-for-wm");
11918 staticpro (&Qwait_for_wm
);
11919 Qfullscreen
= intern ("fullscreen");
11920 staticpro (&Qfullscreen
);
11921 Qfullwidth
= intern ("fullwidth");
11922 staticpro (&Qfullwidth
);
11923 Qfullheight
= intern ("fullheight");
11924 staticpro (&Qfullheight
);
11925 Qfullboth
= intern ("fullboth");
11926 staticpro (&Qfullboth
);
11927 /* This is the end of symbol initialization. */
11929 /* Text property `display' should be nonsticky by default. */
11930 Vtext_property_default_nonsticky
11931 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11934 Qlaplace
= intern ("laplace");
11935 staticpro (&Qlaplace
);
11936 Qemboss
= intern ("emboss");
11937 staticpro (&Qemboss
);
11938 Qedge_detection
= intern ("edge-detection");
11939 staticpro (&Qedge_detection
);
11940 Qheuristic
= intern ("heuristic");
11941 staticpro (&Qheuristic
);
11942 QCmatrix
= intern (":matrix");
11943 staticpro (&QCmatrix
);
11944 QCcolor_adjustment
= intern (":color-adjustment");
11945 staticpro (&QCcolor_adjustment
);
11946 QCmask
= intern (":mask");
11947 staticpro (&QCmask
);
11949 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11950 staticpro (&Qface_set_after_frame_default
);
11952 Fput (Qundefined_color
, Qerror_conditions
,
11953 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11954 Fput (Qundefined_color
, Qerror_message
,
11955 build_string ("Undefined color"));
11957 init_x_parm_symbols ();
11959 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11960 doc
: /* Non-nil means always draw a cross over disabled images.
11961 Disabled images are those having an `:conversion disabled' property.
11962 A cross is always drawn on black & white displays. */);
11963 cross_disabled_images
= 0;
11965 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11966 doc
: /* List of directories to search for bitmap files for X. */);
11967 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11969 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11970 doc
: /* The shape of the pointer when over text.
11971 Changing the value does not affect existing frames
11972 unless you set the mouse color. */);
11973 Vx_pointer_shape
= Qnil
;
11975 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11976 doc
: /* The name Emacs uses to look up X resources.
11977 `x-get-resource' uses this as the first component of the instance name
11978 when requesting resource values.
11979 Emacs initially sets `x-resource-name' to the name under which Emacs
11980 was invoked, or to the value specified with the `-name' or `-rn'
11981 switches, if present.
11983 It may be useful to bind this variable locally around a call
11984 to `x-get-resource'. See also the variable `x-resource-class'. */);
11985 Vx_resource_name
= Qnil
;
11987 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11988 doc
: /* The class Emacs uses to look up X resources.
11989 `x-get-resource' uses this as the first component of the instance class
11990 when requesting resource values.
11992 Emacs initially sets `x-resource-class' to "Emacs".
11994 Setting this variable permanently is not a reasonable thing to do,
11995 but binding this variable locally around a call to `x-get-resource'
11996 is a reasonable practice. See also the variable `x-resource-name'. */);
11997 Vx_resource_class
= build_string (EMACS_CLASS
);
11999 #if 0 /* This doesn't really do anything. */
12000 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
12001 doc
: /* The shape of the pointer when not over text.
12002 This variable takes effect when you create a new frame
12003 or when you set the mouse color. */);
12005 Vx_nontext_pointer_shape
= Qnil
;
12007 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
12008 doc
: /* The shape of the pointer when Emacs is busy.
12009 This variable takes effect when you create a new frame
12010 or when you set the mouse color. */);
12011 Vx_hourglass_pointer_shape
= Qnil
;
12013 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
12014 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
12015 display_hourglass_p
= 1;
12017 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
12018 doc
: /* *Seconds to wait before displaying an hourglass pointer.
12019 Value must be an integer or float. */);
12020 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
12022 #if 0 /* This doesn't really do anything. */
12023 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
12024 doc
: /* The shape of the pointer when over the mode line.
12025 This variable takes effect when you create a new frame
12026 or when you set the mouse color. */);
12028 Vx_mode_pointer_shape
= Qnil
;
12030 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
12031 &Vx_sensitive_text_pointer_shape
,
12032 doc
: /* The shape of the pointer when over mouse-sensitive text.
12033 This variable takes effect when you create a new frame
12034 or when you set the mouse color. */);
12035 Vx_sensitive_text_pointer_shape
= Qnil
;
12037 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
12038 &Vx_window_horizontal_drag_shape
,
12039 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
12040 This variable takes effect when you create a new frame
12041 or when you set the mouse color. */);
12042 Vx_window_horizontal_drag_shape
= Qnil
;
12044 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
12045 doc
: /* A string indicating the foreground color of the cursor box. */);
12046 Vx_cursor_fore_pixel
= Qnil
;
12048 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
12049 doc
: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
12050 Text larger than this is clipped. */);
12051 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
12053 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
12054 doc
: /* Non-nil if no X window manager is in use.
12055 Emacs doesn't try to figure this out; this is always nil
12056 unless you set it to something else. */);
12057 /* We don't have any way to find this out, so set it to nil
12058 and maybe the user would like to set it to t. */
12059 Vx_no_window_manager
= Qnil
;
12061 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
12062 &Vx_pixel_size_width_font_regexp
,
12063 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
12065 Since Emacs gets width of a font matching with this regexp from
12066 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12067 such a font. This is especially effective for such large fonts as
12068 Chinese, Japanese, and Korean. */);
12069 Vx_pixel_size_width_font_regexp
= Qnil
;
12071 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
12072 doc
: /* Time after which cached images are removed from the cache.
12073 When an image has not been displayed this many seconds, remove it
12074 from the image cache. Value must be an integer or nil with nil
12075 meaning don't clear the cache. */);
12076 Vimage_cache_eviction_delay
= make_number (30 * 60);
12078 #ifdef USE_X_TOOLKIT
12079 Fprovide (intern ("x-toolkit"), Qnil
);
12081 Fprovide (intern ("motif"), Qnil
);
12083 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
12084 doc
: /* Version info for LessTif/Motif. */);
12085 Vmotif_version_string
= build_string (XmVERSION_STRING
);
12086 #endif /* USE_MOTIF */
12087 #endif /* USE_X_TOOLKIT */
12089 defsubr (&Sx_get_resource
);
12091 /* X window properties. */
12092 defsubr (&Sx_change_window_property
);
12093 defsubr (&Sx_delete_window_property
);
12094 defsubr (&Sx_window_property
);
12096 defsubr (&Sxw_display_color_p
);
12097 defsubr (&Sx_display_grayscale_p
);
12098 defsubr (&Sxw_color_defined_p
);
12099 defsubr (&Sxw_color_values
);
12100 defsubr (&Sx_server_max_request_size
);
12101 defsubr (&Sx_server_vendor
);
12102 defsubr (&Sx_server_version
);
12103 defsubr (&Sx_display_pixel_width
);
12104 defsubr (&Sx_display_pixel_height
);
12105 defsubr (&Sx_display_mm_width
);
12106 defsubr (&Sx_display_mm_height
);
12107 defsubr (&Sx_display_screens
);
12108 defsubr (&Sx_display_planes
);
12109 defsubr (&Sx_display_color_cells
);
12110 defsubr (&Sx_display_visual_class
);
12111 defsubr (&Sx_display_backing_store
);
12112 defsubr (&Sx_display_save_under
);
12113 defsubr (&Sx_parse_geometry
);
12114 defsubr (&Sx_create_frame
);
12115 defsubr (&Sx_open_connection
);
12116 defsubr (&Sx_close_connection
);
12117 defsubr (&Sx_display_list
);
12118 defsubr (&Sx_synchronize
);
12119 defsubr (&Sx_focus_frame
);
12120 defsubr (&Sx_backspace_delete_keys_p
);
12122 /* Setting callback functions for fontset handler. */
12123 get_font_info_func
= x_get_font_info
;
12125 #if 0 /* This function pointer doesn't seem to be used anywhere.
12126 And the pointer assigned has the wrong type, anyway. */
12127 list_fonts_func
= x_list_fonts
;
12130 load_font_func
= x_load_font
;
12131 find_ccl_program_func
= x_find_ccl_program
;
12132 query_font_func
= x_query_font
;
12133 set_frame_fontset_func
= x_set_font
;
12134 check_window_system_func
= check_x
;
12137 Qxbm
= intern ("xbm");
12139 QCconversion
= intern (":conversion");
12140 staticpro (&QCconversion
);
12141 QCheuristic_mask
= intern (":heuristic-mask");
12142 staticpro (&QCheuristic_mask
);
12143 QCcolor_symbols
= intern (":color-symbols");
12144 staticpro (&QCcolor_symbols
);
12145 QCascent
= intern (":ascent");
12146 staticpro (&QCascent
);
12147 QCmargin
= intern (":margin");
12148 staticpro (&QCmargin
);
12149 QCrelief
= intern (":relief");
12150 staticpro (&QCrelief
);
12151 Qpostscript
= intern ("postscript");
12152 staticpro (&Qpostscript
);
12153 QCloader
= intern (":loader");
12154 staticpro (&QCloader
);
12155 QCbounding_box
= intern (":bounding-box");
12156 staticpro (&QCbounding_box
);
12157 QCpt_width
= intern (":pt-width");
12158 staticpro (&QCpt_width
);
12159 QCpt_height
= intern (":pt-height");
12160 staticpro (&QCpt_height
);
12161 QCindex
= intern (":index");
12162 staticpro (&QCindex
);
12163 Qpbm
= intern ("pbm");
12167 Qxpm
= intern ("xpm");
12172 Qjpeg
= intern ("jpeg");
12173 staticpro (&Qjpeg
);
12177 Qtiff
= intern ("tiff");
12178 staticpro (&Qtiff
);
12182 Qgif
= intern ("gif");
12187 Qpng
= intern ("png");
12191 defsubr (&Sclear_image_cache
);
12192 defsubr (&Simage_size
);
12193 defsubr (&Simage_mask_p
);
12195 hourglass_atimer
= NULL
;
12196 hourglass_shown_p
= 0;
12198 defsubr (&Sx_show_tip
);
12199 defsubr (&Sx_hide_tip
);
12201 staticpro (&tip_timer
);
12203 staticpro (&tip_frame
);
12205 last_show_tip_args
= Qnil
;
12206 staticpro (&last_show_tip_args
);
12209 defsubr (&Sx_file_dialog
);
12217 image_types
= NULL
;
12218 Vimage_types
= Qnil
;
12220 define_image_type (&xbm_type
);
12221 define_image_type (&gs_type
);
12222 define_image_type (&pbm_type
);
12225 define_image_type (&xpm_type
);
12229 define_image_type (&jpeg_type
);
12233 define_image_type (&tiff_type
);
12237 define_image_type (&gif_type
);
12241 define_image_type (&png_type
);
12245 #endif /* HAVE_X_WINDOWS */