1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
40 #include "intervals.h"
41 #include "dispextern.h"
43 #include "blockinput.h"
49 #include "termhooks.h"
55 #include <sys/types.h>
59 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
60 #include "bitmaps/gray.xbm"
62 #include <X11/bitmaps/gray>
65 #include "[.bitmaps]gray.xbm"
69 #include <X11/Shell.h>
72 #include <X11/Xaw/Paned.h>
73 #include <X11/Xaw/Label.h>
74 #endif /* USE_MOTIF */
77 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
86 #include "../lwlib/lwlib.h"
90 #include <Xm/DialogS.h>
91 #include <Xm/FileSB.h>
94 /* Do the EDITRES protocol if running X11R5
95 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
97 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
99 extern void _XEditResCheckMessages ();
100 #endif /* R5 + Athena */
102 /* Unique id counter for widgets created by the Lucid Widget Library. */
104 extern LWLIB_ID widget_id_tick
;
107 /* This is part of a kludge--see lwlib/xlwmenu.c. */
108 extern XFontStruct
*xlwmenu_default_font
;
111 extern void free_frame_menubar ();
112 extern double atof ();
116 /* LessTif/Motif version info. */
118 static Lisp_Object Vmotif_version_string
;
120 #endif /* USE_MOTIF */
122 #endif /* USE_X_TOOLKIT */
125 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
127 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
130 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
131 it, and including `bitmaps/gray' more than once is a problem when
132 config.h defines `static' as an empty replacement string. */
134 int gray_bitmap_width
= gray_width
;
135 int gray_bitmap_height
= gray_height
;
136 char *gray_bitmap_bits
= gray_bits
;
138 /* The name we're using in resource queries. Most often "emacs". */
140 Lisp_Object Vx_resource_name
;
142 /* The application class we're using in resource queries.
145 Lisp_Object Vx_resource_class
;
147 /* Non-zero means we're allowed to display an hourglass cursor. */
149 int display_hourglass_p
;
151 /* The background and shape of the mouse pointer, and shape when not
152 over text or in the modeline. */
154 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
155 Lisp_Object Vx_hourglass_pointer_shape
;
157 /* The shape when over mouse-sensitive text. */
159 Lisp_Object Vx_sensitive_text_pointer_shape
;
161 /* If non-nil, the pointer shape to indicate that windows can be
162 dragged horizontally. */
164 Lisp_Object Vx_window_horizontal_drag_shape
;
166 /* Color of chars displayed in cursor box. */
168 Lisp_Object Vx_cursor_fore_pixel
;
170 /* Nonzero if using X. */
174 /* Non nil if no window manager is in use. */
176 Lisp_Object Vx_no_window_manager
;
178 /* Search path for bitmap files. */
180 Lisp_Object Vx_bitmap_file_path
;
182 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
184 Lisp_Object Vx_pixel_size_width_font_regexp
;
186 Lisp_Object Qauto_raise
;
187 Lisp_Object Qauto_lower
;
189 Lisp_Object Qborder_color
;
190 Lisp_Object Qborder_width
;
192 Lisp_Object Qcursor_color
;
193 Lisp_Object Qcursor_type
;
194 Lisp_Object Qgeometry
;
195 Lisp_Object Qicon_left
;
196 Lisp_Object Qicon_top
;
197 Lisp_Object Qicon_type
;
198 Lisp_Object Qicon_name
;
199 Lisp_Object Qinternal_border_width
;
202 Lisp_Object Qmouse_color
;
204 Lisp_Object Qouter_window_id
;
205 Lisp_Object Qparent_id
;
206 Lisp_Object Qscroll_bar_width
;
207 Lisp_Object Qsuppress_icon
;
208 extern Lisp_Object Qtop
;
209 Lisp_Object Qundefined_color
;
210 Lisp_Object Qvertical_scroll_bars
;
211 Lisp_Object Qvisibility
;
212 Lisp_Object Qwindow_id
;
213 Lisp_Object Qx_frame_parameter
;
214 Lisp_Object Qx_resource_name
;
215 Lisp_Object Quser_position
;
216 Lisp_Object Quser_size
;
217 extern Lisp_Object Qdisplay
;
218 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
219 Lisp_Object Qscreen_gamma
, Qline_spacing
, Qcenter
;
220 Lisp_Object Qcompound_text
, Qcancel_timer
;
221 Lisp_Object Qwait_for_wm
;
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_crosshair
);
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 (NILP (arg
))
1869 /* Treat anything unknown as "box cursor".
1870 It was bad to signal an error; people have trouble fixing
1871 .Xdefaults with Emacs, when it has something bad in it. */
1872 type
= FILLED_BOX_CURSOR
;
1878 x_set_cursor_type (f
, arg
, oldval
)
1880 Lisp_Object arg
, oldval
;
1884 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1885 f
->output_data
.x
->cursor_width
= width
;
1887 /* Make sure the cursor gets redrawn. */
1888 cursor_type_changed
= 1;
1892 x_set_icon_type (f
, arg
, oldval
)
1894 Lisp_Object arg
, oldval
;
1900 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1903 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1908 result
= x_text_icon (f
,
1909 (char *) XSTRING ((!NILP (f
->icon_name
)
1913 result
= x_bitmap_icon (f
, arg
);
1918 error ("No icon window available");
1921 XFlush (FRAME_X_DISPLAY (f
));
1925 /* Return non-nil if frame F wants a bitmap icon. */
1933 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1941 x_set_icon_name (f
, arg
, oldval
)
1943 Lisp_Object arg
, oldval
;
1949 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1952 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1957 if (f
->output_data
.x
->icon_bitmap
!= 0)
1962 result
= x_text_icon (f
,
1963 (char *) XSTRING ((!NILP (f
->icon_name
)
1972 error ("No icon window available");
1975 XFlush (FRAME_X_DISPLAY (f
));
1980 x_set_font (f
, arg
, oldval
)
1982 Lisp_Object arg
, oldval
;
1985 Lisp_Object fontset_name
;
1987 int old_fontset
= f
->output_data
.x
->fontset
;
1991 fontset_name
= Fquery_fontset (arg
, Qnil
);
1994 result
= (STRINGP (fontset_name
)
1995 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1996 : x_new_font (f
, XSTRING (arg
)->data
));
1999 if (EQ (result
, Qnil
))
2000 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
2001 else if (EQ (result
, Qt
))
2002 error ("The characters of the given font have varying widths");
2003 else if (STRINGP (result
))
2005 if (STRINGP (fontset_name
))
2007 /* Fontset names are built from ASCII font names, so the
2008 names may be equal despite there was a change. */
2009 if (old_fontset
== f
->output_data
.x
->fontset
)
2012 else if (!NILP (Fequal (result
, oldval
)))
2015 store_frame_param (f
, Qfont
, result
);
2016 recompute_basic_faces (f
);
2021 do_pending_window_change (0);
2023 /* Don't call `face-set-after-frame-default' when faces haven't been
2024 initialized yet. This is the case when called from
2025 Fx_create_frame. In that case, the X widget or window doesn't
2026 exist either, and we can end up in x_report_frame_params with a
2027 null widget which gives a segfault. */
2028 if (FRAME_FACE_CACHE (f
))
2030 XSETFRAME (frame
, f
);
2031 call1 (Qface_set_after_frame_default
, frame
);
2036 x_set_fringe_width (f
, new_value
, old_value
)
2038 Lisp_Object new_value
, old_value
;
2040 x_compute_fringe_widths (f
, 1);
2044 x_set_border_width (f
, arg
, oldval
)
2046 Lisp_Object arg
, oldval
;
2050 if (XINT (arg
) == f
->output_data
.x
->border_width
)
2053 if (FRAME_X_WINDOW (f
) != 0)
2054 error ("Cannot change the border width of a window");
2056 f
->output_data
.x
->border_width
= XINT (arg
);
2060 x_set_internal_border_width (f
, arg
, oldval
)
2062 Lisp_Object arg
, oldval
;
2064 int old
= f
->output_data
.x
->internal_border_width
;
2067 f
->output_data
.x
->internal_border_width
= XINT (arg
);
2068 if (f
->output_data
.x
->internal_border_width
< 0)
2069 f
->output_data
.x
->internal_border_width
= 0;
2071 #ifdef USE_X_TOOLKIT
2072 if (f
->output_data
.x
->edit_widget
)
2073 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
2076 if (f
->output_data
.x
->internal_border_width
== old
)
2079 if (FRAME_X_WINDOW (f
) != 0)
2081 x_set_window_size (f
, 0, f
->width
, f
->height
);
2082 SET_FRAME_GARBAGED (f
);
2083 do_pending_window_change (0);
2086 SET_FRAME_GARBAGED (f
);
2090 x_set_visibility (f
, value
, oldval
)
2092 Lisp_Object value
, oldval
;
2095 XSETFRAME (frame
, f
);
2098 Fmake_frame_invisible (frame
, Qt
);
2099 else if (EQ (value
, Qicon
))
2100 Ficonify_frame (frame
);
2102 Fmake_frame_visible (frame
);
2106 /* Change window heights in windows rooted in WINDOW by N lines. */
2109 x_change_window_heights (window
, n
)
2113 struct window
*w
= XWINDOW (window
);
2115 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
2116 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
2118 if (INTEGERP (w
->orig_top
))
2119 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
2120 if (INTEGERP (w
->orig_height
))
2121 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
2123 /* Handle just the top child in a vertical split. */
2124 if (!NILP (w
->vchild
))
2125 x_change_window_heights (w
->vchild
, n
);
2127 /* Adjust all children in a horizontal split. */
2128 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
2130 w
= XWINDOW (window
);
2131 x_change_window_heights (window
, n
);
2136 x_set_menu_bar_lines (f
, value
, oldval
)
2138 Lisp_Object value
, oldval
;
2141 #ifndef USE_X_TOOLKIT
2142 int olines
= FRAME_MENU_BAR_LINES (f
);
2145 /* Right now, menu bars don't work properly in minibuf-only frames;
2146 most of the commands try to apply themselves to the minibuffer
2147 frame itself, and get an error because you can't switch buffers
2148 in or split the minibuffer window. */
2149 if (FRAME_MINIBUF_ONLY_P (f
))
2152 if (INTEGERP (value
))
2153 nlines
= XINT (value
);
2157 /* Make sure we redisplay all windows in this frame. */
2158 windows_or_buffers_changed
++;
2160 #ifdef USE_X_TOOLKIT
2161 FRAME_MENU_BAR_LINES (f
) = 0;
2164 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2165 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2166 /* Make sure next redisplay shows the menu bar. */
2167 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2171 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2172 free_frame_menubar (f
);
2173 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2175 f
->output_data
.x
->menubar_widget
= 0;
2177 #else /* not USE_X_TOOLKIT */
2178 FRAME_MENU_BAR_LINES (f
) = nlines
;
2179 x_change_window_heights (f
->root_window
, nlines
- olines
);
2180 #endif /* not USE_X_TOOLKIT */
2185 /* Set the number of lines used for the tool bar of frame F to VALUE.
2186 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2187 is the old number of tool bar lines. This function changes the
2188 height of all windows on frame F to match the new tool bar height.
2189 The frame's height doesn't change. */
2192 x_set_tool_bar_lines (f
, value
, oldval
)
2194 Lisp_Object value
, oldval
;
2196 int delta
, nlines
, root_height
;
2197 Lisp_Object root_window
;
2199 /* Treat tool bars like menu bars. */
2200 if (FRAME_MINIBUF_ONLY_P (f
))
2203 /* Use VALUE only if an integer >= 0. */
2204 if (INTEGERP (value
) && XINT (value
) >= 0)
2205 nlines
= XFASTINT (value
);
2209 /* Make sure we redisplay all windows in this frame. */
2210 ++windows_or_buffers_changed
;
2212 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2214 /* Don't resize the tool-bar to more than we have room for. */
2215 root_window
= FRAME_ROOT_WINDOW (f
);
2216 root_height
= XINT (XWINDOW (root_window
)->height
);
2217 if (root_height
- delta
< 1)
2219 delta
= root_height
- 1;
2220 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2223 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2224 x_change_window_heights (root_window
, delta
);
2227 /* We also have to make sure that the internal border at the top of
2228 the frame, below the menu bar or tool bar, is redrawn when the
2229 tool bar disappears. This is so because the internal border is
2230 below the tool bar if one is displayed, but is below the menu bar
2231 if there isn't a tool bar. The tool bar draws into the area
2232 below the menu bar. */
2233 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2237 clear_current_matrices (f
);
2238 updating_frame
= NULL
;
2241 /* If the tool bar gets smaller, the internal border below it
2242 has to be cleared. It was formerly part of the display
2243 of the larger tool bar, and updating windows won't clear it. */
2246 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2247 int width
= PIXEL_WIDTH (f
);
2248 int y
= nlines
* CANON_Y_UNIT (f
);
2251 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2252 0, y
, width
, height
, False
);
2255 if (WINDOWP (f
->tool_bar_window
))
2256 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2261 /* Set the foreground color for scroll bars on frame F to VALUE.
2262 VALUE should be a string, a color name. If it isn't a string or
2263 isn't a valid color name, do nothing. OLDVAL is the old value of
2264 the frame parameter. */
2267 x_set_scroll_bar_foreground (f
, value
, oldval
)
2269 Lisp_Object value
, oldval
;
2271 unsigned long pixel
;
2273 if (STRINGP (value
))
2274 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2278 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2279 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2281 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2282 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2284 /* Remove all scroll bars because they have wrong colors. */
2285 if (condemn_scroll_bars_hook
)
2286 (*condemn_scroll_bars_hook
) (f
);
2287 if (judge_scroll_bars_hook
)
2288 (*judge_scroll_bars_hook
) (f
);
2290 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2296 /* Set the background color for scroll bars on frame F to VALUE VALUE
2297 should be a string, a color name. If it isn't a string or isn't a
2298 valid color name, do nothing. OLDVAL is the old value of the frame
2302 x_set_scroll_bar_background (f
, value
, oldval
)
2304 Lisp_Object value
, oldval
;
2306 unsigned long pixel
;
2308 if (STRINGP (value
))
2309 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2313 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2314 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2316 #ifdef USE_TOOLKIT_SCROLL_BARS
2317 /* Scrollbar shadow colors. */
2318 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
2320 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
2321 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
2323 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
2325 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
2326 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
2328 #endif /* USE_TOOLKIT_SCROLL_BARS */
2330 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2331 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2333 /* Remove all scroll bars because they have wrong colors. */
2334 if (condemn_scroll_bars_hook
)
2335 (*condemn_scroll_bars_hook
) (f
);
2336 if (judge_scroll_bars_hook
)
2337 (*judge_scroll_bars_hook
) (f
);
2339 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2345 /* Encode Lisp string STRING as a text in a format appropriate for
2346 XICCC (X Inter Client Communication Conventions).
2348 If STRING contains only ASCII characters, do no conversion and
2349 return the string data of STRING. Otherwise, encode the text by
2350 CODING_SYSTEM, and return a newly allocated memory area which
2351 should be freed by `xfree' by a caller.
2353 SELECTIONP non-zero means the string is being encoded for an X
2354 selection, so it is safe to run pre-write conversions (which
2357 Store the byte length of resulting text in *TEXT_BYTES.
2359 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2360 which means that the `encoding' of the result can be `STRING'.
2361 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2362 the result should be `COMPOUND_TEXT'. */
2365 x_encode_text (string
, coding_system
, selectionp
, text_bytes
, stringp
)
2366 Lisp_Object string
, coding_system
;
2367 int *text_bytes
, *stringp
;
2370 unsigned char *str
= XSTRING (string
)->data
;
2371 int chars
= XSTRING (string
)->size
;
2372 int bytes
= STRING_BYTES (XSTRING (string
));
2376 struct coding_system coding
;
2378 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2379 if (charset_info
== 0)
2381 /* No multibyte character in OBJ. We need not encode it. */
2382 *text_bytes
= bytes
;
2387 setup_coding_system (coding_system
, &coding
);
2389 && SYMBOLP (coding
.pre_write_conversion
)
2390 && !NILP (Ffboundp (coding
.pre_write_conversion
)))
2392 string
= run_pre_post_conversion_on_str (string
, &coding
, 1);
2393 str
= XSTRING (string
)->data
;
2394 chars
= XSTRING (string
)->size
;
2395 bytes
= STRING_BYTES (XSTRING (string
));
2397 coding
.src_multibyte
= 1;
2398 coding
.dst_multibyte
= 0;
2399 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2400 if (coding
.type
== coding_type_iso2022
)
2401 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2402 /* We suppress producing escape sequences for composition. */
2403 coding
.composing
= COMPOSITION_DISABLED
;
2404 bufsize
= encoding_buffer_size (&coding
, bytes
);
2405 buf
= (unsigned char *) xmalloc (bufsize
);
2406 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2407 *text_bytes
= coding
.produced
;
2408 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2413 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2416 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2417 name; if NAME is a string, set F's name to NAME and set
2418 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2420 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2421 suggesting a new name, which lisp code should override; if
2422 F->explicit_name is set, ignore the new name; otherwise, set it. */
2425 x_set_name (f
, name
, explicit)
2430 /* Make sure that requests from lisp code override requests from
2431 Emacs redisplay code. */
2434 /* If we're switching from explicit to implicit, we had better
2435 update the mode lines and thereby update the title. */
2436 if (f
->explicit_name
&& NILP (name
))
2437 update_mode_lines
= 1;
2439 f
->explicit_name
= ! NILP (name
);
2441 else if (f
->explicit_name
)
2444 /* If NAME is nil, set the name to the x_id_name. */
2447 /* Check for no change needed in this very common case
2448 before we do any consing. */
2449 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2450 XSTRING (f
->name
)->data
))
2452 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2455 CHECK_STRING (name
);
2457 /* Don't change the name if it's already NAME. */
2458 if (! NILP (Fstring_equal (name
, f
->name
)))
2463 /* For setting the frame title, the title parameter should override
2464 the name parameter. */
2465 if (! NILP (f
->title
))
2468 if (FRAME_X_WINDOW (f
))
2473 XTextProperty text
, icon
;
2475 Lisp_Object coding_system
;
2477 coding_system
= Vlocale_coding_system
;
2478 if (NILP (coding_system
))
2479 coding_system
= Qcompound_text
;
2480 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2481 text
.encoding
= (stringp
? XA_STRING
2482 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2484 text
.nitems
= bytes
;
2486 if (NILP (f
->icon_name
))
2492 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2494 icon
.encoding
= (stringp
? XA_STRING
2495 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2497 icon
.nitems
= bytes
;
2499 #ifdef USE_X_TOOLKIT
2500 XSetWMName (FRAME_X_DISPLAY (f
),
2501 XtWindow (f
->output_data
.x
->widget
), &text
);
2502 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2504 #else /* not USE_X_TOOLKIT */
2505 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2506 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2507 #endif /* not USE_X_TOOLKIT */
2508 if (!NILP (f
->icon_name
)
2509 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2511 if (text
.value
!= XSTRING (name
)->data
)
2514 #else /* not HAVE_X11R4 */
2515 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2516 XSTRING (name
)->data
);
2517 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2518 XSTRING (name
)->data
);
2519 #endif /* not HAVE_X11R4 */
2524 /* This function should be called when the user's lisp code has
2525 specified a name for the frame; the name will override any set by the
2528 x_explicitly_set_name (f
, arg
, oldval
)
2530 Lisp_Object arg
, oldval
;
2532 x_set_name (f
, arg
, 1);
2535 /* This function should be called by Emacs redisplay code to set the
2536 name; names set this way will never override names set by the user's
2539 x_implicitly_set_name (f
, arg
, oldval
)
2541 Lisp_Object arg
, oldval
;
2543 x_set_name (f
, arg
, 0);
2546 /* Change the title of frame F to NAME.
2547 If NAME is nil, use the frame name as the title.
2549 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2550 name; if NAME is a string, set F's name to NAME and set
2551 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2553 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2554 suggesting a new name, which lisp code should override; if
2555 F->explicit_name is set, ignore the new name; otherwise, set it. */
2558 x_set_title (f
, name
, old_name
)
2560 Lisp_Object name
, old_name
;
2562 /* Don't change the title if it's already NAME. */
2563 if (EQ (name
, f
->title
))
2566 update_mode_lines
= 1;
2573 CHECK_STRING (name
);
2575 if (FRAME_X_WINDOW (f
))
2580 XTextProperty text
, icon
;
2582 Lisp_Object coding_system
;
2584 coding_system
= Vlocale_coding_system
;
2585 if (NILP (coding_system
))
2586 coding_system
= Qcompound_text
;
2587 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2588 text
.encoding
= (stringp
? XA_STRING
2589 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2591 text
.nitems
= bytes
;
2593 if (NILP (f
->icon_name
))
2599 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2601 icon
.encoding
= (stringp
? XA_STRING
2602 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2604 icon
.nitems
= bytes
;
2606 #ifdef USE_X_TOOLKIT
2607 XSetWMName (FRAME_X_DISPLAY (f
),
2608 XtWindow (f
->output_data
.x
->widget
), &text
);
2609 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2611 #else /* not USE_X_TOOLKIT */
2612 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2613 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2614 #endif /* not USE_X_TOOLKIT */
2615 if (!NILP (f
->icon_name
)
2616 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2618 if (text
.value
!= XSTRING (name
)->data
)
2621 #else /* not HAVE_X11R4 */
2622 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2623 XSTRING (name
)->data
);
2624 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2625 XSTRING (name
)->data
);
2626 #endif /* not HAVE_X11R4 */
2632 x_set_autoraise (f
, arg
, oldval
)
2634 Lisp_Object arg
, oldval
;
2636 f
->auto_raise
= !EQ (Qnil
, arg
);
2640 x_set_autolower (f
, arg
, oldval
)
2642 Lisp_Object arg
, oldval
;
2644 f
->auto_lower
= !EQ (Qnil
, arg
);
2648 x_set_unsplittable (f
, arg
, oldval
)
2650 Lisp_Object arg
, oldval
;
2652 f
->no_split
= !NILP (arg
);
2656 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2658 Lisp_Object arg
, oldval
;
2660 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2661 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2662 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2663 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2665 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2667 ? vertical_scroll_bar_none
2669 ? vertical_scroll_bar_right
2670 : vertical_scroll_bar_left
);
2672 /* We set this parameter before creating the X window for the
2673 frame, so we can get the geometry right from the start.
2674 However, if the window hasn't been created yet, we shouldn't
2675 call x_set_window_size. */
2676 if (FRAME_X_WINDOW (f
))
2677 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2678 do_pending_window_change (0);
2683 x_set_scroll_bar_width (f
, arg
, oldval
)
2685 Lisp_Object arg
, oldval
;
2687 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2691 #ifdef USE_TOOLKIT_SCROLL_BARS
2692 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2693 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2694 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2695 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2697 /* Make the actual width at least 14 pixels and a multiple of a
2699 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2701 /* Use all of that space (aside from required margins) for the
2703 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2706 if (FRAME_X_WINDOW (f
))
2707 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2708 do_pending_window_change (0);
2710 else if (INTEGERP (arg
) && XINT (arg
) > 0
2711 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2713 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2714 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2716 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2717 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2718 if (FRAME_X_WINDOW (f
))
2719 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2722 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2723 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2724 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2729 /* Subroutines of creating an X frame. */
2731 /* Make sure that Vx_resource_name is set to a reasonable value.
2732 Fix it up, or set it to `emacs' if it is too hopeless. */
2735 validate_x_resource_name ()
2738 /* Number of valid characters in the resource name. */
2740 /* Number of invalid characters in the resource name. */
2745 if (!STRINGP (Vx_resource_class
))
2746 Vx_resource_class
= build_string (EMACS_CLASS
);
2748 if (STRINGP (Vx_resource_name
))
2750 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2753 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2755 /* Only letters, digits, - and _ are valid in resource names.
2756 Count the valid characters and count the invalid ones. */
2757 for (i
= 0; i
< len
; i
++)
2760 if (! ((c
>= 'a' && c
<= 'z')
2761 || (c
>= 'A' && c
<= 'Z')
2762 || (c
>= '0' && c
<= '9')
2763 || c
== '-' || c
== '_'))
2770 /* Not a string => completely invalid. */
2771 bad_count
= 5, good_count
= 0;
2773 /* If name is valid already, return. */
2777 /* If name is entirely invalid, or nearly so, use `emacs'. */
2779 || (good_count
== 1 && bad_count
> 0))
2781 Vx_resource_name
= build_string ("emacs");
2785 /* Name is partly valid. Copy it and replace the invalid characters
2786 with underscores. */
2788 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2790 for (i
= 0; i
< len
; i
++)
2792 int c
= XSTRING (new)->data
[i
];
2793 if (! ((c
>= 'a' && c
<= 'z')
2794 || (c
>= 'A' && c
<= 'Z')
2795 || (c
>= '0' && c
<= '9')
2796 || c
== '-' || c
== '_'))
2797 XSTRING (new)->data
[i
] = '_';
2802 extern char *x_get_string_resource ();
2804 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2805 doc
: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2806 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2807 class, where INSTANCE is the name under which Emacs was invoked, or
2808 the name specified by the `-name' or `-rn' command-line arguments.
2810 The optional arguments COMPONENT and SUBCLASS add to the key and the
2811 class, respectively. You must specify both of them or neither.
2812 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2813 and the class is `Emacs.CLASS.SUBCLASS'. */)
2814 (attribute
, class, component
, subclass
)
2815 Lisp_Object attribute
, class, component
, subclass
;
2817 register char *value
;
2823 CHECK_STRING (attribute
);
2824 CHECK_STRING (class);
2826 if (!NILP (component
))
2827 CHECK_STRING (component
);
2828 if (!NILP (subclass
))
2829 CHECK_STRING (subclass
);
2830 if (NILP (component
) != NILP (subclass
))
2831 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2833 validate_x_resource_name ();
2835 /* Allocate space for the components, the dots which separate them,
2836 and the final '\0'. Make them big enough for the worst case. */
2837 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2838 + (STRINGP (component
)
2839 ? STRING_BYTES (XSTRING (component
)) : 0)
2840 + STRING_BYTES (XSTRING (attribute
))
2843 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2844 + STRING_BYTES (XSTRING (class))
2845 + (STRINGP (subclass
)
2846 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2849 /* Start with emacs.FRAMENAME for the name (the specific one)
2850 and with `Emacs' for the class key (the general one). */
2851 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2852 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2854 strcat (class_key
, ".");
2855 strcat (class_key
, XSTRING (class)->data
);
2857 if (!NILP (component
))
2859 strcat (class_key
, ".");
2860 strcat (class_key
, XSTRING (subclass
)->data
);
2862 strcat (name_key
, ".");
2863 strcat (name_key
, XSTRING (component
)->data
);
2866 strcat (name_key
, ".");
2867 strcat (name_key
, XSTRING (attribute
)->data
);
2869 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2870 name_key
, class_key
);
2872 if (value
!= (char *) 0)
2873 return build_string (value
);
2878 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2881 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2882 struct x_display_info
*dpyinfo
;
2883 Lisp_Object attribute
, class, component
, subclass
;
2885 register char *value
;
2889 CHECK_STRING (attribute
);
2890 CHECK_STRING (class);
2892 if (!NILP (component
))
2893 CHECK_STRING (component
);
2894 if (!NILP (subclass
))
2895 CHECK_STRING (subclass
);
2896 if (NILP (component
) != NILP (subclass
))
2897 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2899 validate_x_resource_name ();
2901 /* Allocate space for the components, the dots which separate them,
2902 and the final '\0'. Make them big enough for the worst case. */
2903 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2904 + (STRINGP (component
)
2905 ? STRING_BYTES (XSTRING (component
)) : 0)
2906 + STRING_BYTES (XSTRING (attribute
))
2909 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2910 + STRING_BYTES (XSTRING (class))
2911 + (STRINGP (subclass
)
2912 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2915 /* Start with emacs.FRAMENAME for the name (the specific one)
2916 and with `Emacs' for the class key (the general one). */
2917 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2918 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2920 strcat (class_key
, ".");
2921 strcat (class_key
, XSTRING (class)->data
);
2923 if (!NILP (component
))
2925 strcat (class_key
, ".");
2926 strcat (class_key
, XSTRING (subclass
)->data
);
2928 strcat (name_key
, ".");
2929 strcat (name_key
, XSTRING (component
)->data
);
2932 strcat (name_key
, ".");
2933 strcat (name_key
, XSTRING (attribute
)->data
);
2935 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2937 if (value
!= (char *) 0)
2938 return build_string (value
);
2943 /* Used when C code wants a resource value. */
2946 x_get_resource_string (attribute
, class)
2947 char *attribute
, *class;
2951 struct frame
*sf
= SELECTED_FRAME ();
2953 /* Allocate space for the components, the dots which separate them,
2954 and the final '\0'. */
2955 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2956 + strlen (attribute
) + 2);
2957 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2958 + strlen (class) + 2);
2960 sprintf (name_key
, "%s.%s",
2961 XSTRING (Vinvocation_name
)->data
,
2963 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2965 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2966 name_key
, class_key
);
2969 /* Types we might convert a resource string into. */
2979 /* Return the value of parameter PARAM.
2981 First search ALIST, then Vdefault_frame_alist, then the X defaults
2982 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2984 Convert the resource to the type specified by desired_type.
2986 If no default is specified, return Qunbound. If you call
2987 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2988 and don't let it get stored in any Lisp-visible variables! */
2991 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2992 struct x_display_info
*dpyinfo
;
2993 Lisp_Object alist
, param
;
2996 enum resource_types type
;
2998 register Lisp_Object tem
;
3000 tem
= Fassq (param
, alist
);
3002 tem
= Fassq (param
, Vdefault_frame_alist
);
3008 tem
= display_x_get_resource (dpyinfo
,
3009 build_string (attribute
),
3010 build_string (class),
3018 case RES_TYPE_NUMBER
:
3019 return make_number (atoi (XSTRING (tem
)->data
));
3021 case RES_TYPE_FLOAT
:
3022 return make_float (atof (XSTRING (tem
)->data
));
3024 case RES_TYPE_BOOLEAN
:
3025 tem
= Fdowncase (tem
);
3026 if (!strcmp (XSTRING (tem
)->data
, "on")
3027 || !strcmp (XSTRING (tem
)->data
, "true"))
3032 case RES_TYPE_STRING
:
3035 case RES_TYPE_SYMBOL
:
3036 /* As a special case, we map the values `true' and `on'
3037 to Qt, and `false' and `off' to Qnil. */
3040 lower
= Fdowncase (tem
);
3041 if (!strcmp (XSTRING (lower
)->data
, "on")
3042 || !strcmp (XSTRING (lower
)->data
, "true"))
3044 else if (!strcmp (XSTRING (lower
)->data
, "off")
3045 || !strcmp (XSTRING (lower
)->data
, "false"))
3048 return Fintern (tem
, Qnil
);
3061 /* Like x_get_arg, but also record the value in f->param_alist. */
3064 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
3066 Lisp_Object alist
, param
;
3069 enum resource_types type
;
3073 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
3074 attribute
, class, type
);
3076 store_frame_param (f
, param
, value
);
3081 /* Record in frame F the specified or default value according to ALIST
3082 of the parameter named PROP (a Lisp symbol).
3083 If no value is specified for PROP, look for an X default for XPROP
3084 on the frame named NAME.
3085 If that is not found either, use the value DEFLT. */
3088 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
3095 enum resource_types type
;
3099 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
3100 if (EQ (tem
, Qunbound
))
3102 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3107 /* Record in frame F the specified or default value according to ALIST
3108 of the parameter named PROP (a Lisp symbol). If no value is
3109 specified for PROP, look for an X default for XPROP on the frame
3110 named NAME. If that is not found either, use the value DEFLT. */
3113 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
3122 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3125 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
3126 if (EQ (tem
, Qunbound
))
3128 #ifdef USE_TOOLKIT_SCROLL_BARS
3130 /* See if an X resource for the scroll bar color has been
3132 tem
= display_x_get_resource (dpyinfo
,
3133 build_string (foreground_p
3137 build_string ("verticalScrollBar"),
3141 /* If nothing has been specified, scroll bars will use a
3142 toolkit-dependent default. Because these defaults are
3143 difficult to get at without actually creating a scroll
3144 bar, use nil to indicate that no color has been
3149 #else /* not USE_TOOLKIT_SCROLL_BARS */
3153 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3156 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3162 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3163 doc
: /* Parse an X-style geometry string STRING.
3164 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3165 The properties returned may include `top', `left', `height', and `width'.
3166 The value of `left' or `top' may be an integer,
3167 or a list (+ N) meaning N pixels relative to top/left corner,
3168 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3173 unsigned int width
, height
;
3176 CHECK_STRING (string
);
3178 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
3179 &x
, &y
, &width
, &height
);
3182 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3183 error ("Must specify both x and y position, or neither");
3187 if (geometry
& XValue
)
3189 Lisp_Object element
;
3191 if (x
>= 0 && (geometry
& XNegative
))
3192 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3193 else if (x
< 0 && ! (geometry
& XNegative
))
3194 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3196 element
= Fcons (Qleft
, make_number (x
));
3197 result
= Fcons (element
, result
);
3200 if (geometry
& YValue
)
3202 Lisp_Object element
;
3204 if (y
>= 0 && (geometry
& YNegative
))
3205 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3206 else if (y
< 0 && ! (geometry
& YNegative
))
3207 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3209 element
= Fcons (Qtop
, make_number (y
));
3210 result
= Fcons (element
, result
);
3213 if (geometry
& WidthValue
)
3214 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3215 if (geometry
& HeightValue
)
3216 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3221 /* Calculate the desired size and position of this window,
3222 and return the flags saying which aspects were specified.
3224 This function does not make the coordinates positive. */
3226 #define DEFAULT_ROWS 40
3227 #define DEFAULT_COLS 80
3230 x_figure_window_size (f
, parms
)
3234 register Lisp_Object tem0
, tem1
, tem2
;
3235 long window_prompting
= 0;
3236 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3238 /* Default values if we fall through.
3239 Actually, if that happens we should get
3240 window manager prompting. */
3241 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3242 f
->height
= DEFAULT_ROWS
;
3243 /* Window managers expect that if program-specified
3244 positions are not (0,0), they're intentional, not defaults. */
3245 f
->output_data
.x
->top_pos
= 0;
3246 f
->output_data
.x
->left_pos
= 0;
3248 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3249 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3250 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3251 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3253 if (!EQ (tem0
, Qunbound
))
3255 CHECK_NUMBER (tem0
);
3256 f
->height
= XINT (tem0
);
3258 if (!EQ (tem1
, Qunbound
))
3260 CHECK_NUMBER (tem1
);
3261 SET_FRAME_WIDTH (f
, XINT (tem1
));
3263 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3264 window_prompting
|= USSize
;
3266 window_prompting
|= PSize
;
3269 f
->output_data
.x
->vertical_scroll_bar_extra
3270 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3272 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3274 x_compute_fringe_widths (f
, 0);
3276 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3277 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3279 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3280 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3281 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3282 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3284 if (EQ (tem0
, Qminus
))
3286 f
->output_data
.x
->top_pos
= 0;
3287 window_prompting
|= YNegative
;
3289 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3290 && CONSP (XCDR (tem0
))
3291 && INTEGERP (XCAR (XCDR (tem0
))))
3293 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3294 window_prompting
|= YNegative
;
3296 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3297 && CONSP (XCDR (tem0
))
3298 && INTEGERP (XCAR (XCDR (tem0
))))
3300 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3302 else if (EQ (tem0
, Qunbound
))
3303 f
->output_data
.x
->top_pos
= 0;
3306 CHECK_NUMBER (tem0
);
3307 f
->output_data
.x
->top_pos
= XINT (tem0
);
3308 if (f
->output_data
.x
->top_pos
< 0)
3309 window_prompting
|= YNegative
;
3312 if (EQ (tem1
, Qminus
))
3314 f
->output_data
.x
->left_pos
= 0;
3315 window_prompting
|= XNegative
;
3317 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3318 && CONSP (XCDR (tem1
))
3319 && INTEGERP (XCAR (XCDR (tem1
))))
3321 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3322 window_prompting
|= XNegative
;
3324 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3325 && CONSP (XCDR (tem1
))
3326 && INTEGERP (XCAR (XCDR (tem1
))))
3328 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3330 else if (EQ (tem1
, Qunbound
))
3331 f
->output_data
.x
->left_pos
= 0;
3334 CHECK_NUMBER (tem1
);
3335 f
->output_data
.x
->left_pos
= XINT (tem1
);
3336 if (f
->output_data
.x
->left_pos
< 0)
3337 window_prompting
|= XNegative
;
3340 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3341 window_prompting
|= USPosition
;
3343 window_prompting
|= PPosition
;
3346 if (f
->output_data
.x
->want_fullscreen
!= FULLSCREEN_NONE
)
3351 /* It takes both for some WM:s to place it where we want */
3352 window_prompting
= USPosition
| PPosition
;
3353 x_fullscreen_adjust (f
, &width
, &height
, &top
, &left
);
3356 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3357 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3358 f
->output_data
.x
->left_pos
= left
;
3359 f
->output_data
.x
->top_pos
= top
;
3362 return window_prompting
;
3365 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3368 XSetWMProtocols (dpy
, w
, protocols
, count
)
3375 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3376 if (prop
== None
) return False
;
3377 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3378 (unsigned char *) protocols
, count
);
3381 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3383 #ifdef USE_X_TOOLKIT
3385 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3386 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3387 already be present because of the toolkit (Motif adds some of them,
3388 for example, but Xt doesn't). */
3391 hack_wm_protocols (f
, widget
)
3395 Display
*dpy
= XtDisplay (widget
);
3396 Window w
= XtWindow (widget
);
3397 int need_delete
= 1;
3403 Atom type
, *atoms
= 0;
3405 unsigned long nitems
= 0;
3406 unsigned long bytes_after
;
3408 if ((XGetWindowProperty (dpy
, w
,
3409 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3410 (long)0, (long)100, False
, XA_ATOM
,
3411 &type
, &format
, &nitems
, &bytes_after
,
3412 (unsigned char **) &atoms
)
3414 && format
== 32 && type
== XA_ATOM
)
3418 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3420 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3422 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3425 if (atoms
) XFree ((char *) atoms
);
3431 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3433 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3435 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3437 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3438 XA_ATOM
, 32, PropModeAppend
,
3439 (unsigned char *) props
, count
);
3447 /* Support routines for XIC (X Input Context). */
3451 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3452 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3455 /* Supported XIM styles, ordered by preferenc. */
3457 static XIMStyle supported_xim_styles
[] =
3459 XIMPreeditPosition
| XIMStatusArea
,
3460 XIMPreeditPosition
| XIMStatusNothing
,
3461 XIMPreeditPosition
| XIMStatusNone
,
3462 XIMPreeditNothing
| XIMStatusArea
,
3463 XIMPreeditNothing
| XIMStatusNothing
,
3464 XIMPreeditNothing
| XIMStatusNone
,
3465 XIMPreeditNone
| XIMStatusArea
,
3466 XIMPreeditNone
| XIMStatusNothing
,
3467 XIMPreeditNone
| XIMStatusNone
,
3472 /* Create an X fontset on frame F with base font name
3476 xic_create_xfontset (f
, base_fontname
)
3478 char *base_fontname
;
3481 char **missing_list
;
3485 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3486 base_fontname
, &missing_list
,
3487 &missing_count
, &def_string
);
3489 XFreeStringList (missing_list
);
3491 /* No need to free def_string. */
3496 /* Value is the best input style, given user preferences USER (already
3497 checked to be supported by Emacs), and styles supported by the
3498 input method XIM. */
3501 best_xim_style (user
, xim
)
3507 for (i
= 0; i
< user
->count_styles
; ++i
)
3508 for (j
= 0; j
< xim
->count_styles
; ++j
)
3509 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3510 return user
->supported_styles
[i
];
3512 /* Return the default style. */
3513 return XIMPreeditNothing
| XIMStatusNothing
;
3516 /* Create XIC for frame F. */
3518 static XIMStyle xic_style
;
3521 create_frame_xic (f
)
3526 XFontSet xfs
= NULL
;
3531 xim
= FRAME_X_XIM (f
);
3536 XVaNestedList preedit_attr
;
3537 XVaNestedList status_attr
;
3538 char *base_fontname
;
3541 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3542 spot
.x
= 0; spot
.y
= 1;
3543 /* Create X fontset. */
3544 fontset
= FRAME_FONTSET (f
);
3546 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3549 /* Determine the base fontname from the ASCII font name of
3551 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3552 char *p
= ascii_font
;
3555 for (i
= 0; *p
; p
++)
3558 /* As the font name doesn't conform to XLFD, we can't
3559 modify it to get a suitable base fontname for the
3561 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3564 int len
= strlen (ascii_font
) + 1;
3567 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3576 base_fontname
= (char *) alloca (len
);
3577 bzero (base_fontname
, len
);
3578 strcpy (base_fontname
, "-*-*-");
3579 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3580 strcat (base_fontname
, "*-*-*-*-*-*-*");
3583 xfs
= xic_create_xfontset (f
, base_fontname
);
3585 /* Determine XIC style. */
3588 XIMStyles supported_list
;
3589 supported_list
.count_styles
= (sizeof supported_xim_styles
3590 / sizeof supported_xim_styles
[0]);
3591 supported_list
.supported_styles
= supported_xim_styles
;
3592 xic_style
= best_xim_style (&supported_list
,
3593 FRAME_X_XIM_STYLES (f
));
3596 preedit_attr
= XVaCreateNestedList (0,
3599 FRAME_FOREGROUND_PIXEL (f
),
3601 FRAME_BACKGROUND_PIXEL (f
),
3602 (xic_style
& XIMPreeditPosition
3607 status_attr
= XVaCreateNestedList (0,
3613 FRAME_FOREGROUND_PIXEL (f
),
3615 FRAME_BACKGROUND_PIXEL (f
),
3618 xic
= XCreateIC (xim
,
3619 XNInputStyle
, xic_style
,
3620 XNClientWindow
, FRAME_X_WINDOW(f
),
3621 XNFocusWindow
, FRAME_X_WINDOW(f
),
3622 XNStatusAttributes
, status_attr
,
3623 XNPreeditAttributes
, preedit_attr
,
3625 XFree (preedit_attr
);
3626 XFree (status_attr
);
3629 FRAME_XIC (f
) = xic
;
3630 FRAME_XIC_STYLE (f
) = xic_style
;
3631 FRAME_XIC_FONTSET (f
) = xfs
;
3635 /* Destroy XIC and free XIC fontset of frame F, if any. */
3641 if (FRAME_XIC (f
) == NULL
)
3644 XDestroyIC (FRAME_XIC (f
));
3645 if (FRAME_XIC_FONTSET (f
))
3646 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3648 FRAME_XIC (f
) = NULL
;
3649 FRAME_XIC_FONTSET (f
) = NULL
;
3653 /* Place preedit area for XIC of window W's frame to specified
3654 pixel position X/Y. X and Y are relative to window W. */
3657 xic_set_preeditarea (w
, x
, y
)
3661 struct frame
*f
= XFRAME (w
->frame
);
3665 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3666 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3667 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3668 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3673 /* Place status area for XIC in bottom right corner of frame F.. */
3676 xic_set_statusarea (f
)
3679 XIC xic
= FRAME_XIC (f
);
3684 /* Negotiate geometry of status area. If input method has existing
3685 status area, use its current size. */
3686 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3687 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3688 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3691 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3692 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3695 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3697 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3698 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3702 area
.width
= needed
->width
;
3703 area
.height
= needed
->height
;
3704 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3705 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3706 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3709 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3710 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3715 /* Set X fontset for XIC of frame F, using base font name
3716 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3719 xic_set_xfontset (f
, base_fontname
)
3721 char *base_fontname
;
3726 xfs
= xic_create_xfontset (f
, base_fontname
);
3728 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3729 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3730 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3731 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3732 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3735 if (FRAME_XIC_FONTSET (f
))
3736 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3737 FRAME_XIC_FONTSET (f
) = xfs
;
3740 #endif /* HAVE_X_I18N */
3744 #ifdef USE_X_TOOLKIT
3746 /* Create and set up the X widget for frame F. */
3749 x_window (f
, window_prompting
, minibuffer_only
)
3751 long window_prompting
;
3752 int minibuffer_only
;
3754 XClassHint class_hints
;
3755 XSetWindowAttributes attributes
;
3756 unsigned long attribute_mask
;
3757 Widget shell_widget
;
3759 Widget frame_widget
;
3765 /* Use the resource name as the top-level widget name
3766 for looking up resources. Make a non-Lisp copy
3767 for the window manager, so GC relocation won't bother it.
3769 Elsewhere we specify the window name for the window manager. */
3772 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3773 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3774 strcpy (f
->namebuf
, str
);
3778 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3779 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3780 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3781 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3782 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3783 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3784 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3785 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3786 applicationShellWidgetClass
,
3787 FRAME_X_DISPLAY (f
), al
, ac
);
3789 f
->output_data
.x
->widget
= shell_widget
;
3790 /* maybe_set_screen_title_format (shell_widget); */
3792 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3793 (widget_value
*) NULL
,
3794 shell_widget
, False
,
3798 (lw_callback
) NULL
);
3801 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3802 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3803 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3804 XtSetValues (pane_widget
, al
, ac
);
3805 f
->output_data
.x
->column_widget
= pane_widget
;
3807 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3808 the emacs screen when changing menubar. This reduces flickering. */
3811 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3812 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3813 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3814 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3815 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3816 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3817 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3818 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3819 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3822 f
->output_data
.x
->edit_widget
= frame_widget
;
3824 XtManageChild (frame_widget
);
3826 /* Do some needed geometry management. */
3829 char *tem
, shell_position
[32];
3832 int extra_borders
= 0;
3834 = (f
->output_data
.x
->menubar_widget
3835 ? (f
->output_data
.x
->menubar_widget
->core
.height
3836 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3839 #if 0 /* Experimentally, we now get the right results
3840 for -geometry -0-0 without this. 24 Aug 96, rms. */
3841 if (FRAME_EXTERNAL_MENU_BAR (f
))
3844 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3845 menubar_size
+= ibw
;
3849 f
->output_data
.x
->menubar_height
= menubar_size
;
3852 /* Motif seems to need this amount added to the sizes
3853 specified for the shell widget. The Athena/Lucid widgets don't.
3854 Both conclusions reached experimentally. -- rms. */
3855 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3856 &extra_borders
, NULL
);
3860 /* Convert our geometry parameters into a geometry string
3862 Note that we do not specify here whether the position
3863 is a user-specified or program-specified one.
3864 We pass that information later, in x_wm_set_size_hints. */
3866 int left
= f
->output_data
.x
->left_pos
;
3867 int xneg
= window_prompting
& XNegative
;
3868 int top
= f
->output_data
.x
->top_pos
;
3869 int yneg
= window_prompting
& YNegative
;
3875 if (window_prompting
& USPosition
)
3876 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3877 PIXEL_WIDTH (f
) + extra_borders
,
3878 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3879 (xneg
? '-' : '+'), left
,
3880 (yneg
? '-' : '+'), top
);
3882 sprintf (shell_position
, "=%dx%d",
3883 PIXEL_WIDTH (f
) + extra_borders
,
3884 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3887 len
= strlen (shell_position
) + 1;
3888 /* We don't free this because we don't know whether
3889 it is safe to free it while the frame exists.
3890 It isn't worth the trouble of arranging to free it
3891 when the frame is deleted. */
3892 tem
= (char *) xmalloc (len
);
3893 strncpy (tem
, shell_position
, len
);
3894 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3895 XtSetValues (shell_widget
, al
, ac
);
3898 XtManageChild (pane_widget
);
3899 XtRealizeWidget (shell_widget
);
3901 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3903 validate_x_resource_name ();
3905 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3906 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3907 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3910 FRAME_XIC (f
) = NULL
;
3912 create_frame_xic (f
);
3916 f
->output_data
.x
->wm_hints
.input
= True
;
3917 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3918 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3919 &f
->output_data
.x
->wm_hints
);
3921 hack_wm_protocols (f
, shell_widget
);
3924 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3927 /* Do a stupid property change to force the server to generate a
3928 PropertyNotify event so that the event_stream server timestamp will
3929 be initialized to something relevant to the time we created the window.
3931 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3932 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3933 XA_ATOM
, 32, PropModeAppend
,
3934 (unsigned char*) NULL
, 0);
3936 /* Make all the standard events reach the Emacs frame. */
3937 attributes
.event_mask
= STANDARD_EVENT_SET
;
3942 /* XIM server might require some X events. */
3943 unsigned long fevent
= NoEventMask
;
3944 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3945 attributes
.event_mask
|= fevent
;
3947 #endif /* HAVE_X_I18N */
3949 attribute_mask
= CWEventMask
;
3950 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3951 attribute_mask
, &attributes
);
3953 XtMapWidget (frame_widget
);
3955 /* x_set_name normally ignores requests to set the name if the
3956 requested name is the same as the current name. This is the one
3957 place where that assumption isn't correct; f->name is set, but
3958 the X server hasn't been told. */
3961 int explicit = f
->explicit_name
;
3963 f
->explicit_name
= 0;
3966 x_set_name (f
, name
, explicit);
3969 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3970 f
->output_data
.x
->text_cursor
);
3974 /* This is a no-op, except under Motif. Make sure main areas are
3975 set to something reasonable, in case we get an error later. */
3976 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3979 #else /* not USE_X_TOOLKIT */
3981 /* Create and set up the X window for frame F. */
3988 XClassHint class_hints
;
3989 XSetWindowAttributes attributes
;
3990 unsigned long attribute_mask
;
3992 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3993 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3994 attributes
.bit_gravity
= StaticGravity
;
3995 attributes
.backing_store
= NotUseful
;
3996 attributes
.save_under
= True
;
3997 attributes
.event_mask
= STANDARD_EVENT_SET
;
3998 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3999 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
4004 = XCreateWindow (FRAME_X_DISPLAY (f
),
4005 f
->output_data
.x
->parent_desc
,
4006 f
->output_data
.x
->left_pos
,
4007 f
->output_data
.x
->top_pos
,
4008 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
4009 f
->output_data
.x
->border_width
,
4010 CopyFromParent
, /* depth */
4011 InputOutput
, /* class */
4013 attribute_mask
, &attributes
);
4017 create_frame_xic (f
);
4020 /* XIM server might require some X events. */
4021 unsigned long fevent
= NoEventMask
;
4022 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
4023 attributes
.event_mask
|= fevent
;
4024 attribute_mask
= CWEventMask
;
4025 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4026 attribute_mask
, &attributes
);
4029 #endif /* HAVE_X_I18N */
4031 validate_x_resource_name ();
4033 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
4034 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
4035 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
4037 /* The menubar is part of the ordinary display;
4038 it does not count in addition to the height of the window. */
4039 f
->output_data
.x
->menubar_height
= 0;
4041 /* This indicates that we use the "Passive Input" input model.
4042 Unless we do this, we don't get the Focus{In,Out} events that we
4043 need to draw the cursor correctly. Accursed bureaucrats.
4044 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
4046 f
->output_data
.x
->wm_hints
.input
= True
;
4047 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
4048 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4049 &f
->output_data
.x
->wm_hints
);
4050 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
4052 /* Request "save yourself" and "delete window" commands from wm. */
4055 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
4056 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
4057 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
4060 /* x_set_name normally ignores requests to set the name if the
4061 requested name is the same as the current name. This is the one
4062 place where that assumption isn't correct; f->name is set, but
4063 the X server hasn't been told. */
4066 int explicit = f
->explicit_name
;
4068 f
->explicit_name
= 0;
4071 x_set_name (f
, name
, explicit);
4074 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4075 f
->output_data
.x
->text_cursor
);
4079 if (FRAME_X_WINDOW (f
) == 0)
4080 error ("Unable to create window");
4083 #endif /* not USE_X_TOOLKIT */
4085 /* Handle the icon stuff for this window. Perhaps later we might
4086 want an x_set_icon_position which can be called interactively as
4094 Lisp_Object icon_x
, icon_y
;
4095 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4097 /* Set the position of the icon. Note that twm groups all
4098 icons in an icon window. */
4099 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4100 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4101 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4103 CHECK_NUMBER (icon_x
);
4104 CHECK_NUMBER (icon_y
);
4106 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4107 error ("Both left and top icon corners of icon must be specified");
4111 if (! EQ (icon_x
, Qunbound
))
4112 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4114 /* Start up iconic or window? */
4115 x_wm_set_window_state
4116 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
4121 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
4128 /* Make the GCs needed for this window, setting the
4129 background, border and mouse colors; also create the
4130 mouse cursor and the gray border tile. */
4132 static char cursor_bits
[] =
4134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4144 XGCValues gc_values
;
4148 /* Create the GCs of this frame.
4149 Note that many default values are used. */
4152 gc_values
.font
= f
->output_data
.x
->font
->fid
;
4153 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
4154 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4155 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
4156 f
->output_data
.x
->normal_gc
4157 = XCreateGC (FRAME_X_DISPLAY (f
),
4159 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
4162 /* Reverse video style. */
4163 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4164 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4165 f
->output_data
.x
->reverse_gc
4166 = XCreateGC (FRAME_X_DISPLAY (f
),
4168 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
4171 /* Cursor has cursor-color background, background-color foreground. */
4172 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4173 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
4174 gc_values
.fill_style
= FillOpaqueStippled
;
4176 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4177 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4178 cursor_bits
, 16, 16);
4179 f
->output_data
.x
->cursor_gc
4180 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4181 (GCFont
| GCForeground
| GCBackground
4182 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
4186 f
->output_data
.x
->white_relief
.gc
= 0;
4187 f
->output_data
.x
->black_relief
.gc
= 0;
4189 /* Create the gray border tile used when the pointer is not in
4190 the frame. Since this depends on the frame's pixel values,
4191 this must be done on a per-frame basis. */
4192 f
->output_data
.x
->border_tile
4193 = (XCreatePixmapFromBitmapData
4194 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
4195 gray_bits
, gray_width
, gray_height
,
4196 f
->output_data
.x
->foreground_pixel
,
4197 f
->output_data
.x
->background_pixel
,
4198 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4204 /* Free what was was allocated in x_make_gc. */
4210 Display
*dpy
= FRAME_X_DISPLAY (f
);
4214 if (f
->output_data
.x
->normal_gc
)
4216 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4217 f
->output_data
.x
->normal_gc
= 0;
4220 if (f
->output_data
.x
->reverse_gc
)
4222 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4223 f
->output_data
.x
->reverse_gc
= 0;
4226 if (f
->output_data
.x
->cursor_gc
)
4228 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4229 f
->output_data
.x
->cursor_gc
= 0;
4232 if (f
->output_data
.x
->border_tile
)
4234 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4235 f
->output_data
.x
->border_tile
= 0;
4242 /* Handler for signals raised during x_create_frame and
4243 x_create_top_frame. FRAME is the frame which is partially
4247 unwind_create_frame (frame
)
4250 struct frame
*f
= XFRAME (frame
);
4252 /* If frame is ``official'', nothing to do. */
4253 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4256 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4259 x_free_frame_resources (f
);
4261 /* Check that reference counts are indeed correct. */
4262 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4263 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4271 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4273 doc
: /* Make a new X window, which is called a "frame" in Emacs terms.
4274 Returns an Emacs frame object.
4275 ALIST is an alist of frame parameters.
4276 If the parameters specify that the frame should not have a minibuffer,
4277 and do not specify a specific minibuffer window to use,
4278 then `default-minibuffer-frame' must be a frame whose minibuffer can
4279 be shared by the new frame.
4281 This function is an internal primitive--use `make-frame' instead. */)
4286 Lisp_Object frame
, tem
;
4288 int minibuffer_only
= 0;
4289 long window_prompting
= 0;
4291 int count
= BINDING_STACK_SIZE ();
4292 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4293 Lisp_Object display
;
4294 struct x_display_info
*dpyinfo
= NULL
;
4300 /* Use this general default value to start with
4301 until we know if this frame has a specified name. */
4302 Vx_resource_name
= Vinvocation_name
;
4304 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4305 if (EQ (display
, Qunbound
))
4307 dpyinfo
= check_x_display_info (display
);
4309 kb
= dpyinfo
->kboard
;
4311 kb
= &the_only_kboard
;
4314 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4316 && ! EQ (name
, Qunbound
)
4318 error ("Invalid frame name--not a string or nil");
4321 Vx_resource_name
= name
;
4323 /* See if parent window is specified. */
4324 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4325 if (EQ (parent
, Qunbound
))
4327 if (! NILP (parent
))
4328 CHECK_NUMBER (parent
);
4330 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4331 /* No need to protect DISPLAY because that's not used after passing
4332 it to make_frame_without_minibuffer. */
4334 GCPRO4 (parms
, parent
, name
, frame
);
4335 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4337 if (EQ (tem
, Qnone
) || NILP (tem
))
4338 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4339 else if (EQ (tem
, Qonly
))
4341 f
= make_minibuffer_frame ();
4342 minibuffer_only
= 1;
4344 else if (WINDOWP (tem
))
4345 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4349 XSETFRAME (frame
, f
);
4351 /* Note that X Windows does support scroll bars. */
4352 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4354 f
->output_method
= output_x_window
;
4355 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4356 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4357 f
->output_data
.x
->icon_bitmap
= -1;
4358 f
->output_data
.x
->fontset
= -1;
4359 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4360 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4361 #ifdef USE_TOOLKIT_SCROLL_BARS
4362 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
4363 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
4364 #endif /* USE_TOOLKIT_SCROLL_BARS */
4365 record_unwind_protect (unwind_create_frame
, frame
);
4368 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4370 if (! STRINGP (f
->icon_name
))
4371 f
->icon_name
= Qnil
;
4373 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4375 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4376 dpyinfo_refcount
= dpyinfo
->reference_count
;
4377 #endif /* GLYPH_DEBUG */
4379 FRAME_KBOARD (f
) = kb
;
4382 /* These colors will be set anyway later, but it's important
4383 to get the color reference counts right, so initialize them! */
4386 struct gcpro gcpro1
;
4388 /* Function x_decode_color can signal an error. Make
4389 sure to initialize color slots so that we won't try
4390 to free colors we haven't allocated. */
4391 f
->output_data
.x
->foreground_pixel
= -1;
4392 f
->output_data
.x
->background_pixel
= -1;
4393 f
->output_data
.x
->cursor_pixel
= -1;
4394 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4395 f
->output_data
.x
->border_pixel
= -1;
4396 f
->output_data
.x
->mouse_pixel
= -1;
4398 black
= build_string ("black");
4400 f
->output_data
.x
->foreground_pixel
4401 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4402 f
->output_data
.x
->background_pixel
4403 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4404 f
->output_data
.x
->cursor_pixel
4405 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4406 f
->output_data
.x
->cursor_foreground_pixel
4407 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4408 f
->output_data
.x
->border_pixel
4409 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4410 f
->output_data
.x
->mouse_pixel
4411 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4415 /* Specify the parent under which to make this X window. */
4419 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4420 f
->output_data
.x
->explicit_parent
= 1;
4424 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4425 f
->output_data
.x
->explicit_parent
= 0;
4428 /* Set the name; the functions to which we pass f expect the name to
4430 if (EQ (name
, Qunbound
) || NILP (name
))
4432 f
->name
= build_string (dpyinfo
->x_id_name
);
4433 f
->explicit_name
= 0;
4438 f
->explicit_name
= 1;
4439 /* use the frame's title when getting resources for this frame. */
4440 specbind (Qx_resource_name
, name
);
4443 /* Extract the window parameters from the supplied values
4444 that are needed to determine window geometry. */
4448 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4451 /* First, try whatever font the caller has specified. */
4454 tem
= Fquery_fontset (font
, Qnil
);
4456 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4458 font
= x_new_font (f
, XSTRING (font
)->data
);
4461 /* Try out a font which we hope has bold and italic variations. */
4462 if (!STRINGP (font
))
4463 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4464 if (!STRINGP (font
))
4465 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4466 if (! STRINGP (font
))
4467 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4468 if (! STRINGP (font
))
4469 /* This was formerly the first thing tried, but it finds too many fonts
4470 and takes too long. */
4471 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4472 /* If those didn't work, look for something which will at least work. */
4473 if (! STRINGP (font
))
4474 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4476 if (! STRINGP (font
))
4477 font
= build_string ("fixed");
4479 x_default_parameter (f
, parms
, Qfont
, font
,
4480 "font", "Font", RES_TYPE_STRING
);
4484 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4485 whereby it fails to get any font. */
4486 xlwmenu_default_font
= f
->output_data
.x
->font
;
4489 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4490 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4492 /* This defaults to 1 in order to match xterm. We recognize either
4493 internalBorderWidth or internalBorder (which is what xterm calls
4495 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4499 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4500 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4501 if (! EQ (value
, Qunbound
))
4502 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4505 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4506 "internalBorderWidth", "internalBorderWidth",
4508 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4509 "verticalScrollBars", "ScrollBars",
4512 /* Also do the stuff which must be set before the window exists. */
4513 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4514 "foreground", "Foreground", RES_TYPE_STRING
);
4515 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4516 "background", "Background", RES_TYPE_STRING
);
4517 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4518 "pointerColor", "Foreground", RES_TYPE_STRING
);
4519 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4520 "cursorColor", "Foreground", RES_TYPE_STRING
);
4521 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4522 "borderColor", "BorderColor", RES_TYPE_STRING
);
4523 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4524 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4525 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4526 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4527 x_default_parameter (f
, parms
, Qleft_fringe
, Qnil
,
4528 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4529 x_default_parameter (f
, parms
, Qright_fringe
, Qnil
,
4530 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4532 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4533 "scrollBarForeground",
4534 "ScrollBarForeground", 1);
4535 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4536 "scrollBarBackground",
4537 "ScrollBarBackground", 0);
4539 /* Init faces before x_default_parameter is called for scroll-bar
4540 parameters because that function calls x_set_scroll_bar_width,
4541 which calls change_frame_size, which calls Fset_window_buffer,
4542 which runs hooks, which call Fvertical_motion. At the end, we
4543 end up in init_iterator with a null face cache, which should not
4545 init_frame_faces (f
);
4547 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4548 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4549 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4550 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4551 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4552 "bufferPredicate", "BufferPredicate",
4554 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4555 "title", "Title", RES_TYPE_STRING
);
4556 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4557 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4558 x_default_parameter (f
, parms
, Qfullscreen
, Qnil
,
4559 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4561 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4563 /* Add the tool-bar height to the initial frame height so that the
4564 user gets a text display area of the size he specified with -g or
4565 via .Xdefaults. Later changes of the tool-bar height don't
4566 change the frame size. This is done so that users can create
4567 tall Emacs frames without having to guess how tall the tool-bar
4569 if (FRAME_TOOL_BAR_LINES (f
))
4571 int margin
, relief
, bar_height
;
4573 relief
= (tool_bar_button_relief
>= 0
4574 ? tool_bar_button_relief
4575 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4577 if (INTEGERP (Vtool_bar_button_margin
)
4578 && XINT (Vtool_bar_button_margin
) > 0)
4579 margin
= XFASTINT (Vtool_bar_button_margin
);
4580 else if (CONSP (Vtool_bar_button_margin
)
4581 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4582 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4583 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4587 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4588 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4591 /* Compute the size of the X window. */
4592 window_prompting
= x_figure_window_size (f
, parms
);
4594 if (window_prompting
& XNegative
)
4596 if (window_prompting
& YNegative
)
4597 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4599 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4603 if (window_prompting
& YNegative
)
4604 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4606 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4609 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4611 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4612 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4614 /* Create the X widget or window. */
4615 #ifdef USE_X_TOOLKIT
4616 x_window (f
, window_prompting
, minibuffer_only
);
4624 /* Now consider the frame official. */
4625 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4626 Vframe_list
= Fcons (frame
, Vframe_list
);
4628 /* We need to do this after creating the X window, so that the
4629 icon-creation functions can say whose icon they're describing. */
4630 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4631 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4633 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4634 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4635 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4636 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4637 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4638 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4639 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4640 "scrollBarWidth", "ScrollBarWidth",
4643 /* Dimensions, especially f->height, must be done via change_frame_size.
4644 Change will not be effected unless different from the current
4650 SET_FRAME_WIDTH (f
, 0);
4651 change_frame_size (f
, height
, width
, 1, 0, 0);
4653 /* Set up faces after all frame parameters are known. This call
4654 also merges in face attributes specified for new frames. If we
4655 don't do this, the `menu' face for instance won't have the right
4656 colors, and the menu bar won't appear in the specified colors for
4658 call1 (Qface_set_after_frame_default
, frame
);
4660 #ifdef USE_X_TOOLKIT
4661 /* Create the menu bar. */
4662 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4664 /* If this signals an error, we haven't set size hints for the
4665 frame and we didn't make it visible. */
4666 initialize_frame_menubar (f
);
4668 /* This is a no-op, except under Motif where it arranges the
4669 main window for the widgets on it. */
4670 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4671 f
->output_data
.x
->menubar_widget
,
4672 f
->output_data
.x
->edit_widget
);
4674 #endif /* USE_X_TOOLKIT */
4676 /* Tell the server what size and position, etc, we want, and how
4677 badly we want them. This should be done after we have the menu
4678 bar so that its size can be taken into account. */
4680 x_wm_set_size_hint (f
, window_prompting
, 0);
4683 /* Make the window appear on the frame and enable display, unless
4684 the caller says not to. However, with explicit parent, Emacs
4685 cannot control visibility, so don't try. */
4686 if (! f
->output_data
.x
->explicit_parent
)
4688 Lisp_Object visibility
;
4690 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4692 if (EQ (visibility
, Qunbound
))
4695 if (EQ (visibility
, Qicon
))
4696 x_iconify_frame (f
);
4697 else if (! NILP (visibility
))
4698 x_make_frame_visible (f
);
4700 /* Must have been Qnil. */
4706 /* Make sure windows on this frame appear in calls to next-window
4707 and similar functions. */
4708 Vwindow_list
= Qnil
;
4710 return unbind_to (count
, frame
);
4714 /* FRAME is used only to get a handle on the X display. We don't pass the
4715 display info directly because we're called from frame.c, which doesn't
4716 know about that structure. */
4719 x_get_focus_frame (frame
)
4720 struct frame
*frame
;
4722 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4724 if (! dpyinfo
->x_focus_frame
)
4727 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4732 /* In certain situations, when the window manager follows a
4733 click-to-focus policy, there seems to be no way around calling
4734 XSetInputFocus to give another frame the input focus .
4736 In an ideal world, XSetInputFocus should generally be avoided so
4737 that applications don't interfere with the window manager's focus
4738 policy. But I think it's okay to use when it's clearly done
4739 following a user-command. */
4741 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4742 doc
: /* Set the input focus to FRAME.
4743 FRAME nil means use the selected frame. */)
4747 struct frame
*f
= check_x_frame (frame
);
4748 Display
*dpy
= FRAME_X_DISPLAY (f
);
4752 count
= x_catch_errors (dpy
);
4753 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4754 RevertToParent
, CurrentTime
);
4755 x_uncatch_errors (dpy
, count
);
4762 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4763 doc
: /* Internal function called by `color-defined-p', which see. */)
4765 Lisp_Object color
, frame
;
4768 FRAME_PTR f
= check_x_frame (frame
);
4770 CHECK_STRING (color
);
4772 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4778 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4779 doc
: /* Internal function called by `color-values', which see. */)
4781 Lisp_Object color
, frame
;
4784 FRAME_PTR f
= check_x_frame (frame
);
4786 CHECK_STRING (color
);
4788 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4792 rgb
[0] = make_number (foo
.red
);
4793 rgb
[1] = make_number (foo
.green
);
4794 rgb
[2] = make_number (foo
.blue
);
4795 return Flist (3, rgb
);
4801 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4802 doc
: /* Internal function called by `display-color-p', which see. */)
4804 Lisp_Object display
;
4806 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4808 if (dpyinfo
->n_planes
<= 2)
4811 switch (dpyinfo
->visual
->class)
4824 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4826 doc
: /* Return t if the X display supports shades of gray.
4827 Note that color displays do support shades of gray.
4828 The optional argument DISPLAY specifies which display to ask about.
4829 DISPLAY should be either a frame or a display name (a string).
4830 If omitted or nil, that stands for the selected frame's display. */)
4832 Lisp_Object display
;
4834 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4836 if (dpyinfo
->n_planes
<= 1)
4839 switch (dpyinfo
->visual
->class)
4854 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4856 doc
: /* Returns the width in pixels of the X display DISPLAY.
4857 The optional argument DISPLAY specifies which display to ask about.
4858 DISPLAY should be either a frame or a display name (a string).
4859 If omitted or nil, that stands for the selected frame's display. */)
4861 Lisp_Object display
;
4863 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4865 return make_number (dpyinfo
->width
);
4868 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4869 Sx_display_pixel_height
, 0, 1, 0,
4870 doc
: /* Returns the height in pixels of the X display DISPLAY.
4871 The optional argument DISPLAY specifies which display to ask about.
4872 DISPLAY should be either a frame or a display name (a string).
4873 If omitted or nil, that stands for the selected frame's display. */)
4875 Lisp_Object display
;
4877 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4879 return make_number (dpyinfo
->height
);
4882 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4884 doc
: /* Returns the number of bitplanes of the X display DISPLAY.
4885 The optional argument DISPLAY specifies which display to ask about.
4886 DISPLAY should be either a frame or a display name (a string).
4887 If omitted or nil, that stands for the selected frame's display. */)
4889 Lisp_Object display
;
4891 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4893 return make_number (dpyinfo
->n_planes
);
4896 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4898 doc
: /* Returns the number of color cells of the X display DISPLAY.
4899 The optional argument DISPLAY specifies which display to ask about.
4900 DISPLAY should be either a frame or a display name (a string).
4901 If omitted or nil, that stands for the selected frame's display. */)
4903 Lisp_Object display
;
4905 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4907 return make_number (DisplayCells (dpyinfo
->display
,
4908 XScreenNumberOfScreen (dpyinfo
->screen
)));
4911 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4912 Sx_server_max_request_size
,
4914 doc
: /* Returns the maximum request size of the X server of display DISPLAY.
4915 The optional argument DISPLAY specifies which display to ask about.
4916 DISPLAY should be either a frame or a display name (a string).
4917 If omitted or nil, that stands for the selected frame's display. */)
4919 Lisp_Object display
;
4921 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4923 return make_number (MAXREQUEST (dpyinfo
->display
));
4926 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4927 doc
: /* Returns the vendor ID string 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
);
4935 char *vendor
= ServerVendor (dpyinfo
->display
);
4937 if (! vendor
) vendor
= "";
4938 return build_string (vendor
);
4941 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4942 doc
: /* Returns the version numbers of the X server of display DISPLAY.
4943 The value is a list of three integers: the major and minor
4944 version numbers of the X Protocol in use, and the vendor-specific release
4945 number. See also the function `x-server-vendor'.
4947 The optional argument DISPLAY specifies which display to ask about.
4948 DISPLAY should be either a frame or a display name (a string).
4949 If omitted or nil, that stands for the selected frame's display. */)
4951 Lisp_Object display
;
4953 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4954 Display
*dpy
= dpyinfo
->display
;
4956 return Fcons (make_number (ProtocolVersion (dpy
)),
4957 Fcons (make_number (ProtocolRevision (dpy
)),
4958 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4961 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4962 doc
: /* Return the number of screens on the X server of display DISPLAY.
4963 The optional argument DISPLAY specifies which display to ask about.
4964 DISPLAY should be either a frame or a display name (a string).
4965 If omitted or nil, that stands for the selected frame's display. */)
4967 Lisp_Object display
;
4969 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4971 return make_number (ScreenCount (dpyinfo
->display
));
4974 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4975 doc
: /* Return the height in millimeters of the X 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 (HeightMMOfScreen (dpyinfo
->screen
));
4987 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4988 doc
: /* Return the width 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 (WidthMMOfScreen (dpyinfo
->screen
));
5000 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
5001 Sx_display_backing_store
, 0, 1, 0,
5002 doc
: /* Returns an indication of whether X display DISPLAY does backing store.
5003 The value may be `always', `when-mapped', or `not-useful'.
5004 The optional argument DISPLAY specifies which display to ask about.
5005 DISPLAY should be either a frame or a display name (a string).
5006 If omitted or nil, that stands for the selected frame's display. */)
5008 Lisp_Object display
;
5010 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5013 switch (DoesBackingStore (dpyinfo
->screen
))
5016 result
= intern ("always");
5020 result
= intern ("when-mapped");
5024 result
= intern ("not-useful");
5028 error ("Strange value for BackingStore parameter of screen");
5035 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
5036 Sx_display_visual_class
, 0, 1, 0,
5037 doc
: /* Return the visual class of the X display DISPLAY.
5038 The value is one of the symbols `static-gray', `gray-scale',
5039 `static-color', `pseudo-color', `true-color', or `direct-color'.
5041 The optional argument DISPLAY specifies which display to ask about.
5042 DISPLAY should be either a frame or a display name (a string).
5043 If omitted or nil, that stands for the selected frame's display. */)
5045 Lisp_Object display
;
5047 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5050 switch (dpyinfo
->visual
->class)
5053 result
= intern ("static-gray");
5056 result
= intern ("gray-scale");
5059 result
= intern ("static-color");
5062 result
= intern ("pseudo-color");
5065 result
= intern ("true-color");
5068 result
= intern ("direct-color");
5071 error ("Display has an unknown visual class");
5078 DEFUN ("x-display-save-under", Fx_display_save_under
,
5079 Sx_display_save_under
, 0, 1, 0,
5080 doc
: /* Returns t if the X display DISPLAY supports the save-under feature.
5081 The optional argument DISPLAY specifies which display to ask about.
5082 DISPLAY should be either a frame or a display name (a string).
5083 If omitted or nil, that stands for the selected frame's display. */)
5085 Lisp_Object display
;
5087 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5089 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
5097 register struct frame
*f
;
5099 return PIXEL_WIDTH (f
);
5104 register struct frame
*f
;
5106 return PIXEL_HEIGHT (f
);
5111 register struct frame
*f
;
5113 return FONT_WIDTH (f
->output_data
.x
->font
);
5118 register struct frame
*f
;
5120 return f
->output_data
.x
->line_height
;
5125 register struct frame
*f
;
5127 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
5132 /************************************************************************
5134 ************************************************************************/
5137 /* Mapping visual names to visuals. */
5139 static struct visual_class
5146 {"StaticGray", StaticGray
},
5147 {"GrayScale", GrayScale
},
5148 {"StaticColor", StaticColor
},
5149 {"PseudoColor", PseudoColor
},
5150 {"TrueColor", TrueColor
},
5151 {"DirectColor", DirectColor
},
5156 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5158 /* Value is the screen number of screen SCR. This is a substitute for
5159 the X function with the same name when that doesn't exist. */
5162 XScreenNumberOfScreen (scr
)
5163 register Screen
*scr
;
5165 Display
*dpy
= scr
->display
;
5168 for (i
= 0; i
< dpy
->nscreens
; ++i
)
5169 if (scr
== dpy
->screens
+ i
)
5175 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5178 /* Select the visual that should be used on display DPYINFO. Set
5179 members of DPYINFO appropriately. Called from x_term_init. */
5182 select_visual (dpyinfo
)
5183 struct x_display_info
*dpyinfo
;
5185 Display
*dpy
= dpyinfo
->display
;
5186 Screen
*screen
= dpyinfo
->screen
;
5189 /* See if a visual is specified. */
5190 value
= display_x_get_resource (dpyinfo
,
5191 build_string ("visualClass"),
5192 build_string ("VisualClass"),
5194 if (STRINGP (value
))
5196 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5197 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5198 depth, a decimal number. NAME is compared with case ignored. */
5199 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
5204 strcpy (s
, XSTRING (value
)->data
);
5205 dash
= index (s
, '-');
5208 dpyinfo
->n_planes
= atoi (dash
+ 1);
5212 /* We won't find a matching visual with depth 0, so that
5213 an error will be printed below. */
5214 dpyinfo
->n_planes
= 0;
5216 /* Determine the visual class. */
5217 for (i
= 0; visual_classes
[i
].name
; ++i
)
5218 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5220 class = visual_classes
[i
].class;
5224 /* Look up a matching visual for the specified class. */
5226 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5227 dpyinfo
->n_planes
, class, &vinfo
))
5228 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
5230 dpyinfo
->visual
= vinfo
.visual
;
5235 XVisualInfo
*vinfo
, vinfo_template
;
5237 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5240 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5242 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5244 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5245 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5246 &vinfo_template
, &n_visuals
);
5248 fatal ("Can't get proper X visual info");
5250 dpyinfo
->n_planes
= vinfo
->depth
;
5251 XFree ((char *) vinfo
);
5256 /* Return the X display structure for the display named NAME.
5257 Open a new connection if necessary. */
5259 struct x_display_info
*
5260 x_display_info_for_name (name
)
5264 struct x_display_info
*dpyinfo
;
5266 CHECK_STRING (name
);
5268 if (! EQ (Vwindow_system
, intern ("x")))
5269 error ("Not using X Windows");
5271 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5273 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5276 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5281 /* Use this general default value to start with. */
5282 Vx_resource_name
= Vinvocation_name
;
5284 validate_x_resource_name ();
5286 dpyinfo
= x_term_init (name
, (char *)0,
5287 (char *) XSTRING (Vx_resource_name
)->data
);
5290 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5293 XSETFASTINT (Vwindow_system_version
, 11);
5299 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5301 doc
: /* Open a connection to an X server.
5302 DISPLAY is the name of the display to connect to.
5303 Optional second arg XRM-STRING is a string of resources in xrdb format.
5304 If the optional third arg MUST-SUCCEED is non-nil,
5305 terminate Emacs if we can't open the connection. */)
5306 (display
, xrm_string
, must_succeed
)
5307 Lisp_Object display
, xrm_string
, must_succeed
;
5309 unsigned char *xrm_option
;
5310 struct x_display_info
*dpyinfo
;
5312 CHECK_STRING (display
);
5313 if (! NILP (xrm_string
))
5314 CHECK_STRING (xrm_string
);
5316 if (! EQ (Vwindow_system
, intern ("x")))
5317 error ("Not using X Windows");
5319 if (! NILP (xrm_string
))
5320 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5322 xrm_option
= (unsigned char *) 0;
5324 validate_x_resource_name ();
5326 /* This is what opens the connection and sets x_current_display.
5327 This also initializes many symbols, such as those used for input. */
5328 dpyinfo
= x_term_init (display
, xrm_option
,
5329 (char *) XSTRING (Vx_resource_name
)->data
);
5333 if (!NILP (must_succeed
))
5334 fatal ("Cannot connect to X server %s.\n\
5335 Check the DISPLAY environment variable or use `-d'.\n\
5336 Also use the `xhost' program to verify that it is set to permit\n\
5337 connections from your machine.\n",
5338 XSTRING (display
)->data
);
5340 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5345 XSETFASTINT (Vwindow_system_version
, 11);
5349 DEFUN ("x-close-connection", Fx_close_connection
,
5350 Sx_close_connection
, 1, 1, 0,
5351 doc
: /* Close the connection to DISPLAY's X server.
5352 For DISPLAY, specify either a frame or a display name (a string).
5353 If DISPLAY is nil, that stands for the selected frame's display. */)
5355 Lisp_Object display
;
5357 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5360 if (dpyinfo
->reference_count
> 0)
5361 error ("Display still has frames on it");
5364 /* Free the fonts in the font table. */
5365 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5366 if (dpyinfo
->font_table
[i
].name
)
5368 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5369 xfree (dpyinfo
->font_table
[i
].full_name
);
5370 xfree (dpyinfo
->font_table
[i
].name
);
5371 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5374 x_destroy_all_bitmaps (dpyinfo
);
5375 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5377 #ifdef USE_X_TOOLKIT
5378 XtCloseDisplay (dpyinfo
->display
);
5380 XCloseDisplay (dpyinfo
->display
);
5383 x_delete_display (dpyinfo
);
5389 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5390 doc
: /* Return the list of display names that Emacs has connections to. */)
5393 Lisp_Object tail
, result
;
5396 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5397 result
= Fcons (XCAR (XCAR (tail
)), result
);
5402 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5403 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5404 If ON is nil, allow buffering of requests.
5405 Turning on synchronization prohibits the Xlib routines from buffering
5406 requests and seriously degrades performance, but makes debugging much
5408 The optional second argument DISPLAY specifies which display to act on.
5409 DISPLAY should be either a frame or a display name (a string).
5410 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5412 Lisp_Object display
, on
;
5414 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5416 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5421 /* Wait for responses to all X commands issued so far for frame F. */
5428 XSync (FRAME_X_DISPLAY (f
), False
);
5433 /***********************************************************************
5435 ***********************************************************************/
5437 /* Value is the number of elements of vector VECTOR. */
5439 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5441 /* List of supported image types. Use define_image_type to add new
5442 types. Use lookup_image_type to find a type for a given symbol. */
5444 static struct image_type
*image_types
;
5446 /* The symbol `image' which is the car of the lists used to represent
5449 extern Lisp_Object Qimage
;
5451 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5457 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5458 extern Lisp_Object QCdata
, QCtype
;
5459 Lisp_Object QCascent
, QCmargin
, QCrelief
;
5460 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5461 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5463 /* Other symbols. */
5465 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5467 /* Time in seconds after which images should be removed from the cache
5468 if not displayed. */
5470 Lisp_Object Vimage_cache_eviction_delay
;
5472 /* Function prototypes. */
5474 static void define_image_type
P_ ((struct image_type
*type
));
5475 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5476 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5477 static void x_laplace
P_ ((struct frame
*, struct image
*));
5478 static void x_emboss
P_ ((struct frame
*, struct image
*));
5479 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5483 /* Define a new image type from TYPE. This adds a copy of TYPE to
5484 image_types and adds the symbol *TYPE->type to Vimage_types. */
5487 define_image_type (type
)
5488 struct image_type
*type
;
5490 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5491 The initialized data segment is read-only. */
5492 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5493 bcopy (type
, p
, sizeof *p
);
5494 p
->next
= image_types
;
5496 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5500 /* Look up image type SYMBOL, and return a pointer to its image_type
5501 structure. Value is null if SYMBOL is not a known image type. */
5503 static INLINE
struct image_type
*
5504 lookup_image_type (symbol
)
5507 struct image_type
*type
;
5509 for (type
= image_types
; type
; type
= type
->next
)
5510 if (EQ (symbol
, *type
->type
))
5517 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5518 valid image specification is a list whose car is the symbol
5519 `image', and whose rest is a property list. The property list must
5520 contain a value for key `:type'. That value must be the name of a
5521 supported image type. The rest of the property list depends on the
5525 valid_image_p (object
)
5530 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5534 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5535 if (EQ (XCAR (tem
), QCtype
))
5538 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5540 struct image_type
*type
;
5541 type
= lookup_image_type (XCAR (tem
));
5543 valid_p
= type
->valid_p (object
);
5554 /* Log error message with format string FORMAT and argument ARG.
5555 Signaling an error, e.g. when an image cannot be loaded, is not a
5556 good idea because this would interrupt redisplay, and the error
5557 message display would lead to another redisplay. This function
5558 therefore simply displays a message. */
5561 image_error (format
, arg1
, arg2
)
5563 Lisp_Object arg1
, arg2
;
5565 add_to_log (format
, arg1
, arg2
);
5570 /***********************************************************************
5571 Image specifications
5572 ***********************************************************************/
5574 enum image_value_type
5576 IMAGE_DONT_CHECK_VALUE_TYPE
,
5578 IMAGE_STRING_OR_NIL_VALUE
,
5580 IMAGE_POSITIVE_INTEGER_VALUE
,
5581 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5582 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5584 IMAGE_INTEGER_VALUE
,
5585 IMAGE_FUNCTION_VALUE
,
5590 /* Structure used when parsing image specifications. */
5592 struct image_keyword
5594 /* Name of keyword. */
5597 /* The type of value allowed. */
5598 enum image_value_type type
;
5600 /* Non-zero means key must be present. */
5603 /* Used to recognize duplicate keywords in a property list. */
5606 /* The value that was found. */
5611 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5613 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5616 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5617 has the format (image KEYWORD VALUE ...). One of the keyword/
5618 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5619 image_keywords structures of size NKEYWORDS describing other
5620 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5623 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5625 struct image_keyword
*keywords
;
5632 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5635 plist
= XCDR (spec
);
5636 while (CONSP (plist
))
5638 Lisp_Object key
, value
;
5640 /* First element of a pair must be a symbol. */
5642 plist
= XCDR (plist
);
5646 /* There must follow a value. */
5649 value
= XCAR (plist
);
5650 plist
= XCDR (plist
);
5652 /* Find key in KEYWORDS. Error if not found. */
5653 for (i
= 0; i
< nkeywords
; ++i
)
5654 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5660 /* Record that we recognized the keyword. If a keywords
5661 was found more than once, it's an error. */
5662 keywords
[i
].value
= value
;
5663 ++keywords
[i
].count
;
5665 if (keywords
[i
].count
> 1)
5668 /* Check type of value against allowed type. */
5669 switch (keywords
[i
].type
)
5671 case IMAGE_STRING_VALUE
:
5672 if (!STRINGP (value
))
5676 case IMAGE_STRING_OR_NIL_VALUE
:
5677 if (!STRINGP (value
) && !NILP (value
))
5681 case IMAGE_SYMBOL_VALUE
:
5682 if (!SYMBOLP (value
))
5686 case IMAGE_POSITIVE_INTEGER_VALUE
:
5687 if (!INTEGERP (value
) || XINT (value
) <= 0)
5691 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5692 if (INTEGERP (value
) && XINT (value
) >= 0)
5695 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5696 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5700 case IMAGE_ASCENT_VALUE
:
5701 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5703 else if (INTEGERP (value
)
5704 && XINT (value
) >= 0
5705 && XINT (value
) <= 100)
5709 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5710 if (!INTEGERP (value
) || XINT (value
) < 0)
5714 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5717 case IMAGE_FUNCTION_VALUE
:
5718 value
= indirect_function (value
);
5720 || COMPILEDP (value
)
5721 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5725 case IMAGE_NUMBER_VALUE
:
5726 if (!INTEGERP (value
) && !FLOATP (value
))
5730 case IMAGE_INTEGER_VALUE
:
5731 if (!INTEGERP (value
))
5735 case IMAGE_BOOL_VALUE
:
5736 if (!NILP (value
) && !EQ (value
, Qt
))
5745 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5749 /* Check that all mandatory fields are present. */
5750 for (i
= 0; i
< nkeywords
; ++i
)
5751 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5754 return NILP (plist
);
5758 /* Return the value of KEY in image specification SPEC. Value is nil
5759 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5760 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5763 image_spec_value (spec
, key
, found
)
5764 Lisp_Object spec
, key
;
5769 xassert (valid_image_p (spec
));
5771 for (tail
= XCDR (spec
);
5772 CONSP (tail
) && CONSP (XCDR (tail
));
5773 tail
= XCDR (XCDR (tail
)))
5775 if (EQ (XCAR (tail
), key
))
5779 return XCAR (XCDR (tail
));
5789 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5790 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5791 PIXELS non-nil means return the size in pixels, otherwise return the
5792 size in canonical character units.
5793 FRAME is the frame on which the image will be displayed. FRAME nil
5794 or omitted means use the selected frame. */)
5795 (spec
, pixels
, frame
)
5796 Lisp_Object spec
, pixels
, frame
;
5801 if (valid_image_p (spec
))
5803 struct frame
*f
= check_x_frame (frame
);
5804 int id
= lookup_image (f
, spec
);
5805 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5806 int width
= img
->width
+ 2 * img
->hmargin
;
5807 int height
= img
->height
+ 2 * img
->vmargin
;
5810 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5811 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5813 size
= Fcons (make_number (width
), make_number (height
));
5816 error ("Invalid image specification");
5822 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5823 doc
: /* Return t if image SPEC has a mask bitmap.
5824 FRAME is the frame on which the image will be displayed. FRAME nil
5825 or omitted means use the selected frame. */)
5827 Lisp_Object spec
, frame
;
5832 if (valid_image_p (spec
))
5834 struct frame
*f
= check_x_frame (frame
);
5835 int id
= lookup_image (f
, spec
);
5836 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5841 error ("Invalid image specification");
5848 /***********************************************************************
5849 Image type independent image structures
5850 ***********************************************************************/
5852 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5853 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5856 /* Allocate and return a new image structure for image specification
5857 SPEC. SPEC has a hash value of HASH. */
5859 static struct image
*
5860 make_image (spec
, hash
)
5864 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5866 xassert (valid_image_p (spec
));
5867 bzero (img
, sizeof *img
);
5868 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5869 xassert (img
->type
!= NULL
);
5871 img
->data
.lisp_val
= Qnil
;
5872 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5878 /* Free image IMG which was used on frame F, including its resources. */
5887 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5889 /* Remove IMG from the hash table of its cache. */
5891 img
->prev
->next
= img
->next
;
5893 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5896 img
->next
->prev
= img
->prev
;
5898 c
->images
[img
->id
] = NULL
;
5900 /* Free resources, then free IMG. */
5901 img
->type
->free (f
, img
);
5907 /* Prepare image IMG for display on frame F. Must be called before
5908 drawing an image. */
5911 prepare_image_for_display (f
, img
)
5917 /* We're about to display IMG, so set its timestamp to `now'. */
5919 img
->timestamp
= EMACS_SECS (t
);
5921 /* If IMG doesn't have a pixmap yet, load it now, using the image
5922 type dependent loader function. */
5923 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5924 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5928 /* Value is the number of pixels for the ascent of image IMG when
5929 drawn in face FACE. */
5932 image_ascent (img
, face
)
5936 int height
= img
->height
+ img
->vmargin
;
5939 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5942 /* This expression is arranged so that if the image can't be
5943 exactly centered, it will be moved slightly up. This is
5944 because a typical font is `top-heavy' (due to the presence
5945 uppercase letters), so the image placement should err towards
5946 being top-heavy too. It also just generally looks better. */
5947 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5949 ascent
= height
/ 2;
5952 ascent
= height
* img
->ascent
/ 100.0;
5958 /* Image background colors. */
5960 static unsigned long
5961 four_corners_best (ximg
, width
, height
)
5963 unsigned long width
, height
;
5965 unsigned long corners
[4], best
;
5968 /* Get the colors at the corners of ximg. */
5969 corners
[0] = XGetPixel (ximg
, 0, 0);
5970 corners
[1] = XGetPixel (ximg
, width
- 1, 0);
5971 corners
[2] = XGetPixel (ximg
, width
- 1, height
- 1);
5972 corners
[3] = XGetPixel (ximg
, 0, height
- 1);
5974 /* Choose the most frequently found color as background. */
5975 for (i
= best_count
= 0; i
< 4; ++i
)
5979 for (j
= n
= 0; j
< 4; ++j
)
5980 if (corners
[i
] == corners
[j
])
5984 best
= corners
[i
], best_count
= n
;
5990 /* Return the `background' field of IMG. If IMG doesn't have one yet,
5991 it is guessed heuristically. If non-zero, XIMG is an existing XImage
5992 object to use for the heuristic. */
5995 image_background (img
, f
, ximg
)
6000 if (! img
->background_valid
)
6001 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6003 int free_ximg
= !ximg
;
6006 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
6007 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6009 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
6012 XDestroyImage (ximg
);
6014 img
->background_valid
= 1;
6017 return img
->background
;
6020 /* Return the `background_transparent' field of IMG. If IMG doesn't
6021 have one yet, it is guessed heuristically. If non-zero, MASK is an
6022 existing XImage object to use for the heuristic. */
6025 image_background_transparent (img
, f
, mask
)
6030 if (! img
->background_transparent_valid
)
6031 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6035 int free_mask
= !mask
;
6038 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
6039 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6041 img
->background_transparent
6042 = !four_corners_best (mask
, img
->width
, img
->height
);
6045 XDestroyImage (mask
);
6048 img
->background_transparent
= 0;
6050 img
->background_transparent_valid
= 1;
6053 return img
->background_transparent
;
6057 /***********************************************************************
6058 Helper functions for X image types
6059 ***********************************************************************/
6061 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
6063 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
6064 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
6066 Lisp_Object color_name
,
6067 unsigned long dflt
));
6070 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6071 free the pixmap if any. MASK_P non-zero means clear the mask
6072 pixmap if any. COLORS_P non-zero means free colors allocated for
6073 the image, if any. */
6076 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
6079 int pixmap_p
, mask_p
, colors_p
;
6081 if (pixmap_p
&& img
->pixmap
)
6083 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6085 img
->background_valid
= 0;
6088 if (mask_p
&& img
->mask
)
6090 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6092 img
->background_transparent_valid
= 0;
6095 if (colors_p
&& img
->ncolors
)
6097 x_free_colors (f
, img
->colors
, img
->ncolors
);
6098 xfree (img
->colors
);
6104 /* Free X resources of image IMG which is used on frame F. */
6107 x_clear_image (f
, img
)
6112 x_clear_image_1 (f
, img
, 1, 1, 1);
6117 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6118 cannot be allocated, use DFLT. Add a newly allocated color to
6119 IMG->colors, so that it can be freed again. Value is the pixel
6122 static unsigned long
6123 x_alloc_image_color (f
, img
, color_name
, dflt
)
6126 Lisp_Object color_name
;
6130 unsigned long result
;
6132 xassert (STRINGP (color_name
));
6134 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
6136 /* This isn't called frequently so we get away with simply
6137 reallocating the color vector to the needed size, here. */
6140 (unsigned long *) xrealloc (img
->colors
,
6141 img
->ncolors
* sizeof *img
->colors
);
6142 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
6143 result
= color
.pixel
;
6153 /***********************************************************************
6155 ***********************************************************************/
6157 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
6158 static void postprocess_image
P_ ((struct frame
*, struct image
*));
6161 /* Return a new, initialized image cache that is allocated from the
6162 heap. Call free_image_cache to free an image cache. */
6164 struct image_cache
*
6167 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
6170 bzero (c
, sizeof *c
);
6172 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
6173 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
6174 c
->buckets
= (struct image
**) xmalloc (size
);
6175 bzero (c
->buckets
, size
);
6180 /* Free image cache of frame F. Be aware that X frames share images
6184 free_image_cache (f
)
6187 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6192 /* Cache should not be referenced by any frame when freed. */
6193 xassert (c
->refcount
== 0);
6195 for (i
= 0; i
< c
->used
; ++i
)
6196 free_image (f
, c
->images
[i
]);
6200 FRAME_X_IMAGE_CACHE (f
) = NULL
;
6205 /* Clear image cache of frame F. FORCE_P non-zero means free all
6206 images. FORCE_P zero means clear only images that haven't been
6207 displayed for some time. Should be called from time to time to
6208 reduce the number of loaded images. If image-eviction-seconds is
6209 non-nil, this frees images in the cache which weren't displayed for
6210 at least that many seconds. */
6213 clear_image_cache (f
, force_p
)
6217 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6219 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
6226 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
6228 /* Block input so that we won't be interrupted by a SIGIO
6229 while being in an inconsistent state. */
6232 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
6234 struct image
*img
= c
->images
[i
];
6236 && (force_p
|| img
->timestamp
< old
))
6238 free_image (f
, img
);
6243 /* We may be clearing the image cache because, for example,
6244 Emacs was iconified for a longer period of time. In that
6245 case, current matrices may still contain references to
6246 images freed above. So, clear these matrices. */
6249 Lisp_Object tail
, frame
;
6251 FOR_EACH_FRAME (tail
, frame
)
6253 struct frame
*f
= XFRAME (frame
);
6255 && FRAME_X_IMAGE_CACHE (f
) == c
)
6256 clear_current_matrices (f
);
6259 ++windows_or_buffers_changed
;
6267 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
6269 doc
: /* Clear the image cache of FRAME.
6270 FRAME nil or omitted means use the selected frame.
6271 FRAME t means clear the image caches of all frames. */)
6279 FOR_EACH_FRAME (tail
, frame
)
6280 if (FRAME_X_P (XFRAME (frame
)))
6281 clear_image_cache (XFRAME (frame
), 1);
6284 clear_image_cache (check_x_frame (frame
), 1);
6290 /* Compute masks and transform image IMG on frame F, as specified
6291 by the image's specification, */
6294 postprocess_image (f
, img
)
6298 /* Manipulation of the image's mask. */
6301 Lisp_Object conversion
, spec
;
6306 /* `:heuristic-mask t'
6308 means build a mask heuristically.
6309 `:heuristic-mask (R G B)'
6310 `:mask (heuristic (R G B))'
6311 means build a mask from color (R G B) in the
6314 means remove a mask, if any. */
6316 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6318 x_build_heuristic_mask (f
, img
, mask
);
6323 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6325 if (EQ (mask
, Qheuristic
))
6326 x_build_heuristic_mask (f
, img
, Qt
);
6327 else if (CONSP (mask
)
6328 && EQ (XCAR (mask
), Qheuristic
))
6330 if (CONSP (XCDR (mask
)))
6331 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6333 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6335 else if (NILP (mask
) && found_p
&& img
->mask
)
6337 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6343 /* Should we apply an image transformation algorithm? */
6344 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6345 if (EQ (conversion
, Qdisabled
))
6346 x_disable_image (f
, img
);
6347 else if (EQ (conversion
, Qlaplace
))
6349 else if (EQ (conversion
, Qemboss
))
6351 else if (CONSP (conversion
)
6352 && EQ (XCAR (conversion
), Qedge_detection
))
6355 tem
= XCDR (conversion
);
6357 x_edge_detection (f
, img
,
6358 Fplist_get (tem
, QCmatrix
),
6359 Fplist_get (tem
, QCcolor_adjustment
));
6365 /* Return the id of image with Lisp specification SPEC on frame F.
6366 SPEC must be a valid Lisp image specification (see valid_image_p). */
6369 lookup_image (f
, spec
)
6373 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6377 struct gcpro gcpro1
;
6380 /* F must be a window-system frame, and SPEC must be a valid image
6382 xassert (FRAME_WINDOW_P (f
));
6383 xassert (valid_image_p (spec
));
6387 /* Look up SPEC in the hash table of the image cache. */
6388 hash
= sxhash (spec
, 0);
6389 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6391 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6392 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6395 /* If not found, create a new image and cache it. */
6398 extern Lisp_Object Qpostscript
;
6401 img
= make_image (spec
, hash
);
6402 cache_image (f
, img
);
6403 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6405 /* If we can't load the image, and we don't have a width and
6406 height, use some arbitrary width and height so that we can
6407 draw a rectangle for it. */
6408 if (img
->load_failed_p
)
6412 value
= image_spec_value (spec
, QCwidth
, NULL
);
6413 img
->width
= (INTEGERP (value
)
6414 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6415 value
= image_spec_value (spec
, QCheight
, NULL
);
6416 img
->height
= (INTEGERP (value
)
6417 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6421 /* Handle image type independent image attributes
6422 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6423 `:background COLOR'. */
6424 Lisp_Object ascent
, margin
, relief
, bg
;
6426 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6427 if (INTEGERP (ascent
))
6428 img
->ascent
= XFASTINT (ascent
);
6429 else if (EQ (ascent
, Qcenter
))
6430 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6432 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6433 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6434 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6435 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6436 && INTEGERP (XCDR (margin
)))
6438 if (XINT (XCAR (margin
)) > 0)
6439 img
->hmargin
= XFASTINT (XCAR (margin
));
6440 if (XINT (XCDR (margin
)) > 0)
6441 img
->vmargin
= XFASTINT (XCDR (margin
));
6444 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6445 if (INTEGERP (relief
))
6447 img
->relief
= XINT (relief
);
6448 img
->hmargin
+= abs (img
->relief
);
6449 img
->vmargin
+= abs (img
->relief
);
6452 if (! img
->background_valid
)
6454 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6458 = x_alloc_image_color (f
, img
, bg
,
6459 FRAME_BACKGROUND_PIXEL (f
));
6460 img
->background_valid
= 1;
6464 /* Do image transformations and compute masks, unless we
6465 don't have the image yet. */
6466 if (!EQ (*img
->type
->type
, Qpostscript
))
6467 postprocess_image (f
, img
);
6471 xassert (!interrupt_input_blocked
);
6474 /* We're using IMG, so set its timestamp to `now'. */
6475 EMACS_GET_TIME (now
);
6476 img
->timestamp
= EMACS_SECS (now
);
6480 /* Value is the image id. */
6485 /* Cache image IMG in the image cache of frame F. */
6488 cache_image (f
, img
)
6492 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6495 /* Find a free slot in c->images. */
6496 for (i
= 0; i
< c
->used
; ++i
)
6497 if (c
->images
[i
] == NULL
)
6500 /* If no free slot found, maybe enlarge c->images. */
6501 if (i
== c
->used
&& c
->used
== c
->size
)
6504 c
->images
= (struct image
**) xrealloc (c
->images
,
6505 c
->size
* sizeof *c
->images
);
6508 /* Add IMG to c->images, and assign IMG an id. */
6514 /* Add IMG to the cache's hash table. */
6515 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6516 img
->next
= c
->buckets
[i
];
6518 img
->next
->prev
= img
;
6520 c
->buckets
[i
] = img
;
6524 /* Call FN on every image in the image cache of frame F. Used to mark
6525 Lisp Objects in the image cache. */
6528 forall_images_in_image_cache (f
, fn
)
6530 void (*fn
) P_ ((struct image
*img
));
6532 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6534 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6538 for (i
= 0; i
< c
->used
; ++i
)
6547 /***********************************************************************
6549 ***********************************************************************/
6551 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6552 XImage
**, Pixmap
*));
6553 static void x_destroy_x_image
P_ ((XImage
*));
6554 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6557 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6558 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6559 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6560 via xmalloc. Print error messages via image_error if an error
6561 occurs. Value is non-zero if successful. */
6564 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6566 int width
, height
, depth
;
6570 Display
*display
= FRAME_X_DISPLAY (f
);
6571 Screen
*screen
= FRAME_X_SCREEN (f
);
6572 Window window
= FRAME_X_WINDOW (f
);
6574 xassert (interrupt_input_blocked
);
6577 depth
= DefaultDepthOfScreen (screen
);
6578 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6579 depth
, ZPixmap
, 0, NULL
, width
, height
,
6580 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6583 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6587 /* Allocate image raster. */
6588 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6590 /* Allocate a pixmap of the same size. */
6591 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6592 if (*pixmap
== None
)
6594 x_destroy_x_image (*ximg
);
6596 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6604 /* Destroy XImage XIMG. Free XIMG->data. */
6607 x_destroy_x_image (ximg
)
6610 xassert (interrupt_input_blocked
);
6615 XDestroyImage (ximg
);
6620 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6621 are width and height of both the image and pixmap. */
6624 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6631 xassert (interrupt_input_blocked
);
6632 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6633 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6634 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6639 /***********************************************************************
6641 ***********************************************************************/
6643 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6644 static char *slurp_file
P_ ((char *, int *));
6647 /* Find image file FILE. Look in data-directory, then
6648 x-bitmap-file-path. Value is the full name of the file found, or
6649 nil if not found. */
6652 x_find_image_file (file
)
6655 Lisp_Object file_found
, search_path
;
6656 struct gcpro gcpro1
, gcpro2
;
6660 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6661 GCPRO2 (file_found
, search_path
);
6663 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6664 fd
= openp (search_path
, file
, Qnil
, &file_found
, 0);
6676 /* Read FILE into memory. Value is a pointer to a buffer allocated
6677 with xmalloc holding FILE's contents. Value is null if an error
6678 occurred. *SIZE is set to the size of the file. */
6681 slurp_file (file
, size
)
6689 if (stat (file
, &st
) == 0
6690 && (fp
= fopen (file
, "r")) != NULL
6691 && (buf
= (char *) xmalloc (st
.st_size
),
6692 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6713 /***********************************************************************
6715 ***********************************************************************/
6717 static int xbm_scan
P_ ((char **, char *, char *, int *));
6718 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6719 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6721 static int xbm_image_p
P_ ((Lisp_Object object
));
6722 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6724 static int xbm_file_p
P_ ((Lisp_Object
));
6727 /* Indices of image specification fields in xbm_format, below. */
6729 enum xbm_keyword_index
6747 /* Vector of image_keyword structures describing the format
6748 of valid XBM image specifications. */
6750 static struct image_keyword xbm_format
[XBM_LAST
] =
6752 {":type", IMAGE_SYMBOL_VALUE
, 1},
6753 {":file", IMAGE_STRING_VALUE
, 0},
6754 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6755 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6756 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6757 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6758 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6759 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6760 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6761 {":relief", IMAGE_INTEGER_VALUE
, 0},
6762 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6763 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6764 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6767 /* Structure describing the image type XBM. */
6769 static struct image_type xbm_type
=
6778 /* Tokens returned from xbm_scan. */
6787 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6788 A valid specification is a list starting with the symbol `image'
6789 The rest of the list is a property list which must contain an
6792 If the specification specifies a file to load, it must contain
6793 an entry `:file FILENAME' where FILENAME is a string.
6795 If the specification is for a bitmap loaded from memory it must
6796 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6797 WIDTH and HEIGHT are integers > 0. DATA may be:
6799 1. a string large enough to hold the bitmap data, i.e. it must
6800 have a size >= (WIDTH + 7) / 8 * HEIGHT
6802 2. a bool-vector of size >= WIDTH * HEIGHT
6804 3. a vector of strings or bool-vectors, one for each line of the
6807 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6808 may not be specified in this case because they are defined in the
6811 Both the file and data forms may contain the additional entries
6812 `:background COLOR' and `:foreground COLOR'. If not present,
6813 foreground and background of the frame on which the image is
6814 displayed is used. */
6817 xbm_image_p (object
)
6820 struct image_keyword kw
[XBM_LAST
];
6822 bcopy (xbm_format
, kw
, sizeof kw
);
6823 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6826 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6828 if (kw
[XBM_FILE
].count
)
6830 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6833 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6835 /* In-memory XBM file. */
6836 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6844 /* Entries for `:width', `:height' and `:data' must be present. */
6845 if (!kw
[XBM_WIDTH
].count
6846 || !kw
[XBM_HEIGHT
].count
6847 || !kw
[XBM_DATA
].count
)
6850 data
= kw
[XBM_DATA
].value
;
6851 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6852 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6854 /* Check type of data, and width and height against contents of
6860 /* Number of elements of the vector must be >= height. */
6861 if (XVECTOR (data
)->size
< height
)
6864 /* Each string or bool-vector in data must be large enough
6865 for one line of the image. */
6866 for (i
= 0; i
< height
; ++i
)
6868 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6872 if (XSTRING (elt
)->size
6873 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6876 else if (BOOL_VECTOR_P (elt
))
6878 if (XBOOL_VECTOR (elt
)->size
< width
)
6885 else if (STRINGP (data
))
6887 if (XSTRING (data
)->size
6888 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6891 else if (BOOL_VECTOR_P (data
))
6893 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6904 /* Scan a bitmap file. FP is the stream to read from. Value is
6905 either an enumerator from enum xbm_token, or a character for a
6906 single-character token, or 0 at end of file. If scanning an
6907 identifier, store the lexeme of the identifier in SVAL. If
6908 scanning a number, store its value in *IVAL. */
6911 xbm_scan (s
, end
, sval
, ival
)
6920 /* Skip white space. */
6921 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6926 else if (isdigit (c
))
6928 int value
= 0, digit
;
6930 if (c
== '0' && *s
< end
)
6933 if (c
== 'x' || c
== 'X')
6940 else if (c
>= 'a' && c
<= 'f')
6941 digit
= c
- 'a' + 10;
6942 else if (c
>= 'A' && c
<= 'F')
6943 digit
= c
- 'A' + 10;
6946 value
= 16 * value
+ digit
;
6949 else if (isdigit (c
))
6953 && (c
= *(*s
)++, isdigit (c
)))
6954 value
= 8 * value
+ c
- '0';
6961 && (c
= *(*s
)++, isdigit (c
)))
6962 value
= 10 * value
+ c
- '0';
6970 else if (isalpha (c
) || c
== '_')
6974 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6981 else if (c
== '/' && **s
== '*')
6983 /* C-style comment. */
6985 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6998 /* Replacement for XReadBitmapFileData which isn't available under old
6999 X versions. CONTENTS is a pointer to a buffer to parse; END is the
7000 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
7001 the image. Return in *DATA the bitmap data allocated with xmalloc.
7002 Value is non-zero if successful. DATA null means just test if
7003 CONTENTS looks like an in-memory XBM file. */
7006 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
7007 char *contents
, *end
;
7008 int *width
, *height
;
7009 unsigned char **data
;
7012 char buffer
[BUFSIZ
];
7015 int bytes_per_line
, i
, nbytes
;
7021 LA1 = xbm_scan (&s, end, buffer, &value)
7023 #define expect(TOKEN) \
7024 if (LA1 != (TOKEN)) \
7029 #define expect_ident(IDENT) \
7030 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
7035 *width
= *height
= -1;
7038 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
7040 /* Parse defines for width, height and hot-spots. */
7044 expect_ident ("define");
7045 expect (XBM_TK_IDENT
);
7047 if (LA1
== XBM_TK_NUMBER
);
7049 char *p
= strrchr (buffer
, '_');
7050 p
= p
? p
+ 1 : buffer
;
7051 if (strcmp (p
, "width") == 0)
7053 else if (strcmp (p
, "height") == 0)
7056 expect (XBM_TK_NUMBER
);
7059 if (*width
< 0 || *height
< 0)
7061 else if (data
== NULL
)
7064 /* Parse bits. Must start with `static'. */
7065 expect_ident ("static");
7066 if (LA1
== XBM_TK_IDENT
)
7068 if (strcmp (buffer
, "unsigned") == 0)
7071 expect_ident ("char");
7073 else if (strcmp (buffer
, "short") == 0)
7077 if (*width
% 16 && *width
% 16 < 9)
7080 else if (strcmp (buffer
, "char") == 0)
7088 expect (XBM_TK_IDENT
);
7094 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
7095 nbytes
= bytes_per_line
* *height
;
7096 p
= *data
= (char *) xmalloc (nbytes
);
7100 for (i
= 0; i
< nbytes
; i
+= 2)
7103 expect (XBM_TK_NUMBER
);
7106 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
7109 if (LA1
== ',' || LA1
== '}')
7117 for (i
= 0; i
< nbytes
; ++i
)
7120 expect (XBM_TK_NUMBER
);
7124 if (LA1
== ',' || LA1
== '}')
7149 /* Load XBM image IMG which will be displayed on frame F from buffer
7150 CONTENTS. END is the end of the buffer. Value is non-zero if
7154 xbm_load_image (f
, img
, contents
, end
)
7157 char *contents
, *end
;
7160 unsigned char *data
;
7163 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
7166 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7167 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7168 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7171 xassert (img
->width
> 0 && img
->height
> 0);
7173 /* Get foreground and background colors, maybe allocate colors. */
7174 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
7176 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
7177 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7180 background
= x_alloc_image_color (f
, img
, value
, background
);
7181 img
->background
= background
;
7182 img
->background_valid
= 1;
7186 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7189 img
->width
, img
->height
,
7190 foreground
, background
,
7194 if (img
->pixmap
== None
)
7196 x_clear_image (f
, img
);
7197 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
7203 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7209 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7216 return (STRINGP (data
)
7217 && xbm_read_bitmap_data (XSTRING (data
)->data
,
7218 (XSTRING (data
)->data
7219 + STRING_BYTES (XSTRING (data
))),
7224 /* Fill image IMG which is used on frame F with pixmap data. Value is
7225 non-zero if successful. */
7233 Lisp_Object file_name
;
7235 xassert (xbm_image_p (img
->spec
));
7237 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7238 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7239 if (STRINGP (file_name
))
7244 struct gcpro gcpro1
;
7246 file
= x_find_image_file (file_name
);
7248 if (!STRINGP (file
))
7250 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7255 contents
= slurp_file (XSTRING (file
)->data
, &size
);
7256 if (contents
== NULL
)
7258 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7263 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
7268 struct image_keyword fmt
[XBM_LAST
];
7271 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7272 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7275 int in_memory_file_p
= 0;
7277 /* See if data looks like an in-memory XBM file. */
7278 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7279 in_memory_file_p
= xbm_file_p (data
);
7281 /* Parse the image specification. */
7282 bcopy (xbm_format
, fmt
, sizeof fmt
);
7283 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
7286 /* Get specified width, and height. */
7287 if (!in_memory_file_p
)
7289 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
7290 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
7291 xassert (img
->width
> 0 && img
->height
> 0);
7294 /* Get foreground and background colors, maybe allocate colors. */
7295 if (fmt
[XBM_FOREGROUND
].count
7296 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
7297 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
7299 if (fmt
[XBM_BACKGROUND
].count
7300 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
7301 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7304 if (in_memory_file_p
)
7305 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
7306 (XSTRING (data
)->data
7307 + STRING_BYTES (XSTRING (data
))));
7314 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7316 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7317 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7319 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7321 bcopy (XSTRING (line
)->data
, p
, nbytes
);
7323 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7326 else if (STRINGP (data
))
7327 bits
= XSTRING (data
)->data
;
7329 bits
= XBOOL_VECTOR (data
)->data
;
7331 /* Create the pixmap. */
7332 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7334 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7337 img
->width
, img
->height
,
7338 foreground
, background
,
7344 image_error ("Unable to create pixmap for XBM image `%s'",
7346 x_clear_image (f
, img
);
7356 /***********************************************************************
7358 ***********************************************************************/
7362 static int xpm_image_p
P_ ((Lisp_Object object
));
7363 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7364 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7366 #include "X11/xpm.h"
7368 /* The symbol `xpm' identifying XPM-format images. */
7372 /* Indices of image specification fields in xpm_format, below. */
7374 enum xpm_keyword_index
7390 /* Vector of image_keyword structures describing the format
7391 of valid XPM image specifications. */
7393 static struct image_keyword xpm_format
[XPM_LAST
] =
7395 {":type", IMAGE_SYMBOL_VALUE
, 1},
7396 {":file", IMAGE_STRING_VALUE
, 0},
7397 {":data", IMAGE_STRING_VALUE
, 0},
7398 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7399 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7400 {":relief", IMAGE_INTEGER_VALUE
, 0},
7401 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7402 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7403 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7404 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7405 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7408 /* Structure describing the image type XBM. */
7410 static struct image_type xpm_type
=
7420 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7421 functions for allocating image colors. Our own functions handle
7422 color allocation failures more gracefully than the ones on the XPM
7425 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7426 #define ALLOC_XPM_COLORS
7429 #ifdef ALLOC_XPM_COLORS
7431 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7432 static void xpm_free_color_cache
P_ ((void));
7433 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7434 static int xpm_color_bucket
P_ ((char *));
7435 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7438 /* An entry in a hash table used to cache color definitions of named
7439 colors. This cache is necessary to speed up XPM image loading in
7440 case we do color allocations ourselves. Without it, we would need
7441 a call to XParseColor per pixel in the image. */
7443 struct xpm_cached_color
7445 /* Next in collision chain. */
7446 struct xpm_cached_color
*next
;
7448 /* Color definition (RGB and pixel color). */
7455 /* The hash table used for the color cache, and its bucket vector
7458 #define XPM_COLOR_CACHE_BUCKETS 1001
7459 struct xpm_cached_color
**xpm_color_cache
;
7461 /* Initialize the color cache. */
7464 xpm_init_color_cache (f
, attrs
)
7466 XpmAttributes
*attrs
;
7468 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7469 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7470 memset (xpm_color_cache
, 0, nbytes
);
7471 init_color_table ();
7473 if (attrs
->valuemask
& XpmColorSymbols
)
7478 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7479 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7480 attrs
->colorsymbols
[i
].value
, &color
))
7482 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7484 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7490 /* Free the color cache. */
7493 xpm_free_color_cache ()
7495 struct xpm_cached_color
*p
, *next
;
7498 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7499 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7505 xfree (xpm_color_cache
);
7506 xpm_color_cache
= NULL
;
7507 free_color_table ();
7511 /* Return the bucket index for color named COLOR_NAME in the color
7515 xpm_color_bucket (color_name
)
7521 for (s
= color_name
; *s
; ++s
)
7523 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7527 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7528 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7531 static struct xpm_cached_color
*
7532 xpm_cache_color (f
, color_name
, color
, bucket
)
7539 struct xpm_cached_color
*p
;
7542 bucket
= xpm_color_bucket (color_name
);
7544 nbytes
= sizeof *p
+ strlen (color_name
);
7545 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7546 strcpy (p
->name
, color_name
);
7548 p
->next
= xpm_color_cache
[bucket
];
7549 xpm_color_cache
[bucket
] = p
;
7554 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7555 return the cached definition in *COLOR. Otherwise, make a new
7556 entry in the cache and allocate the color. Value is zero if color
7557 allocation failed. */
7560 xpm_lookup_color (f
, color_name
, color
)
7565 struct xpm_cached_color
*p
;
7566 int h
= xpm_color_bucket (color_name
);
7568 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7569 if (strcmp (p
->name
, color_name
) == 0)
7574 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7577 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7579 p
= xpm_cache_color (f
, color_name
, color
, h
);
7586 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7587 CLOSURE is a pointer to the frame on which we allocate the
7588 color. Return in *COLOR the allocated color. Value is non-zero
7592 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7599 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7603 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7604 is a pointer to the frame on which we allocate the color. Value is
7605 non-zero if successful. */
7608 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7618 #endif /* ALLOC_XPM_COLORS */
7621 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7622 for XPM images. Such a list must consist of conses whose car and
7626 xpm_valid_color_symbols_p (color_symbols
)
7627 Lisp_Object color_symbols
;
7629 while (CONSP (color_symbols
))
7631 Lisp_Object sym
= XCAR (color_symbols
);
7633 || !STRINGP (XCAR (sym
))
7634 || !STRINGP (XCDR (sym
)))
7636 color_symbols
= XCDR (color_symbols
);
7639 return NILP (color_symbols
);
7643 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7646 xpm_image_p (object
)
7649 struct image_keyword fmt
[XPM_LAST
];
7650 bcopy (xpm_format
, fmt
, sizeof fmt
);
7651 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7652 /* Either `:file' or `:data' must be present. */
7653 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7654 /* Either no `:color-symbols' or it's a list of conses
7655 whose car and cdr are strings. */
7656 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7657 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7661 /* Load image IMG which will be displayed on frame F. Value is
7662 non-zero if successful. */
7670 XpmAttributes attrs
;
7671 Lisp_Object specified_file
, color_symbols
;
7673 /* Configure the XPM lib. Use the visual of frame F. Allocate
7674 close colors. Return colors allocated. */
7675 bzero (&attrs
, sizeof attrs
);
7676 attrs
.visual
= FRAME_X_VISUAL (f
);
7677 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7678 attrs
.valuemask
|= XpmVisual
;
7679 attrs
.valuemask
|= XpmColormap
;
7681 #ifdef ALLOC_XPM_COLORS
7682 /* Allocate colors with our own functions which handle
7683 failing color allocation more gracefully. */
7684 attrs
.color_closure
= f
;
7685 attrs
.alloc_color
= xpm_alloc_color
;
7686 attrs
.free_colors
= xpm_free_colors
;
7687 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7688 #else /* not ALLOC_XPM_COLORS */
7689 /* Let the XPM lib allocate colors. */
7690 attrs
.valuemask
|= XpmReturnAllocPixels
;
7691 #ifdef XpmAllocCloseColors
7692 attrs
.alloc_close_colors
= 1;
7693 attrs
.valuemask
|= XpmAllocCloseColors
;
7694 #else /* not XpmAllocCloseColors */
7695 attrs
.closeness
= 600;
7696 attrs
.valuemask
|= XpmCloseness
;
7697 #endif /* not XpmAllocCloseColors */
7698 #endif /* ALLOC_XPM_COLORS */
7700 /* If image specification contains symbolic color definitions, add
7701 these to `attrs'. */
7702 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7703 if (CONSP (color_symbols
))
7706 XpmColorSymbol
*xpm_syms
;
7709 attrs
.valuemask
|= XpmColorSymbols
;
7711 /* Count number of symbols. */
7712 attrs
.numsymbols
= 0;
7713 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7716 /* Allocate an XpmColorSymbol array. */
7717 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7718 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7719 bzero (xpm_syms
, size
);
7720 attrs
.colorsymbols
= xpm_syms
;
7722 /* Fill the color symbol array. */
7723 for (tail
= color_symbols
, i
= 0;
7725 ++i
, tail
= XCDR (tail
))
7727 Lisp_Object name
= XCAR (XCAR (tail
));
7728 Lisp_Object color
= XCDR (XCAR (tail
));
7729 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7730 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7731 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7732 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7736 /* Create a pixmap for the image, either from a file, or from a
7737 string buffer containing data in the same format as an XPM file. */
7738 #ifdef ALLOC_XPM_COLORS
7739 xpm_init_color_cache (f
, &attrs
);
7742 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7743 if (STRINGP (specified_file
))
7745 Lisp_Object file
= x_find_image_file (specified_file
);
7746 if (!STRINGP (file
))
7748 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7752 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7753 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7758 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7759 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7760 XSTRING (buffer
)->data
,
7761 &img
->pixmap
, &img
->mask
,
7765 if (rc
== XpmSuccess
)
7767 #ifdef ALLOC_XPM_COLORS
7768 img
->colors
= colors_in_color_table (&img
->ncolors
);
7769 #else /* not ALLOC_XPM_COLORS */
7772 img
->ncolors
= attrs
.nalloc_pixels
;
7773 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7774 * sizeof *img
->colors
);
7775 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7777 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7778 #ifdef DEBUG_X_COLORS
7779 register_color (img
->colors
[i
]);
7782 #endif /* not ALLOC_XPM_COLORS */
7784 img
->width
= attrs
.width
;
7785 img
->height
= attrs
.height
;
7786 xassert (img
->width
> 0 && img
->height
> 0);
7788 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7789 XpmFreeAttributes (&attrs
);
7796 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7799 case XpmFileInvalid
:
7800 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7804 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7807 case XpmColorFailed
:
7808 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7812 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7817 #ifdef ALLOC_XPM_COLORS
7818 xpm_free_color_cache ();
7820 return rc
== XpmSuccess
;
7823 #endif /* HAVE_XPM != 0 */
7826 /***********************************************************************
7828 ***********************************************************************/
7830 /* An entry in the color table mapping an RGB color to a pixel color. */
7835 unsigned long pixel
;
7837 /* Next in color table collision list. */
7838 struct ct_color
*next
;
7841 /* The bucket vector size to use. Must be prime. */
7845 /* Value is a hash of the RGB color given by R, G, and B. */
7847 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7849 /* The color hash table. */
7851 struct ct_color
**ct_table
;
7853 /* Number of entries in the color table. */
7855 int ct_colors_allocated
;
7857 /* Initialize the color table. */
7862 int size
= CT_SIZE
* sizeof (*ct_table
);
7863 ct_table
= (struct ct_color
**) xmalloc (size
);
7864 bzero (ct_table
, size
);
7865 ct_colors_allocated
= 0;
7869 /* Free memory associated with the color table. */
7875 struct ct_color
*p
, *next
;
7877 for (i
= 0; i
< CT_SIZE
; ++i
)
7878 for (p
= ct_table
[i
]; p
; p
= next
)
7889 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7890 entry for that color already is in the color table, return the
7891 pixel color of that entry. Otherwise, allocate a new color for R,
7892 G, B, and make an entry in the color table. */
7894 static unsigned long
7895 lookup_rgb_color (f
, r
, g
, b
)
7899 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7900 int i
= hash
% CT_SIZE
;
7903 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7904 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7917 cmap
= FRAME_X_COLORMAP (f
);
7918 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7922 ++ct_colors_allocated
;
7924 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7928 p
->pixel
= color
.pixel
;
7929 p
->next
= ct_table
[i
];
7933 return FRAME_FOREGROUND_PIXEL (f
);
7940 /* Look up pixel color PIXEL which is used on frame F in the color
7941 table. If not already present, allocate it. Value is PIXEL. */
7943 static unsigned long
7944 lookup_pixel_color (f
, pixel
)
7946 unsigned long pixel
;
7948 int i
= pixel
% CT_SIZE
;
7951 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7952 if (p
->pixel
== pixel
)
7961 cmap
= FRAME_X_COLORMAP (f
);
7962 color
.pixel
= pixel
;
7963 x_query_color (f
, &color
);
7964 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7968 ++ct_colors_allocated
;
7970 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7975 p
->next
= ct_table
[i
];
7979 return FRAME_FOREGROUND_PIXEL (f
);
7986 /* Value is a vector of all pixel colors contained in the color table,
7987 allocated via xmalloc. Set *N to the number of colors. */
7989 static unsigned long *
7990 colors_in_color_table (n
)
7995 unsigned long *colors
;
7997 if (ct_colors_allocated
== 0)
8004 colors
= (unsigned long *) xmalloc (ct_colors_allocated
8006 *n
= ct_colors_allocated
;
8008 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
8009 for (p
= ct_table
[i
]; p
; p
= p
->next
)
8010 colors
[j
++] = p
->pixel
;
8018 /***********************************************************************
8020 ***********************************************************************/
8022 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
8023 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
8024 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
8026 /* Non-zero means draw a cross on images having `:conversion
8029 int cross_disabled_images
;
8031 /* Edge detection matrices for different edge-detection
8034 static int emboss_matrix
[9] = {
8036 2, -1, 0, /* y - 1 */
8038 0, 1, -2 /* y + 1 */
8041 static int laplace_matrix
[9] = {
8043 1, 0, 0, /* y - 1 */
8045 0, 0, -1 /* y + 1 */
8048 /* Value is the intensity of the color whose red/green/blue values
8051 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8054 /* On frame F, return an array of XColor structures describing image
8055 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8056 non-zero means also fill the red/green/blue members of the XColor
8057 structures. Value is a pointer to the array of XColors structures,
8058 allocated with xmalloc; it must be freed by the caller. */
8061 x_to_xcolors (f
, img
, rgb_p
)
8070 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
8072 /* Get the X image IMG->pixmap. */
8073 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8074 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8076 /* Fill the `pixel' members of the XColor array. I wished there
8077 were an easy and portable way to circumvent XGetPixel. */
8079 for (y
= 0; y
< img
->height
; ++y
)
8083 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8084 p
->pixel
= XGetPixel (ximg
, x
, y
);
8087 x_query_colors (f
, row
, img
->width
);
8090 XDestroyImage (ximg
);
8095 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8096 RGB members are set. F is the frame on which this all happens.
8097 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8100 x_from_xcolors (f
, img
, colors
)
8110 init_color_table ();
8112 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
8115 for (y
= 0; y
< img
->height
; ++y
)
8116 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8118 unsigned long pixel
;
8119 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
8120 XPutPixel (oimg
, x
, y
, pixel
);
8124 x_clear_image_1 (f
, img
, 1, 0, 1);
8126 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
8127 x_destroy_x_image (oimg
);
8128 img
->pixmap
= pixmap
;
8129 img
->colors
= colors_in_color_table (&img
->ncolors
);
8130 free_color_table ();
8134 /* On frame F, perform edge-detection on image IMG.
8136 MATRIX is a nine-element array specifying the transformation
8137 matrix. See emboss_matrix for an example.
8139 COLOR_ADJUST is a color adjustment added to each pixel of the
8143 x_detect_edges (f
, img
, matrix
, color_adjust
)
8146 int matrix
[9], color_adjust
;
8148 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8152 for (i
= sum
= 0; i
< 9; ++i
)
8153 sum
+= abs (matrix
[i
]);
8155 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8157 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
8159 for (y
= 0; y
< img
->height
; ++y
)
8161 p
= COLOR (new, 0, y
);
8162 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8163 p
= COLOR (new, img
->width
- 1, y
);
8164 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8167 for (x
= 1; x
< img
->width
- 1; ++x
)
8169 p
= COLOR (new, x
, 0);
8170 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8171 p
= COLOR (new, x
, img
->height
- 1);
8172 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8175 for (y
= 1; y
< img
->height
- 1; ++y
)
8177 p
= COLOR (new, 1, y
);
8179 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
8181 int r
, g
, b
, y1
, x1
;
8184 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
8185 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
8188 XColor
*t
= COLOR (colors
, x1
, y1
);
8189 r
+= matrix
[i
] * t
->red
;
8190 g
+= matrix
[i
] * t
->green
;
8191 b
+= matrix
[i
] * t
->blue
;
8194 r
= (r
/ sum
+ color_adjust
) & 0xffff;
8195 g
= (g
/ sum
+ color_adjust
) & 0xffff;
8196 b
= (b
/ sum
+ color_adjust
) & 0xffff;
8197 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
8202 x_from_xcolors (f
, img
, new);
8208 /* Perform the pre-defined `emboss' edge-detection on image IMG
8216 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
8220 /* Perform the pre-defined `laplace' edge-detection on image IMG
8228 x_detect_edges (f
, img
, laplace_matrix
, 45000);
8232 /* Perform edge-detection on image IMG on frame F, with specified
8233 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8235 MATRIX must be either
8237 - a list of at least 9 numbers in row-major form
8238 - a vector of at least 9 numbers
8240 COLOR_ADJUST nil means use a default; otherwise it must be a
8244 x_edge_detection (f
, img
, matrix
, color_adjust
)
8247 Lisp_Object matrix
, color_adjust
;
8255 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
8256 ++i
, matrix
= XCDR (matrix
))
8257 trans
[i
] = XFLOATINT (XCAR (matrix
));
8259 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
8261 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
8262 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
8265 if (NILP (color_adjust
))
8266 color_adjust
= make_number (0xffff / 2);
8268 if (i
== 9 && NUMBERP (color_adjust
))
8269 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
8273 /* Transform image IMG on frame F so that it looks disabled. */
8276 x_disable_image (f
, img
)
8280 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8282 if (dpyinfo
->n_planes
>= 2)
8284 /* Color (or grayscale). Convert to gray, and equalize. Just
8285 drawing such images with a stipple can look very odd, so
8286 we're using this method instead. */
8287 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8289 const int h
= 15000;
8290 const int l
= 30000;
8292 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
8296 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
8297 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
8298 p
->red
= p
->green
= p
->blue
= i2
;
8301 x_from_xcolors (f
, img
, colors
);
8304 /* Draw a cross over the disabled image, if we must or if we
8306 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
8308 Display
*dpy
= FRAME_X_DISPLAY (f
);
8311 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
8312 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
8313 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
8314 img
->width
- 1, img
->height
- 1);
8315 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
8321 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
8322 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8323 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8324 img
->width
- 1, img
->height
- 1);
8325 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8333 /* Build a mask for image IMG which is used on frame F. FILE is the
8334 name of an image file, for error messages. HOW determines how to
8335 determine the background color of IMG. If it is a list '(R G B)',
8336 with R, G, and B being integers >= 0, take that as the color of the
8337 background. Otherwise, determine the background color of IMG
8338 heuristically. Value is non-zero if successful. */
8341 x_build_heuristic_mask (f
, img
, how
)
8346 Display
*dpy
= FRAME_X_DISPLAY (f
);
8347 XImage
*ximg
, *mask_img
;
8348 int x
, y
, rc
, use_img_background
;
8349 unsigned long bg
= 0;
8353 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8355 img
->background_transparent_valid
= 0;
8358 /* Create an image and pixmap serving as mask. */
8359 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8360 &mask_img
, &img
->mask
);
8364 /* Get the X image of IMG->pixmap. */
8365 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8368 /* Determine the background color of ximg. If HOW is `(R G B)'
8369 take that as color. Otherwise, use the image's background color. */
8370 use_img_background
= 1;
8376 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
8378 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8382 if (i
== 3 && NILP (how
))
8384 char color_name
[30];
8385 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8386 bg
= x_alloc_image_color (f
, img
, build_string (color_name
), 0);
8387 use_img_background
= 0;
8391 if (use_img_background
)
8392 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
8394 /* Set all bits in mask_img to 1 whose color in ximg is different
8395 from the background color bg. */
8396 for (y
= 0; y
< img
->height
; ++y
)
8397 for (x
= 0; x
< img
->width
; ++x
)
8398 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8400 /* Fill in the background_transparent field while we have the mask handy. */
8401 image_background_transparent (img
, f
, mask_img
);
8403 /* Put mask_img into img->mask. */
8404 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8405 x_destroy_x_image (mask_img
);
8406 XDestroyImage (ximg
);
8413 /***********************************************************************
8414 PBM (mono, gray, color)
8415 ***********************************************************************/
8417 static int pbm_image_p
P_ ((Lisp_Object object
));
8418 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8419 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8421 /* The symbol `pbm' identifying images of this type. */
8425 /* Indices of image specification fields in gs_format, below. */
8427 enum pbm_keyword_index
8443 /* Vector of image_keyword structures describing the format
8444 of valid user-defined image specifications. */
8446 static struct image_keyword pbm_format
[PBM_LAST
] =
8448 {":type", IMAGE_SYMBOL_VALUE
, 1},
8449 {":file", IMAGE_STRING_VALUE
, 0},
8450 {":data", IMAGE_STRING_VALUE
, 0},
8451 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8452 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8453 {":relief", IMAGE_INTEGER_VALUE
, 0},
8454 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8455 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8456 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8457 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8458 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8461 /* Structure describing the image type `pbm'. */
8463 static struct image_type pbm_type
=
8473 /* Return non-zero if OBJECT is a valid PBM image specification. */
8476 pbm_image_p (object
)
8479 struct image_keyword fmt
[PBM_LAST
];
8481 bcopy (pbm_format
, fmt
, sizeof fmt
);
8483 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8486 /* Must specify either :data or :file. */
8487 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8491 /* Scan a decimal number from *S and return it. Advance *S while
8492 reading the number. END is the end of the string. Value is -1 at
8496 pbm_scan_number (s
, end
)
8497 unsigned char **s
, *end
;
8499 int c
= 0, val
= -1;
8503 /* Skip white-space. */
8504 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8509 /* Skip comment to end of line. */
8510 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8513 else if (isdigit (c
))
8515 /* Read decimal number. */
8517 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8518 val
= 10 * val
+ c
- '0';
8529 /* Load PBM image IMG for use on frame F. */
8537 int width
, height
, max_color_idx
= 0;
8539 Lisp_Object file
, specified_file
;
8540 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8541 struct gcpro gcpro1
;
8542 unsigned char *contents
= NULL
;
8543 unsigned char *end
, *p
;
8546 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8550 if (STRINGP (specified_file
))
8552 file
= x_find_image_file (specified_file
);
8553 if (!STRINGP (file
))
8555 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8560 contents
= slurp_file (XSTRING (file
)->data
, &size
);
8561 if (contents
== NULL
)
8563 image_error ("Error reading `%s'", file
, Qnil
);
8569 end
= contents
+ size
;
8574 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8575 p
= XSTRING (data
)->data
;
8576 end
= p
+ STRING_BYTES (XSTRING (data
));
8579 /* Check magic number. */
8580 if (end
- p
< 2 || *p
++ != 'P')
8582 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8592 raw_p
= 0, type
= PBM_MONO
;
8596 raw_p
= 0, type
= PBM_GRAY
;
8600 raw_p
= 0, type
= PBM_COLOR
;
8604 raw_p
= 1, type
= PBM_MONO
;
8608 raw_p
= 1, type
= PBM_GRAY
;
8612 raw_p
= 1, type
= PBM_COLOR
;
8616 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8620 /* Read width, height, maximum color-component. Characters
8621 starting with `#' up to the end of a line are ignored. */
8622 width
= pbm_scan_number (&p
, end
);
8623 height
= pbm_scan_number (&p
, end
);
8625 if (type
!= PBM_MONO
)
8627 max_color_idx
= pbm_scan_number (&p
, end
);
8628 if (raw_p
&& max_color_idx
> 255)
8629 max_color_idx
= 255;
8634 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8637 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8638 &ximg
, &img
->pixmap
))
8641 /* Initialize the color hash table. */
8642 init_color_table ();
8644 if (type
== PBM_MONO
)
8647 struct image_keyword fmt
[PBM_LAST
];
8648 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8649 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8651 /* Parse the image specification. */
8652 bcopy (pbm_format
, fmt
, sizeof fmt
);
8653 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8655 /* Get foreground and background colors, maybe allocate colors. */
8656 if (fmt
[PBM_FOREGROUND
].count
8657 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8658 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8659 if (fmt
[PBM_BACKGROUND
].count
8660 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8662 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8663 img
->background
= bg
;
8664 img
->background_valid
= 1;
8667 for (y
= 0; y
< height
; ++y
)
8668 for (x
= 0; x
< width
; ++x
)
8678 g
= pbm_scan_number (&p
, end
);
8680 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8685 for (y
= 0; y
< height
; ++y
)
8686 for (x
= 0; x
< width
; ++x
)
8690 if (type
== PBM_GRAY
)
8691 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8700 r
= pbm_scan_number (&p
, end
);
8701 g
= pbm_scan_number (&p
, end
);
8702 b
= pbm_scan_number (&p
, end
);
8705 if (r
< 0 || g
< 0 || b
< 0)
8709 XDestroyImage (ximg
);
8710 image_error ("Invalid pixel value in image `%s'",
8715 /* RGB values are now in the range 0..max_color_idx.
8716 Scale this to the range 0..0xffff supported by X. */
8717 r
= (double) r
* 65535 / max_color_idx
;
8718 g
= (double) g
* 65535 / max_color_idx
;
8719 b
= (double) b
* 65535 / max_color_idx
;
8720 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8724 /* Store in IMG->colors the colors allocated for the image, and
8725 free the color table. */
8726 img
->colors
= colors_in_color_table (&img
->ncolors
);
8727 free_color_table ();
8729 /* Maybe fill in the background field while we have ximg handy. */
8730 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8731 IMAGE_BACKGROUND (img
, f
, ximg
);
8733 /* Put the image into a pixmap. */
8734 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8735 x_destroy_x_image (ximg
);
8738 img
->height
= height
;
8747 /***********************************************************************
8749 ***********************************************************************/
8755 /* Function prototypes. */
8757 static int png_image_p
P_ ((Lisp_Object object
));
8758 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8760 /* The symbol `png' identifying images of this type. */
8764 /* Indices of image specification fields in png_format, below. */
8766 enum png_keyword_index
8781 /* Vector of image_keyword structures describing the format
8782 of valid user-defined image specifications. */
8784 static struct image_keyword png_format
[PNG_LAST
] =
8786 {":type", IMAGE_SYMBOL_VALUE
, 1},
8787 {":data", IMAGE_STRING_VALUE
, 0},
8788 {":file", IMAGE_STRING_VALUE
, 0},
8789 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8790 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8791 {":relief", IMAGE_INTEGER_VALUE
, 0},
8792 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8793 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8794 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8795 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8798 /* Structure describing the image type `png'. */
8800 static struct image_type png_type
=
8810 /* Return non-zero if OBJECT is a valid PNG image specification. */
8813 png_image_p (object
)
8816 struct image_keyword fmt
[PNG_LAST
];
8817 bcopy (png_format
, fmt
, sizeof fmt
);
8819 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8822 /* Must specify either the :data or :file keyword. */
8823 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8827 /* Error and warning handlers installed when the PNG library
8831 my_png_error (png_ptr
, msg
)
8832 png_struct
*png_ptr
;
8835 xassert (png_ptr
!= NULL
);
8836 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8837 longjmp (png_ptr
->jmpbuf
, 1);
8842 my_png_warning (png_ptr
, msg
)
8843 png_struct
*png_ptr
;
8846 xassert (png_ptr
!= NULL
);
8847 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8850 /* Memory source for PNG decoding. */
8852 struct png_memory_storage
8854 unsigned char *bytes
; /* The data */
8855 size_t len
; /* How big is it? */
8856 int index
; /* Where are we? */
8860 /* Function set as reader function when reading PNG image from memory.
8861 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8862 bytes from the input to DATA. */
8865 png_read_from_memory (png_ptr
, data
, length
)
8866 png_structp png_ptr
;
8870 struct png_memory_storage
*tbr
8871 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8873 if (length
> tbr
->len
- tbr
->index
)
8874 png_error (png_ptr
, "Read error");
8876 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8877 tbr
->index
= tbr
->index
+ length
;
8880 /* Load PNG image IMG for use on frame F. Value is non-zero if
8888 Lisp_Object file
, specified_file
;
8889 Lisp_Object specified_data
;
8891 XImage
*ximg
, *mask_img
= NULL
;
8892 struct gcpro gcpro1
;
8893 png_struct
*png_ptr
= NULL
;
8894 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8895 FILE *volatile fp
= NULL
;
8897 png_byte
* volatile pixels
= NULL
;
8898 png_byte
** volatile rows
= NULL
;
8899 png_uint_32 width
, height
;
8900 int bit_depth
, color_type
, interlace_type
;
8902 png_uint_32 row_bytes
;
8904 double screen_gamma
, image_gamma
;
8906 struct png_memory_storage tbr
; /* Data to be read */
8908 /* Find out what file to load. */
8909 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8910 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8914 if (NILP (specified_data
))
8916 file
= x_find_image_file (specified_file
);
8917 if (!STRINGP (file
))
8919 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8924 /* Open the image file. */
8925 fp
= fopen (XSTRING (file
)->data
, "rb");
8928 image_error ("Cannot open image file `%s'", file
, Qnil
);
8934 /* Check PNG signature. */
8935 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8936 || !png_check_sig (sig
, sizeof sig
))
8938 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8946 /* Read from memory. */
8947 tbr
.bytes
= XSTRING (specified_data
)->data
;
8948 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8951 /* Check PNG signature. */
8952 if (tbr
.len
< sizeof sig
8953 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8955 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8960 /* Need to skip past the signature. */
8961 tbr
.bytes
+= sizeof (sig
);
8964 /* Initialize read and info structs for PNG lib. */
8965 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8966 my_png_error
, my_png_warning
);
8969 if (fp
) fclose (fp
);
8974 info_ptr
= png_create_info_struct (png_ptr
);
8977 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8978 if (fp
) fclose (fp
);
8983 end_info
= png_create_info_struct (png_ptr
);
8986 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8987 if (fp
) fclose (fp
);
8992 /* Set error jump-back. We come back here when the PNG library
8993 detects an error. */
8994 if (setjmp (png_ptr
->jmpbuf
))
8998 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9001 if (fp
) fclose (fp
);
9006 /* Read image info. */
9007 if (!NILP (specified_data
))
9008 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
9010 png_init_io (png_ptr
, fp
);
9012 png_set_sig_bytes (png_ptr
, sizeof sig
);
9013 png_read_info (png_ptr
, info_ptr
);
9014 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
9015 &interlace_type
, NULL
, NULL
);
9017 /* If image contains simply transparency data, we prefer to
9018 construct a clipping mask. */
9019 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
9024 /* This function is easier to write if we only have to handle
9025 one data format: RGB or RGBA with 8 bits per channel. Let's
9026 transform other formats into that format. */
9028 /* Strip more than 8 bits per channel. */
9029 if (bit_depth
== 16)
9030 png_set_strip_16 (png_ptr
);
9032 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
9034 png_set_expand (png_ptr
);
9036 /* Convert grayscale images to RGB. */
9037 if (color_type
== PNG_COLOR_TYPE_GRAY
9038 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
9039 png_set_gray_to_rgb (png_ptr
);
9041 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
9043 /* Tell the PNG lib to handle gamma correction for us. */
9045 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9046 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
9047 /* The libpng documentation says this is right in this case. */
9048 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9051 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
9052 /* Image contains gamma information. */
9053 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
9055 /* Use the standard default for the image gamma. */
9056 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9058 /* Handle alpha channel by combining the image with a background
9059 color. Do this only if a real alpha channel is supplied. For
9060 simple transparency, we prefer a clipping mask. */
9063 png_color_16
*image_bg
;
9064 Lisp_Object specified_bg
9065 = image_spec_value (img
->spec
, QCbackground
, NULL
);
9067 if (STRINGP (specified_bg
))
9068 /* The user specified `:background', use that. */
9071 if (x_defined_color (f
, XSTRING (specified_bg
)->data
, &color
, 0))
9073 png_color_16 user_bg
;
9075 bzero (&user_bg
, sizeof user_bg
);
9076 user_bg
.red
= color
.red
;
9077 user_bg
.green
= color
.green
;
9078 user_bg
.blue
= color
.blue
;
9080 png_set_background (png_ptr
, &user_bg
,
9081 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9084 else if (png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
9085 /* Image contains a background color with which to
9086 combine the image. */
9087 png_set_background (png_ptr
, image_bg
,
9088 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
9091 /* Image does not contain a background color with which
9092 to combine the image data via an alpha channel. Use
9093 the frame's background instead. */
9096 png_color_16 frame_background
;
9098 cmap
= FRAME_X_COLORMAP (f
);
9099 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
9100 x_query_color (f
, &color
);
9102 bzero (&frame_background
, sizeof frame_background
);
9103 frame_background
.red
= color
.red
;
9104 frame_background
.green
= color
.green
;
9105 frame_background
.blue
= color
.blue
;
9107 png_set_background (png_ptr
, &frame_background
,
9108 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9112 /* Update info structure. */
9113 png_read_update_info (png_ptr
, info_ptr
);
9115 /* Get number of channels. Valid values are 1 for grayscale images
9116 and images with a palette, 2 for grayscale images with transparency
9117 information (alpha channel), 3 for RGB images, and 4 for RGB
9118 images with alpha channel, i.e. RGBA. If conversions above were
9119 sufficient we should only have 3 or 4 channels here. */
9120 channels
= png_get_channels (png_ptr
, info_ptr
);
9121 xassert (channels
== 3 || channels
== 4);
9123 /* Number of bytes needed for one row of the image. */
9124 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
9126 /* Allocate memory for the image. */
9127 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
9128 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
9129 for (i
= 0; i
< height
; ++i
)
9130 rows
[i
] = pixels
+ i
* row_bytes
;
9132 /* Read the entire image. */
9133 png_read_image (png_ptr
, rows
);
9134 png_read_end (png_ptr
, info_ptr
);
9141 /* Create the X image and pixmap. */
9142 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
9146 /* Create an image and pixmap serving as mask if the PNG image
9147 contains an alpha channel. */
9150 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
9151 &mask_img
, &img
->mask
))
9153 x_destroy_x_image (ximg
);
9154 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
9159 /* Fill the X image and mask from PNG data. */
9160 init_color_table ();
9162 for (y
= 0; y
< height
; ++y
)
9164 png_byte
*p
= rows
[y
];
9166 for (x
= 0; x
< width
; ++x
)
9173 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
9175 /* An alpha channel, aka mask channel, associates variable
9176 transparency with an image. Where other image formats
9177 support binary transparency---fully transparent or fully
9178 opaque---PNG allows up to 254 levels of partial transparency.
9179 The PNG library implements partial transparency by combining
9180 the image with a specified background color.
9182 I'm not sure how to handle this here nicely: because the
9183 background on which the image is displayed may change, for
9184 real alpha channel support, it would be necessary to create
9185 a new image for each possible background.
9187 What I'm doing now is that a mask is created if we have
9188 boolean transparency information. Otherwise I'm using
9189 the frame's background color to combine the image with. */
9194 XPutPixel (mask_img
, x
, y
, *p
> 0);
9200 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9201 /* Set IMG's background color from the PNG image, unless the user
9205 if (png_get_bKGD (png_ptr
, info_ptr
, &bg
))
9207 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
9208 img
->background_valid
= 1;
9212 /* Remember colors allocated for this image. */
9213 img
->colors
= colors_in_color_table (&img
->ncolors
);
9214 free_color_table ();
9217 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9222 img
->height
= height
;
9224 /* Maybe fill in the background field while we have ximg handy. */
9225 IMAGE_BACKGROUND (img
, f
, ximg
);
9227 /* Put the image into the pixmap, then free the X image and its buffer. */
9228 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9229 x_destroy_x_image (ximg
);
9231 /* Same for the mask. */
9234 /* Fill in the background_transparent field while we have the mask
9236 image_background_transparent (img
, f
, mask_img
);
9238 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
9239 x_destroy_x_image (mask_img
);
9246 #endif /* HAVE_PNG != 0 */
9250 /***********************************************************************
9252 ***********************************************************************/
9256 /* Work around a warning about HAVE_STDLIB_H being redefined in
9258 #ifdef HAVE_STDLIB_H
9259 #define HAVE_STDLIB_H_1
9260 #undef HAVE_STDLIB_H
9261 #endif /* HAVE_STLIB_H */
9263 #include <jpeglib.h>
9267 #ifdef HAVE_STLIB_H_1
9268 #define HAVE_STDLIB_H 1
9271 static int jpeg_image_p
P_ ((Lisp_Object object
));
9272 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
9274 /* The symbol `jpeg' identifying images of this type. */
9278 /* Indices of image specification fields in gs_format, below. */
9280 enum jpeg_keyword_index
9289 JPEG_HEURISTIC_MASK
,
9295 /* Vector of image_keyword structures describing the format
9296 of valid user-defined image specifications. */
9298 static struct image_keyword jpeg_format
[JPEG_LAST
] =
9300 {":type", IMAGE_SYMBOL_VALUE
, 1},
9301 {":data", IMAGE_STRING_VALUE
, 0},
9302 {":file", IMAGE_STRING_VALUE
, 0},
9303 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9304 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9305 {":relief", IMAGE_INTEGER_VALUE
, 0},
9306 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9307 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9308 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9309 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9312 /* Structure describing the image type `jpeg'. */
9314 static struct image_type jpeg_type
=
9324 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9327 jpeg_image_p (object
)
9330 struct image_keyword fmt
[JPEG_LAST
];
9332 bcopy (jpeg_format
, fmt
, sizeof fmt
);
9334 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
9337 /* Must specify either the :data or :file keyword. */
9338 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9342 struct my_jpeg_error_mgr
9344 struct jpeg_error_mgr pub
;
9345 jmp_buf setjmp_buffer
;
9350 my_error_exit (cinfo
)
9353 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9354 longjmp (mgr
->setjmp_buffer
, 1);
9358 /* Init source method for JPEG data source manager. Called by
9359 jpeg_read_header() before any data is actually read. See
9360 libjpeg.doc from the JPEG lib distribution. */
9363 our_init_source (cinfo
)
9364 j_decompress_ptr cinfo
;
9369 /* Fill input buffer method for JPEG data source manager. Called
9370 whenever more data is needed. We read the whole image in one step,
9371 so this only adds a fake end of input marker at the end. */
9374 our_fill_input_buffer (cinfo
)
9375 j_decompress_ptr cinfo
;
9377 /* Insert a fake EOI marker. */
9378 struct jpeg_source_mgr
*src
= cinfo
->src
;
9379 static JOCTET buffer
[2];
9381 buffer
[0] = (JOCTET
) 0xFF;
9382 buffer
[1] = (JOCTET
) JPEG_EOI
;
9384 src
->next_input_byte
= buffer
;
9385 src
->bytes_in_buffer
= 2;
9390 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9391 is the JPEG data source manager. */
9394 our_skip_input_data (cinfo
, num_bytes
)
9395 j_decompress_ptr cinfo
;
9398 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9402 if (num_bytes
> src
->bytes_in_buffer
)
9403 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9405 src
->bytes_in_buffer
-= num_bytes
;
9406 src
->next_input_byte
+= num_bytes
;
9411 /* Method to terminate data source. Called by
9412 jpeg_finish_decompress() after all data has been processed. */
9415 our_term_source (cinfo
)
9416 j_decompress_ptr cinfo
;
9421 /* Set up the JPEG lib for reading an image from DATA which contains
9422 LEN bytes. CINFO is the decompression info structure created for
9423 reading the image. */
9426 jpeg_memory_src (cinfo
, data
, len
)
9427 j_decompress_ptr cinfo
;
9431 struct jpeg_source_mgr
*src
;
9433 if (cinfo
->src
== NULL
)
9435 /* First time for this JPEG object? */
9436 cinfo
->src
= (struct jpeg_source_mgr
*)
9437 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9438 sizeof (struct jpeg_source_mgr
));
9439 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9440 src
->next_input_byte
= data
;
9443 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9444 src
->init_source
= our_init_source
;
9445 src
->fill_input_buffer
= our_fill_input_buffer
;
9446 src
->skip_input_data
= our_skip_input_data
;
9447 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9448 src
->term_source
= our_term_source
;
9449 src
->bytes_in_buffer
= len
;
9450 src
->next_input_byte
= data
;
9454 /* Load image IMG for use on frame F. Patterned after example.c
9455 from the JPEG lib. */
9462 struct jpeg_decompress_struct cinfo
;
9463 struct my_jpeg_error_mgr mgr
;
9464 Lisp_Object file
, specified_file
;
9465 Lisp_Object specified_data
;
9466 FILE * volatile fp
= NULL
;
9468 int row_stride
, x
, y
;
9469 XImage
*ximg
= NULL
;
9471 unsigned long *colors
;
9473 struct gcpro gcpro1
;
9475 /* Open the JPEG file. */
9476 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9477 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9481 if (NILP (specified_data
))
9483 file
= x_find_image_file (specified_file
);
9484 if (!STRINGP (file
))
9486 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9491 fp
= fopen (XSTRING (file
)->data
, "r");
9494 image_error ("Cannot open `%s'", file
, Qnil
);
9500 /* Customize libjpeg's error handling to call my_error_exit when an
9501 error is detected. This function will perform a longjmp. */
9502 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9503 mgr
.pub
.error_exit
= my_error_exit
;
9505 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9509 /* Called from my_error_exit. Display a JPEG error. */
9510 char buffer
[JMSG_LENGTH_MAX
];
9511 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9512 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9513 build_string (buffer
));
9516 /* Close the input file and destroy the JPEG object. */
9518 fclose ((FILE *) fp
);
9519 jpeg_destroy_decompress (&cinfo
);
9521 /* If we already have an XImage, free that. */
9522 x_destroy_x_image (ximg
);
9524 /* Free pixmap and colors. */
9525 x_clear_image (f
, img
);
9531 /* Create the JPEG decompression object. Let it read from fp.
9532 Read the JPEG image header. */
9533 jpeg_create_decompress (&cinfo
);
9535 if (NILP (specified_data
))
9536 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9538 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
9539 STRING_BYTES (XSTRING (specified_data
)));
9541 jpeg_read_header (&cinfo
, TRUE
);
9543 /* Customize decompression so that color quantization will be used.
9544 Start decompression. */
9545 cinfo
.quantize_colors
= TRUE
;
9546 jpeg_start_decompress (&cinfo
);
9547 width
= img
->width
= cinfo
.output_width
;
9548 height
= img
->height
= cinfo
.output_height
;
9550 /* Create X image and pixmap. */
9551 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9552 longjmp (mgr
.setjmp_buffer
, 2);
9554 /* Allocate colors. When color quantization is used,
9555 cinfo.actual_number_of_colors has been set with the number of
9556 colors generated, and cinfo.colormap is a two-dimensional array
9557 of color indices in the range 0..cinfo.actual_number_of_colors.
9558 No more than 255 colors will be generated. */
9562 if (cinfo
.out_color_components
> 2)
9563 ir
= 0, ig
= 1, ib
= 2;
9564 else if (cinfo
.out_color_components
> 1)
9565 ir
= 0, ig
= 1, ib
= 0;
9567 ir
= 0, ig
= 0, ib
= 0;
9569 /* Use the color table mechanism because it handles colors that
9570 cannot be allocated nicely. Such colors will be replaced with
9571 a default color, and we don't have to care about which colors
9572 can be freed safely, and which can't. */
9573 init_color_table ();
9574 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9577 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9579 /* Multiply RGB values with 255 because X expects RGB values
9580 in the range 0..0xffff. */
9581 int r
= cinfo
.colormap
[ir
][i
] << 8;
9582 int g
= cinfo
.colormap
[ig
][i
] << 8;
9583 int b
= cinfo
.colormap
[ib
][i
] << 8;
9584 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9587 /* Remember those colors actually allocated. */
9588 img
->colors
= colors_in_color_table (&img
->ncolors
);
9589 free_color_table ();
9593 row_stride
= width
* cinfo
.output_components
;
9594 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9596 for (y
= 0; y
< height
; ++y
)
9598 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9599 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9600 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9604 jpeg_finish_decompress (&cinfo
);
9605 jpeg_destroy_decompress (&cinfo
);
9607 fclose ((FILE *) fp
);
9609 /* Maybe fill in the background field while we have ximg handy. */
9610 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9611 IMAGE_BACKGROUND (img
, f
, ximg
);
9613 /* Put the image into the pixmap. */
9614 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9615 x_destroy_x_image (ximg
);
9620 #endif /* HAVE_JPEG */
9624 /***********************************************************************
9626 ***********************************************************************/
9632 static int tiff_image_p
P_ ((Lisp_Object object
));
9633 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9635 /* The symbol `tiff' identifying images of this type. */
9639 /* Indices of image specification fields in tiff_format, below. */
9641 enum tiff_keyword_index
9650 TIFF_HEURISTIC_MASK
,
9656 /* Vector of image_keyword structures describing the format
9657 of valid user-defined image specifications. */
9659 static struct image_keyword tiff_format
[TIFF_LAST
] =
9661 {":type", IMAGE_SYMBOL_VALUE
, 1},
9662 {":data", IMAGE_STRING_VALUE
, 0},
9663 {":file", IMAGE_STRING_VALUE
, 0},
9664 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9665 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9666 {":relief", IMAGE_INTEGER_VALUE
, 0},
9667 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9668 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9669 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9670 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9673 /* Structure describing the image type `tiff'. */
9675 static struct image_type tiff_type
=
9685 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9688 tiff_image_p (object
)
9691 struct image_keyword fmt
[TIFF_LAST
];
9692 bcopy (tiff_format
, fmt
, sizeof fmt
);
9694 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9697 /* Must specify either the :data or :file keyword. */
9698 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9702 /* Reading from a memory buffer for TIFF images Based on the PNG
9703 memory source, but we have to provide a lot of extra functions.
9706 We really only need to implement read and seek, but I am not
9707 convinced that the TIFF library is smart enough not to destroy
9708 itself if we only hand it the function pointers we need to
9713 unsigned char *bytes
;
9721 tiff_read_from_memory (data
, buf
, size
)
9726 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9728 if (size
> src
->len
- src
->index
)
9730 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9737 tiff_write_from_memory (data
, buf
, size
)
9747 tiff_seek_in_memory (data
, off
, whence
)
9752 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9757 case SEEK_SET
: /* Go from beginning of source. */
9761 case SEEK_END
: /* Go from end of source. */
9762 idx
= src
->len
+ off
;
9765 case SEEK_CUR
: /* Go from current position. */
9766 idx
= src
->index
+ off
;
9769 default: /* Invalid `whence'. */
9773 if (idx
> src
->len
|| idx
< 0)
9782 tiff_close_memory (data
)
9791 tiff_mmap_memory (data
, pbase
, psize
)
9796 /* It is already _IN_ memory. */
9802 tiff_unmap_memory (data
, base
, size
)
9807 /* We don't need to do this. */
9812 tiff_size_of_memory (data
)
9815 return ((tiff_memory_source
*) data
)->len
;
9820 tiff_error_handler (title
, format
, ap
)
9821 const char *title
, *format
;
9827 len
= sprintf (buf
, "TIFF error: %s ", title
);
9828 vsprintf (buf
+ len
, format
, ap
);
9829 add_to_log (buf
, Qnil
, Qnil
);
9834 tiff_warning_handler (title
, format
, ap
)
9835 const char *title
, *format
;
9841 len
= sprintf (buf
, "TIFF warning: %s ", title
);
9842 vsprintf (buf
+ len
, format
, ap
);
9843 add_to_log (buf
, Qnil
, Qnil
);
9847 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9855 Lisp_Object file
, specified_file
;
9856 Lisp_Object specified_data
;
9858 int width
, height
, x
, y
;
9862 struct gcpro gcpro1
;
9863 tiff_memory_source memsrc
;
9865 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9866 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9870 TIFFSetErrorHandler (tiff_error_handler
);
9871 TIFFSetWarningHandler (tiff_warning_handler
);
9873 if (NILP (specified_data
))
9875 /* Read from a file */
9876 file
= x_find_image_file (specified_file
);
9877 if (!STRINGP (file
))
9879 image_error ("Cannot find image file `%s'", file
, Qnil
);
9884 /* Try to open the image file. */
9885 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9888 image_error ("Cannot open `%s'", file
, Qnil
);
9895 /* Memory source! */
9896 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9897 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9900 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9901 (TIFFReadWriteProc
) tiff_read_from_memory
,
9902 (TIFFReadWriteProc
) tiff_write_from_memory
,
9903 tiff_seek_in_memory
,
9905 tiff_size_of_memory
,
9911 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9917 /* Get width and height of the image, and allocate a raster buffer
9918 of width x height 32-bit values. */
9919 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9920 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9921 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9923 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9927 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9933 /* Create the X image and pixmap. */
9934 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9941 /* Initialize the color table. */
9942 init_color_table ();
9944 /* Process the pixel raster. Origin is in the lower-left corner. */
9945 for (y
= 0; y
< height
; ++y
)
9947 uint32
*row
= buf
+ y
* width
;
9949 for (x
= 0; x
< width
; ++x
)
9951 uint32 abgr
= row
[x
];
9952 int r
= TIFFGetR (abgr
) << 8;
9953 int g
= TIFFGetG (abgr
) << 8;
9954 int b
= TIFFGetB (abgr
) << 8;
9955 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9959 /* Remember the colors allocated for the image. Free the color table. */
9960 img
->colors
= colors_in_color_table (&img
->ncolors
);
9961 free_color_table ();
9964 img
->height
= height
;
9966 /* Maybe fill in the background field while we have ximg handy. */
9967 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9968 IMAGE_BACKGROUND (img
, f
, ximg
);
9970 /* Put the image into the pixmap, then free the X image and its buffer. */
9971 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9972 x_destroy_x_image (ximg
);
9979 #endif /* HAVE_TIFF != 0 */
9983 /***********************************************************************
9985 ***********************************************************************/
9989 #include <gif_lib.h>
9991 static int gif_image_p
P_ ((Lisp_Object object
));
9992 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9994 /* The symbol `gif' identifying images of this type. */
9998 /* Indices of image specification fields in gif_format, below. */
10000 enum gif_keyword_index
10009 GIF_HEURISTIC_MASK
,
10016 /* Vector of image_keyword structures describing the format
10017 of valid user-defined image specifications. */
10019 static struct image_keyword gif_format
[GIF_LAST
] =
10021 {":type", IMAGE_SYMBOL_VALUE
, 1},
10022 {":data", IMAGE_STRING_VALUE
, 0},
10023 {":file", IMAGE_STRING_VALUE
, 0},
10024 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10025 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10026 {":relief", IMAGE_INTEGER_VALUE
, 0},
10027 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10028 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10029 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10030 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
10031 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10034 /* Structure describing the image type `gif'. */
10036 static struct image_type gif_type
=
10046 /* Return non-zero if OBJECT is a valid GIF image specification. */
10049 gif_image_p (object
)
10050 Lisp_Object object
;
10052 struct image_keyword fmt
[GIF_LAST
];
10053 bcopy (gif_format
, fmt
, sizeof fmt
);
10055 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
10058 /* Must specify either the :data or :file keyword. */
10059 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
10063 /* Reading a GIF image from memory
10064 Based on the PNG memory stuff to a certain extent. */
10068 unsigned char *bytes
;
10075 /* Make the current memory source available to gif_read_from_memory.
10076 It's done this way because not all versions of libungif support
10077 a UserData field in the GifFileType structure. */
10078 static gif_memory_source
*current_gif_memory_src
;
10081 gif_read_from_memory (file
, buf
, len
)
10086 gif_memory_source
*src
= current_gif_memory_src
;
10088 if (len
> src
->len
- src
->index
)
10091 bcopy (src
->bytes
+ src
->index
, buf
, len
);
10097 /* Load GIF image IMG for use on frame F. Value is non-zero if
10105 Lisp_Object file
, specified_file
;
10106 Lisp_Object specified_data
;
10107 int rc
, width
, height
, x
, y
, i
;
10109 ColorMapObject
*gif_color_map
;
10110 unsigned long pixel_colors
[256];
10112 struct gcpro gcpro1
;
10114 int ino
, image_left
, image_top
, image_width
, image_height
;
10115 gif_memory_source memsrc
;
10116 unsigned char *raster
;
10118 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10119 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10123 if (NILP (specified_data
))
10125 file
= x_find_image_file (specified_file
);
10126 if (!STRINGP (file
))
10128 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
10133 /* Open the GIF file. */
10134 gif
= DGifOpenFileName (XSTRING (file
)->data
);
10137 image_error ("Cannot open `%s'", file
, Qnil
);
10144 /* Read from memory! */
10145 current_gif_memory_src
= &memsrc
;
10146 memsrc
.bytes
= XSTRING (specified_data
)->data
;
10147 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
10150 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
10153 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
10159 /* Read entire contents. */
10160 rc
= DGifSlurp (gif
);
10161 if (rc
== GIF_ERROR
)
10163 image_error ("Error reading `%s'", img
->spec
, Qnil
);
10164 DGifCloseFile (gif
);
10169 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
10170 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
10171 if (ino
>= gif
->ImageCount
)
10173 image_error ("Invalid image number `%s' in image `%s'",
10175 DGifCloseFile (gif
);
10180 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
10181 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
10183 /* Create the X image and pixmap. */
10184 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
10186 DGifCloseFile (gif
);
10191 /* Allocate colors. */
10192 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
10193 if (!gif_color_map
)
10194 gif_color_map
= gif
->SColorMap
;
10195 init_color_table ();
10196 bzero (pixel_colors
, sizeof pixel_colors
);
10198 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
10200 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
10201 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
10202 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
10203 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
10206 img
->colors
= colors_in_color_table (&img
->ncolors
);
10207 free_color_table ();
10209 /* Clear the part of the screen image that are not covered by
10210 the image from the GIF file. Full animated GIF support
10211 requires more than can be done here (see the gif89 spec,
10212 disposal methods). Let's simply assume that the part
10213 not covered by a sub-image is in the frame's background color. */
10214 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
10215 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
10216 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
10217 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
10219 for (y
= 0; y
< image_top
; ++y
)
10220 for (x
= 0; x
< width
; ++x
)
10221 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10223 for (y
= image_top
+ image_height
; y
< height
; ++y
)
10224 for (x
= 0; x
< width
; ++x
)
10225 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10227 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
10229 for (x
= 0; x
< image_left
; ++x
)
10230 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10231 for (x
= image_left
+ image_width
; x
< width
; ++x
)
10232 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10235 /* Read the GIF image into the X image. We use a local variable
10236 `raster' here because RasterBits below is a char *, and invites
10237 problems with bytes >= 0x80. */
10238 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
10240 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
10242 static int interlace_start
[] = {0, 4, 2, 1};
10243 static int interlace_increment
[] = {8, 8, 4, 2};
10245 int row
= interlace_start
[0];
10249 for (y
= 0; y
< image_height
; y
++)
10251 if (row
>= image_height
)
10253 row
= interlace_start
[++pass
];
10254 while (row
>= image_height
)
10255 row
= interlace_start
[++pass
];
10258 for (x
= 0; x
< image_width
; x
++)
10260 int i
= raster
[(y
* image_width
) + x
];
10261 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
10265 row
+= interlace_increment
[pass
];
10270 for (y
= 0; y
< image_height
; ++y
)
10271 for (x
= 0; x
< image_width
; ++x
)
10273 int i
= raster
[y
* image_width
+ x
];
10274 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
10278 DGifCloseFile (gif
);
10280 /* Maybe fill in the background field while we have ximg handy. */
10281 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
10282 IMAGE_BACKGROUND (img
, f
, ximg
);
10284 /* Put the image into the pixmap, then free the X image and its buffer. */
10285 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10286 x_destroy_x_image (ximg
);
10292 #endif /* HAVE_GIF != 0 */
10296 /***********************************************************************
10298 ***********************************************************************/
10300 static int gs_image_p
P_ ((Lisp_Object object
));
10301 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
10302 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
10304 /* The symbol `postscript' identifying images of this type. */
10306 Lisp_Object Qpostscript
;
10308 /* Keyword symbols. */
10310 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
10312 /* Indices of image specification fields in gs_format, below. */
10314 enum gs_keyword_index
10332 /* Vector of image_keyword structures describing the format
10333 of valid user-defined image specifications. */
10335 static struct image_keyword gs_format
[GS_LAST
] =
10337 {":type", IMAGE_SYMBOL_VALUE
, 1},
10338 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10339 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10340 {":file", IMAGE_STRING_VALUE
, 1},
10341 {":loader", IMAGE_FUNCTION_VALUE
, 0},
10342 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
10343 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10344 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10345 {":relief", IMAGE_INTEGER_VALUE
, 0},
10346 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10347 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10348 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10349 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10352 /* Structure describing the image type `ghostscript'. */
10354 static struct image_type gs_type
=
10364 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10367 gs_clear_image (f
, img
)
10371 /* IMG->data.ptr_val may contain a recorded colormap. */
10372 xfree (img
->data
.ptr_val
);
10373 x_clear_image (f
, img
);
10377 /* Return non-zero if OBJECT is a valid Ghostscript image
10381 gs_image_p (object
)
10382 Lisp_Object object
;
10384 struct image_keyword fmt
[GS_LAST
];
10388 bcopy (gs_format
, fmt
, sizeof fmt
);
10390 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10393 /* Bounding box must be a list or vector containing 4 integers. */
10394 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10397 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10398 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10403 else if (VECTORP (tem
))
10405 if (XVECTOR (tem
)->size
!= 4)
10407 for (i
= 0; i
< 4; ++i
)
10408 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10418 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10427 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10428 struct gcpro gcpro1
, gcpro2
;
10430 double in_width
, in_height
;
10431 Lisp_Object pixel_colors
= Qnil
;
10433 /* Compute pixel size of pixmap needed from the given size in the
10434 image specification. Sizes in the specification are in pt. 1 pt
10435 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10437 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10438 in_width
= XFASTINT (pt_width
) / 72.0;
10439 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10440 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10441 in_height
= XFASTINT (pt_height
) / 72.0;
10442 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10444 /* Create the pixmap. */
10445 xassert (img
->pixmap
== None
);
10446 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10447 img
->width
, img
->height
,
10448 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10452 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10456 /* Call the loader to fill the pixmap. It returns a process object
10457 if successful. We do not record_unwind_protect here because
10458 other places in redisplay like calling window scroll functions
10459 don't either. Let the Lisp loader use `unwind-protect' instead. */
10460 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10462 sprintf (buffer
, "%lu %lu",
10463 (unsigned long) FRAME_X_WINDOW (f
),
10464 (unsigned long) img
->pixmap
);
10465 window_and_pixmap_id
= build_string (buffer
);
10467 sprintf (buffer
, "%lu %lu",
10468 FRAME_FOREGROUND_PIXEL (f
),
10469 FRAME_BACKGROUND_PIXEL (f
));
10470 pixel_colors
= build_string (buffer
);
10472 XSETFRAME (frame
, f
);
10473 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10475 loader
= intern ("gs-load-image");
10477 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10478 make_number (img
->width
),
10479 make_number (img
->height
),
10480 window_and_pixmap_id
,
10483 return PROCESSP (img
->data
.lisp_val
);
10487 /* Kill the Ghostscript process that was started to fill PIXMAP on
10488 frame F. Called from XTread_socket when receiving an event
10489 telling Emacs that Ghostscript has finished drawing. */
10492 x_kill_gs_process (pixmap
, f
)
10496 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10500 /* Find the image containing PIXMAP. */
10501 for (i
= 0; i
< c
->used
; ++i
)
10502 if (c
->images
[i
]->pixmap
== pixmap
)
10505 /* Should someone in between have cleared the image cache, for
10506 instance, give up. */
10510 /* Kill the GS process. We should have found PIXMAP in the image
10511 cache and its image should contain a process object. */
10512 img
= c
->images
[i
];
10513 xassert (PROCESSP (img
->data
.lisp_val
));
10514 Fkill_process (img
->data
.lisp_val
, Qnil
);
10515 img
->data
.lisp_val
= Qnil
;
10517 /* On displays with a mutable colormap, figure out the colors
10518 allocated for the image by looking at the pixels of an XImage for
10520 class = FRAME_X_VISUAL (f
)->class;
10521 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10527 /* Try to get an XImage for img->pixmep. */
10528 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10529 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10534 /* Initialize the color table. */
10535 init_color_table ();
10537 /* For each pixel of the image, look its color up in the
10538 color table. After having done so, the color table will
10539 contain an entry for each color used by the image. */
10540 for (y
= 0; y
< img
->height
; ++y
)
10541 for (x
= 0; x
< img
->width
; ++x
)
10543 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10544 lookup_pixel_color (f
, pixel
);
10547 /* Record colors in the image. Free color table and XImage. */
10548 img
->colors
= colors_in_color_table (&img
->ncolors
);
10549 free_color_table ();
10550 XDestroyImage (ximg
);
10552 #if 0 /* This doesn't seem to be the case. If we free the colors
10553 here, we get a BadAccess later in x_clear_image when
10554 freeing the colors. */
10555 /* We have allocated colors once, but Ghostscript has also
10556 allocated colors on behalf of us. So, to get the
10557 reference counts right, free them once. */
10559 x_free_colors (f
, img
->colors
, img
->ncolors
);
10563 image_error ("Cannot get X image of `%s'; colors will not be freed",
10569 /* Now that we have the pixmap, compute mask and transform the
10570 image if requested. */
10572 postprocess_image (f
, img
);
10578 /***********************************************************************
10580 ***********************************************************************/
10582 DEFUN ("x-change-window-property", Fx_change_window_property
,
10583 Sx_change_window_property
, 2, 3, 0,
10584 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
10585 PROP and VALUE must be strings. FRAME nil or omitted means use the
10586 selected frame. Value is VALUE. */)
10587 (prop
, value
, frame
)
10588 Lisp_Object frame
, prop
, value
;
10590 struct frame
*f
= check_x_frame (frame
);
10593 CHECK_STRING (prop
);
10594 CHECK_STRING (value
);
10597 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10598 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10599 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10600 XSTRING (value
)->data
, XSTRING (value
)->size
);
10602 /* Make sure the property is set when we return. */
10603 XFlush (FRAME_X_DISPLAY (f
));
10610 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10611 Sx_delete_window_property
, 1, 2, 0,
10612 doc
: /* Remove window property PROP from X window of FRAME.
10613 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10615 Lisp_Object prop
, frame
;
10617 struct frame
*f
= check_x_frame (frame
);
10620 CHECK_STRING (prop
);
10622 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10623 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10625 /* Make sure the property is removed when we return. */
10626 XFlush (FRAME_X_DISPLAY (f
));
10633 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10635 doc
: /* Value is the value of window property PROP on FRAME.
10636 If FRAME is nil or omitted, use the selected frame. Value is nil
10637 if FRAME hasn't a property with name PROP or if PROP has no string
10640 Lisp_Object prop
, frame
;
10642 struct frame
*f
= check_x_frame (frame
);
10645 Lisp_Object prop_value
= Qnil
;
10646 char *tmp_data
= NULL
;
10649 unsigned long actual_size
, bytes_remaining
;
10651 CHECK_STRING (prop
);
10653 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10654 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10655 prop_atom
, 0, 0, False
, XA_STRING
,
10656 &actual_type
, &actual_format
, &actual_size
,
10657 &bytes_remaining
, (unsigned char **) &tmp_data
);
10660 int size
= bytes_remaining
;
10665 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10666 prop_atom
, 0, bytes_remaining
,
10668 &actual_type
, &actual_format
,
10669 &actual_size
, &bytes_remaining
,
10670 (unsigned char **) &tmp_data
);
10671 if (rc
== Success
&& tmp_data
)
10672 prop_value
= make_string (tmp_data
, size
);
10683 /***********************************************************************
10685 ***********************************************************************/
10687 /* If non-null, an asynchronous timer that, when it expires, displays
10688 an hourglass cursor on all frames. */
10690 static struct atimer
*hourglass_atimer
;
10692 /* Non-zero means an hourglass cursor is currently shown. */
10694 static int hourglass_shown_p
;
10696 /* Number of seconds to wait before displaying an hourglass cursor. */
10698 static Lisp_Object Vhourglass_delay
;
10700 /* Default number of seconds to wait before displaying an hourglass
10703 #define DEFAULT_HOURGLASS_DELAY 1
10705 /* Function prototypes. */
10707 static void show_hourglass
P_ ((struct atimer
*));
10708 static void hide_hourglass
P_ ((void));
10711 /* Cancel a currently active hourglass timer, and start a new one. */
10717 int secs
, usecs
= 0;
10719 cancel_hourglass ();
10721 if (INTEGERP (Vhourglass_delay
)
10722 && XINT (Vhourglass_delay
) > 0)
10723 secs
= XFASTINT (Vhourglass_delay
);
10724 else if (FLOATP (Vhourglass_delay
)
10725 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10728 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10729 secs
= XFASTINT (tem
);
10730 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10733 secs
= DEFAULT_HOURGLASS_DELAY
;
10735 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10736 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10737 show_hourglass
, NULL
);
10741 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10745 cancel_hourglass ()
10747 if (hourglass_atimer
)
10749 cancel_atimer (hourglass_atimer
);
10750 hourglass_atimer
= NULL
;
10753 if (hourglass_shown_p
)
10758 /* Timer function of hourglass_atimer. TIMER is equal to
10761 Display an hourglass pointer on all frames by mapping the frames'
10762 hourglass_window. Set the hourglass_p flag in the frames'
10763 output_data.x structure to indicate that an hourglass cursor is
10764 shown on the frames. */
10767 show_hourglass (timer
)
10768 struct atimer
*timer
;
10770 /* The timer implementation will cancel this timer automatically
10771 after this function has run. Set hourglass_atimer to null
10772 so that we know the timer doesn't have to be canceled. */
10773 hourglass_atimer
= NULL
;
10775 if (!hourglass_shown_p
)
10777 Lisp_Object rest
, frame
;
10781 FOR_EACH_FRAME (rest
, frame
)
10783 struct frame
*f
= XFRAME (frame
);
10785 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10787 Display
*dpy
= FRAME_X_DISPLAY (f
);
10789 #ifdef USE_X_TOOLKIT
10790 if (f
->output_data
.x
->widget
)
10792 if (FRAME_OUTER_WINDOW (f
))
10795 f
->output_data
.x
->hourglass_p
= 1;
10797 if (!f
->output_data
.x
->hourglass_window
)
10799 unsigned long mask
= CWCursor
;
10800 XSetWindowAttributes attrs
;
10802 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10804 f
->output_data
.x
->hourglass_window
10805 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10806 0, 0, 32000, 32000, 0, 0,
10812 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10818 hourglass_shown_p
= 1;
10824 /* Hide the hourglass pointer on all frames, if it is currently
10830 if (hourglass_shown_p
)
10832 Lisp_Object rest
, frame
;
10835 FOR_EACH_FRAME (rest
, frame
)
10837 struct frame
*f
= XFRAME (frame
);
10840 /* Watch out for newly created frames. */
10841 && f
->output_data
.x
->hourglass_window
)
10843 XUnmapWindow (FRAME_X_DISPLAY (f
),
10844 f
->output_data
.x
->hourglass_window
);
10845 /* Sync here because XTread_socket looks at the
10846 hourglass_p flag that is reset to zero below. */
10847 XSync (FRAME_X_DISPLAY (f
), False
);
10848 f
->output_data
.x
->hourglass_p
= 0;
10852 hourglass_shown_p
= 0;
10859 /***********************************************************************
10861 ***********************************************************************/
10863 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10864 Lisp_Object
, Lisp_Object
));
10865 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10866 Lisp_Object
, int, int, int *, int *));
10868 /* The frame of a currently visible tooltip. */
10870 Lisp_Object tip_frame
;
10872 /* If non-nil, a timer started that hides the last tooltip when it
10875 Lisp_Object tip_timer
;
10878 /* If non-nil, a vector of 3 elements containing the last args
10879 with which x-show-tip was called. See there. */
10881 Lisp_Object last_show_tip_args
;
10883 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10885 Lisp_Object Vx_max_tooltip_size
;
10889 unwind_create_tip_frame (frame
)
10892 Lisp_Object deleted
;
10894 deleted
= unwind_create_frame (frame
);
10895 if (EQ (deleted
, Qt
))
10905 /* Create a frame for a tooltip on the display described by DPYINFO.
10906 PARMS is a list of frame parameters. TEXT is the string to
10907 display in the tip frame. Value is the frame.
10909 Note that functions called here, esp. x_default_parameter can
10910 signal errors, for instance when a specified color name is
10911 undefined. We have to make sure that we're in a consistent state
10912 when this happens. */
10915 x_create_tip_frame (dpyinfo
, parms
, text
)
10916 struct x_display_info
*dpyinfo
;
10917 Lisp_Object parms
, text
;
10920 Lisp_Object frame
, tem
;
10922 long window_prompting
= 0;
10924 int count
= BINDING_STACK_SIZE ();
10925 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10927 int face_change_count_before
= face_change_count
;
10928 Lisp_Object buffer
;
10929 struct buffer
*old_buffer
;
10933 /* Use this general default value to start with until we know if
10934 this frame has a specified name. */
10935 Vx_resource_name
= Vinvocation_name
;
10937 #ifdef MULTI_KBOARD
10938 kb
= dpyinfo
->kboard
;
10940 kb
= &the_only_kboard
;
10943 /* Get the name of the frame to use for resource lookup. */
10944 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10945 if (!STRINGP (name
)
10946 && !EQ (name
, Qunbound
)
10948 error ("Invalid frame name--not a string or nil");
10949 Vx_resource_name
= name
;
10952 GCPRO3 (parms
, name
, frame
);
10953 f
= make_frame (1);
10954 XSETFRAME (frame
, f
);
10956 buffer
= Fget_buffer_create (build_string (" *tip*"));
10957 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10958 old_buffer
= current_buffer
;
10959 set_buffer_internal_1 (XBUFFER (buffer
));
10960 current_buffer
->truncate_lines
= Qnil
;
10962 Finsert (1, &text
);
10963 set_buffer_internal_1 (old_buffer
);
10965 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10966 record_unwind_protect (unwind_create_tip_frame
, frame
);
10968 /* By setting the output method, we're essentially saying that
10969 the frame is live, as per FRAME_LIVE_P. If we get a signal
10970 from this point on, x_destroy_window might screw up reference
10972 f
->output_method
= output_x_window
;
10973 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10974 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10975 f
->output_data
.x
->icon_bitmap
= -1;
10976 f
->output_data
.x
->fontset
= -1;
10977 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10978 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10979 #ifdef USE_TOOLKIT_SCROLL_BARS
10980 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
10981 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
10982 #endif /* USE_TOOLKIT_SCROLL_BARS */
10983 f
->icon_name
= Qnil
;
10984 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10986 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
10987 dpyinfo_refcount
= dpyinfo
->reference_count
;
10988 #endif /* GLYPH_DEBUG */
10989 #ifdef MULTI_KBOARD
10990 FRAME_KBOARD (f
) = kb
;
10992 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10993 f
->output_data
.x
->explicit_parent
= 0;
10995 /* These colors will be set anyway later, but it's important
10996 to get the color reference counts right, so initialize them! */
10999 struct gcpro gcpro1
;
11001 black
= build_string ("black");
11003 f
->output_data
.x
->foreground_pixel
11004 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11005 f
->output_data
.x
->background_pixel
11006 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11007 f
->output_data
.x
->cursor_pixel
11008 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11009 f
->output_data
.x
->cursor_foreground_pixel
11010 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11011 f
->output_data
.x
->border_pixel
11012 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11013 f
->output_data
.x
->mouse_pixel
11014 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11018 /* Set the name; the functions to which we pass f expect the name to
11020 if (EQ (name
, Qunbound
) || NILP (name
))
11022 f
->name
= build_string (dpyinfo
->x_id_name
);
11023 f
->explicit_name
= 0;
11028 f
->explicit_name
= 1;
11029 /* use the frame's title when getting resources for this frame. */
11030 specbind (Qx_resource_name
, name
);
11033 /* Extract the window parameters from the supplied values that are
11034 needed to determine window geometry. */
11038 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
11041 /* First, try whatever font the caller has specified. */
11042 if (STRINGP (font
))
11044 tem
= Fquery_fontset (font
, Qnil
);
11046 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
11048 font
= x_new_font (f
, XSTRING (font
)->data
);
11051 /* Try out a font which we hope has bold and italic variations. */
11052 if (!STRINGP (font
))
11053 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
11054 if (!STRINGP (font
))
11055 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11056 if (! STRINGP (font
))
11057 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11058 if (! STRINGP (font
))
11059 /* This was formerly the first thing tried, but it finds too many fonts
11060 and takes too long. */
11061 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
11062 /* If those didn't work, look for something which will at least work. */
11063 if (! STRINGP (font
))
11064 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
11066 if (! STRINGP (font
))
11067 font
= build_string ("fixed");
11069 x_default_parameter (f
, parms
, Qfont
, font
,
11070 "font", "Font", RES_TYPE_STRING
);
11073 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
11074 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
11076 /* This defaults to 2 in order to match xterm. We recognize either
11077 internalBorderWidth or internalBorder (which is what xterm calls
11079 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11083 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
11084 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
11085 if (! EQ (value
, Qunbound
))
11086 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
11090 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
11091 "internalBorderWidth", "internalBorderWidth",
11094 /* Also do the stuff which must be set before the window exists. */
11095 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
11096 "foreground", "Foreground", RES_TYPE_STRING
);
11097 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
11098 "background", "Background", RES_TYPE_STRING
);
11099 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
11100 "pointerColor", "Foreground", RES_TYPE_STRING
);
11101 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
11102 "cursorColor", "Foreground", RES_TYPE_STRING
);
11103 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
11104 "borderColor", "BorderColor", RES_TYPE_STRING
);
11106 /* Init faces before x_default_parameter is called for scroll-bar
11107 parameters because that function calls x_set_scroll_bar_width,
11108 which calls change_frame_size, which calls Fset_window_buffer,
11109 which runs hooks, which call Fvertical_motion. At the end, we
11110 end up in init_iterator with a null face cache, which should not
11112 init_frame_faces (f
);
11114 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
11115 window_prompting
= x_figure_window_size (f
, parms
);
11117 if (window_prompting
& XNegative
)
11119 if (window_prompting
& YNegative
)
11120 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
11122 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
11126 if (window_prompting
& YNegative
)
11127 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
11129 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11132 f
->output_data
.x
->size_hint_flags
= window_prompting
;
11134 XSetWindowAttributes attrs
;
11135 unsigned long mask
;
11138 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
11139 if (DoesSaveUnders (dpyinfo
->screen
))
11140 mask
|= CWSaveUnder
;
11142 /* Window managers look at the override-redirect flag to determine
11143 whether or net to give windows a decoration (Xlib spec, chapter
11145 attrs
.override_redirect
= True
;
11146 attrs
.save_under
= True
;
11147 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
11148 /* Arrange for getting MapNotify and UnmapNotify events. */
11149 attrs
.event_mask
= StructureNotifyMask
;
11151 = FRAME_X_WINDOW (f
)
11152 = XCreateWindow (FRAME_X_DISPLAY (f
),
11153 FRAME_X_DISPLAY_INFO (f
)->root_window
,
11154 /* x, y, width, height */
11158 CopyFromParent
, InputOutput
, CopyFromParent
,
11165 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
11166 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11167 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
11168 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11169 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
11170 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
11172 /* Dimensions, especially f->height, must be done via change_frame_size.
11173 Change will not be effected unless different from the current
11176 height
= f
->height
;
11178 SET_FRAME_WIDTH (f
, 0);
11179 change_frame_size (f
, height
, width
, 1, 0, 0);
11181 /* Set up faces after all frame parameters are known. This call
11182 also merges in face attributes specified for new frames.
11184 Frame parameters may be changed if .Xdefaults contains
11185 specifications for the default font. For example, if there is an
11186 `Emacs.default.attributeBackground: pink', the `background-color'
11187 attribute of the frame get's set, which let's the internal border
11188 of the tooltip frame appear in pink. Prevent this. */
11190 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
11192 /* Set tip_frame here, so that */
11194 call1 (Qface_set_after_frame_default
, frame
);
11196 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
11197 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
11205 /* It is now ok to make the frame official even if we get an error
11206 below. And the frame needs to be on Vframe_list or making it
11207 visible won't work. */
11208 Vframe_list
= Fcons (frame
, Vframe_list
);
11210 /* Now that the frame is official, it counts as a reference to
11212 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
11214 /* Setting attributes of faces of the tooltip frame from resources
11215 and similar will increment face_change_count, which leads to the
11216 clearing of all current matrices. Since this isn't necessary
11217 here, avoid it by resetting face_change_count to the value it
11218 had before we created the tip frame. */
11219 face_change_count
= face_change_count_before
;
11221 /* Discard the unwind_protect. */
11222 return unbind_to (count
, frame
);
11226 /* Compute where to display tip frame F. PARMS is the list of frame
11227 parameters for F. DX and DY are specified offsets from the current
11228 location of the mouse. WIDTH and HEIGHT are the width and height
11229 of the tooltip. Return coordinates relative to the root window of
11230 the display in *ROOT_X, and *ROOT_Y. */
11233 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
11235 Lisp_Object parms
, dx
, dy
;
11237 int *root_x
, *root_y
;
11239 Lisp_Object left
, top
;
11241 Window root
, child
;
11244 /* User-specified position? */
11245 left
= Fcdr (Fassq (Qleft
, parms
));
11246 top
= Fcdr (Fassq (Qtop
, parms
));
11248 /* Move the tooltip window where the mouse pointer is. Resize and
11250 if (!INTEGERP (left
) || !INTEGERP (top
))
11253 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
11254 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
11258 if (INTEGERP (top
))
11259 *root_y
= XINT (top
);
11260 else if (*root_y
+ XINT (dy
) - height
< 0)
11261 *root_y
-= XINT (dy
);
11265 *root_y
+= XINT (dy
);
11268 if (INTEGERP (left
))
11269 *root_x
= XINT (left
);
11270 else if (*root_x
+ XINT (dx
) + width
<= FRAME_X_DISPLAY_INFO (f
)->width
)
11271 /* It fits to the right of the pointer. */
11272 *root_x
+= XINT (dx
);
11273 else if (width
+ XINT (dx
) <= *root_x
)
11274 /* It fits to the left of the pointer. */
11275 *root_x
-= width
+ XINT (dx
);
11277 /* Put it left-justified on the screen--it ought to fit that way. */
11282 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
11283 doc
: /* Show STRING in a "tooltip" window on frame FRAME.
11284 A tooltip window is a small X window displaying a string.
11286 FRAME nil or omitted means use the selected frame.
11288 PARMS is an optional list of frame parameters which can be used to
11289 change the tooltip's appearance.
11291 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11292 means use the default timeout of 5 seconds.
11294 If the list of frame parameters PARAMS contains a `left' parameters,
11295 the tooltip is displayed at that x-position. Otherwise it is
11296 displayed at the mouse position, with offset DX added (default is 5 if
11297 DX isn't specified). Likewise for the y-position; if a `top' frame
11298 parameter is specified, it determines the y-position of the tooltip
11299 window, otherwise it is displayed at the mouse position, with offset
11300 DY added (default is -10).
11302 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11303 Text larger than the specified size is clipped. */)
11304 (string
, frame
, parms
, timeout
, dx
, dy
)
11305 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
11309 int root_x
, root_y
;
11310 struct buffer
*old_buffer
;
11311 struct text_pos pos
;
11312 int i
, width
, height
;
11313 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
11314 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
11315 int count
= BINDING_STACK_SIZE ();
11317 specbind (Qinhibit_redisplay
, Qt
);
11319 GCPRO4 (string
, parms
, frame
, timeout
);
11321 CHECK_STRING (string
);
11322 f
= check_x_frame (frame
);
11323 if (NILP (timeout
))
11324 timeout
= make_number (5);
11326 CHECK_NATNUM (timeout
);
11329 dx
= make_number (5);
11334 dy
= make_number (-10);
11338 if (NILP (last_show_tip_args
))
11339 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
11341 if (!NILP (tip_frame
))
11343 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
11344 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
11345 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
11347 if (EQ (frame
, last_frame
)
11348 && !NILP (Fequal (last_string
, string
))
11349 && !NILP (Fequal (last_parms
, parms
)))
11351 struct frame
*f
= XFRAME (tip_frame
);
11353 /* Only DX and DY have changed. */
11354 if (!NILP (tip_timer
))
11356 Lisp_Object timer
= tip_timer
;
11358 call1 (Qcancel_timer
, timer
);
11362 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
11363 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
11364 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11371 /* Hide a previous tip, if any. */
11374 ASET (last_show_tip_args
, 0, string
);
11375 ASET (last_show_tip_args
, 1, frame
);
11376 ASET (last_show_tip_args
, 2, parms
);
11378 /* Add default values to frame parameters. */
11379 if (NILP (Fassq (Qname
, parms
)))
11380 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
11381 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11382 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
11383 if (NILP (Fassq (Qborder_width
, parms
)))
11384 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
11385 if (NILP (Fassq (Qborder_color
, parms
)))
11386 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
11387 if (NILP (Fassq (Qbackground_color
, parms
)))
11388 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
11391 /* Create a frame for the tooltip, and record it in the global
11392 variable tip_frame. */
11393 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
11394 f
= XFRAME (frame
);
11396 /* Set up the frame's root window. */
11397 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
11398 w
->left
= w
->top
= make_number (0);
11400 if (CONSP (Vx_max_tooltip_size
)
11401 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11402 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11403 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11404 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11406 w
->width
= XCAR (Vx_max_tooltip_size
);
11407 w
->height
= XCDR (Vx_max_tooltip_size
);
11411 w
->width
= make_number (80);
11412 w
->height
= make_number (40);
11415 f
->window_width
= XINT (w
->width
);
11417 w
->pseudo_window_p
= 1;
11419 /* Display the tooltip text in a temporary buffer. */
11420 old_buffer
= current_buffer
;
11421 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11422 current_buffer
->truncate_lines
= Qnil
;
11423 clear_glyph_matrix (w
->desired_matrix
);
11424 clear_glyph_matrix (w
->current_matrix
);
11425 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11426 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11428 /* Compute width and height of the tooltip. */
11429 width
= height
= 0;
11430 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11432 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11433 struct glyph
*last
;
11436 /* Stop at the first empty row at the end. */
11437 if (!row
->enabled_p
|| !row
->displays_text_p
)
11440 /* Let the row go over the full width of the frame. */
11441 row
->full_width_p
= 1;
11443 /* There's a glyph at the end of rows that is used to place
11444 the cursor there. Don't include the width of this glyph. */
11445 if (row
->used
[TEXT_AREA
])
11447 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11448 row_width
= row
->pixel_width
- last
->pixel_width
;
11451 row_width
= row
->pixel_width
;
11453 height
+= row
->height
;
11454 width
= max (width
, row_width
);
11457 /* Add the frame's internal border to the width and height the X
11458 window should have. */
11459 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11460 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11462 /* Move the tooltip window where the mouse pointer is. Resize and
11464 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11467 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11468 root_x
, root_y
, width
, height
);
11469 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11472 /* Draw into the window. */
11473 w
->must_be_updated_p
= 1;
11474 update_single_window (w
, 1);
11476 /* Restore original current buffer. */
11477 set_buffer_internal_1 (old_buffer
);
11478 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11481 /* Let the tip disappear after timeout seconds. */
11482 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11483 intern ("x-hide-tip"));
11486 return unbind_to (count
, Qnil
);
11490 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11491 doc
: /* Hide the current tooltip window, if there is any.
11492 Value is t if tooltip was open, nil otherwise. */)
11496 Lisp_Object deleted
, frame
, timer
;
11497 struct gcpro gcpro1
, gcpro2
;
11499 /* Return quickly if nothing to do. */
11500 if (NILP (tip_timer
) && NILP (tip_frame
))
11505 GCPRO2 (frame
, timer
);
11506 tip_frame
= tip_timer
= deleted
= Qnil
;
11508 count
= BINDING_STACK_SIZE ();
11509 specbind (Qinhibit_redisplay
, Qt
);
11510 specbind (Qinhibit_quit
, Qt
);
11513 call1 (Qcancel_timer
, timer
);
11515 if (FRAMEP (frame
))
11517 Fdelete_frame (frame
, Qnil
);
11521 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11522 redisplay procedure is not called when a tip frame over menu
11523 items is unmapped. Redisplay the menu manually... */
11525 struct frame
*f
= SELECTED_FRAME ();
11526 Widget w
= f
->output_data
.x
->menubar_widget
;
11527 extern void xlwmenu_redisplay
P_ ((Widget
));
11529 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11533 xlwmenu_redisplay (w
);
11537 #endif /* USE_LUCID */
11541 return unbind_to (count
, deleted
);
11546 /***********************************************************************
11547 File selection dialog
11548 ***********************************************************************/
11552 /* Callback for "OK" and "Cancel" on file selection dialog. */
11555 file_dialog_cb (widget
, client_data
, call_data
)
11557 XtPointer call_data
, client_data
;
11559 int *result
= (int *) client_data
;
11560 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11561 *result
= cb
->reason
;
11565 /* Callback for unmapping a file selection dialog. This is used to
11566 capture the case where a dialog is closed via a window manager's
11567 closer button, for example. Using a XmNdestroyCallback didn't work
11571 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11573 XtPointer call_data
, client_data
;
11575 int *result
= (int *) client_data
;
11576 *result
= XmCR_CANCEL
;
11580 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11581 doc
: /* Read file name, prompting with PROMPT in directory DIR.
11582 Use a file selection dialog.
11583 Select DEFAULT-FILENAME in the dialog's file selection box, if
11584 specified. Don't let the user enter a file name in the file
11585 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11586 (prompt
, dir
, default_filename
, mustmatch
)
11587 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11590 struct frame
*f
= SELECTED_FRAME ();
11591 Lisp_Object file
= Qnil
;
11592 Widget dialog
, text
, list
, help
;
11595 extern XtAppContext Xt_app_con
;
11596 XmString dir_xmstring
, pattern_xmstring
;
11597 int count
= specpdl_ptr
- specpdl
;
11598 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11600 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11601 CHECK_STRING (prompt
);
11602 CHECK_STRING (dir
);
11604 /* Prevent redisplay. */
11605 specbind (Qinhibit_redisplay
, Qt
);
11609 /* Create the dialog with PROMPT as title, using DIR as initial
11610 directory and using "*" as pattern. */
11611 dir
= Fexpand_file_name (dir
, Qnil
);
11612 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
11613 pattern_xmstring
= XmStringCreateLocalized ("*");
11615 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
11616 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11617 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11618 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11619 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11620 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11622 XmStringFree (dir_xmstring
);
11623 XmStringFree (pattern_xmstring
);
11625 /* Add callbacks for OK and Cancel. */
11626 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11627 (XtPointer
) &result
);
11628 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11629 (XtPointer
) &result
);
11630 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11631 (XtPointer
) &result
);
11633 /* Disable the help button since we can't display help. */
11634 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11635 XtSetSensitive (help
, False
);
11637 /* Mark OK button as default. */
11638 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11639 XmNshowAsDefault
, True
, NULL
);
11641 /* If MUSTMATCH is non-nil, disable the file entry field of the
11642 dialog, so that the user must select a file from the files list
11643 box. We can't remove it because we wouldn't have a way to get at
11644 the result file name, then. */
11645 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11646 if (!NILP (mustmatch
))
11649 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11650 XtSetSensitive (text
, False
);
11651 XtSetSensitive (label
, False
);
11654 /* Manage the dialog, so that list boxes get filled. */
11655 XtManageChild (dialog
);
11657 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11658 must include the path for this to work. */
11659 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11660 if (STRINGP (default_filename
))
11662 XmString default_xmstring
;
11666 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
11668 if (!XmListItemExists (list
, default_xmstring
))
11670 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11671 XmListAddItem (list
, default_xmstring
, 0);
11675 item_pos
= XmListItemPos (list
, default_xmstring
);
11676 XmStringFree (default_xmstring
);
11678 /* Select the item and scroll it into view. */
11679 XmListSelectPos (list
, item_pos
, True
);
11680 XmListSetPos (list
, item_pos
);
11683 /* Process events until the user presses Cancel or OK. Block
11684 and unblock input here so that we get a chance of processing
11688 while (result
== 0)
11691 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11696 /* Get the result. */
11697 if (result
== XmCR_OK
)
11702 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11703 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11704 XmStringFree (text
);
11705 file
= build_string (data
);
11712 XtUnmanageChild (dialog
);
11713 XtDestroyWidget (dialog
);
11717 /* Make "Cancel" equivalent to C-g. */
11719 Fsignal (Qquit
, Qnil
);
11721 return unbind_to (count
, file
);
11724 #endif /* USE_MOTIF */
11728 /***********************************************************************
11730 ***********************************************************************/
11732 #ifdef HAVE_XKBGETKEYBOARD
11733 #include <X11/XKBlib.h>
11734 #include <X11/keysym.h>
11737 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11738 Sx_backspace_delete_keys_p
, 0, 1, 0,
11739 doc
: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11740 FRAME nil means use the selected frame.
11741 Value is t if we know that both keys are present, and are mapped to the
11742 usual X keysyms. */)
11746 #ifdef HAVE_XKBGETKEYBOARD
11748 struct frame
*f
= check_x_frame (frame
);
11749 Display
*dpy
= FRAME_X_DISPLAY (f
);
11750 Lisp_Object have_keys
;
11751 int major
, minor
, op
, event
, error
;
11755 /* Check library version in case we're dynamically linked. */
11756 major
= XkbMajorVersion
;
11757 minor
= XkbMinorVersion
;
11758 if (!XkbLibraryVersion (&major
, &minor
))
11764 /* Check that the server supports XKB. */
11765 major
= XkbMajorVersion
;
11766 minor
= XkbMinorVersion
;
11767 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11774 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11777 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11779 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11781 for (i
= kb
->min_key_code
;
11782 (i
< kb
->max_key_code
11783 && (delete_keycode
== 0 || backspace_keycode
== 0));
11786 /* The XKB symbolic key names can be seen most easily in
11787 the PS file generated by `xkbprint -label name
11789 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11790 delete_keycode
= i
;
11791 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11792 backspace_keycode
= i
;
11795 XkbFreeNames (kb
, 0, True
);
11798 XkbFreeClientMap (kb
, 0, True
);
11801 && backspace_keycode
11802 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11803 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11808 #else /* not HAVE_XKBGETKEYBOARD */
11810 #endif /* not HAVE_XKBGETKEYBOARD */
11815 /***********************************************************************
11817 ***********************************************************************/
11822 /* This is zero if not using X windows. */
11825 /* The section below is built by the lisp expression at the top of the file,
11826 just above where these variables are declared. */
11827 /*&&& init symbols here &&&*/
11828 Qauto_raise
= intern ("auto-raise");
11829 staticpro (&Qauto_raise
);
11830 Qauto_lower
= intern ("auto-lower");
11831 staticpro (&Qauto_lower
);
11832 Qbar
= intern ("bar");
11834 Qborder_color
= intern ("border-color");
11835 staticpro (&Qborder_color
);
11836 Qborder_width
= intern ("border-width");
11837 staticpro (&Qborder_width
);
11838 Qbox
= intern ("box");
11840 Qcursor_color
= intern ("cursor-color");
11841 staticpro (&Qcursor_color
);
11842 Qcursor_type
= intern ("cursor-type");
11843 staticpro (&Qcursor_type
);
11844 Qgeometry
= intern ("geometry");
11845 staticpro (&Qgeometry
);
11846 Qicon_left
= intern ("icon-left");
11847 staticpro (&Qicon_left
);
11848 Qicon_top
= intern ("icon-top");
11849 staticpro (&Qicon_top
);
11850 Qicon_type
= intern ("icon-type");
11851 staticpro (&Qicon_type
);
11852 Qicon_name
= intern ("icon-name");
11853 staticpro (&Qicon_name
);
11854 Qinternal_border_width
= intern ("internal-border-width");
11855 staticpro (&Qinternal_border_width
);
11856 Qleft
= intern ("left");
11857 staticpro (&Qleft
);
11858 Qright
= intern ("right");
11859 staticpro (&Qright
);
11860 Qmouse_color
= intern ("mouse-color");
11861 staticpro (&Qmouse_color
);
11862 Qnone
= intern ("none");
11863 staticpro (&Qnone
);
11864 Qparent_id
= intern ("parent-id");
11865 staticpro (&Qparent_id
);
11866 Qscroll_bar_width
= intern ("scroll-bar-width");
11867 staticpro (&Qscroll_bar_width
);
11868 Qsuppress_icon
= intern ("suppress-icon");
11869 staticpro (&Qsuppress_icon
);
11870 Qundefined_color
= intern ("undefined-color");
11871 staticpro (&Qundefined_color
);
11872 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11873 staticpro (&Qvertical_scroll_bars
);
11874 Qvisibility
= intern ("visibility");
11875 staticpro (&Qvisibility
);
11876 Qwindow_id
= intern ("window-id");
11877 staticpro (&Qwindow_id
);
11878 Qouter_window_id
= intern ("outer-window-id");
11879 staticpro (&Qouter_window_id
);
11880 Qx_frame_parameter
= intern ("x-frame-parameter");
11881 staticpro (&Qx_frame_parameter
);
11882 Qx_resource_name
= intern ("x-resource-name");
11883 staticpro (&Qx_resource_name
);
11884 Quser_position
= intern ("user-position");
11885 staticpro (&Quser_position
);
11886 Quser_size
= intern ("user-size");
11887 staticpro (&Quser_size
);
11888 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11889 staticpro (&Qscroll_bar_foreground
);
11890 Qscroll_bar_background
= intern ("scroll-bar-background");
11891 staticpro (&Qscroll_bar_background
);
11892 Qscreen_gamma
= intern ("screen-gamma");
11893 staticpro (&Qscreen_gamma
);
11894 Qline_spacing
= intern ("line-spacing");
11895 staticpro (&Qline_spacing
);
11896 Qcenter
= intern ("center");
11897 staticpro (&Qcenter
);
11898 Qcompound_text
= intern ("compound-text");
11899 staticpro (&Qcompound_text
);
11900 Qcancel_timer
= intern ("cancel-timer");
11901 staticpro (&Qcancel_timer
);
11902 Qwait_for_wm
= intern ("wait-for-wm");
11903 staticpro (&Qwait_for_wm
);
11904 Qfullscreen
= intern ("fullscreen");
11905 staticpro (&Qfullscreen
);
11906 Qfullwidth
= intern ("fullwidth");
11907 staticpro (&Qfullwidth
);
11908 Qfullheight
= intern ("fullheight");
11909 staticpro (&Qfullheight
);
11910 Qfullboth
= intern ("fullboth");
11911 staticpro (&Qfullboth
);
11912 /* This is the end of symbol initialization. */
11914 /* Text property `display' should be nonsticky by default. */
11915 Vtext_property_default_nonsticky
11916 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11919 Qlaplace
= intern ("laplace");
11920 staticpro (&Qlaplace
);
11921 Qemboss
= intern ("emboss");
11922 staticpro (&Qemboss
);
11923 Qedge_detection
= intern ("edge-detection");
11924 staticpro (&Qedge_detection
);
11925 Qheuristic
= intern ("heuristic");
11926 staticpro (&Qheuristic
);
11927 QCmatrix
= intern (":matrix");
11928 staticpro (&QCmatrix
);
11929 QCcolor_adjustment
= intern (":color-adjustment");
11930 staticpro (&QCcolor_adjustment
);
11931 QCmask
= intern (":mask");
11932 staticpro (&QCmask
);
11934 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11935 staticpro (&Qface_set_after_frame_default
);
11937 Fput (Qundefined_color
, Qerror_conditions
,
11938 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11939 Fput (Qundefined_color
, Qerror_message
,
11940 build_string ("Undefined color"));
11942 init_x_parm_symbols ();
11944 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11945 doc
: /* Non-nil means always draw a cross over disabled images.
11946 Disabled images are those having an `:conversion disabled' property.
11947 A cross is always drawn on black & white displays. */);
11948 cross_disabled_images
= 0;
11950 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11951 doc
: /* List of directories to search for bitmap files for X. */);
11952 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11954 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11955 doc
: /* The shape of the pointer when over text.
11956 Changing the value does not affect existing frames
11957 unless you set the mouse color. */);
11958 Vx_pointer_shape
= Qnil
;
11960 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11961 doc
: /* The name Emacs uses to look up X resources.
11962 `x-get-resource' uses this as the first component of the instance name
11963 when requesting resource values.
11964 Emacs initially sets `x-resource-name' to the name under which Emacs
11965 was invoked, or to the value specified with the `-name' or `-rn'
11966 switches, if present.
11968 It may be useful to bind this variable locally around a call
11969 to `x-get-resource'. See also the variable `x-resource-class'. */);
11970 Vx_resource_name
= Qnil
;
11972 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11973 doc
: /* The class Emacs uses to look up X resources.
11974 `x-get-resource' uses this as the first component of the instance class
11975 when requesting resource values.
11977 Emacs initially sets `x-resource-class' to "Emacs".
11979 Setting this variable permanently is not a reasonable thing to do,
11980 but binding this variable locally around a call to `x-get-resource'
11981 is a reasonable practice. See also the variable `x-resource-name'. */);
11982 Vx_resource_class
= build_string (EMACS_CLASS
);
11984 #if 0 /* This doesn't really do anything. */
11985 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11986 doc
: /* The shape of the pointer when not over text.
11987 This variable takes effect when you create a new frame
11988 or when you set the mouse color. */);
11990 Vx_nontext_pointer_shape
= Qnil
;
11992 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
11993 doc
: /* The shape of the pointer when Emacs is busy.
11994 This variable takes effect when you create a new frame
11995 or when you set the mouse color. */);
11996 Vx_hourglass_pointer_shape
= Qnil
;
11998 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
11999 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
12000 display_hourglass_p
= 1;
12002 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
12003 doc
: /* *Seconds to wait before displaying an hourglass pointer.
12004 Value must be an integer or float. */);
12005 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
12007 #if 0 /* This doesn't really do anything. */
12008 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
12009 doc
: /* The shape of the pointer when over the mode line.
12010 This variable takes effect when you create a new frame
12011 or when you set the mouse color. */);
12013 Vx_mode_pointer_shape
= Qnil
;
12015 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
12016 &Vx_sensitive_text_pointer_shape
,
12017 doc
: /* The shape of the pointer when over mouse-sensitive text.
12018 This variable takes effect when you create a new frame
12019 or when you set the mouse color. */);
12020 Vx_sensitive_text_pointer_shape
= Qnil
;
12022 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
12023 &Vx_window_horizontal_drag_shape
,
12024 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
12025 This variable takes effect when you create a new frame
12026 or when you set the mouse color. */);
12027 Vx_window_horizontal_drag_shape
= Qnil
;
12029 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
12030 doc
: /* A string indicating the foreground color of the cursor box. */);
12031 Vx_cursor_fore_pixel
= Qnil
;
12033 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
12034 doc
: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
12035 Text larger than this is clipped. */);
12036 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
12038 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
12039 doc
: /* Non-nil if no X window manager is in use.
12040 Emacs doesn't try to figure this out; this is always nil
12041 unless you set it to something else. */);
12042 /* We don't have any way to find this out, so set it to nil
12043 and maybe the user would like to set it to t. */
12044 Vx_no_window_manager
= Qnil
;
12046 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
12047 &Vx_pixel_size_width_font_regexp
,
12048 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
12050 Since Emacs gets width of a font matching with this regexp from
12051 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12052 such a font. This is especially effective for such large fonts as
12053 Chinese, Japanese, and Korean. */);
12054 Vx_pixel_size_width_font_regexp
= Qnil
;
12056 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
12057 doc
: /* Time after which cached images are removed from the cache.
12058 When an image has not been displayed this many seconds, remove it
12059 from the image cache. Value must be an integer or nil with nil
12060 meaning don't clear the cache. */);
12061 Vimage_cache_eviction_delay
= make_number (30 * 60);
12063 #ifdef USE_X_TOOLKIT
12064 Fprovide (intern ("x-toolkit"), Qnil
);
12066 Fprovide (intern ("motif"), Qnil
);
12068 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
12069 doc
: /* Version info for LessTif/Motif. */);
12070 Vmotif_version_string
= build_string (XmVERSION_STRING
);
12071 #endif /* USE_MOTIF */
12072 #endif /* USE_X_TOOLKIT */
12074 defsubr (&Sx_get_resource
);
12076 /* X window properties. */
12077 defsubr (&Sx_change_window_property
);
12078 defsubr (&Sx_delete_window_property
);
12079 defsubr (&Sx_window_property
);
12081 defsubr (&Sxw_display_color_p
);
12082 defsubr (&Sx_display_grayscale_p
);
12083 defsubr (&Sxw_color_defined_p
);
12084 defsubr (&Sxw_color_values
);
12085 defsubr (&Sx_server_max_request_size
);
12086 defsubr (&Sx_server_vendor
);
12087 defsubr (&Sx_server_version
);
12088 defsubr (&Sx_display_pixel_width
);
12089 defsubr (&Sx_display_pixel_height
);
12090 defsubr (&Sx_display_mm_width
);
12091 defsubr (&Sx_display_mm_height
);
12092 defsubr (&Sx_display_screens
);
12093 defsubr (&Sx_display_planes
);
12094 defsubr (&Sx_display_color_cells
);
12095 defsubr (&Sx_display_visual_class
);
12096 defsubr (&Sx_display_backing_store
);
12097 defsubr (&Sx_display_save_under
);
12098 defsubr (&Sx_parse_geometry
);
12099 defsubr (&Sx_create_frame
);
12100 defsubr (&Sx_open_connection
);
12101 defsubr (&Sx_close_connection
);
12102 defsubr (&Sx_display_list
);
12103 defsubr (&Sx_synchronize
);
12104 defsubr (&Sx_focus_frame
);
12105 defsubr (&Sx_backspace_delete_keys_p
);
12107 /* Setting callback functions for fontset handler. */
12108 get_font_info_func
= x_get_font_info
;
12110 #if 0 /* This function pointer doesn't seem to be used anywhere.
12111 And the pointer assigned has the wrong type, anyway. */
12112 list_fonts_func
= x_list_fonts
;
12115 load_font_func
= x_load_font
;
12116 find_ccl_program_func
= x_find_ccl_program
;
12117 query_font_func
= x_query_font
;
12118 set_frame_fontset_func
= x_set_font
;
12119 check_window_system_func
= check_x
;
12122 Qxbm
= intern ("xbm");
12124 QCconversion
= intern (":conversion");
12125 staticpro (&QCconversion
);
12126 QCheuristic_mask
= intern (":heuristic-mask");
12127 staticpro (&QCheuristic_mask
);
12128 QCcolor_symbols
= intern (":color-symbols");
12129 staticpro (&QCcolor_symbols
);
12130 QCascent
= intern (":ascent");
12131 staticpro (&QCascent
);
12132 QCmargin
= intern (":margin");
12133 staticpro (&QCmargin
);
12134 QCrelief
= intern (":relief");
12135 staticpro (&QCrelief
);
12136 Qpostscript
= intern ("postscript");
12137 staticpro (&Qpostscript
);
12138 QCloader
= intern (":loader");
12139 staticpro (&QCloader
);
12140 QCbounding_box
= intern (":bounding-box");
12141 staticpro (&QCbounding_box
);
12142 QCpt_width
= intern (":pt-width");
12143 staticpro (&QCpt_width
);
12144 QCpt_height
= intern (":pt-height");
12145 staticpro (&QCpt_height
);
12146 QCindex
= intern (":index");
12147 staticpro (&QCindex
);
12148 Qpbm
= intern ("pbm");
12152 Qxpm
= intern ("xpm");
12157 Qjpeg
= intern ("jpeg");
12158 staticpro (&Qjpeg
);
12162 Qtiff
= intern ("tiff");
12163 staticpro (&Qtiff
);
12167 Qgif
= intern ("gif");
12172 Qpng
= intern ("png");
12176 defsubr (&Sclear_image_cache
);
12177 defsubr (&Simage_size
);
12178 defsubr (&Simage_mask_p
);
12180 hourglass_atimer
= NULL
;
12181 hourglass_shown_p
= 0;
12183 defsubr (&Sx_show_tip
);
12184 defsubr (&Sx_hide_tip
);
12186 staticpro (&tip_timer
);
12188 staticpro (&tip_frame
);
12190 last_show_tip_args
= Qnil
;
12191 staticpro (&last_show_tip_args
);
12194 defsubr (&Sx_file_dialog
);
12202 image_types
= NULL
;
12203 Vimage_types
= Qnil
;
12205 define_image_type (&xbm_type
);
12206 define_image_type (&gs_type
);
12207 define_image_type (&pbm_type
);
12210 define_image_type (&xpm_type
);
12214 define_image_type (&jpeg_type
);
12218 define_image_type (&tiff_type
);
12222 define_image_type (&gif_type
);
12226 define_image_type (&png_type
);
12230 #endif /* HAVE_X_WINDOWS */