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
;
1180 XQueryTree (FRAME_X_DISPLAY (f
), win
, &rootw
,
1181 &wm_window
, &tmp_children
, &tmp_nchildren
);
1182 XFree ((char *) tmp_children
);
1184 had_errors
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1186 if (wm_window
== rootw
|| had_errors
)
1195 Window child
, rootw
;
1197 /* Get the real coordinates for the WM window upper left corner */
1198 XGetGeometry (FRAME_X_DISPLAY (f
), win
,
1199 &rootw
, &real_x
, &real_y
, &ign
, &ign
, &ign
, &ign
);
1201 /* Translate real coordinates to coordinates relative to our
1202 window. For our window, the upper left corner is 0, 0.
1203 Since the upper left corner of the WM window is outside
1204 our window, win_x and win_y will be negative:
1206 ------------------ ---> x
1208 | ----------------- v y
1211 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1213 /* From-window, to-window. */
1214 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1217 /* From-position, to-position. */
1218 real_x
, real_y
, &win_x
, &win_y
,
1223 if (FRAME_X_WINDOW (f
) == FRAME_OUTER_WINDOW (f
))
1230 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1232 /* From-window, to-window. */
1233 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1234 FRAME_OUTER_WINDOW (f
),
1236 /* From-position, to-position. */
1237 real_x
, real_y
, &outer_x
, &outer_y
,
1243 had_errors
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1246 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1250 if (had_errors
) return;
1252 f
->output_data
.x
->x_pixels_diff
= -win_x
;
1253 f
->output_data
.x
->y_pixels_diff
= -win_y
;
1254 f
->output_data
.x
->x_pixels_outer_diff
= -outer_x
;
1255 f
->output_data
.x
->y_pixels_outer_diff
= -outer_y
;
1261 /* Insert a description of internally-recorded parameters of frame X
1262 into the parameter alist *ALISTPTR that is to be given to the user.
1263 Only parameters that are specific to the X window system
1264 and whose values are not correctly recorded in the frame's
1265 param_alist need to be considered here. */
1268 x_report_frame_params (f
, alistptr
)
1270 Lisp_Object
*alistptr
;
1275 /* Represent negative positions (off the top or left screen edge)
1276 in a way that Fmodify_frame_parameters will understand correctly. */
1277 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1278 if (f
->output_data
.x
->left_pos
>= 0)
1279 store_in_alist (alistptr
, Qleft
, tem
);
1281 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1283 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1284 if (f
->output_data
.x
->top_pos
>= 0)
1285 store_in_alist (alistptr
, Qtop
, tem
);
1287 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1289 store_in_alist (alistptr
, Qborder_width
,
1290 make_number (f
->output_data
.x
->border_width
));
1291 store_in_alist (alistptr
, Qinternal_border_width
,
1292 make_number (f
->output_data
.x
->internal_border_width
));
1293 store_in_alist (alistptr
, Qleft_fringe
,
1294 make_number (f
->output_data
.x
->left_fringe_width
));
1295 store_in_alist (alistptr
, Qright_fringe
,
1296 make_number (f
->output_data
.x
->right_fringe_width
));
1297 store_in_alist (alistptr
, Qscroll_bar_width
,
1298 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
1299 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f
)
1301 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1302 store_in_alist (alistptr
, Qwindow_id
,
1303 build_string (buf
));
1304 #ifdef USE_X_TOOLKIT
1305 /* Tooltip frame may not have this widget. */
1306 if (f
->output_data
.x
->widget
)
1308 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1309 store_in_alist (alistptr
, Qouter_window_id
,
1310 build_string (buf
));
1311 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1312 FRAME_SAMPLE_VISIBILITY (f
);
1313 store_in_alist (alistptr
, Qvisibility
,
1314 (FRAME_VISIBLE_P (f
) ? Qt
1315 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1316 store_in_alist (alistptr
, Qdisplay
,
1317 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1319 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1322 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1323 store_in_alist (alistptr
, Qparent_id
, tem
);
1328 /* Gamma-correct COLOR on frame F. */
1331 gamma_correct (f
, color
)
1337 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1338 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1339 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1344 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1345 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1346 allocate the color. Value is zero if COLOR_NAME is invalid, or
1347 no color could be allocated. */
1350 x_defined_color (f
, color_name
, color
, alloc_p
)
1357 Display
*dpy
= FRAME_X_DISPLAY (f
);
1358 Colormap cmap
= FRAME_X_COLORMAP (f
);
1361 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1362 if (success_p
&& alloc_p
)
1363 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1370 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1371 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1372 Signal an error if color can't be allocated. */
1375 x_decode_color (f
, color_name
, mono_color
)
1377 Lisp_Object color_name
;
1382 CHECK_STRING (color_name
);
1384 #if 0 /* Don't do this. It's wrong when we're not using the default
1385 colormap, it makes freeing difficult, and it's probably not
1386 an important optimization. */
1387 if (strcmp (XSTRING (color_name
)->data
, "black") == 0)
1388 return BLACK_PIX_DEFAULT (f
);
1389 else if (strcmp (XSTRING (color_name
)->data
, "white") == 0)
1390 return WHITE_PIX_DEFAULT (f
);
1393 /* Return MONO_COLOR for monochrome frames. */
1394 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1397 /* x_defined_color is responsible for coping with failures
1398 by looking for a near-miss. */
1399 if (x_defined_color (f
, XSTRING (color_name
)->data
, &cdef
, 1))
1402 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1403 Fcons (color_name
, Qnil
)));
1409 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1410 the previous value of that parameter, NEW_VALUE is the new value. */
1413 x_set_line_spacing (f
, new_value
, old_value
)
1415 Lisp_Object new_value
, old_value
;
1417 if (NILP (new_value
))
1418 f
->extra_line_spacing
= 0;
1419 else if (NATNUMP (new_value
))
1420 f
->extra_line_spacing
= XFASTINT (new_value
);
1422 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1423 Fcons (new_value
, Qnil
)));
1424 if (FRAME_VISIBLE_P (f
))
1429 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1430 the previous value of that parameter, NEW_VALUE is the new value.
1431 See also the comment of wait_for_wm in struct x_output. */
1434 x_set_wait_for_wm (f
, new_value
, old_value
)
1436 Lisp_Object new_value
, old_value
;
1438 f
->output_data
.x
->wait_for_wm
= !NILP (new_value
);
1442 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
1443 the previous value of that parameter, NEW_VALUE is the new value. */
1446 x_set_fullscreen (f
, new_value
, old_value
)
1448 Lisp_Object new_value
, old_value
;
1450 if (NILP (new_value
))
1451 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_NONE
;
1452 else if (EQ (new_value
, Qfullboth
))
1453 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_BOTH
;
1454 else if (EQ (new_value
, Qfullwidth
))
1455 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_WIDTH
;
1456 else if (EQ (new_value
, Qfullheight
))
1457 f
->output_data
.x
->want_fullscreen
= FULLSCREEN_HEIGHT
;
1461 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1462 the previous value of that parameter, NEW_VALUE is the new
1466 x_set_screen_gamma (f
, new_value
, old_value
)
1468 Lisp_Object new_value
, old_value
;
1470 if (NILP (new_value
))
1472 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1473 /* The value 0.4545 is the normal viewing gamma. */
1474 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1476 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1477 Fcons (new_value
, Qnil
)));
1479 clear_face_cache (0);
1483 /* Functions called only from `x_set_frame_param'
1484 to set individual parameters.
1486 If FRAME_X_WINDOW (f) is 0,
1487 the frame is being created and its X-window does not exist yet.
1488 In that case, just record the parameter's new value
1489 in the standard place; do not attempt to change the window. */
1492 x_set_foreground_color (f
, arg
, oldval
)
1494 Lisp_Object arg
, oldval
;
1496 struct x_output
*x
= f
->output_data
.x
;
1497 unsigned long fg
, old_fg
;
1499 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1500 old_fg
= x
->foreground_pixel
;
1501 x
->foreground_pixel
= fg
;
1503 if (FRAME_X_WINDOW (f
) != 0)
1505 Display
*dpy
= FRAME_X_DISPLAY (f
);
1508 XSetForeground (dpy
, x
->normal_gc
, fg
);
1509 XSetBackground (dpy
, x
->reverse_gc
, fg
);
1511 if (x
->cursor_pixel
== old_fg
)
1513 unload_color (f
, x
->cursor_pixel
);
1514 x
->cursor_pixel
= x_copy_color (f
, fg
);
1515 XSetBackground (dpy
, x
->cursor_gc
, x
->cursor_pixel
);
1520 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1522 if (FRAME_VISIBLE_P (f
))
1526 unload_color (f
, old_fg
);
1530 x_set_background_color (f
, arg
, oldval
)
1532 Lisp_Object arg
, oldval
;
1534 struct x_output
*x
= f
->output_data
.x
;
1537 bg
= x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1538 unload_color (f
, x
->background_pixel
);
1539 x
->background_pixel
= bg
;
1541 if (FRAME_X_WINDOW (f
) != 0)
1543 Display
*dpy
= FRAME_X_DISPLAY (f
);
1546 XSetBackground (dpy
, x
->normal_gc
, bg
);
1547 XSetForeground (dpy
, x
->reverse_gc
, bg
);
1548 XSetWindowBackground (dpy
, FRAME_X_WINDOW (f
), bg
);
1549 XSetForeground (dpy
, x
->cursor_gc
, bg
);
1551 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1552 toolkit scroll bars. */
1555 for (bar
= FRAME_SCROLL_BARS (f
);
1557 bar
= XSCROLL_BAR (bar
)->next
)
1559 Window window
= SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
));
1560 XSetWindowBackground (dpy
, window
, bg
);
1563 #endif /* USE_TOOLKIT_SCROLL_BARS */
1566 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1568 if (FRAME_VISIBLE_P (f
))
1574 x_set_mouse_color (f
, arg
, oldval
)
1576 Lisp_Object arg
, oldval
;
1578 struct x_output
*x
= f
->output_data
.x
;
1579 Display
*dpy
= FRAME_X_DISPLAY (f
);
1580 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1581 Cursor hourglass_cursor
, horizontal_drag_cursor
;
1583 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1584 unsigned long mask_color
= x
->background_pixel
;
1586 /* Don't let pointers be invisible. */
1587 if (mask_color
== pixel
)
1589 x_free_colors (f
, &pixel
, 1);
1590 pixel
= x_copy_color (f
, x
->foreground_pixel
);
1593 unload_color (f
, x
->mouse_pixel
);
1594 x
->mouse_pixel
= pixel
;
1598 /* It's not okay to crash if the user selects a screwy cursor. */
1599 count
= x_catch_errors (dpy
);
1601 if (!NILP (Vx_pointer_shape
))
1603 CHECK_NUMBER (Vx_pointer_shape
);
1604 cursor
= XCreateFontCursor (dpy
, XINT (Vx_pointer_shape
));
1607 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1608 x_check_errors (dpy
, "bad text pointer cursor: %s");
1610 if (!NILP (Vx_nontext_pointer_shape
))
1612 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1614 = XCreateFontCursor (dpy
, XINT (Vx_nontext_pointer_shape
));
1617 nontext_cursor
= XCreateFontCursor (dpy
, XC_left_ptr
);
1618 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1620 if (!NILP (Vx_hourglass_pointer_shape
))
1622 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1624 = XCreateFontCursor (dpy
, XINT (Vx_hourglass_pointer_shape
));
1627 hourglass_cursor
= XCreateFontCursor (dpy
, XC_watch
);
1628 x_check_errors (dpy
, "bad hourglass pointer cursor: %s");
1630 x_check_errors (dpy
, "bad nontext pointer cursor: %s");
1631 if (!NILP (Vx_mode_pointer_shape
))
1633 CHECK_NUMBER (Vx_mode_pointer_shape
);
1634 mode_cursor
= XCreateFontCursor (dpy
, XINT (Vx_mode_pointer_shape
));
1637 mode_cursor
= XCreateFontCursor (dpy
, XC_xterm
);
1638 x_check_errors (dpy
, "bad modeline pointer cursor: %s");
1640 if (!NILP (Vx_sensitive_text_pointer_shape
))
1642 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1644 = XCreateFontCursor (dpy
, XINT (Vx_sensitive_text_pointer_shape
));
1647 cross_cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
1649 if (!NILP (Vx_window_horizontal_drag_shape
))
1651 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1652 horizontal_drag_cursor
1653 = XCreateFontCursor (dpy
, XINT (Vx_window_horizontal_drag_shape
));
1656 horizontal_drag_cursor
1657 = XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
1659 /* Check and report errors with the above calls. */
1660 x_check_errors (dpy
, "can't set cursor shape: %s");
1661 x_uncatch_errors (dpy
, count
);
1664 XColor fore_color
, back_color
;
1666 fore_color
.pixel
= x
->mouse_pixel
;
1667 x_query_color (f
, &fore_color
);
1668 back_color
.pixel
= mask_color
;
1669 x_query_color (f
, &back_color
);
1671 XRecolorCursor (dpy
, cursor
, &fore_color
, &back_color
);
1672 XRecolorCursor (dpy
, nontext_cursor
, &fore_color
, &back_color
);
1673 XRecolorCursor (dpy
, mode_cursor
, &fore_color
, &back_color
);
1674 XRecolorCursor (dpy
, cross_cursor
, &fore_color
, &back_color
);
1675 XRecolorCursor (dpy
, hourglass_cursor
, &fore_color
, &back_color
);
1676 XRecolorCursor (dpy
, horizontal_drag_cursor
, &fore_color
, &back_color
);
1679 if (FRAME_X_WINDOW (f
) != 0)
1680 XDefineCursor (dpy
, FRAME_X_WINDOW (f
), cursor
);
1682 if (cursor
!= x
->text_cursor
1683 && x
->text_cursor
!= 0)
1684 XFreeCursor (dpy
, x
->text_cursor
);
1685 x
->text_cursor
= cursor
;
1687 if (nontext_cursor
!= x
->nontext_cursor
1688 && x
->nontext_cursor
!= 0)
1689 XFreeCursor (dpy
, x
->nontext_cursor
);
1690 x
->nontext_cursor
= nontext_cursor
;
1692 if (hourglass_cursor
!= x
->hourglass_cursor
1693 && x
->hourglass_cursor
!= 0)
1694 XFreeCursor (dpy
, x
->hourglass_cursor
);
1695 x
->hourglass_cursor
= hourglass_cursor
;
1697 if (mode_cursor
!= x
->modeline_cursor
1698 && x
->modeline_cursor
!= 0)
1699 XFreeCursor (dpy
, f
->output_data
.x
->modeline_cursor
);
1700 x
->modeline_cursor
= mode_cursor
;
1702 if (cross_cursor
!= x
->cross_cursor
1703 && x
->cross_cursor
!= 0)
1704 XFreeCursor (dpy
, x
->cross_cursor
);
1705 x
->cross_cursor
= cross_cursor
;
1707 if (horizontal_drag_cursor
!= x
->horizontal_drag_cursor
1708 && x
->horizontal_drag_cursor
!= 0)
1709 XFreeCursor (dpy
, x
->horizontal_drag_cursor
);
1710 x
->horizontal_drag_cursor
= horizontal_drag_cursor
;
1715 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1719 x_set_cursor_color (f
, arg
, oldval
)
1721 Lisp_Object arg
, oldval
;
1723 unsigned long fore_pixel
, pixel
;
1724 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1725 struct x_output
*x
= f
->output_data
.x
;
1727 if (!NILP (Vx_cursor_fore_pixel
))
1729 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1730 WHITE_PIX_DEFAULT (f
));
1731 fore_pixel_allocated_p
= 1;
1734 fore_pixel
= x
->background_pixel
;
1736 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1737 pixel_allocated_p
= 1;
1739 /* Make sure that the cursor color differs from the background color. */
1740 if (pixel
== x
->background_pixel
)
1742 if (pixel_allocated_p
)
1744 x_free_colors (f
, &pixel
, 1);
1745 pixel_allocated_p
= 0;
1748 pixel
= x
->mouse_pixel
;
1749 if (pixel
== fore_pixel
)
1751 if (fore_pixel_allocated_p
)
1753 x_free_colors (f
, &fore_pixel
, 1);
1754 fore_pixel_allocated_p
= 0;
1756 fore_pixel
= x
->background_pixel
;
1760 unload_color (f
, x
->cursor_foreground_pixel
);
1761 if (!fore_pixel_allocated_p
)
1762 fore_pixel
= x_copy_color (f
, fore_pixel
);
1763 x
->cursor_foreground_pixel
= fore_pixel
;
1765 unload_color (f
, x
->cursor_pixel
);
1766 if (!pixel_allocated_p
)
1767 pixel
= x_copy_color (f
, pixel
);
1768 x
->cursor_pixel
= pixel
;
1770 if (FRAME_X_WINDOW (f
) != 0)
1773 XSetBackground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, x
->cursor_pixel
);
1774 XSetForeground (FRAME_X_DISPLAY (f
), x
->cursor_gc
, fore_pixel
);
1777 if (FRAME_VISIBLE_P (f
))
1779 x_update_cursor (f
, 0);
1780 x_update_cursor (f
, 1);
1784 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1787 /* Set the border-color of frame F to value described by ARG.
1788 ARG can be a string naming a color.
1789 The border-color is used for the border that is drawn by the X server.
1790 Note that this does not fully take effect if done before
1791 F has an x-window; it must be redone when the window is created.
1793 Note: this is done in two routines because of the way X10 works.
1795 Note: under X11, this is normally the province of the window manager,
1796 and so emacs' border colors may be overridden. */
1799 x_set_border_color (f
, arg
, oldval
)
1801 Lisp_Object arg
, oldval
;
1806 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1807 x_set_border_pixel (f
, pix
);
1808 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1811 /* Set the border-color of frame F to pixel value PIX.
1812 Note that this does not fully take effect if done before
1813 F has an x-window. */
1816 x_set_border_pixel (f
, pix
)
1820 unload_color (f
, f
->output_data
.x
->border_pixel
);
1821 f
->output_data
.x
->border_pixel
= pix
;
1823 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1826 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1827 (unsigned long)pix
);
1830 if (FRAME_VISIBLE_P (f
))
1836 /* Value is the internal representation of the specified cursor type
1837 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1838 of the bar cursor. */
1840 enum text_cursor_kinds
1841 x_specified_cursor_type (arg
, width
)
1845 enum text_cursor_kinds type
;
1852 else if (CONSP (arg
)
1853 && EQ (XCAR (arg
), Qbar
)
1854 && INTEGERP (XCDR (arg
))
1855 && XINT (XCDR (arg
)) >= 0)
1858 *width
= XINT (XCDR (arg
));
1860 else if (NILP (arg
))
1863 /* Treat anything unknown as "box cursor".
1864 It was bad to signal an error; people have trouble fixing
1865 .Xdefaults with Emacs, when it has something bad in it. */
1866 type
= FILLED_BOX_CURSOR
;
1872 x_set_cursor_type (f
, arg
, oldval
)
1874 Lisp_Object arg
, oldval
;
1878 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1879 f
->output_data
.x
->cursor_width
= width
;
1881 /* Make sure the cursor gets redrawn. This is overkill, but how
1882 often do people change cursor types? */
1883 update_mode_lines
++;
1887 x_set_icon_type (f
, arg
, oldval
)
1889 Lisp_Object arg
, oldval
;
1895 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1898 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1903 result
= x_text_icon (f
,
1904 (char *) XSTRING ((!NILP (f
->icon_name
)
1908 result
= x_bitmap_icon (f
, arg
);
1913 error ("No icon window available");
1916 XFlush (FRAME_X_DISPLAY (f
));
1920 /* Return non-nil if frame F wants a bitmap icon. */
1928 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1936 x_set_icon_name (f
, arg
, oldval
)
1938 Lisp_Object arg
, oldval
;
1944 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1947 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1952 if (f
->output_data
.x
->icon_bitmap
!= 0)
1957 result
= x_text_icon (f
,
1958 (char *) XSTRING ((!NILP (f
->icon_name
)
1967 error ("No icon window available");
1970 XFlush (FRAME_X_DISPLAY (f
));
1975 x_set_font (f
, arg
, oldval
)
1977 Lisp_Object arg
, oldval
;
1980 Lisp_Object fontset_name
;
1982 int old_fontset
= f
->output_data
.x
->fontset
;
1986 fontset_name
= Fquery_fontset (arg
, Qnil
);
1989 result
= (STRINGP (fontset_name
)
1990 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1991 : x_new_font (f
, XSTRING (arg
)->data
));
1994 if (EQ (result
, Qnil
))
1995 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1996 else if (EQ (result
, Qt
))
1997 error ("The characters of the given font have varying widths");
1998 else if (STRINGP (result
))
2000 if (STRINGP (fontset_name
))
2002 /* Fontset names are built from ASCII font names, so the
2003 names may be equal despite there was a change. */
2004 if (old_fontset
== f
->output_data
.x
->fontset
)
2007 else if (!NILP (Fequal (result
, oldval
)))
2010 store_frame_param (f
, Qfont
, result
);
2011 recompute_basic_faces (f
);
2016 do_pending_window_change (0);
2018 /* Don't call `face-set-after-frame-default' when faces haven't been
2019 initialized yet. This is the case when called from
2020 Fx_create_frame. In that case, the X widget or window doesn't
2021 exist either, and we can end up in x_report_frame_params with a
2022 null widget which gives a segfault. */
2023 if (FRAME_FACE_CACHE (f
))
2025 XSETFRAME (frame
, f
);
2026 call1 (Qface_set_after_frame_default
, frame
);
2031 x_set_fringe_width (f
, new_value
, old_value
)
2033 Lisp_Object new_value
, old_value
;
2035 x_compute_fringe_widths (f
, 1);
2039 x_set_border_width (f
, arg
, oldval
)
2041 Lisp_Object arg
, oldval
;
2045 if (XINT (arg
) == f
->output_data
.x
->border_width
)
2048 if (FRAME_X_WINDOW (f
) != 0)
2049 error ("Cannot change the border width of a window");
2051 f
->output_data
.x
->border_width
= XINT (arg
);
2055 x_set_internal_border_width (f
, arg
, oldval
)
2057 Lisp_Object arg
, oldval
;
2059 int old
= f
->output_data
.x
->internal_border_width
;
2062 f
->output_data
.x
->internal_border_width
= XINT (arg
);
2063 if (f
->output_data
.x
->internal_border_width
< 0)
2064 f
->output_data
.x
->internal_border_width
= 0;
2066 #ifdef USE_X_TOOLKIT
2067 if (f
->output_data
.x
->edit_widget
)
2068 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
2071 if (f
->output_data
.x
->internal_border_width
== old
)
2074 if (FRAME_X_WINDOW (f
) != 0)
2076 x_set_window_size (f
, 0, f
->width
, f
->height
);
2077 SET_FRAME_GARBAGED (f
);
2078 do_pending_window_change (0);
2081 SET_FRAME_GARBAGED (f
);
2085 x_set_visibility (f
, value
, oldval
)
2087 Lisp_Object value
, oldval
;
2090 XSETFRAME (frame
, f
);
2093 Fmake_frame_invisible (frame
, Qt
);
2094 else if (EQ (value
, Qicon
))
2095 Ficonify_frame (frame
);
2097 Fmake_frame_visible (frame
);
2101 /* Change window heights in windows rooted in WINDOW by N lines. */
2104 x_change_window_heights (window
, n
)
2108 struct window
*w
= XWINDOW (window
);
2110 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
2111 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
2113 if (INTEGERP (w
->orig_top
))
2114 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
2115 if (INTEGERP (w
->orig_height
))
2116 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
2118 /* Handle just the top child in a vertical split. */
2119 if (!NILP (w
->vchild
))
2120 x_change_window_heights (w
->vchild
, n
);
2122 /* Adjust all children in a horizontal split. */
2123 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
2125 w
= XWINDOW (window
);
2126 x_change_window_heights (window
, n
);
2131 x_set_menu_bar_lines (f
, value
, oldval
)
2133 Lisp_Object value
, oldval
;
2136 #ifndef USE_X_TOOLKIT
2137 int olines
= FRAME_MENU_BAR_LINES (f
);
2140 /* Right now, menu bars don't work properly in minibuf-only frames;
2141 most of the commands try to apply themselves to the minibuffer
2142 frame itself, and get an error because you can't switch buffers
2143 in or split the minibuffer window. */
2144 if (FRAME_MINIBUF_ONLY_P (f
))
2147 if (INTEGERP (value
))
2148 nlines
= XINT (value
);
2152 /* Make sure we redisplay all windows in this frame. */
2153 windows_or_buffers_changed
++;
2155 #ifdef USE_X_TOOLKIT
2156 FRAME_MENU_BAR_LINES (f
) = 0;
2159 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2160 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
2161 /* Make sure next redisplay shows the menu bar. */
2162 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
2166 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2167 free_frame_menubar (f
);
2168 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2170 f
->output_data
.x
->menubar_widget
= 0;
2172 #else /* not USE_X_TOOLKIT */
2173 FRAME_MENU_BAR_LINES (f
) = nlines
;
2174 x_change_window_heights (f
->root_window
, nlines
- olines
);
2175 #endif /* not USE_X_TOOLKIT */
2180 /* Set the number of lines used for the tool bar of frame F to VALUE.
2181 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2182 is the old number of tool bar lines. This function changes the
2183 height of all windows on frame F to match the new tool bar height.
2184 The frame's height doesn't change. */
2187 x_set_tool_bar_lines (f
, value
, oldval
)
2189 Lisp_Object value
, oldval
;
2191 int delta
, nlines
, root_height
;
2192 Lisp_Object root_window
;
2194 /* Treat tool bars like menu bars. */
2195 if (FRAME_MINIBUF_ONLY_P (f
))
2198 /* Use VALUE only if an integer >= 0. */
2199 if (INTEGERP (value
) && XINT (value
) >= 0)
2200 nlines
= XFASTINT (value
);
2204 /* Make sure we redisplay all windows in this frame. */
2205 ++windows_or_buffers_changed
;
2207 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2209 /* Don't resize the tool-bar to more than we have room for. */
2210 root_window
= FRAME_ROOT_WINDOW (f
);
2211 root_height
= XINT (XWINDOW (root_window
)->height
);
2212 if (root_height
- delta
< 1)
2214 delta
= root_height
- 1;
2215 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2218 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2219 x_change_window_heights (root_window
, delta
);
2222 /* We also have to make sure that the internal border at the top of
2223 the frame, below the menu bar or tool bar, is redrawn when the
2224 tool bar disappears. This is so because the internal border is
2225 below the tool bar if one is displayed, but is below the menu bar
2226 if there isn't a tool bar. The tool bar draws into the area
2227 below the menu bar. */
2228 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2232 clear_current_matrices (f
);
2233 updating_frame
= NULL
;
2236 /* If the tool bar gets smaller, the internal border below it
2237 has to be cleared. It was formerly part of the display
2238 of the larger tool bar, and updating windows won't clear it. */
2241 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2242 int width
= PIXEL_WIDTH (f
);
2243 int y
= nlines
* CANON_Y_UNIT (f
);
2246 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2247 0, y
, width
, height
, False
);
2250 if (WINDOWP (f
->tool_bar_window
))
2251 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2256 /* Set the foreground color for scroll bars on frame F to VALUE.
2257 VALUE should be a string, a color name. If it isn't a string or
2258 isn't a valid color name, do nothing. OLDVAL is the old value of
2259 the frame parameter. */
2262 x_set_scroll_bar_foreground (f
, value
, oldval
)
2264 Lisp_Object value
, oldval
;
2266 unsigned long pixel
;
2268 if (STRINGP (value
))
2269 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2273 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2274 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2276 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2277 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2279 /* Remove all scroll bars because they have wrong colors. */
2280 if (condemn_scroll_bars_hook
)
2281 (*condemn_scroll_bars_hook
) (f
);
2282 if (judge_scroll_bars_hook
)
2283 (*judge_scroll_bars_hook
) (f
);
2285 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2291 /* Set the background color for scroll bars on frame F to VALUE VALUE
2292 should be a string, a color name. If it isn't a string or isn't a
2293 valid color name, do nothing. OLDVAL is the old value of the frame
2297 x_set_scroll_bar_background (f
, value
, oldval
)
2299 Lisp_Object value
, oldval
;
2301 unsigned long pixel
;
2303 if (STRINGP (value
))
2304 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2308 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2309 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2311 #ifdef USE_TOOLKIT_SCROLL_BARS
2312 /* Scrollbar shadow colors. */
2313 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
2315 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
2316 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
2318 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
2320 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
2321 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
2323 #endif /* USE_TOOLKIT_SCROLL_BARS */
2325 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2326 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2328 /* Remove all scroll bars because they have wrong colors. */
2329 if (condemn_scroll_bars_hook
)
2330 (*condemn_scroll_bars_hook
) (f
);
2331 if (judge_scroll_bars_hook
)
2332 (*judge_scroll_bars_hook
) (f
);
2334 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2340 /* Encode Lisp string STRING as a text in a format appropriate for
2341 XICCC (X Inter Client Communication Conventions).
2343 If STRING contains only ASCII characters, do no conversion and
2344 return the string data of STRING. Otherwise, encode the text by
2345 CODING_SYSTEM, and return a newly allocated memory area which
2346 should be freed by `xfree' by a caller.
2348 SELECTIONP non-zero means the string is being encoded for an X
2349 selection, so it is safe to run pre-write conversions (which
2352 Store the byte length of resulting text in *TEXT_BYTES.
2354 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2355 which means that the `encoding' of the result can be `STRING'.
2356 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2357 the result should be `COMPOUND_TEXT'. */
2360 x_encode_text (string
, coding_system
, selectionp
, text_bytes
, stringp
)
2361 Lisp_Object string
, coding_system
;
2362 int *text_bytes
, *stringp
;
2365 unsigned char *str
= XSTRING (string
)->data
;
2366 int chars
= XSTRING (string
)->size
;
2367 int bytes
= STRING_BYTES (XSTRING (string
));
2371 struct coding_system coding
;
2373 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2374 if (charset_info
== 0)
2376 /* No multibyte character in OBJ. We need not encode it. */
2377 *text_bytes
= bytes
;
2382 setup_coding_system (coding_system
, &coding
);
2384 && SYMBOLP (coding
.pre_write_conversion
)
2385 && !NILP (Ffboundp (coding
.pre_write_conversion
)))
2387 string
= run_pre_post_conversion_on_str (string
, &coding
, 1);
2388 str
= XSTRING (string
)->data
;
2389 chars
= XSTRING (string
)->size
;
2390 bytes
= STRING_BYTES (XSTRING (string
));
2392 coding
.src_multibyte
= 1;
2393 coding
.dst_multibyte
= 0;
2394 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2395 if (coding
.type
== coding_type_iso2022
)
2396 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2397 /* We suppress producing escape sequences for composition. */
2398 coding
.composing
= COMPOSITION_DISABLED
;
2399 bufsize
= encoding_buffer_size (&coding
, bytes
);
2400 buf
= (unsigned char *) xmalloc (bufsize
);
2401 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2402 *text_bytes
= coding
.produced
;
2403 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2408 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2411 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2412 name; if NAME is a string, set F's name to NAME and set
2413 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2415 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2416 suggesting a new name, which lisp code should override; if
2417 F->explicit_name is set, ignore the new name; otherwise, set it. */
2420 x_set_name (f
, name
, explicit)
2425 /* Make sure that requests from lisp code override requests from
2426 Emacs redisplay code. */
2429 /* If we're switching from explicit to implicit, we had better
2430 update the mode lines and thereby update the title. */
2431 if (f
->explicit_name
&& NILP (name
))
2432 update_mode_lines
= 1;
2434 f
->explicit_name
= ! NILP (name
);
2436 else if (f
->explicit_name
)
2439 /* If NAME is nil, set the name to the x_id_name. */
2442 /* Check for no change needed in this very common case
2443 before we do any consing. */
2444 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2445 XSTRING (f
->name
)->data
))
2447 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2450 CHECK_STRING (name
);
2452 /* Don't change the name if it's already NAME. */
2453 if (! NILP (Fstring_equal (name
, f
->name
)))
2458 /* For setting the frame title, the title parameter should override
2459 the name parameter. */
2460 if (! NILP (f
->title
))
2463 if (FRAME_X_WINDOW (f
))
2468 XTextProperty text
, icon
;
2470 Lisp_Object coding_system
;
2472 coding_system
= Vlocale_coding_system
;
2473 if (NILP (coding_system
))
2474 coding_system
= Qcompound_text
;
2475 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2476 text
.encoding
= (stringp
? XA_STRING
2477 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2479 text
.nitems
= bytes
;
2481 if (NILP (f
->icon_name
))
2487 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2489 icon
.encoding
= (stringp
? XA_STRING
2490 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2492 icon
.nitems
= bytes
;
2494 #ifdef USE_X_TOOLKIT
2495 XSetWMName (FRAME_X_DISPLAY (f
),
2496 XtWindow (f
->output_data
.x
->widget
), &text
);
2497 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2499 #else /* not USE_X_TOOLKIT */
2500 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2501 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2502 #endif /* not USE_X_TOOLKIT */
2503 if (!NILP (f
->icon_name
)
2504 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2506 if (text
.value
!= XSTRING (name
)->data
)
2509 #else /* not HAVE_X11R4 */
2510 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2511 XSTRING (name
)->data
);
2512 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2513 XSTRING (name
)->data
);
2514 #endif /* not HAVE_X11R4 */
2519 /* This function should be called when the user's lisp code has
2520 specified a name for the frame; the name will override any set by the
2523 x_explicitly_set_name (f
, arg
, oldval
)
2525 Lisp_Object arg
, oldval
;
2527 x_set_name (f
, arg
, 1);
2530 /* This function should be called by Emacs redisplay code to set the
2531 name; names set this way will never override names set by the user's
2534 x_implicitly_set_name (f
, arg
, oldval
)
2536 Lisp_Object arg
, oldval
;
2538 x_set_name (f
, arg
, 0);
2541 /* Change the title of frame F to NAME.
2542 If NAME is nil, use the frame name as the title.
2544 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2545 name; if NAME is a string, set F's name to NAME and set
2546 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2548 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2549 suggesting a new name, which lisp code should override; if
2550 F->explicit_name is set, ignore the new name; otherwise, set it. */
2553 x_set_title (f
, name
, old_name
)
2555 Lisp_Object name
, old_name
;
2557 /* Don't change the title if it's already NAME. */
2558 if (EQ (name
, f
->title
))
2561 update_mode_lines
= 1;
2568 CHECK_STRING (name
);
2570 if (FRAME_X_WINDOW (f
))
2575 XTextProperty text
, icon
;
2577 Lisp_Object coding_system
;
2579 coding_system
= Vlocale_coding_system
;
2580 if (NILP (coding_system
))
2581 coding_system
= Qcompound_text
;
2582 text
.value
= x_encode_text (name
, coding_system
, 0, &bytes
, &stringp
);
2583 text
.encoding
= (stringp
? XA_STRING
2584 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2586 text
.nitems
= bytes
;
2588 if (NILP (f
->icon_name
))
2594 icon
.value
= x_encode_text (f
->icon_name
, coding_system
, 0,
2596 icon
.encoding
= (stringp
? XA_STRING
2597 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2599 icon
.nitems
= bytes
;
2601 #ifdef USE_X_TOOLKIT
2602 XSetWMName (FRAME_X_DISPLAY (f
),
2603 XtWindow (f
->output_data
.x
->widget
), &text
);
2604 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2606 #else /* not USE_X_TOOLKIT */
2607 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2608 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2609 #endif /* not USE_X_TOOLKIT */
2610 if (!NILP (f
->icon_name
)
2611 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2613 if (text
.value
!= XSTRING (name
)->data
)
2616 #else /* not HAVE_X11R4 */
2617 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2618 XSTRING (name
)->data
);
2619 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2620 XSTRING (name
)->data
);
2621 #endif /* not HAVE_X11R4 */
2627 x_set_autoraise (f
, arg
, oldval
)
2629 Lisp_Object arg
, oldval
;
2631 f
->auto_raise
= !EQ (Qnil
, arg
);
2635 x_set_autolower (f
, arg
, oldval
)
2637 Lisp_Object arg
, oldval
;
2639 f
->auto_lower
= !EQ (Qnil
, arg
);
2643 x_set_unsplittable (f
, arg
, oldval
)
2645 Lisp_Object arg
, oldval
;
2647 f
->no_split
= !NILP (arg
);
2651 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2653 Lisp_Object arg
, oldval
;
2655 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2656 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2657 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2658 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2660 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2662 ? vertical_scroll_bar_none
2664 ? vertical_scroll_bar_right
2665 : vertical_scroll_bar_left
);
2667 /* We set this parameter before creating the X window for the
2668 frame, so we can get the geometry right from the start.
2669 However, if the window hasn't been created yet, we shouldn't
2670 call x_set_window_size. */
2671 if (FRAME_X_WINDOW (f
))
2672 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2673 do_pending_window_change (0);
2678 x_set_scroll_bar_width (f
, arg
, oldval
)
2680 Lisp_Object arg
, oldval
;
2682 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2686 #ifdef USE_TOOLKIT_SCROLL_BARS
2687 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2688 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2689 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2690 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2692 /* Make the actual width at least 14 pixels and a multiple of a
2694 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2696 /* Use all of that space (aside from required margins) for the
2698 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2701 if (FRAME_X_WINDOW (f
))
2702 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2703 do_pending_window_change (0);
2705 else if (INTEGERP (arg
) && XINT (arg
) > 0
2706 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2708 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2709 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2711 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2712 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2713 if (FRAME_X_WINDOW (f
))
2714 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2717 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2718 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2719 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2724 /* Subroutines of creating an X frame. */
2726 /* Make sure that Vx_resource_name is set to a reasonable value.
2727 Fix it up, or set it to `emacs' if it is too hopeless. */
2730 validate_x_resource_name ()
2733 /* Number of valid characters in the resource name. */
2735 /* Number of invalid characters in the resource name. */
2740 if (!STRINGP (Vx_resource_class
))
2741 Vx_resource_class
= build_string (EMACS_CLASS
);
2743 if (STRINGP (Vx_resource_name
))
2745 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2748 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2750 /* Only letters, digits, - and _ are valid in resource names.
2751 Count the valid characters and count the invalid ones. */
2752 for (i
= 0; i
< len
; i
++)
2755 if (! ((c
>= 'a' && c
<= 'z')
2756 || (c
>= 'A' && c
<= 'Z')
2757 || (c
>= '0' && c
<= '9')
2758 || c
== '-' || c
== '_'))
2765 /* Not a string => completely invalid. */
2766 bad_count
= 5, good_count
= 0;
2768 /* If name is valid already, return. */
2772 /* If name is entirely invalid, or nearly so, use `emacs'. */
2774 || (good_count
== 1 && bad_count
> 0))
2776 Vx_resource_name
= build_string ("emacs");
2780 /* Name is partly valid. Copy it and replace the invalid characters
2781 with underscores. */
2783 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2785 for (i
= 0; i
< len
; i
++)
2787 int c
= XSTRING (new)->data
[i
];
2788 if (! ((c
>= 'a' && c
<= 'z')
2789 || (c
>= 'A' && c
<= 'Z')
2790 || (c
>= '0' && c
<= '9')
2791 || c
== '-' || c
== '_'))
2792 XSTRING (new)->data
[i
] = '_';
2797 extern char *x_get_string_resource ();
2799 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2800 doc
: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2801 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2802 class, where INSTANCE is the name under which Emacs was invoked, or
2803 the name specified by the `-name' or `-rn' command-line arguments.
2805 The optional arguments COMPONENT and SUBCLASS add to the key and the
2806 class, respectively. You must specify both of them or neither.
2807 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2808 and the class is `Emacs.CLASS.SUBCLASS'. */)
2809 (attribute
, class, component
, subclass
)
2810 Lisp_Object attribute
, class, component
, subclass
;
2812 register char *value
;
2818 CHECK_STRING (attribute
);
2819 CHECK_STRING (class);
2821 if (!NILP (component
))
2822 CHECK_STRING (component
);
2823 if (!NILP (subclass
))
2824 CHECK_STRING (subclass
);
2825 if (NILP (component
) != NILP (subclass
))
2826 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2828 validate_x_resource_name ();
2830 /* Allocate space for the components, the dots which separate them,
2831 and the final '\0'. Make them big enough for the worst case. */
2832 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2833 + (STRINGP (component
)
2834 ? STRING_BYTES (XSTRING (component
)) : 0)
2835 + STRING_BYTES (XSTRING (attribute
))
2838 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2839 + STRING_BYTES (XSTRING (class))
2840 + (STRINGP (subclass
)
2841 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2844 /* Start with emacs.FRAMENAME for the name (the specific one)
2845 and with `Emacs' for the class key (the general one). */
2846 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2847 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2849 strcat (class_key
, ".");
2850 strcat (class_key
, XSTRING (class)->data
);
2852 if (!NILP (component
))
2854 strcat (class_key
, ".");
2855 strcat (class_key
, XSTRING (subclass
)->data
);
2857 strcat (name_key
, ".");
2858 strcat (name_key
, XSTRING (component
)->data
);
2861 strcat (name_key
, ".");
2862 strcat (name_key
, XSTRING (attribute
)->data
);
2864 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2865 name_key
, class_key
);
2867 if (value
!= (char *) 0)
2868 return build_string (value
);
2873 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2876 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2877 struct x_display_info
*dpyinfo
;
2878 Lisp_Object attribute
, class, component
, subclass
;
2880 register char *value
;
2884 CHECK_STRING (attribute
);
2885 CHECK_STRING (class);
2887 if (!NILP (component
))
2888 CHECK_STRING (component
);
2889 if (!NILP (subclass
))
2890 CHECK_STRING (subclass
);
2891 if (NILP (component
) != NILP (subclass
))
2892 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2894 validate_x_resource_name ();
2896 /* Allocate space for the components, the dots which separate them,
2897 and the final '\0'. Make them big enough for the worst case. */
2898 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2899 + (STRINGP (component
)
2900 ? STRING_BYTES (XSTRING (component
)) : 0)
2901 + STRING_BYTES (XSTRING (attribute
))
2904 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2905 + STRING_BYTES (XSTRING (class))
2906 + (STRINGP (subclass
)
2907 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2910 /* Start with emacs.FRAMENAME for the name (the specific one)
2911 and with `Emacs' for the class key (the general one). */
2912 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2913 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2915 strcat (class_key
, ".");
2916 strcat (class_key
, XSTRING (class)->data
);
2918 if (!NILP (component
))
2920 strcat (class_key
, ".");
2921 strcat (class_key
, XSTRING (subclass
)->data
);
2923 strcat (name_key
, ".");
2924 strcat (name_key
, XSTRING (component
)->data
);
2927 strcat (name_key
, ".");
2928 strcat (name_key
, XSTRING (attribute
)->data
);
2930 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2932 if (value
!= (char *) 0)
2933 return build_string (value
);
2938 /* Used when C code wants a resource value. */
2941 x_get_resource_string (attribute
, class)
2942 char *attribute
, *class;
2946 struct frame
*sf
= SELECTED_FRAME ();
2948 /* Allocate space for the components, the dots which separate them,
2949 and the final '\0'. */
2950 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2951 + strlen (attribute
) + 2);
2952 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2953 + strlen (class) + 2);
2955 sprintf (name_key
, "%s.%s",
2956 XSTRING (Vinvocation_name
)->data
,
2958 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2960 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2961 name_key
, class_key
);
2964 /* Types we might convert a resource string into. */
2974 /* Return the value of parameter PARAM.
2976 First search ALIST, then Vdefault_frame_alist, then the X defaults
2977 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2979 Convert the resource to the type specified by desired_type.
2981 If no default is specified, return Qunbound. If you call
2982 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2983 and don't let it get stored in any Lisp-visible variables! */
2986 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2987 struct x_display_info
*dpyinfo
;
2988 Lisp_Object alist
, param
;
2991 enum resource_types type
;
2993 register Lisp_Object tem
;
2995 tem
= Fassq (param
, alist
);
2997 tem
= Fassq (param
, Vdefault_frame_alist
);
3003 tem
= display_x_get_resource (dpyinfo
,
3004 build_string (attribute
),
3005 build_string (class),
3013 case RES_TYPE_NUMBER
:
3014 return make_number (atoi (XSTRING (tem
)->data
));
3016 case RES_TYPE_FLOAT
:
3017 return make_float (atof (XSTRING (tem
)->data
));
3019 case RES_TYPE_BOOLEAN
:
3020 tem
= Fdowncase (tem
);
3021 if (!strcmp (XSTRING (tem
)->data
, "on")
3022 || !strcmp (XSTRING (tem
)->data
, "true"))
3027 case RES_TYPE_STRING
:
3030 case RES_TYPE_SYMBOL
:
3031 /* As a special case, we map the values `true' and `on'
3032 to Qt, and `false' and `off' to Qnil. */
3035 lower
= Fdowncase (tem
);
3036 if (!strcmp (XSTRING (lower
)->data
, "on")
3037 || !strcmp (XSTRING (lower
)->data
, "true"))
3039 else if (!strcmp (XSTRING (lower
)->data
, "off")
3040 || !strcmp (XSTRING (lower
)->data
, "false"))
3043 return Fintern (tem
, Qnil
);
3056 /* Like x_get_arg, but also record the value in f->param_alist. */
3059 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
3061 Lisp_Object alist
, param
;
3064 enum resource_types type
;
3068 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
3069 attribute
, class, type
);
3071 store_frame_param (f
, param
, value
);
3076 /* Record in frame F the specified or default value according to ALIST
3077 of the parameter named PROP (a Lisp symbol).
3078 If no value is specified for PROP, look for an X default for XPROP
3079 on the frame named NAME.
3080 If that is not found either, use the value DEFLT. */
3083 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
3090 enum resource_types type
;
3094 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
3095 if (EQ (tem
, Qunbound
))
3097 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3102 /* Record in frame F the specified or default value according to ALIST
3103 of the parameter named PROP (a Lisp symbol). If no value is
3104 specified for PROP, look for an X default for XPROP on the frame
3105 named NAME. If that is not found either, use the value DEFLT. */
3108 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
3117 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3120 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
3121 if (EQ (tem
, Qunbound
))
3123 #ifdef USE_TOOLKIT_SCROLL_BARS
3125 /* See if an X resource for the scroll bar color has been
3127 tem
= display_x_get_resource (dpyinfo
,
3128 build_string (foreground_p
3132 build_string ("verticalScrollBar"),
3136 /* If nothing has been specified, scroll bars will use a
3137 toolkit-dependent default. Because these defaults are
3138 difficult to get at without actually creating a scroll
3139 bar, use nil to indicate that no color has been
3144 #else /* not USE_TOOLKIT_SCROLL_BARS */
3148 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3151 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3157 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3158 doc
: /* Parse an X-style geometry string STRING.
3159 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3160 The properties returned may include `top', `left', `height', and `width'.
3161 The value of `left' or `top' may be an integer,
3162 or a list (+ N) meaning N pixels relative to top/left corner,
3163 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3168 unsigned int width
, height
;
3171 CHECK_STRING (string
);
3173 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
3174 &x
, &y
, &width
, &height
);
3177 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
3178 error ("Must specify both x and y position, or neither");
3182 if (geometry
& XValue
)
3184 Lisp_Object element
;
3186 if (x
>= 0 && (geometry
& XNegative
))
3187 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3188 else if (x
< 0 && ! (geometry
& XNegative
))
3189 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3191 element
= Fcons (Qleft
, make_number (x
));
3192 result
= Fcons (element
, result
);
3195 if (geometry
& YValue
)
3197 Lisp_Object element
;
3199 if (y
>= 0 && (geometry
& YNegative
))
3200 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3201 else if (y
< 0 && ! (geometry
& YNegative
))
3202 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3204 element
= Fcons (Qtop
, make_number (y
));
3205 result
= Fcons (element
, result
);
3208 if (geometry
& WidthValue
)
3209 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3210 if (geometry
& HeightValue
)
3211 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3216 /* Calculate the desired size and position of this window,
3217 and return the flags saying which aspects were specified.
3219 This function does not make the coordinates positive. */
3221 #define DEFAULT_ROWS 40
3222 #define DEFAULT_COLS 80
3225 x_figure_window_size (f
, parms
)
3229 register Lisp_Object tem0
, tem1
, tem2
;
3230 long window_prompting
= 0;
3231 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3233 /* Default values if we fall through.
3234 Actually, if that happens we should get
3235 window manager prompting. */
3236 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3237 f
->height
= DEFAULT_ROWS
;
3238 /* Window managers expect that if program-specified
3239 positions are not (0,0), they're intentional, not defaults. */
3240 f
->output_data
.x
->top_pos
= 0;
3241 f
->output_data
.x
->left_pos
= 0;
3243 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3244 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3245 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3246 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3248 if (!EQ (tem0
, Qunbound
))
3250 CHECK_NUMBER (tem0
);
3251 f
->height
= XINT (tem0
);
3253 if (!EQ (tem1
, Qunbound
))
3255 CHECK_NUMBER (tem1
);
3256 SET_FRAME_WIDTH (f
, XINT (tem1
));
3258 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3259 window_prompting
|= USSize
;
3261 window_prompting
|= PSize
;
3264 f
->output_data
.x
->vertical_scroll_bar_extra
3265 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3267 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3269 x_compute_fringe_widths (f
, 0);
3271 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3272 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3274 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3275 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3276 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3277 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3279 if (EQ (tem0
, Qminus
))
3281 f
->output_data
.x
->top_pos
= 0;
3282 window_prompting
|= YNegative
;
3284 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3285 && CONSP (XCDR (tem0
))
3286 && INTEGERP (XCAR (XCDR (tem0
))))
3288 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3289 window_prompting
|= YNegative
;
3291 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3292 && CONSP (XCDR (tem0
))
3293 && INTEGERP (XCAR (XCDR (tem0
))))
3295 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3297 else if (EQ (tem0
, Qunbound
))
3298 f
->output_data
.x
->top_pos
= 0;
3301 CHECK_NUMBER (tem0
);
3302 f
->output_data
.x
->top_pos
= XINT (tem0
);
3303 if (f
->output_data
.x
->top_pos
< 0)
3304 window_prompting
|= YNegative
;
3307 if (EQ (tem1
, Qminus
))
3309 f
->output_data
.x
->left_pos
= 0;
3310 window_prompting
|= XNegative
;
3312 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3313 && CONSP (XCDR (tem1
))
3314 && INTEGERP (XCAR (XCDR (tem1
))))
3316 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3317 window_prompting
|= XNegative
;
3319 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3320 && CONSP (XCDR (tem1
))
3321 && INTEGERP (XCAR (XCDR (tem1
))))
3323 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3325 else if (EQ (tem1
, Qunbound
))
3326 f
->output_data
.x
->left_pos
= 0;
3329 CHECK_NUMBER (tem1
);
3330 f
->output_data
.x
->left_pos
= XINT (tem1
);
3331 if (f
->output_data
.x
->left_pos
< 0)
3332 window_prompting
|= XNegative
;
3335 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3336 window_prompting
|= USPosition
;
3338 window_prompting
|= PPosition
;
3341 if (f
->output_data
.x
->want_fullscreen
!= FULLSCREEN_NONE
)
3346 /* It takes both for some WM:s to place it where we want */
3347 window_prompting
= USPosition
| PPosition
;
3348 x_fullscreen_adjust (f
, &width
, &height
, &top
, &left
);
3351 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3352 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3353 f
->output_data
.x
->left_pos
= left
;
3354 f
->output_data
.x
->top_pos
= top
;
3357 return window_prompting
;
3360 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3363 XSetWMProtocols (dpy
, w
, protocols
, count
)
3370 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3371 if (prop
== None
) return False
;
3372 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3373 (unsigned char *) protocols
, count
);
3376 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3378 #ifdef USE_X_TOOLKIT
3380 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3381 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3382 already be present because of the toolkit (Motif adds some of them,
3383 for example, but Xt doesn't). */
3386 hack_wm_protocols (f
, widget
)
3390 Display
*dpy
= XtDisplay (widget
);
3391 Window w
= XtWindow (widget
);
3392 int need_delete
= 1;
3398 Atom type
, *atoms
= 0;
3400 unsigned long nitems
= 0;
3401 unsigned long bytes_after
;
3403 if ((XGetWindowProperty (dpy
, w
,
3404 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3405 (long)0, (long)100, False
, XA_ATOM
,
3406 &type
, &format
, &nitems
, &bytes_after
,
3407 (unsigned char **) &atoms
)
3409 && format
== 32 && type
== XA_ATOM
)
3413 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3415 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3417 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3420 if (atoms
) XFree ((char *) atoms
);
3426 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3428 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3430 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3432 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3433 XA_ATOM
, 32, PropModeAppend
,
3434 (unsigned char *) props
, count
);
3442 /* Support routines for XIC (X Input Context). */
3446 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3447 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3450 /* Supported XIM styles, ordered by preferenc. */
3452 static XIMStyle supported_xim_styles
[] =
3454 XIMPreeditPosition
| XIMStatusArea
,
3455 XIMPreeditPosition
| XIMStatusNothing
,
3456 XIMPreeditPosition
| XIMStatusNone
,
3457 XIMPreeditNothing
| XIMStatusArea
,
3458 XIMPreeditNothing
| XIMStatusNothing
,
3459 XIMPreeditNothing
| XIMStatusNone
,
3460 XIMPreeditNone
| XIMStatusArea
,
3461 XIMPreeditNone
| XIMStatusNothing
,
3462 XIMPreeditNone
| XIMStatusNone
,
3467 /* Create an X fontset on frame F with base font name
3471 xic_create_xfontset (f
, base_fontname
)
3473 char *base_fontname
;
3476 char **missing_list
;
3480 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3481 base_fontname
, &missing_list
,
3482 &missing_count
, &def_string
);
3484 XFreeStringList (missing_list
);
3486 /* No need to free def_string. */
3491 /* Value is the best input style, given user preferences USER (already
3492 checked to be supported by Emacs), and styles supported by the
3493 input method XIM. */
3496 best_xim_style (user
, xim
)
3502 for (i
= 0; i
< user
->count_styles
; ++i
)
3503 for (j
= 0; j
< xim
->count_styles
; ++j
)
3504 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3505 return user
->supported_styles
[i
];
3507 /* Return the default style. */
3508 return XIMPreeditNothing
| XIMStatusNothing
;
3511 /* Create XIC for frame F. */
3513 static XIMStyle xic_style
;
3516 create_frame_xic (f
)
3521 XFontSet xfs
= NULL
;
3526 xim
= FRAME_X_XIM (f
);
3531 XVaNestedList preedit_attr
;
3532 XVaNestedList status_attr
;
3533 char *base_fontname
;
3536 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3537 spot
.x
= 0; spot
.y
= 1;
3538 /* Create X fontset. */
3539 fontset
= FRAME_FONTSET (f
);
3541 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3544 /* Determine the base fontname from the ASCII font name of
3546 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3547 char *p
= ascii_font
;
3550 for (i
= 0; *p
; p
++)
3553 /* As the font name doesn't conform to XLFD, we can't
3554 modify it to get a suitable base fontname for the
3556 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3559 int len
= strlen (ascii_font
) + 1;
3562 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3571 base_fontname
= (char *) alloca (len
);
3572 bzero (base_fontname
, len
);
3573 strcpy (base_fontname
, "-*-*-");
3574 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3575 strcat (base_fontname
, "*-*-*-*-*-*-*");
3578 xfs
= xic_create_xfontset (f
, base_fontname
);
3580 /* Determine XIC style. */
3583 XIMStyles supported_list
;
3584 supported_list
.count_styles
= (sizeof supported_xim_styles
3585 / sizeof supported_xim_styles
[0]);
3586 supported_list
.supported_styles
= supported_xim_styles
;
3587 xic_style
= best_xim_style (&supported_list
,
3588 FRAME_X_XIM_STYLES (f
));
3591 preedit_attr
= XVaCreateNestedList (0,
3594 FRAME_FOREGROUND_PIXEL (f
),
3596 FRAME_BACKGROUND_PIXEL (f
),
3597 (xic_style
& XIMPreeditPosition
3602 status_attr
= XVaCreateNestedList (0,
3608 FRAME_FOREGROUND_PIXEL (f
),
3610 FRAME_BACKGROUND_PIXEL (f
),
3613 xic
= XCreateIC (xim
,
3614 XNInputStyle
, xic_style
,
3615 XNClientWindow
, FRAME_X_WINDOW(f
),
3616 XNFocusWindow
, FRAME_X_WINDOW(f
),
3617 XNStatusAttributes
, status_attr
,
3618 XNPreeditAttributes
, preedit_attr
,
3620 XFree (preedit_attr
);
3621 XFree (status_attr
);
3624 FRAME_XIC (f
) = xic
;
3625 FRAME_XIC_STYLE (f
) = xic_style
;
3626 FRAME_XIC_FONTSET (f
) = xfs
;
3630 /* Destroy XIC and free XIC fontset of frame F, if any. */
3636 if (FRAME_XIC (f
) == NULL
)
3639 XDestroyIC (FRAME_XIC (f
));
3640 if (FRAME_XIC_FONTSET (f
))
3641 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3643 FRAME_XIC (f
) = NULL
;
3644 FRAME_XIC_FONTSET (f
) = NULL
;
3648 /* Place preedit area for XIC of window W's frame to specified
3649 pixel position X/Y. X and Y are relative to window W. */
3652 xic_set_preeditarea (w
, x
, y
)
3656 struct frame
*f
= XFRAME (w
->frame
);
3660 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3661 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3662 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3663 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3668 /* Place status area for XIC in bottom right corner of frame F.. */
3671 xic_set_statusarea (f
)
3674 XIC xic
= FRAME_XIC (f
);
3679 /* Negotiate geometry of status area. If input method has existing
3680 status area, use its current size. */
3681 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3682 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3683 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3686 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3687 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3690 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3692 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3693 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3697 area
.width
= needed
->width
;
3698 area
.height
= needed
->height
;
3699 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3700 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3701 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3704 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3705 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3710 /* Set X fontset for XIC of frame F, using base font name
3711 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3714 xic_set_xfontset (f
, base_fontname
)
3716 char *base_fontname
;
3721 xfs
= xic_create_xfontset (f
, base_fontname
);
3723 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3724 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3725 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3726 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3727 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3730 if (FRAME_XIC_FONTSET (f
))
3731 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3732 FRAME_XIC_FONTSET (f
) = xfs
;
3735 #endif /* HAVE_X_I18N */
3739 #ifdef USE_X_TOOLKIT
3741 /* Create and set up the X widget for frame F. */
3744 x_window (f
, window_prompting
, minibuffer_only
)
3746 long window_prompting
;
3747 int minibuffer_only
;
3749 XClassHint class_hints
;
3750 XSetWindowAttributes attributes
;
3751 unsigned long attribute_mask
;
3752 Widget shell_widget
;
3754 Widget frame_widget
;
3760 /* Use the resource name as the top-level widget name
3761 for looking up resources. Make a non-Lisp copy
3762 for the window manager, so GC relocation won't bother it.
3764 Elsewhere we specify the window name for the window manager. */
3767 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3768 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3769 strcpy (f
->namebuf
, str
);
3773 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3774 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3775 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3776 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3777 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3778 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3779 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3780 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3781 applicationShellWidgetClass
,
3782 FRAME_X_DISPLAY (f
), al
, ac
);
3784 f
->output_data
.x
->widget
= shell_widget
;
3785 /* maybe_set_screen_title_format (shell_widget); */
3787 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3788 (widget_value
*) NULL
,
3789 shell_widget
, False
,
3793 (lw_callback
) NULL
);
3796 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3797 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3798 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3799 XtSetValues (pane_widget
, al
, ac
);
3800 f
->output_data
.x
->column_widget
= pane_widget
;
3802 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3803 the emacs screen when changing menubar. This reduces flickering. */
3806 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3807 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3808 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3809 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3810 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3811 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3812 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3813 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3814 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3817 f
->output_data
.x
->edit_widget
= frame_widget
;
3819 XtManageChild (frame_widget
);
3821 /* Do some needed geometry management. */
3824 char *tem
, shell_position
[32];
3827 int extra_borders
= 0;
3829 = (f
->output_data
.x
->menubar_widget
3830 ? (f
->output_data
.x
->menubar_widget
->core
.height
3831 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3834 #if 0 /* Experimentally, we now get the right results
3835 for -geometry -0-0 without this. 24 Aug 96, rms. */
3836 if (FRAME_EXTERNAL_MENU_BAR (f
))
3839 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3840 menubar_size
+= ibw
;
3844 f
->output_data
.x
->menubar_height
= menubar_size
;
3847 /* Motif seems to need this amount added to the sizes
3848 specified for the shell widget. The Athena/Lucid widgets don't.
3849 Both conclusions reached experimentally. -- rms. */
3850 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3851 &extra_borders
, NULL
);
3855 /* Convert our geometry parameters into a geometry string
3857 Note that we do not specify here whether the position
3858 is a user-specified or program-specified one.
3859 We pass that information later, in x_wm_set_size_hints. */
3861 int left
= f
->output_data
.x
->left_pos
;
3862 int xneg
= window_prompting
& XNegative
;
3863 int top
= f
->output_data
.x
->top_pos
;
3864 int yneg
= window_prompting
& YNegative
;
3870 if (window_prompting
& USPosition
)
3871 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3872 PIXEL_WIDTH (f
) + extra_borders
,
3873 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3874 (xneg
? '-' : '+'), left
,
3875 (yneg
? '-' : '+'), top
);
3877 sprintf (shell_position
, "=%dx%d",
3878 PIXEL_WIDTH (f
) + extra_borders
,
3879 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3882 len
= strlen (shell_position
) + 1;
3883 /* We don't free this because we don't know whether
3884 it is safe to free it while the frame exists.
3885 It isn't worth the trouble of arranging to free it
3886 when the frame is deleted. */
3887 tem
= (char *) xmalloc (len
);
3888 strncpy (tem
, shell_position
, len
);
3889 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3890 XtSetValues (shell_widget
, al
, ac
);
3893 XtManageChild (pane_widget
);
3894 XtRealizeWidget (shell_widget
);
3896 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3898 validate_x_resource_name ();
3900 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3901 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3902 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3905 FRAME_XIC (f
) = NULL
;
3907 create_frame_xic (f
);
3911 f
->output_data
.x
->wm_hints
.input
= True
;
3912 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3913 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3914 &f
->output_data
.x
->wm_hints
);
3916 hack_wm_protocols (f
, shell_widget
);
3919 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3922 /* Do a stupid property change to force the server to generate a
3923 PropertyNotify event so that the event_stream server timestamp will
3924 be initialized to something relevant to the time we created the window.
3926 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3927 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3928 XA_ATOM
, 32, PropModeAppend
,
3929 (unsigned char*) NULL
, 0);
3931 /* Make all the standard events reach the Emacs frame. */
3932 attributes
.event_mask
= STANDARD_EVENT_SET
;
3937 /* XIM server might require some X events. */
3938 unsigned long fevent
= NoEventMask
;
3939 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3940 attributes
.event_mask
|= fevent
;
3942 #endif /* HAVE_X_I18N */
3944 attribute_mask
= CWEventMask
;
3945 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3946 attribute_mask
, &attributes
);
3948 XtMapWidget (frame_widget
);
3950 /* x_set_name normally ignores requests to set the name if the
3951 requested name is the same as the current name. This is the one
3952 place where that assumption isn't correct; f->name is set, but
3953 the X server hasn't been told. */
3956 int explicit = f
->explicit_name
;
3958 f
->explicit_name
= 0;
3961 x_set_name (f
, name
, explicit);
3964 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3965 f
->output_data
.x
->text_cursor
);
3969 /* This is a no-op, except under Motif. Make sure main areas are
3970 set to something reasonable, in case we get an error later. */
3971 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3974 #else /* not USE_X_TOOLKIT */
3976 /* Create and set up the X window for frame F. */
3983 XClassHint class_hints
;
3984 XSetWindowAttributes attributes
;
3985 unsigned long attribute_mask
;
3987 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3988 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3989 attributes
.bit_gravity
= StaticGravity
;
3990 attributes
.backing_store
= NotUseful
;
3991 attributes
.save_under
= True
;
3992 attributes
.event_mask
= STANDARD_EVENT_SET
;
3993 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3994 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3999 = XCreateWindow (FRAME_X_DISPLAY (f
),
4000 f
->output_data
.x
->parent_desc
,
4001 f
->output_data
.x
->left_pos
,
4002 f
->output_data
.x
->top_pos
,
4003 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
4004 f
->output_data
.x
->border_width
,
4005 CopyFromParent
, /* depth */
4006 InputOutput
, /* class */
4008 attribute_mask
, &attributes
);
4012 create_frame_xic (f
);
4015 /* XIM server might require some X events. */
4016 unsigned long fevent
= NoEventMask
;
4017 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
4018 attributes
.event_mask
|= fevent
;
4019 attribute_mask
= CWEventMask
;
4020 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4021 attribute_mask
, &attributes
);
4024 #endif /* HAVE_X_I18N */
4026 validate_x_resource_name ();
4028 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
4029 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
4030 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
4032 /* The menubar is part of the ordinary display;
4033 it does not count in addition to the height of the window. */
4034 f
->output_data
.x
->menubar_height
= 0;
4036 /* This indicates that we use the "Passive Input" input model.
4037 Unless we do this, we don't get the Focus{In,Out} events that we
4038 need to draw the cursor correctly. Accursed bureaucrats.
4039 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
4041 f
->output_data
.x
->wm_hints
.input
= True
;
4042 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
4043 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4044 &f
->output_data
.x
->wm_hints
);
4045 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
4047 /* Request "save yourself" and "delete window" commands from wm. */
4050 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
4051 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
4052 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
4055 /* x_set_name normally ignores requests to set the name if the
4056 requested name is the same as the current name. This is the one
4057 place where that assumption isn't correct; f->name is set, but
4058 the X server hasn't been told. */
4061 int explicit = f
->explicit_name
;
4063 f
->explicit_name
= 0;
4066 x_set_name (f
, name
, explicit);
4069 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4070 f
->output_data
.x
->text_cursor
);
4074 if (FRAME_X_WINDOW (f
) == 0)
4075 error ("Unable to create window");
4078 #endif /* not USE_X_TOOLKIT */
4080 /* Handle the icon stuff for this window. Perhaps later we might
4081 want an x_set_icon_position which can be called interactively as
4089 Lisp_Object icon_x
, icon_y
;
4090 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4092 /* Set the position of the icon. Note that twm groups all
4093 icons in an icon window. */
4094 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4095 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4096 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4098 CHECK_NUMBER (icon_x
);
4099 CHECK_NUMBER (icon_y
);
4101 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4102 error ("Both left and top icon corners of icon must be specified");
4106 if (! EQ (icon_x
, Qunbound
))
4107 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4109 /* Start up iconic or window? */
4110 x_wm_set_window_state
4111 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
4116 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
4123 /* Make the GCs needed for this window, setting the
4124 background, border and mouse colors; also create the
4125 mouse cursor and the gray border tile. */
4127 static char cursor_bits
[] =
4129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4139 XGCValues gc_values
;
4143 /* Create the GCs of this frame.
4144 Note that many default values are used. */
4147 gc_values
.font
= f
->output_data
.x
->font
->fid
;
4148 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
4149 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4150 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
4151 f
->output_data
.x
->normal_gc
4152 = XCreateGC (FRAME_X_DISPLAY (f
),
4154 GCLineWidth
| GCFont
| GCForeground
| GCBackground
,
4157 /* Reverse video style. */
4158 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4159 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4160 f
->output_data
.x
->reverse_gc
4161 = XCreateGC (FRAME_X_DISPLAY (f
),
4163 GCFont
| GCForeground
| GCBackground
| GCLineWidth
,
4166 /* Cursor has cursor-color background, background-color foreground. */
4167 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4168 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
4169 gc_values
.fill_style
= FillOpaqueStippled
;
4171 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4172 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4173 cursor_bits
, 16, 16);
4174 f
->output_data
.x
->cursor_gc
4175 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4176 (GCFont
| GCForeground
| GCBackground
4177 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
4181 f
->output_data
.x
->white_relief
.gc
= 0;
4182 f
->output_data
.x
->black_relief
.gc
= 0;
4184 /* Create the gray border tile used when the pointer is not in
4185 the frame. Since this depends on the frame's pixel values,
4186 this must be done on a per-frame basis. */
4187 f
->output_data
.x
->border_tile
4188 = (XCreatePixmapFromBitmapData
4189 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
4190 gray_bits
, gray_width
, gray_height
,
4191 f
->output_data
.x
->foreground_pixel
,
4192 f
->output_data
.x
->background_pixel
,
4193 DefaultDepth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
))));
4199 /* Free what was was allocated in x_make_gc. */
4205 Display
*dpy
= FRAME_X_DISPLAY (f
);
4209 if (f
->output_data
.x
->normal_gc
)
4211 XFreeGC (dpy
, f
->output_data
.x
->normal_gc
);
4212 f
->output_data
.x
->normal_gc
= 0;
4215 if (f
->output_data
.x
->reverse_gc
)
4217 XFreeGC (dpy
, f
->output_data
.x
->reverse_gc
);
4218 f
->output_data
.x
->reverse_gc
= 0;
4221 if (f
->output_data
.x
->cursor_gc
)
4223 XFreeGC (dpy
, f
->output_data
.x
->cursor_gc
);
4224 f
->output_data
.x
->cursor_gc
= 0;
4227 if (f
->output_data
.x
->border_tile
)
4229 XFreePixmap (dpy
, f
->output_data
.x
->border_tile
);
4230 f
->output_data
.x
->border_tile
= 0;
4237 /* Handler for signals raised during x_create_frame and
4238 x_create_top_frame. FRAME is the frame which is partially
4242 unwind_create_frame (frame
)
4245 struct frame
*f
= XFRAME (frame
);
4247 /* If frame is ``official'', nothing to do. */
4248 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4251 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4254 x_free_frame_resources (f
);
4256 /* Check that reference counts are indeed correct. */
4257 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4258 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4266 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4268 doc
: /* Make a new X window, which is called a "frame" in Emacs terms.
4269 Returns an Emacs frame object.
4270 ALIST is an alist of frame parameters.
4271 If the parameters specify that the frame should not have a minibuffer,
4272 and do not specify a specific minibuffer window to use,
4273 then `default-minibuffer-frame' must be a frame whose minibuffer can
4274 be shared by the new frame.
4276 This function is an internal primitive--use `make-frame' instead. */)
4281 Lisp_Object frame
, tem
;
4283 int minibuffer_only
= 0;
4284 long window_prompting
= 0;
4286 int count
= BINDING_STACK_SIZE ();
4287 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4288 Lisp_Object display
;
4289 struct x_display_info
*dpyinfo
= NULL
;
4295 /* Use this general default value to start with
4296 until we know if this frame has a specified name. */
4297 Vx_resource_name
= Vinvocation_name
;
4299 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4300 if (EQ (display
, Qunbound
))
4302 dpyinfo
= check_x_display_info (display
);
4304 kb
= dpyinfo
->kboard
;
4306 kb
= &the_only_kboard
;
4309 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
4311 && ! EQ (name
, Qunbound
)
4313 error ("Invalid frame name--not a string or nil");
4316 Vx_resource_name
= name
;
4318 /* See if parent window is specified. */
4319 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4320 if (EQ (parent
, Qunbound
))
4322 if (! NILP (parent
))
4323 CHECK_NUMBER (parent
);
4325 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4326 /* No need to protect DISPLAY because that's not used after passing
4327 it to make_frame_without_minibuffer. */
4329 GCPRO4 (parms
, parent
, name
, frame
);
4330 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4332 if (EQ (tem
, Qnone
) || NILP (tem
))
4333 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4334 else if (EQ (tem
, Qonly
))
4336 f
= make_minibuffer_frame ();
4337 minibuffer_only
= 1;
4339 else if (WINDOWP (tem
))
4340 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4344 XSETFRAME (frame
, f
);
4346 /* Note that X Windows does support scroll bars. */
4347 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4349 f
->output_method
= output_x_window
;
4350 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4351 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4352 f
->output_data
.x
->icon_bitmap
= -1;
4353 f
->output_data
.x
->fontset
= -1;
4354 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4355 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4356 #ifdef USE_TOOLKIT_SCROLL_BARS
4357 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
4358 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
4359 #endif /* USE_TOOLKIT_SCROLL_BARS */
4360 record_unwind_protect (unwind_create_frame
, frame
);
4363 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4365 if (! STRINGP (f
->icon_name
))
4366 f
->icon_name
= Qnil
;
4368 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4370 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
4371 dpyinfo_refcount
= dpyinfo
->reference_count
;
4372 #endif /* GLYPH_DEBUG */
4374 FRAME_KBOARD (f
) = kb
;
4377 /* These colors will be set anyway later, but it's important
4378 to get the color reference counts right, so initialize them! */
4381 struct gcpro gcpro1
;
4383 /* Function x_decode_color can signal an error. Make
4384 sure to initialize color slots so that we won't try
4385 to free colors we haven't allocated. */
4386 f
->output_data
.x
->foreground_pixel
= -1;
4387 f
->output_data
.x
->background_pixel
= -1;
4388 f
->output_data
.x
->cursor_pixel
= -1;
4389 f
->output_data
.x
->cursor_foreground_pixel
= -1;
4390 f
->output_data
.x
->border_pixel
= -1;
4391 f
->output_data
.x
->mouse_pixel
= -1;
4393 black
= build_string ("black");
4395 f
->output_data
.x
->foreground_pixel
4396 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4397 f
->output_data
.x
->background_pixel
4398 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4399 f
->output_data
.x
->cursor_pixel
4400 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4401 f
->output_data
.x
->cursor_foreground_pixel
4402 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4403 f
->output_data
.x
->border_pixel
4404 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4405 f
->output_data
.x
->mouse_pixel
4406 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4410 /* Specify the parent under which to make this X window. */
4414 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4415 f
->output_data
.x
->explicit_parent
= 1;
4419 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4420 f
->output_data
.x
->explicit_parent
= 0;
4423 /* Set the name; the functions to which we pass f expect the name to
4425 if (EQ (name
, Qunbound
) || NILP (name
))
4427 f
->name
= build_string (dpyinfo
->x_id_name
);
4428 f
->explicit_name
= 0;
4433 f
->explicit_name
= 1;
4434 /* use the frame's title when getting resources for this frame. */
4435 specbind (Qx_resource_name
, name
);
4438 /* Extract the window parameters from the supplied values
4439 that are needed to determine window geometry. */
4443 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4446 /* First, try whatever font the caller has specified. */
4449 tem
= Fquery_fontset (font
, Qnil
);
4451 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4453 font
= x_new_font (f
, XSTRING (font
)->data
);
4456 /* Try out a font which we hope has bold and italic variations. */
4457 if (!STRINGP (font
))
4458 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4459 if (!STRINGP (font
))
4460 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4461 if (! STRINGP (font
))
4462 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4463 if (! STRINGP (font
))
4464 /* This was formerly the first thing tried, but it finds too many fonts
4465 and takes too long. */
4466 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4467 /* If those didn't work, look for something which will at least work. */
4468 if (! STRINGP (font
))
4469 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4471 if (! STRINGP (font
))
4472 font
= build_string ("fixed");
4474 x_default_parameter (f
, parms
, Qfont
, font
,
4475 "font", "Font", RES_TYPE_STRING
);
4479 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4480 whereby it fails to get any font. */
4481 xlwmenu_default_font
= f
->output_data
.x
->font
;
4484 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4485 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4487 /* This defaults to 1 in order to match xterm. We recognize either
4488 internalBorderWidth or internalBorder (which is what xterm calls
4490 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4494 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4495 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4496 if (! EQ (value
, Qunbound
))
4497 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4500 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4501 "internalBorderWidth", "internalBorderWidth",
4503 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4504 "verticalScrollBars", "ScrollBars",
4507 /* Also do the stuff which must be set before the window exists. */
4508 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4509 "foreground", "Foreground", RES_TYPE_STRING
);
4510 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4511 "background", "Background", RES_TYPE_STRING
);
4512 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4513 "pointerColor", "Foreground", RES_TYPE_STRING
);
4514 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4515 "cursorColor", "Foreground", RES_TYPE_STRING
);
4516 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4517 "borderColor", "BorderColor", RES_TYPE_STRING
);
4518 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4519 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4520 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4521 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4522 x_default_parameter (f
, parms
, Qleft_fringe
, Qnil
,
4523 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4524 x_default_parameter (f
, parms
, Qright_fringe
, Qnil
,
4525 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4527 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4528 "scrollBarForeground",
4529 "ScrollBarForeground", 1);
4530 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4531 "scrollBarBackground",
4532 "ScrollBarBackground", 0);
4534 /* Init faces before x_default_parameter is called for scroll-bar
4535 parameters because that function calls x_set_scroll_bar_width,
4536 which calls change_frame_size, which calls Fset_window_buffer,
4537 which runs hooks, which call Fvertical_motion. At the end, we
4538 end up in init_iterator with a null face cache, which should not
4540 init_frame_faces (f
);
4542 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4543 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4544 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4545 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4546 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4547 "bufferPredicate", "BufferPredicate",
4549 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4550 "title", "Title", RES_TYPE_STRING
);
4551 x_default_parameter (f
, parms
, Qwait_for_wm
, Qt
,
4552 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN
);
4553 x_default_parameter (f
, parms
, Qfullscreen
, Qnil
,
4554 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4556 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4558 /* Add the tool-bar height to the initial frame height so that the
4559 user gets a text display area of the size he specified with -g or
4560 via .Xdefaults. Later changes of the tool-bar height don't
4561 change the frame size. This is done so that users can create
4562 tall Emacs frames without having to guess how tall the tool-bar
4564 if (FRAME_TOOL_BAR_LINES (f
))
4566 int margin
, relief
, bar_height
;
4568 relief
= (tool_bar_button_relief
>= 0
4569 ? tool_bar_button_relief
4570 : DEFAULT_TOOL_BAR_BUTTON_RELIEF
);
4572 if (INTEGERP (Vtool_bar_button_margin
)
4573 && XINT (Vtool_bar_button_margin
) > 0)
4574 margin
= XFASTINT (Vtool_bar_button_margin
);
4575 else if (CONSP (Vtool_bar_button_margin
)
4576 && INTEGERP (XCDR (Vtool_bar_button_margin
))
4577 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
4578 margin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
4582 bar_height
= DEFAULT_TOOL_BAR_IMAGE_HEIGHT
+ 2 * margin
+ 2 * relief
;
4583 f
->height
+= (bar_height
+ CANON_Y_UNIT (f
) - 1) / CANON_Y_UNIT (f
);
4586 /* Compute the size of the X window. */
4587 window_prompting
= x_figure_window_size (f
, parms
);
4589 if (window_prompting
& XNegative
)
4591 if (window_prompting
& YNegative
)
4592 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4594 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4598 if (window_prompting
& YNegative
)
4599 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4601 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4604 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4606 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4607 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4609 /* Create the X widget or window. */
4610 #ifdef USE_X_TOOLKIT
4611 x_window (f
, window_prompting
, minibuffer_only
);
4619 /* Now consider the frame official. */
4620 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4621 Vframe_list
= Fcons (frame
, Vframe_list
);
4623 /* We need to do this after creating the X window, so that the
4624 icon-creation functions can say whose icon they're describing. */
4625 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4626 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4628 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4629 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4630 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4631 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4632 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4633 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4634 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4635 "scrollBarWidth", "ScrollBarWidth",
4638 /* Dimensions, especially f->height, must be done via change_frame_size.
4639 Change will not be effected unless different from the current
4645 SET_FRAME_WIDTH (f
, 0);
4646 change_frame_size (f
, height
, width
, 1, 0, 0);
4648 /* Set up faces after all frame parameters are known. This call
4649 also merges in face attributes specified for new frames. If we
4650 don't do this, the `menu' face for instance won't have the right
4651 colors, and the menu bar won't appear in the specified colors for
4653 call1 (Qface_set_after_frame_default
, frame
);
4655 #ifdef USE_X_TOOLKIT
4656 /* Create the menu bar. */
4657 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4659 /* If this signals an error, we haven't set size hints for the
4660 frame and we didn't make it visible. */
4661 initialize_frame_menubar (f
);
4663 /* This is a no-op, except under Motif where it arranges the
4664 main window for the widgets on it. */
4665 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4666 f
->output_data
.x
->menubar_widget
,
4667 f
->output_data
.x
->edit_widget
);
4669 #endif /* USE_X_TOOLKIT */
4671 /* Tell the server what size and position, etc, we want, and how
4672 badly we want them. This should be done after we have the menu
4673 bar so that its size can be taken into account. */
4675 x_wm_set_size_hint (f
, window_prompting
, 0);
4678 /* Make the window appear on the frame and enable display, unless
4679 the caller says not to. However, with explicit parent, Emacs
4680 cannot control visibility, so don't try. */
4681 if (! f
->output_data
.x
->explicit_parent
)
4683 Lisp_Object visibility
;
4685 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4687 if (EQ (visibility
, Qunbound
))
4690 if (EQ (visibility
, Qicon
))
4691 x_iconify_frame (f
);
4692 else if (! NILP (visibility
))
4693 x_make_frame_visible (f
);
4695 /* Must have been Qnil. */
4701 /* Make sure windows on this frame appear in calls to next-window
4702 and similar functions. */
4703 Vwindow_list
= Qnil
;
4705 return unbind_to (count
, frame
);
4709 /* FRAME is used only to get a handle on the X display. We don't pass the
4710 display info directly because we're called from frame.c, which doesn't
4711 know about that structure. */
4714 x_get_focus_frame (frame
)
4715 struct frame
*frame
;
4717 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4719 if (! dpyinfo
->x_focus_frame
)
4722 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4727 /* In certain situations, when the window manager follows a
4728 click-to-focus policy, there seems to be no way around calling
4729 XSetInputFocus to give another frame the input focus .
4731 In an ideal world, XSetInputFocus should generally be avoided so
4732 that applications don't interfere with the window manager's focus
4733 policy. But I think it's okay to use when it's clearly done
4734 following a user-command. */
4736 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4737 doc
: /* Set the input focus to FRAME.
4738 FRAME nil means use the selected frame. */)
4742 struct frame
*f
= check_x_frame (frame
);
4743 Display
*dpy
= FRAME_X_DISPLAY (f
);
4747 count
= x_catch_errors (dpy
);
4748 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4749 RevertToParent
, CurrentTime
);
4750 x_uncatch_errors (dpy
, count
);
4757 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4758 doc
: /* Internal function called by `color-defined-p', which see. */)
4760 Lisp_Object color
, frame
;
4763 FRAME_PTR f
= check_x_frame (frame
);
4765 CHECK_STRING (color
);
4767 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4773 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4774 doc
: /* Internal function called by `color-values', which see. */)
4776 Lisp_Object color
, frame
;
4779 FRAME_PTR f
= check_x_frame (frame
);
4781 CHECK_STRING (color
);
4783 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4787 rgb
[0] = make_number (foo
.red
);
4788 rgb
[1] = make_number (foo
.green
);
4789 rgb
[2] = make_number (foo
.blue
);
4790 return Flist (3, rgb
);
4796 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4797 doc
: /* Internal function called by `display-color-p', which see. */)
4799 Lisp_Object display
;
4801 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4803 if (dpyinfo
->n_planes
<= 2)
4806 switch (dpyinfo
->visual
->class)
4819 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4821 doc
: /* Return t if the X display supports shades of gray.
4822 Note that color displays do support shades of gray.
4823 The optional argument DISPLAY specifies which display to ask about.
4824 DISPLAY should be either a frame or a display name (a string).
4825 If omitted or nil, that stands for the selected frame's display. */)
4827 Lisp_Object display
;
4829 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4831 if (dpyinfo
->n_planes
<= 1)
4834 switch (dpyinfo
->visual
->class)
4849 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4851 doc
: /* Returns the width in pixels of the X display DISPLAY.
4852 The optional argument DISPLAY specifies which display to ask about.
4853 DISPLAY should be either a frame or a display name (a string).
4854 If omitted or nil, that stands for the selected frame's display. */)
4856 Lisp_Object display
;
4858 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4860 return make_number (dpyinfo
->width
);
4863 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4864 Sx_display_pixel_height
, 0, 1, 0,
4865 doc
: /* Returns the height in pixels of the X display DISPLAY.
4866 The optional argument DISPLAY specifies which display to ask about.
4867 DISPLAY should be either a frame or a display name (a string).
4868 If omitted or nil, that stands for the selected frame's display. */)
4870 Lisp_Object display
;
4872 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4874 return make_number (dpyinfo
->height
);
4877 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4879 doc
: /* Returns the number of bitplanes of the X display DISPLAY.
4880 The optional argument DISPLAY specifies which display to ask about.
4881 DISPLAY should be either a frame or a display name (a string).
4882 If omitted or nil, that stands for the selected frame's display. */)
4884 Lisp_Object display
;
4886 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4888 return make_number (dpyinfo
->n_planes
);
4891 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4893 doc
: /* Returns the number of color cells of the X display DISPLAY.
4894 The optional argument DISPLAY specifies which display to ask about.
4895 DISPLAY should be either a frame or a display name (a string).
4896 If omitted or nil, that stands for the selected frame's display. */)
4898 Lisp_Object display
;
4900 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4902 return make_number (DisplayCells (dpyinfo
->display
,
4903 XScreenNumberOfScreen (dpyinfo
->screen
)));
4906 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4907 Sx_server_max_request_size
,
4909 doc
: /* Returns the maximum request size of the X server of display DISPLAY.
4910 The optional argument DISPLAY specifies which display to ask about.
4911 DISPLAY should be either a frame or a display name (a string).
4912 If omitted or nil, that stands for the selected frame's display. */)
4914 Lisp_Object display
;
4916 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4918 return make_number (MAXREQUEST (dpyinfo
->display
));
4921 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4922 doc
: /* Returns the vendor ID string of the X server of display DISPLAY.
4923 The optional argument DISPLAY specifies which display to ask about.
4924 DISPLAY should be either a frame or a display name (a string).
4925 If omitted or nil, that stands for the selected frame's display. */)
4927 Lisp_Object display
;
4929 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4930 char *vendor
= ServerVendor (dpyinfo
->display
);
4932 if (! vendor
) vendor
= "";
4933 return build_string (vendor
);
4936 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4937 doc
: /* Returns the version numbers of the X server of display DISPLAY.
4938 The value is a list of three integers: the major and minor
4939 version numbers of the X Protocol in use, and the vendor-specific release
4940 number. See also the function `x-server-vendor'.
4942 The optional argument DISPLAY specifies which display to ask about.
4943 DISPLAY should be either a frame or a display name (a string).
4944 If omitted or nil, that stands for the selected frame's display. */)
4946 Lisp_Object display
;
4948 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4949 Display
*dpy
= dpyinfo
->display
;
4951 return Fcons (make_number (ProtocolVersion (dpy
)),
4952 Fcons (make_number (ProtocolRevision (dpy
)),
4953 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4956 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4957 doc
: /* Return the number of screens on the X server of display DISPLAY.
4958 The optional argument DISPLAY specifies which display to ask about.
4959 DISPLAY should be either a frame or a display name (a string).
4960 If omitted or nil, that stands for the selected frame's display. */)
4962 Lisp_Object display
;
4964 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4966 return make_number (ScreenCount (dpyinfo
->display
));
4969 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4970 doc
: /* Return the height in millimeters of the X display DISPLAY.
4971 The optional argument DISPLAY specifies which display to ask about.
4972 DISPLAY should be either a frame or a display name (a string).
4973 If omitted or nil, that stands for the selected frame's display. */)
4975 Lisp_Object display
;
4977 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4979 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4982 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4983 doc
: /* Return the width in millimeters of the X display DISPLAY.
4984 The optional argument DISPLAY specifies which display to ask about.
4985 DISPLAY should be either a frame or a display name (a string).
4986 If omitted or nil, that stands for the selected frame's display. */)
4988 Lisp_Object display
;
4990 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4992 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4995 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4996 Sx_display_backing_store
, 0, 1, 0,
4997 doc
: /* Returns an indication of whether X display DISPLAY does backing store.
4998 The value may be `always', `when-mapped', or `not-useful'.
4999 The optional argument DISPLAY specifies which display to ask about.
5000 DISPLAY should be either a frame or a display name (a string).
5001 If omitted or nil, that stands for the selected frame's display. */)
5003 Lisp_Object display
;
5005 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5008 switch (DoesBackingStore (dpyinfo
->screen
))
5011 result
= intern ("always");
5015 result
= intern ("when-mapped");
5019 result
= intern ("not-useful");
5023 error ("Strange value for BackingStore parameter of screen");
5030 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
5031 Sx_display_visual_class
, 0, 1, 0,
5032 doc
: /* Return the visual class of the X display DISPLAY.
5033 The value is one of the symbols `static-gray', `gray-scale',
5034 `static-color', `pseudo-color', `true-color', or `direct-color'.
5036 The optional argument DISPLAY specifies which display to ask about.
5037 DISPLAY should be either a frame or a display name (a string).
5038 If omitted or nil, that stands for the selected frame's display. */)
5040 Lisp_Object display
;
5042 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5045 switch (dpyinfo
->visual
->class)
5048 result
= intern ("static-gray");
5051 result
= intern ("gray-scale");
5054 result
= intern ("static-color");
5057 result
= intern ("pseudo-color");
5060 result
= intern ("true-color");
5063 result
= intern ("direct-color");
5066 error ("Display has an unknown visual class");
5073 DEFUN ("x-display-save-under", Fx_display_save_under
,
5074 Sx_display_save_under
, 0, 1, 0,
5075 doc
: /* Returns t if the X display DISPLAY supports the save-under feature.
5076 The optional argument DISPLAY specifies which display to ask about.
5077 DISPLAY should be either a frame or a display name (a string).
5078 If omitted or nil, that stands for the selected frame's display. */)
5080 Lisp_Object display
;
5082 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5084 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
5092 register struct frame
*f
;
5094 return PIXEL_WIDTH (f
);
5099 register struct frame
*f
;
5101 return PIXEL_HEIGHT (f
);
5106 register struct frame
*f
;
5108 return FONT_WIDTH (f
->output_data
.x
->font
);
5113 register struct frame
*f
;
5115 return f
->output_data
.x
->line_height
;
5120 register struct frame
*f
;
5122 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
5127 /************************************************************************
5129 ************************************************************************/
5132 /* Mapping visual names to visuals. */
5134 static struct visual_class
5141 {"StaticGray", StaticGray
},
5142 {"GrayScale", GrayScale
},
5143 {"StaticColor", StaticColor
},
5144 {"PseudoColor", PseudoColor
},
5145 {"TrueColor", TrueColor
},
5146 {"DirectColor", DirectColor
},
5151 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5153 /* Value is the screen number of screen SCR. This is a substitute for
5154 the X function with the same name when that doesn't exist. */
5157 XScreenNumberOfScreen (scr
)
5158 register Screen
*scr
;
5160 Display
*dpy
= scr
->display
;
5163 for (i
= 0; i
< dpy
->nscreens
; ++i
)
5164 if (scr
== dpy
->screens
+ i
)
5170 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5173 /* Select the visual that should be used on display DPYINFO. Set
5174 members of DPYINFO appropriately. Called from x_term_init. */
5177 select_visual (dpyinfo
)
5178 struct x_display_info
*dpyinfo
;
5180 Display
*dpy
= dpyinfo
->display
;
5181 Screen
*screen
= dpyinfo
->screen
;
5184 /* See if a visual is specified. */
5185 value
= display_x_get_resource (dpyinfo
,
5186 build_string ("visualClass"),
5187 build_string ("VisualClass"),
5189 if (STRINGP (value
))
5191 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5192 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5193 depth, a decimal number. NAME is compared with case ignored. */
5194 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
5199 strcpy (s
, XSTRING (value
)->data
);
5200 dash
= index (s
, '-');
5203 dpyinfo
->n_planes
= atoi (dash
+ 1);
5207 /* We won't find a matching visual with depth 0, so that
5208 an error will be printed below. */
5209 dpyinfo
->n_planes
= 0;
5211 /* Determine the visual class. */
5212 for (i
= 0; visual_classes
[i
].name
; ++i
)
5213 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
5215 class = visual_classes
[i
].class;
5219 /* Look up a matching visual for the specified class. */
5221 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
5222 dpyinfo
->n_planes
, class, &vinfo
))
5223 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
5225 dpyinfo
->visual
= vinfo
.visual
;
5230 XVisualInfo
*vinfo
, vinfo_template
;
5232 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
5235 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
5237 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
5239 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5240 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
5241 &vinfo_template
, &n_visuals
);
5243 fatal ("Can't get proper X visual info");
5245 dpyinfo
->n_planes
= vinfo
->depth
;
5246 XFree ((char *) vinfo
);
5251 /* Return the X display structure for the display named NAME.
5252 Open a new connection if necessary. */
5254 struct x_display_info
*
5255 x_display_info_for_name (name
)
5259 struct x_display_info
*dpyinfo
;
5261 CHECK_STRING (name
);
5263 if (! EQ (Vwindow_system
, intern ("x")))
5264 error ("Not using X Windows");
5266 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5268 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5271 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5276 /* Use this general default value to start with. */
5277 Vx_resource_name
= Vinvocation_name
;
5279 validate_x_resource_name ();
5281 dpyinfo
= x_term_init (name
, (char *)0,
5282 (char *) XSTRING (Vx_resource_name
)->data
);
5285 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5288 XSETFASTINT (Vwindow_system_version
, 11);
5294 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5296 doc
: /* Open a connection to an X server.
5297 DISPLAY is the name of the display to connect to.
5298 Optional second arg XRM-STRING is a string of resources in xrdb format.
5299 If the optional third arg MUST-SUCCEED is non-nil,
5300 terminate Emacs if we can't open the connection. */)
5301 (display
, xrm_string
, must_succeed
)
5302 Lisp_Object display
, xrm_string
, must_succeed
;
5304 unsigned char *xrm_option
;
5305 struct x_display_info
*dpyinfo
;
5307 CHECK_STRING (display
);
5308 if (! NILP (xrm_string
))
5309 CHECK_STRING (xrm_string
);
5311 if (! EQ (Vwindow_system
, intern ("x")))
5312 error ("Not using X Windows");
5314 if (! NILP (xrm_string
))
5315 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5317 xrm_option
= (unsigned char *) 0;
5319 validate_x_resource_name ();
5321 /* This is what opens the connection and sets x_current_display.
5322 This also initializes many symbols, such as those used for input. */
5323 dpyinfo
= x_term_init (display
, xrm_option
,
5324 (char *) XSTRING (Vx_resource_name
)->data
);
5328 if (!NILP (must_succeed
))
5329 fatal ("Cannot connect to X server %s.\n\
5330 Check the DISPLAY environment variable or use `-d'.\n\
5331 Also use the `xhost' program to verify that it is set to permit\n\
5332 connections from your machine.\n",
5333 XSTRING (display
)->data
);
5335 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5340 XSETFASTINT (Vwindow_system_version
, 11);
5344 DEFUN ("x-close-connection", Fx_close_connection
,
5345 Sx_close_connection
, 1, 1, 0,
5346 doc
: /* Close the connection to DISPLAY's X server.
5347 For DISPLAY, specify either a frame or a display name (a string).
5348 If DISPLAY is nil, that stands for the selected frame's display. */)
5350 Lisp_Object display
;
5352 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5355 if (dpyinfo
->reference_count
> 0)
5356 error ("Display still has frames on it");
5359 /* Free the fonts in the font table. */
5360 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5361 if (dpyinfo
->font_table
[i
].name
)
5363 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
5364 xfree (dpyinfo
->font_table
[i
].full_name
);
5365 xfree (dpyinfo
->font_table
[i
].name
);
5366 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5369 x_destroy_all_bitmaps (dpyinfo
);
5370 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5372 #ifdef USE_X_TOOLKIT
5373 XtCloseDisplay (dpyinfo
->display
);
5375 XCloseDisplay (dpyinfo
->display
);
5378 x_delete_display (dpyinfo
);
5384 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5385 doc
: /* Return the list of display names that Emacs has connections to. */)
5388 Lisp_Object tail
, result
;
5391 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5392 result
= Fcons (XCAR (XCAR (tail
)), result
);
5397 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5398 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5399 If ON is nil, allow buffering of requests.
5400 Turning on synchronization prohibits the Xlib routines from buffering
5401 requests and seriously degrades performance, but makes debugging much
5403 The optional second argument DISPLAY specifies which display to act on.
5404 DISPLAY should be either a frame or a display name (a string).
5405 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5407 Lisp_Object display
, on
;
5409 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5411 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5416 /* Wait for responses to all X commands issued so far for frame F. */
5423 XSync (FRAME_X_DISPLAY (f
), False
);
5428 /***********************************************************************
5430 ***********************************************************************/
5432 /* Value is the number of elements of vector VECTOR. */
5434 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5436 /* List of supported image types. Use define_image_type to add new
5437 types. Use lookup_image_type to find a type for a given symbol. */
5439 static struct image_type
*image_types
;
5441 /* The symbol `image' which is the car of the lists used to represent
5444 extern Lisp_Object Qimage
;
5446 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5452 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5453 extern Lisp_Object QCdata
;
5454 Lisp_Object QCtype
, QCascent
, QCmargin
, QCrelief
;
5455 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
5456 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5458 /* Other symbols. */
5460 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5462 /* Time in seconds after which images should be removed from the cache
5463 if not displayed. */
5465 Lisp_Object Vimage_cache_eviction_delay
;
5467 /* Function prototypes. */
5469 static void define_image_type
P_ ((struct image_type
*type
));
5470 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5471 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5472 static void x_laplace
P_ ((struct frame
*, struct image
*));
5473 static void x_emboss
P_ ((struct frame
*, struct image
*));
5474 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5478 /* Define a new image type from TYPE. This adds a copy of TYPE to
5479 image_types and adds the symbol *TYPE->type to Vimage_types. */
5482 define_image_type (type
)
5483 struct image_type
*type
;
5485 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5486 The initialized data segment is read-only. */
5487 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5488 bcopy (type
, p
, sizeof *p
);
5489 p
->next
= image_types
;
5491 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5495 /* Look up image type SYMBOL, and return a pointer to its image_type
5496 structure. Value is null if SYMBOL is not a known image type. */
5498 static INLINE
struct image_type
*
5499 lookup_image_type (symbol
)
5502 struct image_type
*type
;
5504 for (type
= image_types
; type
; type
= type
->next
)
5505 if (EQ (symbol
, *type
->type
))
5512 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5513 valid image specification is a list whose car is the symbol
5514 `image', and whose rest is a property list. The property list must
5515 contain a value for key `:type'. That value must be the name of a
5516 supported image type. The rest of the property list depends on the
5520 valid_image_p (object
)
5525 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5529 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
5530 if (EQ (XCAR (tem
), QCtype
))
5533 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
5535 struct image_type
*type
;
5536 type
= lookup_image_type (XCAR (tem
));
5538 valid_p
= type
->valid_p (object
);
5549 /* Log error message with format string FORMAT and argument ARG.
5550 Signaling an error, e.g. when an image cannot be loaded, is not a
5551 good idea because this would interrupt redisplay, and the error
5552 message display would lead to another redisplay. This function
5553 therefore simply displays a message. */
5556 image_error (format
, arg1
, arg2
)
5558 Lisp_Object arg1
, arg2
;
5560 add_to_log (format
, arg1
, arg2
);
5565 /***********************************************************************
5566 Image specifications
5567 ***********************************************************************/
5569 enum image_value_type
5571 IMAGE_DONT_CHECK_VALUE_TYPE
,
5573 IMAGE_STRING_OR_NIL_VALUE
,
5575 IMAGE_POSITIVE_INTEGER_VALUE
,
5576 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
5577 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5579 IMAGE_INTEGER_VALUE
,
5580 IMAGE_FUNCTION_VALUE
,
5585 /* Structure used when parsing image specifications. */
5587 struct image_keyword
5589 /* Name of keyword. */
5592 /* The type of value allowed. */
5593 enum image_value_type type
;
5595 /* Non-zero means key must be present. */
5598 /* Used to recognize duplicate keywords in a property list. */
5601 /* The value that was found. */
5606 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5608 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5611 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5612 has the format (image KEYWORD VALUE ...). One of the keyword/
5613 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5614 image_keywords structures of size NKEYWORDS describing other
5615 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5618 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5620 struct image_keyword
*keywords
;
5627 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5630 plist
= XCDR (spec
);
5631 while (CONSP (plist
))
5633 Lisp_Object key
, value
;
5635 /* First element of a pair must be a symbol. */
5637 plist
= XCDR (plist
);
5641 /* There must follow a value. */
5644 value
= XCAR (plist
);
5645 plist
= XCDR (plist
);
5647 /* Find key in KEYWORDS. Error if not found. */
5648 for (i
= 0; i
< nkeywords
; ++i
)
5649 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5655 /* Record that we recognized the keyword. If a keywords
5656 was found more than once, it's an error. */
5657 keywords
[i
].value
= value
;
5658 ++keywords
[i
].count
;
5660 if (keywords
[i
].count
> 1)
5663 /* Check type of value against allowed type. */
5664 switch (keywords
[i
].type
)
5666 case IMAGE_STRING_VALUE
:
5667 if (!STRINGP (value
))
5671 case IMAGE_STRING_OR_NIL_VALUE
:
5672 if (!STRINGP (value
) && !NILP (value
))
5676 case IMAGE_SYMBOL_VALUE
:
5677 if (!SYMBOLP (value
))
5681 case IMAGE_POSITIVE_INTEGER_VALUE
:
5682 if (!INTEGERP (value
) || XINT (value
) <= 0)
5686 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
5687 if (INTEGERP (value
) && XINT (value
) >= 0)
5690 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
5691 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
5695 case IMAGE_ASCENT_VALUE
:
5696 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5698 else if (INTEGERP (value
)
5699 && XINT (value
) >= 0
5700 && XINT (value
) <= 100)
5704 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5705 if (!INTEGERP (value
) || XINT (value
) < 0)
5709 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5712 case IMAGE_FUNCTION_VALUE
:
5713 value
= indirect_function (value
);
5715 || COMPILEDP (value
)
5716 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5720 case IMAGE_NUMBER_VALUE
:
5721 if (!INTEGERP (value
) && !FLOATP (value
))
5725 case IMAGE_INTEGER_VALUE
:
5726 if (!INTEGERP (value
))
5730 case IMAGE_BOOL_VALUE
:
5731 if (!NILP (value
) && !EQ (value
, Qt
))
5740 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5744 /* Check that all mandatory fields are present. */
5745 for (i
= 0; i
< nkeywords
; ++i
)
5746 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5749 return NILP (plist
);
5753 /* Return the value of KEY in image specification SPEC. Value is nil
5754 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5755 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5758 image_spec_value (spec
, key
, found
)
5759 Lisp_Object spec
, key
;
5764 xassert (valid_image_p (spec
));
5766 for (tail
= XCDR (spec
);
5767 CONSP (tail
) && CONSP (XCDR (tail
));
5768 tail
= XCDR (XCDR (tail
)))
5770 if (EQ (XCAR (tail
), key
))
5774 return XCAR (XCDR (tail
));
5784 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5785 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5786 PIXELS non-nil means return the size in pixels, otherwise return the
5787 size in canonical character units.
5788 FRAME is the frame on which the image will be displayed. FRAME nil
5789 or omitted means use the selected frame. */)
5790 (spec
, pixels
, frame
)
5791 Lisp_Object spec
, pixels
, frame
;
5796 if (valid_image_p (spec
))
5798 struct frame
*f
= check_x_frame (frame
);
5799 int id
= lookup_image (f
, spec
);
5800 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5801 int width
= img
->width
+ 2 * img
->hmargin
;
5802 int height
= img
->height
+ 2 * img
->vmargin
;
5805 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5806 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5808 size
= Fcons (make_number (width
), make_number (height
));
5811 error ("Invalid image specification");
5817 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5818 doc
: /* Return t if image SPEC has a mask bitmap.
5819 FRAME is the frame on which the image will be displayed. FRAME nil
5820 or omitted means use the selected frame. */)
5822 Lisp_Object spec
, frame
;
5827 if (valid_image_p (spec
))
5829 struct frame
*f
= check_x_frame (frame
);
5830 int id
= lookup_image (f
, spec
);
5831 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5836 error ("Invalid image specification");
5843 /***********************************************************************
5844 Image type independent image structures
5845 ***********************************************************************/
5847 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5848 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5851 /* Allocate and return a new image structure for image specification
5852 SPEC. SPEC has a hash value of HASH. */
5854 static struct image
*
5855 make_image (spec
, hash
)
5859 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5861 xassert (valid_image_p (spec
));
5862 bzero (img
, sizeof *img
);
5863 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5864 xassert (img
->type
!= NULL
);
5866 img
->data
.lisp_val
= Qnil
;
5867 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5873 /* Free image IMG which was used on frame F, including its resources. */
5882 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5884 /* Remove IMG from the hash table of its cache. */
5886 img
->prev
->next
= img
->next
;
5888 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5891 img
->next
->prev
= img
->prev
;
5893 c
->images
[img
->id
] = NULL
;
5895 /* Free resources, then free IMG. */
5896 img
->type
->free (f
, img
);
5902 /* Prepare image IMG for display on frame F. Must be called before
5903 drawing an image. */
5906 prepare_image_for_display (f
, img
)
5912 /* We're about to display IMG, so set its timestamp to `now'. */
5914 img
->timestamp
= EMACS_SECS (t
);
5916 /* If IMG doesn't have a pixmap yet, load it now, using the image
5917 type dependent loader function. */
5918 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5919 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5923 /* Value is the number of pixels for the ascent of image IMG when
5924 drawn in face FACE. */
5927 image_ascent (img
, face
)
5931 int height
= img
->height
+ img
->vmargin
;
5934 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5937 /* This expression is arranged so that if the image can't be
5938 exactly centered, it will be moved slightly up. This is
5939 because a typical font is `top-heavy' (due to the presence
5940 uppercase letters), so the image placement should err towards
5941 being top-heavy too. It also just generally looks better. */
5942 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5944 ascent
= height
/ 2;
5947 ascent
= height
* img
->ascent
/ 100.0;
5953 /* Image background colors. */
5955 static unsigned long
5956 four_corners_best (ximg
, width
, height
)
5958 unsigned long width
, height
;
5960 unsigned long corners
[4], best
;
5963 /* Get the colors at the corners of ximg. */
5964 corners
[0] = XGetPixel (ximg
, 0, 0);
5965 corners
[1] = XGetPixel (ximg
, width
- 1, 0);
5966 corners
[2] = XGetPixel (ximg
, width
- 1, height
- 1);
5967 corners
[3] = XGetPixel (ximg
, 0, height
- 1);
5969 /* Choose the most frequently found color as background. */
5970 for (i
= best_count
= 0; i
< 4; ++i
)
5974 for (j
= n
= 0; j
< 4; ++j
)
5975 if (corners
[i
] == corners
[j
])
5979 best
= corners
[i
], best_count
= n
;
5985 /* Return the `background' field of IMG. If IMG doesn't have one yet,
5986 it is guessed heuristically. If non-zero, XIMG is an existing XImage
5987 object to use for the heuristic. */
5990 image_background (img
, f
, ximg
)
5995 if (! img
->background_valid
)
5996 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5998 int free_ximg
= !ximg
;
6001 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
6002 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6004 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
6007 XDestroyImage (ximg
);
6009 img
->background_valid
= 1;
6012 return img
->background
;
6015 /* Return the `background_transparent' field of IMG. If IMG doesn't
6016 have one yet, it is guessed heuristically. If non-zero, MASK is an
6017 existing XImage object to use for the heuristic. */
6020 image_background_transparent (img
, f
, mask
)
6025 if (! img
->background_transparent_valid
)
6026 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6030 int free_mask
= !mask
;
6033 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
6034 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6036 img
->background_transparent
6037 = !four_corners_best (mask
, img
->width
, img
->height
);
6040 XDestroyImage (mask
);
6043 img
->background_transparent
= 0;
6045 img
->background_transparent_valid
= 1;
6048 return img
->background_transparent
;
6052 /***********************************************************************
6053 Helper functions for X image types
6054 ***********************************************************************/
6056 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
6058 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
6059 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
6061 Lisp_Object color_name
,
6062 unsigned long dflt
));
6065 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6066 free the pixmap if any. MASK_P non-zero means clear the mask
6067 pixmap if any. COLORS_P non-zero means free colors allocated for
6068 the image, if any. */
6071 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
6074 int pixmap_p
, mask_p
, colors_p
;
6076 if (pixmap_p
&& img
->pixmap
)
6078 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6080 img
->background_valid
= 0;
6083 if (mask_p
&& img
->mask
)
6085 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6087 img
->background_transparent_valid
= 0;
6090 if (colors_p
&& img
->ncolors
)
6092 x_free_colors (f
, img
->colors
, img
->ncolors
);
6093 xfree (img
->colors
);
6099 /* Free X resources of image IMG which is used on frame F. */
6102 x_clear_image (f
, img
)
6107 x_clear_image_1 (f
, img
, 1, 1, 1);
6112 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6113 cannot be allocated, use DFLT. Add a newly allocated color to
6114 IMG->colors, so that it can be freed again. Value is the pixel
6117 static unsigned long
6118 x_alloc_image_color (f
, img
, color_name
, dflt
)
6121 Lisp_Object color_name
;
6125 unsigned long result
;
6127 xassert (STRINGP (color_name
));
6129 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
6131 /* This isn't called frequently so we get away with simply
6132 reallocating the color vector to the needed size, here. */
6135 (unsigned long *) xrealloc (img
->colors
,
6136 img
->ncolors
* sizeof *img
->colors
);
6137 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
6138 result
= color
.pixel
;
6148 /***********************************************************************
6150 ***********************************************************************/
6152 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
6153 static void postprocess_image
P_ ((struct frame
*, struct image
*));
6156 /* Return a new, initialized image cache that is allocated from the
6157 heap. Call free_image_cache to free an image cache. */
6159 struct image_cache
*
6162 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
6165 bzero (c
, sizeof *c
);
6167 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
6168 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
6169 c
->buckets
= (struct image
**) xmalloc (size
);
6170 bzero (c
->buckets
, size
);
6175 /* Free image cache of frame F. Be aware that X frames share images
6179 free_image_cache (f
)
6182 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6187 /* Cache should not be referenced by any frame when freed. */
6188 xassert (c
->refcount
== 0);
6190 for (i
= 0; i
< c
->used
; ++i
)
6191 free_image (f
, c
->images
[i
]);
6195 FRAME_X_IMAGE_CACHE (f
) = NULL
;
6200 /* Clear image cache of frame F. FORCE_P non-zero means free all
6201 images. FORCE_P zero means clear only images that haven't been
6202 displayed for some time. Should be called from time to time to
6203 reduce the number of loaded images. If image-eviction-seconds is
6204 non-nil, this frees images in the cache which weren't displayed for
6205 at least that many seconds. */
6208 clear_image_cache (f
, force_p
)
6212 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6214 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
6221 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
6223 /* Block input so that we won't be interrupted by a SIGIO
6224 while being in an inconsistent state. */
6227 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
6229 struct image
*img
= c
->images
[i
];
6231 && (force_p
|| img
->timestamp
< old
))
6233 free_image (f
, img
);
6238 /* We may be clearing the image cache because, for example,
6239 Emacs was iconified for a longer period of time. In that
6240 case, current matrices may still contain references to
6241 images freed above. So, clear these matrices. */
6244 Lisp_Object tail
, frame
;
6246 FOR_EACH_FRAME (tail
, frame
)
6248 struct frame
*f
= XFRAME (frame
);
6250 && FRAME_X_IMAGE_CACHE (f
) == c
)
6251 clear_current_matrices (f
);
6254 ++windows_or_buffers_changed
;
6262 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
6264 doc
: /* Clear the image cache of FRAME.
6265 FRAME nil or omitted means use the selected frame.
6266 FRAME t means clear the image caches of all frames. */)
6274 FOR_EACH_FRAME (tail
, frame
)
6275 if (FRAME_X_P (XFRAME (frame
)))
6276 clear_image_cache (XFRAME (frame
), 1);
6279 clear_image_cache (check_x_frame (frame
), 1);
6285 /* Compute masks and transform image IMG on frame F, as specified
6286 by the image's specification, */
6289 postprocess_image (f
, img
)
6293 /* Manipulation of the image's mask. */
6296 Lisp_Object conversion
, spec
;
6301 /* `:heuristic-mask t'
6303 means build a mask heuristically.
6304 `:heuristic-mask (R G B)'
6305 `:mask (heuristic (R G B))'
6306 means build a mask from color (R G B) in the
6309 means remove a mask, if any. */
6311 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6313 x_build_heuristic_mask (f
, img
, mask
);
6318 mask
= image_spec_value (spec
, QCmask
, &found_p
);
6320 if (EQ (mask
, Qheuristic
))
6321 x_build_heuristic_mask (f
, img
, Qt
);
6322 else if (CONSP (mask
)
6323 && EQ (XCAR (mask
), Qheuristic
))
6325 if (CONSP (XCDR (mask
)))
6326 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
6328 x_build_heuristic_mask (f
, img
, XCDR (mask
));
6330 else if (NILP (mask
) && found_p
&& img
->mask
)
6332 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
6338 /* Should we apply an image transformation algorithm? */
6339 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
6340 if (EQ (conversion
, Qdisabled
))
6341 x_disable_image (f
, img
);
6342 else if (EQ (conversion
, Qlaplace
))
6344 else if (EQ (conversion
, Qemboss
))
6346 else if (CONSP (conversion
)
6347 && EQ (XCAR (conversion
), Qedge_detection
))
6350 tem
= XCDR (conversion
);
6352 x_edge_detection (f
, img
,
6353 Fplist_get (tem
, QCmatrix
),
6354 Fplist_get (tem
, QCcolor_adjustment
));
6360 /* Return the id of image with Lisp specification SPEC on frame F.
6361 SPEC must be a valid Lisp image specification (see valid_image_p). */
6364 lookup_image (f
, spec
)
6368 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6372 struct gcpro gcpro1
;
6375 /* F must be a window-system frame, and SPEC must be a valid image
6377 xassert (FRAME_WINDOW_P (f
));
6378 xassert (valid_image_p (spec
));
6382 /* Look up SPEC in the hash table of the image cache. */
6383 hash
= sxhash (spec
, 0);
6384 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6386 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6387 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6390 /* If not found, create a new image and cache it. */
6393 extern Lisp_Object Qpostscript
;
6396 img
= make_image (spec
, hash
);
6397 cache_image (f
, img
);
6398 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6400 /* If we can't load the image, and we don't have a width and
6401 height, use some arbitrary width and height so that we can
6402 draw a rectangle for it. */
6403 if (img
->load_failed_p
)
6407 value
= image_spec_value (spec
, QCwidth
, NULL
);
6408 img
->width
= (INTEGERP (value
)
6409 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6410 value
= image_spec_value (spec
, QCheight
, NULL
);
6411 img
->height
= (INTEGERP (value
)
6412 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6416 /* Handle image type independent image attributes
6417 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6418 `:background COLOR'. */
6419 Lisp_Object ascent
, margin
, relief
, bg
;
6421 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6422 if (INTEGERP (ascent
))
6423 img
->ascent
= XFASTINT (ascent
);
6424 else if (EQ (ascent
, Qcenter
))
6425 img
->ascent
= CENTERED_IMAGE_ASCENT
;
6427 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6428 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6429 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
6430 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
6431 && INTEGERP (XCDR (margin
)))
6433 if (XINT (XCAR (margin
)) > 0)
6434 img
->hmargin
= XFASTINT (XCAR (margin
));
6435 if (XINT (XCDR (margin
)) > 0)
6436 img
->vmargin
= XFASTINT (XCDR (margin
));
6439 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6440 if (INTEGERP (relief
))
6442 img
->relief
= XINT (relief
);
6443 img
->hmargin
+= abs (img
->relief
);
6444 img
->vmargin
+= abs (img
->relief
);
6447 if (! img
->background_valid
)
6449 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6453 = x_alloc_image_color (f
, img
, bg
,
6454 FRAME_BACKGROUND_PIXEL (f
));
6455 img
->background_valid
= 1;
6459 /* Do image transformations and compute masks, unless we
6460 don't have the image yet. */
6461 if (!EQ (*img
->type
->type
, Qpostscript
))
6462 postprocess_image (f
, img
);
6466 xassert (!interrupt_input_blocked
);
6469 /* We're using IMG, so set its timestamp to `now'. */
6470 EMACS_GET_TIME (now
);
6471 img
->timestamp
= EMACS_SECS (now
);
6475 /* Value is the image id. */
6480 /* Cache image IMG in the image cache of frame F. */
6483 cache_image (f
, img
)
6487 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6490 /* Find a free slot in c->images. */
6491 for (i
= 0; i
< c
->used
; ++i
)
6492 if (c
->images
[i
] == NULL
)
6495 /* If no free slot found, maybe enlarge c->images. */
6496 if (i
== c
->used
&& c
->used
== c
->size
)
6499 c
->images
= (struct image
**) xrealloc (c
->images
,
6500 c
->size
* sizeof *c
->images
);
6503 /* Add IMG to c->images, and assign IMG an id. */
6509 /* Add IMG to the cache's hash table. */
6510 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6511 img
->next
= c
->buckets
[i
];
6513 img
->next
->prev
= img
;
6515 c
->buckets
[i
] = img
;
6519 /* Call FN on every image in the image cache of frame F. Used to mark
6520 Lisp Objects in the image cache. */
6523 forall_images_in_image_cache (f
, fn
)
6525 void (*fn
) P_ ((struct image
*img
));
6527 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6529 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6533 for (i
= 0; i
< c
->used
; ++i
)
6542 /***********************************************************************
6544 ***********************************************************************/
6546 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6547 XImage
**, Pixmap
*));
6548 static void x_destroy_x_image
P_ ((XImage
*));
6549 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6552 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6553 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6554 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6555 via xmalloc. Print error messages via image_error if an error
6556 occurs. Value is non-zero if successful. */
6559 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6561 int width
, height
, depth
;
6565 Display
*display
= FRAME_X_DISPLAY (f
);
6566 Screen
*screen
= FRAME_X_SCREEN (f
);
6567 Window window
= FRAME_X_WINDOW (f
);
6569 xassert (interrupt_input_blocked
);
6572 depth
= DefaultDepthOfScreen (screen
);
6573 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6574 depth
, ZPixmap
, 0, NULL
, width
, height
,
6575 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6578 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6582 /* Allocate image raster. */
6583 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6585 /* Allocate a pixmap of the same size. */
6586 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6587 if (*pixmap
== None
)
6589 x_destroy_x_image (*ximg
);
6591 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6599 /* Destroy XImage XIMG. Free XIMG->data. */
6602 x_destroy_x_image (ximg
)
6605 xassert (interrupt_input_blocked
);
6610 XDestroyImage (ximg
);
6615 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6616 are width and height of both the image and pixmap. */
6619 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6626 xassert (interrupt_input_blocked
);
6627 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6628 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6629 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6634 /***********************************************************************
6636 ***********************************************************************/
6638 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6639 static char *slurp_file
P_ ((char *, int *));
6642 /* Find image file FILE. Look in data-directory, then
6643 x-bitmap-file-path. Value is the full name of the file found, or
6644 nil if not found. */
6647 x_find_image_file (file
)
6650 Lisp_Object file_found
, search_path
;
6651 struct gcpro gcpro1
, gcpro2
;
6655 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6656 GCPRO2 (file_found
, search_path
);
6658 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6659 fd
= openp (search_path
, file
, Qnil
, &file_found
, 0);
6671 /* Read FILE into memory. Value is a pointer to a buffer allocated
6672 with xmalloc holding FILE's contents. Value is null if an error
6673 occurred. *SIZE is set to the size of the file. */
6676 slurp_file (file
, size
)
6684 if (stat (file
, &st
) == 0
6685 && (fp
= fopen (file
, "r")) != NULL
6686 && (buf
= (char *) xmalloc (st
.st_size
),
6687 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6708 /***********************************************************************
6710 ***********************************************************************/
6712 static int xbm_scan
P_ ((char **, char *, char *, int *));
6713 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6714 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6716 static int xbm_image_p
P_ ((Lisp_Object object
));
6717 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6719 static int xbm_file_p
P_ ((Lisp_Object
));
6722 /* Indices of image specification fields in xbm_format, below. */
6724 enum xbm_keyword_index
6742 /* Vector of image_keyword structures describing the format
6743 of valid XBM image specifications. */
6745 static struct image_keyword xbm_format
[XBM_LAST
] =
6747 {":type", IMAGE_SYMBOL_VALUE
, 1},
6748 {":file", IMAGE_STRING_VALUE
, 0},
6749 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6750 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6751 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6752 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6753 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6754 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6755 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6756 {":relief", IMAGE_INTEGER_VALUE
, 0},
6757 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6758 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6759 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6762 /* Structure describing the image type XBM. */
6764 static struct image_type xbm_type
=
6773 /* Tokens returned from xbm_scan. */
6782 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6783 A valid specification is a list starting with the symbol `image'
6784 The rest of the list is a property list which must contain an
6787 If the specification specifies a file to load, it must contain
6788 an entry `:file FILENAME' where FILENAME is a string.
6790 If the specification is for a bitmap loaded from memory it must
6791 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6792 WIDTH and HEIGHT are integers > 0. DATA may be:
6794 1. a string large enough to hold the bitmap data, i.e. it must
6795 have a size >= (WIDTH + 7) / 8 * HEIGHT
6797 2. a bool-vector of size >= WIDTH * HEIGHT
6799 3. a vector of strings or bool-vectors, one for each line of the
6802 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6803 may not be specified in this case because they are defined in the
6806 Both the file and data forms may contain the additional entries
6807 `:background COLOR' and `:foreground COLOR'. If not present,
6808 foreground and background of the frame on which the image is
6809 displayed is used. */
6812 xbm_image_p (object
)
6815 struct image_keyword kw
[XBM_LAST
];
6817 bcopy (xbm_format
, kw
, sizeof kw
);
6818 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6821 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6823 if (kw
[XBM_FILE
].count
)
6825 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6828 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6830 /* In-memory XBM file. */
6831 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6839 /* Entries for `:width', `:height' and `:data' must be present. */
6840 if (!kw
[XBM_WIDTH
].count
6841 || !kw
[XBM_HEIGHT
].count
6842 || !kw
[XBM_DATA
].count
)
6845 data
= kw
[XBM_DATA
].value
;
6846 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6847 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6849 /* Check type of data, and width and height against contents of
6855 /* Number of elements of the vector must be >= height. */
6856 if (XVECTOR (data
)->size
< height
)
6859 /* Each string or bool-vector in data must be large enough
6860 for one line of the image. */
6861 for (i
= 0; i
< height
; ++i
)
6863 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6867 if (XSTRING (elt
)->size
6868 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6871 else if (BOOL_VECTOR_P (elt
))
6873 if (XBOOL_VECTOR (elt
)->size
< width
)
6880 else if (STRINGP (data
))
6882 if (XSTRING (data
)->size
6883 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6886 else if (BOOL_VECTOR_P (data
))
6888 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6899 /* Scan a bitmap file. FP is the stream to read from. Value is
6900 either an enumerator from enum xbm_token, or a character for a
6901 single-character token, or 0 at end of file. If scanning an
6902 identifier, store the lexeme of the identifier in SVAL. If
6903 scanning a number, store its value in *IVAL. */
6906 xbm_scan (s
, end
, sval
, ival
)
6915 /* Skip white space. */
6916 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6921 else if (isdigit (c
))
6923 int value
= 0, digit
;
6925 if (c
== '0' && *s
< end
)
6928 if (c
== 'x' || c
== 'X')
6935 else if (c
>= 'a' && c
<= 'f')
6936 digit
= c
- 'a' + 10;
6937 else if (c
>= 'A' && c
<= 'F')
6938 digit
= c
- 'A' + 10;
6941 value
= 16 * value
+ digit
;
6944 else if (isdigit (c
))
6948 && (c
= *(*s
)++, isdigit (c
)))
6949 value
= 8 * value
+ c
- '0';
6956 && (c
= *(*s
)++, isdigit (c
)))
6957 value
= 10 * value
+ c
- '0';
6965 else if (isalpha (c
) || c
== '_')
6969 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6976 else if (c
== '/' && **s
== '*')
6978 /* C-style comment. */
6980 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6993 /* Replacement for XReadBitmapFileData which isn't available under old
6994 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6995 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6996 the image. Return in *DATA the bitmap data allocated with xmalloc.
6997 Value is non-zero if successful. DATA null means just test if
6998 CONTENTS looks like an in-memory XBM file. */
7001 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
7002 char *contents
, *end
;
7003 int *width
, *height
;
7004 unsigned char **data
;
7007 char buffer
[BUFSIZ
];
7010 int bytes_per_line
, i
, nbytes
;
7016 LA1 = xbm_scan (&s, end, buffer, &value)
7018 #define expect(TOKEN) \
7019 if (LA1 != (TOKEN)) \
7024 #define expect_ident(IDENT) \
7025 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
7030 *width
= *height
= -1;
7033 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
7035 /* Parse defines for width, height and hot-spots. */
7039 expect_ident ("define");
7040 expect (XBM_TK_IDENT
);
7042 if (LA1
== XBM_TK_NUMBER
);
7044 char *p
= strrchr (buffer
, '_');
7045 p
= p
? p
+ 1 : buffer
;
7046 if (strcmp (p
, "width") == 0)
7048 else if (strcmp (p
, "height") == 0)
7051 expect (XBM_TK_NUMBER
);
7054 if (*width
< 0 || *height
< 0)
7056 else if (data
== NULL
)
7059 /* Parse bits. Must start with `static'. */
7060 expect_ident ("static");
7061 if (LA1
== XBM_TK_IDENT
)
7063 if (strcmp (buffer
, "unsigned") == 0)
7066 expect_ident ("char");
7068 else if (strcmp (buffer
, "short") == 0)
7072 if (*width
% 16 && *width
% 16 < 9)
7075 else if (strcmp (buffer
, "char") == 0)
7083 expect (XBM_TK_IDENT
);
7089 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
7090 nbytes
= bytes_per_line
* *height
;
7091 p
= *data
= (char *) xmalloc (nbytes
);
7095 for (i
= 0; i
< nbytes
; i
+= 2)
7098 expect (XBM_TK_NUMBER
);
7101 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
7104 if (LA1
== ',' || LA1
== '}')
7112 for (i
= 0; i
< nbytes
; ++i
)
7115 expect (XBM_TK_NUMBER
);
7119 if (LA1
== ',' || LA1
== '}')
7144 /* Load XBM image IMG which will be displayed on frame F from buffer
7145 CONTENTS. END is the end of the buffer. Value is non-zero if
7149 xbm_load_image (f
, img
, contents
, end
)
7152 char *contents
, *end
;
7155 unsigned char *data
;
7158 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
7161 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7162 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7163 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7166 xassert (img
->width
> 0 && img
->height
> 0);
7168 /* Get foreground and background colors, maybe allocate colors. */
7169 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
7171 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
7172 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7175 background
= x_alloc_image_color (f
, img
, value
, background
);
7176 img
->background
= background
;
7177 img
->background_valid
= 1;
7181 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7184 img
->width
, img
->height
,
7185 foreground
, background
,
7189 if (img
->pixmap
== None
)
7191 x_clear_image (f
, img
);
7192 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
7198 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7204 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7211 return (STRINGP (data
)
7212 && xbm_read_bitmap_data (XSTRING (data
)->data
,
7213 (XSTRING (data
)->data
7214 + STRING_BYTES (XSTRING (data
))),
7219 /* Fill image IMG which is used on frame F with pixmap data. Value is
7220 non-zero if successful. */
7228 Lisp_Object file_name
;
7230 xassert (xbm_image_p (img
->spec
));
7232 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7233 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7234 if (STRINGP (file_name
))
7239 struct gcpro gcpro1
;
7241 file
= x_find_image_file (file_name
);
7243 if (!STRINGP (file
))
7245 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7250 contents
= slurp_file (XSTRING (file
)->data
, &size
);
7251 if (contents
== NULL
)
7253 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7258 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
7263 struct image_keyword fmt
[XBM_LAST
];
7266 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7267 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7270 int in_memory_file_p
= 0;
7272 /* See if data looks like an in-memory XBM file. */
7273 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7274 in_memory_file_p
= xbm_file_p (data
);
7276 /* Parse the image specification. */
7277 bcopy (xbm_format
, fmt
, sizeof fmt
);
7278 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
7281 /* Get specified width, and height. */
7282 if (!in_memory_file_p
)
7284 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
7285 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
7286 xassert (img
->width
> 0 && img
->height
> 0);
7289 /* Get foreground and background colors, maybe allocate colors. */
7290 if (fmt
[XBM_FOREGROUND
].count
7291 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
7292 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
7294 if (fmt
[XBM_BACKGROUND
].count
7295 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
7296 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7299 if (in_memory_file_p
)
7300 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
7301 (XSTRING (data
)->data
7302 + STRING_BYTES (XSTRING (data
))));
7309 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7311 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7312 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7314 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7316 bcopy (XSTRING (line
)->data
, p
, nbytes
);
7318 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7321 else if (STRINGP (data
))
7322 bits
= XSTRING (data
)->data
;
7324 bits
= XBOOL_VECTOR (data
)->data
;
7326 /* Create the pixmap. */
7327 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7329 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7332 img
->width
, img
->height
,
7333 foreground
, background
,
7339 image_error ("Unable to create pixmap for XBM image `%s'",
7341 x_clear_image (f
, img
);
7351 /***********************************************************************
7353 ***********************************************************************/
7357 static int xpm_image_p
P_ ((Lisp_Object object
));
7358 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7359 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7361 #include "X11/xpm.h"
7363 /* The symbol `xpm' identifying XPM-format images. */
7367 /* Indices of image specification fields in xpm_format, below. */
7369 enum xpm_keyword_index
7385 /* Vector of image_keyword structures describing the format
7386 of valid XPM image specifications. */
7388 static struct image_keyword xpm_format
[XPM_LAST
] =
7390 {":type", IMAGE_SYMBOL_VALUE
, 1},
7391 {":file", IMAGE_STRING_VALUE
, 0},
7392 {":data", IMAGE_STRING_VALUE
, 0},
7393 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7394 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7395 {":relief", IMAGE_INTEGER_VALUE
, 0},
7396 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7397 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7398 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7399 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7400 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7403 /* Structure describing the image type XBM. */
7405 static struct image_type xpm_type
=
7415 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7416 functions for allocating image colors. Our own functions handle
7417 color allocation failures more gracefully than the ones on the XPM
7420 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7421 #define ALLOC_XPM_COLORS
7424 #ifdef ALLOC_XPM_COLORS
7426 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
7427 static void xpm_free_color_cache
P_ ((void));
7428 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
7429 static int xpm_color_bucket
P_ ((char *));
7430 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
7433 /* An entry in a hash table used to cache color definitions of named
7434 colors. This cache is necessary to speed up XPM image loading in
7435 case we do color allocations ourselves. Without it, we would need
7436 a call to XParseColor per pixel in the image. */
7438 struct xpm_cached_color
7440 /* Next in collision chain. */
7441 struct xpm_cached_color
*next
;
7443 /* Color definition (RGB and pixel color). */
7450 /* The hash table used for the color cache, and its bucket vector
7453 #define XPM_COLOR_CACHE_BUCKETS 1001
7454 struct xpm_cached_color
**xpm_color_cache
;
7456 /* Initialize the color cache. */
7459 xpm_init_color_cache (f
, attrs
)
7461 XpmAttributes
*attrs
;
7463 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
7464 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
7465 memset (xpm_color_cache
, 0, nbytes
);
7466 init_color_table ();
7468 if (attrs
->valuemask
& XpmColorSymbols
)
7473 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
7474 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7475 attrs
->colorsymbols
[i
].value
, &color
))
7477 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
7479 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
7485 /* Free the color cache. */
7488 xpm_free_color_cache ()
7490 struct xpm_cached_color
*p
, *next
;
7493 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
7494 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
7500 xfree (xpm_color_cache
);
7501 xpm_color_cache
= NULL
;
7502 free_color_table ();
7506 /* Return the bucket index for color named COLOR_NAME in the color
7510 xpm_color_bucket (color_name
)
7516 for (s
= color_name
; *s
; ++s
)
7518 return h
%= XPM_COLOR_CACHE_BUCKETS
;
7522 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7523 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7526 static struct xpm_cached_color
*
7527 xpm_cache_color (f
, color_name
, color
, bucket
)
7534 struct xpm_cached_color
*p
;
7537 bucket
= xpm_color_bucket (color_name
);
7539 nbytes
= sizeof *p
+ strlen (color_name
);
7540 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
7541 strcpy (p
->name
, color_name
);
7543 p
->next
= xpm_color_cache
[bucket
];
7544 xpm_color_cache
[bucket
] = p
;
7549 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7550 return the cached definition in *COLOR. Otherwise, make a new
7551 entry in the cache and allocate the color. Value is zero if color
7552 allocation failed. */
7555 xpm_lookup_color (f
, color_name
, color
)
7560 struct xpm_cached_color
*p
;
7561 int h
= xpm_color_bucket (color_name
);
7563 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7564 if (strcmp (p
->name
, color_name
) == 0)
7569 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7572 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7574 p
= xpm_cache_color (f
, color_name
, color
, h
);
7581 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7582 CLOSURE is a pointer to the frame on which we allocate the
7583 color. Return in *COLOR the allocated color. Value is non-zero
7587 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7594 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7598 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7599 is a pointer to the frame on which we allocate the color. Value is
7600 non-zero if successful. */
7603 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7613 #endif /* ALLOC_XPM_COLORS */
7616 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7617 for XPM images. Such a list must consist of conses whose car and
7621 xpm_valid_color_symbols_p (color_symbols
)
7622 Lisp_Object color_symbols
;
7624 while (CONSP (color_symbols
))
7626 Lisp_Object sym
= XCAR (color_symbols
);
7628 || !STRINGP (XCAR (sym
))
7629 || !STRINGP (XCDR (sym
)))
7631 color_symbols
= XCDR (color_symbols
);
7634 return NILP (color_symbols
);
7638 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7641 xpm_image_p (object
)
7644 struct image_keyword fmt
[XPM_LAST
];
7645 bcopy (xpm_format
, fmt
, sizeof fmt
);
7646 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7647 /* Either `:file' or `:data' must be present. */
7648 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7649 /* Either no `:color-symbols' or it's a list of conses
7650 whose car and cdr are strings. */
7651 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7652 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7656 /* Load image IMG which will be displayed on frame F. Value is
7657 non-zero if successful. */
7665 XpmAttributes attrs
;
7666 Lisp_Object specified_file
, color_symbols
;
7668 /* Configure the XPM lib. Use the visual of frame F. Allocate
7669 close colors. Return colors allocated. */
7670 bzero (&attrs
, sizeof attrs
);
7671 attrs
.visual
= FRAME_X_VISUAL (f
);
7672 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7673 attrs
.valuemask
|= XpmVisual
;
7674 attrs
.valuemask
|= XpmColormap
;
7676 #ifdef ALLOC_XPM_COLORS
7677 /* Allocate colors with our own functions which handle
7678 failing color allocation more gracefully. */
7679 attrs
.color_closure
= f
;
7680 attrs
.alloc_color
= xpm_alloc_color
;
7681 attrs
.free_colors
= xpm_free_colors
;
7682 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7683 #else /* not ALLOC_XPM_COLORS */
7684 /* Let the XPM lib allocate colors. */
7685 attrs
.valuemask
|= XpmReturnAllocPixels
;
7686 #ifdef XpmAllocCloseColors
7687 attrs
.alloc_close_colors
= 1;
7688 attrs
.valuemask
|= XpmAllocCloseColors
;
7689 #else /* not XpmAllocCloseColors */
7690 attrs
.closeness
= 600;
7691 attrs
.valuemask
|= XpmCloseness
;
7692 #endif /* not XpmAllocCloseColors */
7693 #endif /* ALLOC_XPM_COLORS */
7695 /* If image specification contains symbolic color definitions, add
7696 these to `attrs'. */
7697 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7698 if (CONSP (color_symbols
))
7701 XpmColorSymbol
*xpm_syms
;
7704 attrs
.valuemask
|= XpmColorSymbols
;
7706 /* Count number of symbols. */
7707 attrs
.numsymbols
= 0;
7708 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7711 /* Allocate an XpmColorSymbol array. */
7712 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7713 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7714 bzero (xpm_syms
, size
);
7715 attrs
.colorsymbols
= xpm_syms
;
7717 /* Fill the color symbol array. */
7718 for (tail
= color_symbols
, i
= 0;
7720 ++i
, tail
= XCDR (tail
))
7722 Lisp_Object name
= XCAR (XCAR (tail
));
7723 Lisp_Object color
= XCDR (XCAR (tail
));
7724 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7725 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7726 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7727 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7731 /* Create a pixmap for the image, either from a file, or from a
7732 string buffer containing data in the same format as an XPM file. */
7733 #ifdef ALLOC_XPM_COLORS
7734 xpm_init_color_cache (f
, &attrs
);
7737 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7738 if (STRINGP (specified_file
))
7740 Lisp_Object file
= x_find_image_file (specified_file
);
7741 if (!STRINGP (file
))
7743 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7747 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7748 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7753 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7754 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7755 XSTRING (buffer
)->data
,
7756 &img
->pixmap
, &img
->mask
,
7760 if (rc
== XpmSuccess
)
7762 #ifdef ALLOC_XPM_COLORS
7763 img
->colors
= colors_in_color_table (&img
->ncolors
);
7764 #else /* not ALLOC_XPM_COLORS */
7767 img
->ncolors
= attrs
.nalloc_pixels
;
7768 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7769 * sizeof *img
->colors
);
7770 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7772 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7773 #ifdef DEBUG_X_COLORS
7774 register_color (img
->colors
[i
]);
7777 #endif /* not ALLOC_XPM_COLORS */
7779 img
->width
= attrs
.width
;
7780 img
->height
= attrs
.height
;
7781 xassert (img
->width
> 0 && img
->height
> 0);
7783 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7784 XpmFreeAttributes (&attrs
);
7791 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7794 case XpmFileInvalid
:
7795 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7799 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7802 case XpmColorFailed
:
7803 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7807 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7812 #ifdef ALLOC_XPM_COLORS
7813 xpm_free_color_cache ();
7815 return rc
== XpmSuccess
;
7818 #endif /* HAVE_XPM != 0 */
7821 /***********************************************************************
7823 ***********************************************************************/
7825 /* An entry in the color table mapping an RGB color to a pixel color. */
7830 unsigned long pixel
;
7832 /* Next in color table collision list. */
7833 struct ct_color
*next
;
7836 /* The bucket vector size to use. Must be prime. */
7840 /* Value is a hash of the RGB color given by R, G, and B. */
7842 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7844 /* The color hash table. */
7846 struct ct_color
**ct_table
;
7848 /* Number of entries in the color table. */
7850 int ct_colors_allocated
;
7852 /* Initialize the color table. */
7857 int size
= CT_SIZE
* sizeof (*ct_table
);
7858 ct_table
= (struct ct_color
**) xmalloc (size
);
7859 bzero (ct_table
, size
);
7860 ct_colors_allocated
= 0;
7864 /* Free memory associated with the color table. */
7870 struct ct_color
*p
, *next
;
7872 for (i
= 0; i
< CT_SIZE
; ++i
)
7873 for (p
= ct_table
[i
]; p
; p
= next
)
7884 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7885 entry for that color already is in the color table, return the
7886 pixel color of that entry. Otherwise, allocate a new color for R,
7887 G, B, and make an entry in the color table. */
7889 static unsigned long
7890 lookup_rgb_color (f
, r
, g
, b
)
7894 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7895 int i
= hash
% CT_SIZE
;
7898 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7899 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7912 cmap
= FRAME_X_COLORMAP (f
);
7913 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7917 ++ct_colors_allocated
;
7919 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7923 p
->pixel
= color
.pixel
;
7924 p
->next
= ct_table
[i
];
7928 return FRAME_FOREGROUND_PIXEL (f
);
7935 /* Look up pixel color PIXEL which is used on frame F in the color
7936 table. If not already present, allocate it. Value is PIXEL. */
7938 static unsigned long
7939 lookup_pixel_color (f
, pixel
)
7941 unsigned long pixel
;
7943 int i
= pixel
% CT_SIZE
;
7946 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7947 if (p
->pixel
== pixel
)
7956 cmap
= FRAME_X_COLORMAP (f
);
7957 color
.pixel
= pixel
;
7958 x_query_color (f
, &color
);
7959 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7963 ++ct_colors_allocated
;
7965 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7970 p
->next
= ct_table
[i
];
7974 return FRAME_FOREGROUND_PIXEL (f
);
7981 /* Value is a vector of all pixel colors contained in the color table,
7982 allocated via xmalloc. Set *N to the number of colors. */
7984 static unsigned long *
7985 colors_in_color_table (n
)
7990 unsigned long *colors
;
7992 if (ct_colors_allocated
== 0)
7999 colors
= (unsigned long *) xmalloc (ct_colors_allocated
8001 *n
= ct_colors_allocated
;
8003 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
8004 for (p
= ct_table
[i
]; p
; p
= p
->next
)
8005 colors
[j
++] = p
->pixel
;
8013 /***********************************************************************
8015 ***********************************************************************/
8017 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
8018 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
8019 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
8021 /* Non-zero means draw a cross on images having `:conversion
8024 int cross_disabled_images
;
8026 /* Edge detection matrices for different edge-detection
8029 static int emboss_matrix
[9] = {
8031 2, -1, 0, /* y - 1 */
8033 0, 1, -2 /* y + 1 */
8036 static int laplace_matrix
[9] = {
8038 1, 0, 0, /* y - 1 */
8040 0, 0, -1 /* y + 1 */
8043 /* Value is the intensity of the color whose red/green/blue values
8046 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8049 /* On frame F, return an array of XColor structures describing image
8050 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8051 non-zero means also fill the red/green/blue members of the XColor
8052 structures. Value is a pointer to the array of XColors structures,
8053 allocated with xmalloc; it must be freed by the caller. */
8056 x_to_xcolors (f
, img
, rgb_p
)
8065 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
8067 /* Get the X image IMG->pixmap. */
8068 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8069 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8071 /* Fill the `pixel' members of the XColor array. I wished there
8072 were an easy and portable way to circumvent XGetPixel. */
8074 for (y
= 0; y
< img
->height
; ++y
)
8078 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8079 p
->pixel
= XGetPixel (ximg
, x
, y
);
8082 x_query_colors (f
, row
, img
->width
);
8085 XDestroyImage (ximg
);
8090 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8091 RGB members are set. F is the frame on which this all happens.
8092 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8095 x_from_xcolors (f
, img
, colors
)
8105 init_color_table ();
8107 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
8110 for (y
= 0; y
< img
->height
; ++y
)
8111 for (x
= 0; x
< img
->width
; ++x
, ++p
)
8113 unsigned long pixel
;
8114 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
8115 XPutPixel (oimg
, x
, y
, pixel
);
8119 x_clear_image_1 (f
, img
, 1, 0, 1);
8121 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
8122 x_destroy_x_image (oimg
);
8123 img
->pixmap
= pixmap
;
8124 img
->colors
= colors_in_color_table (&img
->ncolors
);
8125 free_color_table ();
8129 /* On frame F, perform edge-detection on image IMG.
8131 MATRIX is a nine-element array specifying the transformation
8132 matrix. See emboss_matrix for an example.
8134 COLOR_ADJUST is a color adjustment added to each pixel of the
8138 x_detect_edges (f
, img
, matrix
, color_adjust
)
8141 int matrix
[9], color_adjust
;
8143 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8147 for (i
= sum
= 0; i
< 9; ++i
)
8148 sum
+= abs (matrix
[i
]);
8150 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8152 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
8154 for (y
= 0; y
< img
->height
; ++y
)
8156 p
= COLOR (new, 0, y
);
8157 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8158 p
= COLOR (new, img
->width
- 1, y
);
8159 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8162 for (x
= 1; x
< img
->width
- 1; ++x
)
8164 p
= COLOR (new, x
, 0);
8165 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8166 p
= COLOR (new, x
, img
->height
- 1);
8167 p
->red
= p
->green
= p
->blue
= 0xffff/2;
8170 for (y
= 1; y
< img
->height
- 1; ++y
)
8172 p
= COLOR (new, 1, y
);
8174 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
8176 int r
, g
, b
, y1
, x1
;
8179 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
8180 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
8183 XColor
*t
= COLOR (colors
, x1
, y1
);
8184 r
+= matrix
[i
] * t
->red
;
8185 g
+= matrix
[i
] * t
->green
;
8186 b
+= matrix
[i
] * t
->blue
;
8189 r
= (r
/ sum
+ color_adjust
) & 0xffff;
8190 g
= (g
/ sum
+ color_adjust
) & 0xffff;
8191 b
= (b
/ sum
+ color_adjust
) & 0xffff;
8192 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
8197 x_from_xcolors (f
, img
, new);
8203 /* Perform the pre-defined `emboss' edge-detection on image IMG
8211 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
8215 /* Perform the pre-defined `laplace' edge-detection on image IMG
8223 x_detect_edges (f
, img
, laplace_matrix
, 45000);
8227 /* Perform edge-detection on image IMG on frame F, with specified
8228 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8230 MATRIX must be either
8232 - a list of at least 9 numbers in row-major form
8233 - a vector of at least 9 numbers
8235 COLOR_ADJUST nil means use a default; otherwise it must be a
8239 x_edge_detection (f
, img
, matrix
, color_adjust
)
8242 Lisp_Object matrix
, color_adjust
;
8250 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
8251 ++i
, matrix
= XCDR (matrix
))
8252 trans
[i
] = XFLOATINT (XCAR (matrix
));
8254 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
8256 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
8257 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
8260 if (NILP (color_adjust
))
8261 color_adjust
= make_number (0xffff / 2);
8263 if (i
== 9 && NUMBERP (color_adjust
))
8264 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
8268 /* Transform image IMG on frame F so that it looks disabled. */
8271 x_disable_image (f
, img
)
8275 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8277 if (dpyinfo
->n_planes
>= 2)
8279 /* Color (or grayscale). Convert to gray, and equalize. Just
8280 drawing such images with a stipple can look very odd, so
8281 we're using this method instead. */
8282 XColor
*colors
= x_to_xcolors (f
, img
, 1);
8284 const int h
= 15000;
8285 const int l
= 30000;
8287 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
8291 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
8292 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
8293 p
->red
= p
->green
= p
->blue
= i2
;
8296 x_from_xcolors (f
, img
, colors
);
8299 /* Draw a cross over the disabled image, if we must or if we
8301 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
8303 Display
*dpy
= FRAME_X_DISPLAY (f
);
8306 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
8307 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
8308 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
8309 img
->width
- 1, img
->height
- 1);
8310 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
8316 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
8317 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
8318 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
8319 img
->width
- 1, img
->height
- 1);
8320 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
8328 /* Build a mask for image IMG which is used on frame F. FILE is the
8329 name of an image file, for error messages. HOW determines how to
8330 determine the background color of IMG. If it is a list '(R G B)',
8331 with R, G, and B being integers >= 0, take that as the color of the
8332 background. Otherwise, determine the background color of IMG
8333 heuristically. Value is non-zero if successful. */
8336 x_build_heuristic_mask (f
, img
, how
)
8341 Display
*dpy
= FRAME_X_DISPLAY (f
);
8342 XImage
*ximg
, *mask_img
;
8343 int x
, y
, rc
, use_img_background
;
8344 unsigned long bg
= 0;
8348 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
8350 img
->background_transparent_valid
= 0;
8353 /* Create an image and pixmap serving as mask. */
8354 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
8355 &mask_img
, &img
->mask
);
8359 /* Get the X image of IMG->pixmap. */
8360 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
8363 /* Determine the background color of ximg. If HOW is `(R G B)'
8364 take that as color. Otherwise, use the image's background color. */
8365 use_img_background
= 1;
8371 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
8373 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
8377 if (i
== 3 && NILP (how
))
8379 char color_name
[30];
8380 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
8381 bg
= x_alloc_image_color (f
, img
, build_string (color_name
), 0);
8382 use_img_background
= 0;
8386 if (use_img_background
)
8387 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
8389 /* Set all bits in mask_img to 1 whose color in ximg is different
8390 from the background color bg. */
8391 for (y
= 0; y
< img
->height
; ++y
)
8392 for (x
= 0; x
< img
->width
; ++x
)
8393 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
8395 /* Fill in the background_transparent field while we have the mask handy. */
8396 image_background_transparent (img
, f
, mask_img
);
8398 /* Put mask_img into img->mask. */
8399 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8400 x_destroy_x_image (mask_img
);
8401 XDestroyImage (ximg
);
8408 /***********************************************************************
8409 PBM (mono, gray, color)
8410 ***********************************************************************/
8412 static int pbm_image_p
P_ ((Lisp_Object object
));
8413 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
8414 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
8416 /* The symbol `pbm' identifying images of this type. */
8420 /* Indices of image specification fields in gs_format, below. */
8422 enum pbm_keyword_index
8438 /* Vector of image_keyword structures describing the format
8439 of valid user-defined image specifications. */
8441 static struct image_keyword pbm_format
[PBM_LAST
] =
8443 {":type", IMAGE_SYMBOL_VALUE
, 1},
8444 {":file", IMAGE_STRING_VALUE
, 0},
8445 {":data", IMAGE_STRING_VALUE
, 0},
8446 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8447 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8448 {":relief", IMAGE_INTEGER_VALUE
, 0},
8449 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8450 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8451 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8452 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
8453 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8456 /* Structure describing the image type `pbm'. */
8458 static struct image_type pbm_type
=
8468 /* Return non-zero if OBJECT is a valid PBM image specification. */
8471 pbm_image_p (object
)
8474 struct image_keyword fmt
[PBM_LAST
];
8476 bcopy (pbm_format
, fmt
, sizeof fmt
);
8478 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
8481 /* Must specify either :data or :file. */
8482 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
8486 /* Scan a decimal number from *S and return it. Advance *S while
8487 reading the number. END is the end of the string. Value is -1 at
8491 pbm_scan_number (s
, end
)
8492 unsigned char **s
, *end
;
8494 int c
= 0, val
= -1;
8498 /* Skip white-space. */
8499 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
8504 /* Skip comment to end of line. */
8505 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
8508 else if (isdigit (c
))
8510 /* Read decimal number. */
8512 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
8513 val
= 10 * val
+ c
- '0';
8524 /* Load PBM image IMG for use on frame F. */
8532 int width
, height
, max_color_idx
= 0;
8534 Lisp_Object file
, specified_file
;
8535 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8536 struct gcpro gcpro1
;
8537 unsigned char *contents
= NULL
;
8538 unsigned char *end
, *p
;
8541 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8545 if (STRINGP (specified_file
))
8547 file
= x_find_image_file (specified_file
);
8548 if (!STRINGP (file
))
8550 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8555 contents
= slurp_file (XSTRING (file
)->data
, &size
);
8556 if (contents
== NULL
)
8558 image_error ("Error reading `%s'", file
, Qnil
);
8564 end
= contents
+ size
;
8569 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8570 p
= XSTRING (data
)->data
;
8571 end
= p
+ STRING_BYTES (XSTRING (data
));
8574 /* Check magic number. */
8575 if (end
- p
< 2 || *p
++ != 'P')
8577 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8587 raw_p
= 0, type
= PBM_MONO
;
8591 raw_p
= 0, type
= PBM_GRAY
;
8595 raw_p
= 0, type
= PBM_COLOR
;
8599 raw_p
= 1, type
= PBM_MONO
;
8603 raw_p
= 1, type
= PBM_GRAY
;
8607 raw_p
= 1, type
= PBM_COLOR
;
8611 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8615 /* Read width, height, maximum color-component. Characters
8616 starting with `#' up to the end of a line are ignored. */
8617 width
= pbm_scan_number (&p
, end
);
8618 height
= pbm_scan_number (&p
, end
);
8620 if (type
!= PBM_MONO
)
8622 max_color_idx
= pbm_scan_number (&p
, end
);
8623 if (raw_p
&& max_color_idx
> 255)
8624 max_color_idx
= 255;
8629 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8632 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8633 &ximg
, &img
->pixmap
))
8636 /* Initialize the color hash table. */
8637 init_color_table ();
8639 if (type
== PBM_MONO
)
8642 struct image_keyword fmt
[PBM_LAST
];
8643 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8644 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8646 /* Parse the image specification. */
8647 bcopy (pbm_format
, fmt
, sizeof fmt
);
8648 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8650 /* Get foreground and background colors, maybe allocate colors. */
8651 if (fmt
[PBM_FOREGROUND
].count
8652 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
8653 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8654 if (fmt
[PBM_BACKGROUND
].count
8655 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
8657 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8658 img
->background
= bg
;
8659 img
->background_valid
= 1;
8662 for (y
= 0; y
< height
; ++y
)
8663 for (x
= 0; x
< width
; ++x
)
8673 g
= pbm_scan_number (&p
, end
);
8675 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8680 for (y
= 0; y
< height
; ++y
)
8681 for (x
= 0; x
< width
; ++x
)
8685 if (type
== PBM_GRAY
)
8686 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8695 r
= pbm_scan_number (&p
, end
);
8696 g
= pbm_scan_number (&p
, end
);
8697 b
= pbm_scan_number (&p
, end
);
8700 if (r
< 0 || g
< 0 || b
< 0)
8704 XDestroyImage (ximg
);
8705 image_error ("Invalid pixel value in image `%s'",
8710 /* RGB values are now in the range 0..max_color_idx.
8711 Scale this to the range 0..0xffff supported by X. */
8712 r
= (double) r
* 65535 / max_color_idx
;
8713 g
= (double) g
* 65535 / max_color_idx
;
8714 b
= (double) b
* 65535 / max_color_idx
;
8715 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8719 /* Store in IMG->colors the colors allocated for the image, and
8720 free the color table. */
8721 img
->colors
= colors_in_color_table (&img
->ncolors
);
8722 free_color_table ();
8724 /* Maybe fill in the background field while we have ximg handy. */
8725 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8726 IMAGE_BACKGROUND (img
, f
, ximg
);
8728 /* Put the image into a pixmap. */
8729 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8730 x_destroy_x_image (ximg
);
8733 img
->height
= height
;
8742 /***********************************************************************
8744 ***********************************************************************/
8750 /* Function prototypes. */
8752 static int png_image_p
P_ ((Lisp_Object object
));
8753 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8755 /* The symbol `png' identifying images of this type. */
8759 /* Indices of image specification fields in png_format, below. */
8761 enum png_keyword_index
8776 /* Vector of image_keyword structures describing the format
8777 of valid user-defined image specifications. */
8779 static struct image_keyword png_format
[PNG_LAST
] =
8781 {":type", IMAGE_SYMBOL_VALUE
, 1},
8782 {":data", IMAGE_STRING_VALUE
, 0},
8783 {":file", IMAGE_STRING_VALUE
, 0},
8784 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8785 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8786 {":relief", IMAGE_INTEGER_VALUE
, 0},
8787 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8788 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8789 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8790 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8793 /* Structure describing the image type `png'. */
8795 static struct image_type png_type
=
8805 /* Return non-zero if OBJECT is a valid PNG image specification. */
8808 png_image_p (object
)
8811 struct image_keyword fmt
[PNG_LAST
];
8812 bcopy (png_format
, fmt
, sizeof fmt
);
8814 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8817 /* Must specify either the :data or :file keyword. */
8818 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8822 /* Error and warning handlers installed when the PNG library
8826 my_png_error (png_ptr
, msg
)
8827 png_struct
*png_ptr
;
8830 xassert (png_ptr
!= NULL
);
8831 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8832 longjmp (png_ptr
->jmpbuf
, 1);
8837 my_png_warning (png_ptr
, msg
)
8838 png_struct
*png_ptr
;
8841 xassert (png_ptr
!= NULL
);
8842 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8845 /* Memory source for PNG decoding. */
8847 struct png_memory_storage
8849 unsigned char *bytes
; /* The data */
8850 size_t len
; /* How big is it? */
8851 int index
; /* Where are we? */
8855 /* Function set as reader function when reading PNG image from memory.
8856 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8857 bytes from the input to DATA. */
8860 png_read_from_memory (png_ptr
, data
, length
)
8861 png_structp png_ptr
;
8865 struct png_memory_storage
*tbr
8866 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8868 if (length
> tbr
->len
- tbr
->index
)
8869 png_error (png_ptr
, "Read error");
8871 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8872 tbr
->index
= tbr
->index
+ length
;
8875 /* Load PNG image IMG for use on frame F. Value is non-zero if
8883 Lisp_Object file
, specified_file
;
8884 Lisp_Object specified_data
;
8886 XImage
*ximg
, *mask_img
= NULL
;
8887 struct gcpro gcpro1
;
8888 png_struct
*png_ptr
= NULL
;
8889 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8890 FILE *volatile fp
= NULL
;
8892 png_byte
* volatile pixels
= NULL
;
8893 png_byte
** volatile rows
= NULL
;
8894 png_uint_32 width
, height
;
8895 int bit_depth
, color_type
, interlace_type
;
8897 png_uint_32 row_bytes
;
8900 double screen_gamma
, image_gamma
;
8902 struct png_memory_storage tbr
; /* Data to be read */
8904 /* Find out what file to load. */
8905 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8906 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8910 if (NILP (specified_data
))
8912 file
= x_find_image_file (specified_file
);
8913 if (!STRINGP (file
))
8915 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8920 /* Open the image file. */
8921 fp
= fopen (XSTRING (file
)->data
, "rb");
8924 image_error ("Cannot open image file `%s'", file
, Qnil
);
8930 /* Check PNG signature. */
8931 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8932 || !png_check_sig (sig
, sizeof sig
))
8934 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8942 /* Read from memory. */
8943 tbr
.bytes
= XSTRING (specified_data
)->data
;
8944 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8947 /* Check PNG signature. */
8948 if (tbr
.len
< sizeof sig
8949 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8951 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8956 /* Need to skip past the signature. */
8957 tbr
.bytes
+= sizeof (sig
);
8960 /* Initialize read and info structs for PNG lib. */
8961 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8962 my_png_error
, my_png_warning
);
8965 if (fp
) fclose (fp
);
8970 info_ptr
= png_create_info_struct (png_ptr
);
8973 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8974 if (fp
) fclose (fp
);
8979 end_info
= png_create_info_struct (png_ptr
);
8982 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8983 if (fp
) fclose (fp
);
8988 /* Set error jump-back. We come back here when the PNG library
8989 detects an error. */
8990 if (setjmp (png_ptr
->jmpbuf
))
8994 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8997 if (fp
) fclose (fp
);
9002 /* Read image info. */
9003 if (!NILP (specified_data
))
9004 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
9006 png_init_io (png_ptr
, fp
);
9008 png_set_sig_bytes (png_ptr
, sizeof sig
);
9009 png_read_info (png_ptr
, info_ptr
);
9010 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
9011 &interlace_type
, NULL
, NULL
);
9013 /* If image contains simply transparency data, we prefer to
9014 construct a clipping mask. */
9015 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
9020 /* This function is easier to write if we only have to handle
9021 one data format: RGB or RGBA with 8 bits per channel. Let's
9022 transform other formats into that format. */
9024 /* Strip more than 8 bits per channel. */
9025 if (bit_depth
== 16)
9026 png_set_strip_16 (png_ptr
);
9028 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
9030 png_set_expand (png_ptr
);
9032 /* Convert grayscale images to RGB. */
9033 if (color_type
== PNG_COLOR_TYPE_GRAY
9034 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
9035 png_set_gray_to_rgb (png_ptr
);
9037 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
9039 /* Tell the PNG lib to handle gamma correction for us. */
9041 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9042 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
9043 /* The libpng documentation says this is right in this case. */
9044 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9047 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
9048 /* Image contains gamma information. */
9049 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
9051 /* Use the standard default for the image gamma. */
9052 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
9054 /* Handle alpha channel by combining the image with a background
9055 color. Do this only if a real alpha channel is supplied. For
9056 simple transparency, we prefer a clipping mask. */
9059 png_color_16
*image_bg
;
9060 Lisp_Object specified_bg
9061 = image_spec_value (img
->spec
, QCbackground
, NULL
);
9063 if (STRINGP (specified_bg
))
9064 /* The user specified `:background', use that. */
9067 if (x_defined_color (f
, XSTRING (specified_bg
)->data
, &color
, 0))
9069 png_color_16 user_bg
;
9071 bzero (&user_bg
, sizeof user_bg
);
9072 user_bg
.red
= color
.red
;
9073 user_bg
.green
= color
.green
;
9074 user_bg
.blue
= color
.blue
;
9076 png_set_background (png_ptr
, &user_bg
,
9077 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9080 else if (png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
9081 /* Image contains a background color with which to
9082 combine the image. */
9083 png_set_background (png_ptr
, image_bg
,
9084 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
9087 /* Image does not contain a background color with which
9088 to combine the image data via an alpha channel. Use
9089 the frame's background instead. */
9092 png_color_16 frame_background
;
9094 cmap
= FRAME_X_COLORMAP (f
);
9095 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
9096 x_query_color (f
, &color
);
9098 bzero (&frame_background
, sizeof frame_background
);
9099 frame_background
.red
= color
.red
;
9100 frame_background
.green
= color
.green
;
9101 frame_background
.blue
= color
.blue
;
9103 png_set_background (png_ptr
, &frame_background
,
9104 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
9108 /* Update info structure. */
9109 png_read_update_info (png_ptr
, info_ptr
);
9111 /* Get number of channels. Valid values are 1 for grayscale images
9112 and images with a palette, 2 for grayscale images with transparency
9113 information (alpha channel), 3 for RGB images, and 4 for RGB
9114 images with alpha channel, i.e. RGBA. If conversions above were
9115 sufficient we should only have 3 or 4 channels here. */
9116 channels
= png_get_channels (png_ptr
, info_ptr
);
9117 xassert (channels
== 3 || channels
== 4);
9119 /* Number of bytes needed for one row of the image. */
9120 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
9122 /* Allocate memory for the image. */
9123 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
9124 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
9125 for (i
= 0; i
< height
; ++i
)
9126 rows
[i
] = pixels
+ i
* row_bytes
;
9128 /* Read the entire image. */
9129 png_read_image (png_ptr
, rows
);
9130 png_read_end (png_ptr
, info_ptr
);
9137 /* Create the X image and pixmap. */
9138 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
9142 /* Create an image and pixmap serving as mask if the PNG image
9143 contains an alpha channel. */
9146 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
9147 &mask_img
, &img
->mask
))
9149 x_destroy_x_image (ximg
);
9150 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
9155 /* Fill the X image and mask from PNG data. */
9156 init_color_table ();
9158 for (y
= 0; y
< height
; ++y
)
9160 png_byte
*p
= rows
[y
];
9162 for (x
= 0; x
< width
; ++x
)
9169 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
9171 /* An alpha channel, aka mask channel, associates variable
9172 transparency with an image. Where other image formats
9173 support binary transparency---fully transparent or fully
9174 opaque---PNG allows up to 254 levels of partial transparency.
9175 The PNG library implements partial transparency by combining
9176 the image with a specified background color.
9178 I'm not sure how to handle this here nicely: because the
9179 background on which the image is displayed may change, for
9180 real alpha channel support, it would be necessary to create
9181 a new image for each possible background.
9183 What I'm doing now is that a mask is created if we have
9184 boolean transparency information. Otherwise I'm using
9185 the frame's background color to combine the image with. */
9190 XPutPixel (mask_img
, x
, y
, *p
> 0);
9196 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9197 /* Set IMG's background color from the PNG image, unless the user
9201 if (png_get_bKGD (png_ptr
, info_ptr
, &bg
))
9203 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
9204 img
->background_valid
= 1;
9208 /* Remember colors allocated for this image. */
9209 img
->colors
= colors_in_color_table (&img
->ncolors
);
9210 free_color_table ();
9213 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
9218 img
->height
= height
;
9220 /* Maybe fill in the background field while we have ximg handy. */
9221 IMAGE_BACKGROUND (img
, f
, ximg
);
9223 /* Put the image into the pixmap, then free the X image and its buffer. */
9224 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9225 x_destroy_x_image (ximg
);
9227 /* Same for the mask. */
9230 /* Fill in the background_transparent field while we have the mask
9232 image_background_transparent (img
, f
, mask_img
);
9234 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
9235 x_destroy_x_image (mask_img
);
9242 #endif /* HAVE_PNG != 0 */
9246 /***********************************************************************
9248 ***********************************************************************/
9252 /* Work around a warning about HAVE_STDLIB_H being redefined in
9254 #ifdef HAVE_STDLIB_H
9255 #define HAVE_STDLIB_H_1
9256 #undef HAVE_STDLIB_H
9257 #endif /* HAVE_STLIB_H */
9259 #include <jpeglib.h>
9263 #ifdef HAVE_STLIB_H_1
9264 #define HAVE_STDLIB_H 1
9267 static int jpeg_image_p
P_ ((Lisp_Object object
));
9268 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
9270 /* The symbol `jpeg' identifying images of this type. */
9274 /* Indices of image specification fields in gs_format, below. */
9276 enum jpeg_keyword_index
9285 JPEG_HEURISTIC_MASK
,
9291 /* Vector of image_keyword structures describing the format
9292 of valid user-defined image specifications. */
9294 static struct image_keyword jpeg_format
[JPEG_LAST
] =
9296 {":type", IMAGE_SYMBOL_VALUE
, 1},
9297 {":data", IMAGE_STRING_VALUE
, 0},
9298 {":file", IMAGE_STRING_VALUE
, 0},
9299 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9300 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9301 {":relief", IMAGE_INTEGER_VALUE
, 0},
9302 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9303 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9304 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9305 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9308 /* Structure describing the image type `jpeg'. */
9310 static struct image_type jpeg_type
=
9320 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9323 jpeg_image_p (object
)
9326 struct image_keyword fmt
[JPEG_LAST
];
9328 bcopy (jpeg_format
, fmt
, sizeof fmt
);
9330 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
9333 /* Must specify either the :data or :file keyword. */
9334 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
9338 struct my_jpeg_error_mgr
9340 struct jpeg_error_mgr pub
;
9341 jmp_buf setjmp_buffer
;
9346 my_error_exit (cinfo
)
9349 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
9350 longjmp (mgr
->setjmp_buffer
, 1);
9354 /* Init source method for JPEG data source manager. Called by
9355 jpeg_read_header() before any data is actually read. See
9356 libjpeg.doc from the JPEG lib distribution. */
9359 our_init_source (cinfo
)
9360 j_decompress_ptr cinfo
;
9365 /* Fill input buffer method for JPEG data source manager. Called
9366 whenever more data is needed. We read the whole image in one step,
9367 so this only adds a fake end of input marker at the end. */
9370 our_fill_input_buffer (cinfo
)
9371 j_decompress_ptr cinfo
;
9373 /* Insert a fake EOI marker. */
9374 struct jpeg_source_mgr
*src
= cinfo
->src
;
9375 static JOCTET buffer
[2];
9377 buffer
[0] = (JOCTET
) 0xFF;
9378 buffer
[1] = (JOCTET
) JPEG_EOI
;
9380 src
->next_input_byte
= buffer
;
9381 src
->bytes_in_buffer
= 2;
9386 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9387 is the JPEG data source manager. */
9390 our_skip_input_data (cinfo
, num_bytes
)
9391 j_decompress_ptr cinfo
;
9394 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9398 if (num_bytes
> src
->bytes_in_buffer
)
9399 ERREXIT (cinfo
, JERR_INPUT_EOF
);
9401 src
->bytes_in_buffer
-= num_bytes
;
9402 src
->next_input_byte
+= num_bytes
;
9407 /* Method to terminate data source. Called by
9408 jpeg_finish_decompress() after all data has been processed. */
9411 our_term_source (cinfo
)
9412 j_decompress_ptr cinfo
;
9417 /* Set up the JPEG lib for reading an image from DATA which contains
9418 LEN bytes. CINFO is the decompression info structure created for
9419 reading the image. */
9422 jpeg_memory_src (cinfo
, data
, len
)
9423 j_decompress_ptr cinfo
;
9427 struct jpeg_source_mgr
*src
;
9429 if (cinfo
->src
== NULL
)
9431 /* First time for this JPEG object? */
9432 cinfo
->src
= (struct jpeg_source_mgr
*)
9433 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
9434 sizeof (struct jpeg_source_mgr
));
9435 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9436 src
->next_input_byte
= data
;
9439 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
9440 src
->init_source
= our_init_source
;
9441 src
->fill_input_buffer
= our_fill_input_buffer
;
9442 src
->skip_input_data
= our_skip_input_data
;
9443 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
9444 src
->term_source
= our_term_source
;
9445 src
->bytes_in_buffer
= len
;
9446 src
->next_input_byte
= data
;
9450 /* Load image IMG for use on frame F. Patterned after example.c
9451 from the JPEG lib. */
9458 struct jpeg_decompress_struct cinfo
;
9459 struct my_jpeg_error_mgr mgr
;
9460 Lisp_Object file
, specified_file
;
9461 Lisp_Object specified_data
;
9462 FILE * volatile fp
= NULL
;
9464 int row_stride
, x
, y
;
9465 XImage
*ximg
= NULL
;
9467 unsigned long *colors
;
9469 struct gcpro gcpro1
;
9471 /* Open the JPEG file. */
9472 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9473 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9477 if (NILP (specified_data
))
9479 file
= x_find_image_file (specified_file
);
9480 if (!STRINGP (file
))
9482 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9487 fp
= fopen (XSTRING (file
)->data
, "r");
9490 image_error ("Cannot open `%s'", file
, Qnil
);
9496 /* Customize libjpeg's error handling to call my_error_exit when an
9497 error is detected. This function will perform a longjmp. */
9498 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
9499 mgr
.pub
.error_exit
= my_error_exit
;
9501 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
9505 /* Called from my_error_exit. Display a JPEG error. */
9506 char buffer
[JMSG_LENGTH_MAX
];
9507 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
9508 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
9509 build_string (buffer
));
9512 /* Close the input file and destroy the JPEG object. */
9514 fclose ((FILE *) fp
);
9515 jpeg_destroy_decompress (&cinfo
);
9517 /* If we already have an XImage, free that. */
9518 x_destroy_x_image (ximg
);
9520 /* Free pixmap and colors. */
9521 x_clear_image (f
, img
);
9527 /* Create the JPEG decompression object. Let it read from fp.
9528 Read the JPEG image header. */
9529 jpeg_create_decompress (&cinfo
);
9531 if (NILP (specified_data
))
9532 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
9534 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
9535 STRING_BYTES (XSTRING (specified_data
)));
9537 jpeg_read_header (&cinfo
, TRUE
);
9539 /* Customize decompression so that color quantization will be used.
9540 Start decompression. */
9541 cinfo
.quantize_colors
= TRUE
;
9542 jpeg_start_decompress (&cinfo
);
9543 width
= img
->width
= cinfo
.output_width
;
9544 height
= img
->height
= cinfo
.output_height
;
9546 /* Create X image and pixmap. */
9547 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9548 longjmp (mgr
.setjmp_buffer
, 2);
9550 /* Allocate colors. When color quantization is used,
9551 cinfo.actual_number_of_colors has been set with the number of
9552 colors generated, and cinfo.colormap is a two-dimensional array
9553 of color indices in the range 0..cinfo.actual_number_of_colors.
9554 No more than 255 colors will be generated. */
9558 if (cinfo
.out_color_components
> 2)
9559 ir
= 0, ig
= 1, ib
= 2;
9560 else if (cinfo
.out_color_components
> 1)
9561 ir
= 0, ig
= 1, ib
= 0;
9563 ir
= 0, ig
= 0, ib
= 0;
9565 /* Use the color table mechanism because it handles colors that
9566 cannot be allocated nicely. Such colors will be replaced with
9567 a default color, and we don't have to care about which colors
9568 can be freed safely, and which can't. */
9569 init_color_table ();
9570 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
9573 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9575 /* Multiply RGB values with 255 because X expects RGB values
9576 in the range 0..0xffff. */
9577 int r
= cinfo
.colormap
[ir
][i
] << 8;
9578 int g
= cinfo
.colormap
[ig
][i
] << 8;
9579 int b
= cinfo
.colormap
[ib
][i
] << 8;
9580 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9583 /* Remember those colors actually allocated. */
9584 img
->colors
= colors_in_color_table (&img
->ncolors
);
9585 free_color_table ();
9589 row_stride
= width
* cinfo
.output_components
;
9590 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9592 for (y
= 0; y
< height
; ++y
)
9594 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9595 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9596 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9600 jpeg_finish_decompress (&cinfo
);
9601 jpeg_destroy_decompress (&cinfo
);
9603 fclose ((FILE *) fp
);
9605 /* Maybe fill in the background field while we have ximg handy. */
9606 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9607 IMAGE_BACKGROUND (img
, f
, ximg
);
9609 /* Put the image into the pixmap. */
9610 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9611 x_destroy_x_image (ximg
);
9616 #endif /* HAVE_JPEG */
9620 /***********************************************************************
9622 ***********************************************************************/
9628 static int tiff_image_p
P_ ((Lisp_Object object
));
9629 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9631 /* The symbol `tiff' identifying images of this type. */
9635 /* Indices of image specification fields in tiff_format, below. */
9637 enum tiff_keyword_index
9646 TIFF_HEURISTIC_MASK
,
9652 /* Vector of image_keyword structures describing the format
9653 of valid user-defined image specifications. */
9655 static struct image_keyword tiff_format
[TIFF_LAST
] =
9657 {":type", IMAGE_SYMBOL_VALUE
, 1},
9658 {":data", IMAGE_STRING_VALUE
, 0},
9659 {":file", IMAGE_STRING_VALUE
, 0},
9660 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9661 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9662 {":relief", IMAGE_INTEGER_VALUE
, 0},
9663 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9664 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9665 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9666 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9669 /* Structure describing the image type `tiff'. */
9671 static struct image_type tiff_type
=
9681 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9684 tiff_image_p (object
)
9687 struct image_keyword fmt
[TIFF_LAST
];
9688 bcopy (tiff_format
, fmt
, sizeof fmt
);
9690 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9693 /* Must specify either the :data or :file keyword. */
9694 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9698 /* Reading from a memory buffer for TIFF images Based on the PNG
9699 memory source, but we have to provide a lot of extra functions.
9702 We really only need to implement read and seek, but I am not
9703 convinced that the TIFF library is smart enough not to destroy
9704 itself if we only hand it the function pointers we need to
9709 unsigned char *bytes
;
9717 tiff_read_from_memory (data
, buf
, size
)
9722 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9724 if (size
> src
->len
- src
->index
)
9726 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9733 tiff_write_from_memory (data
, buf
, size
)
9743 tiff_seek_in_memory (data
, off
, whence
)
9748 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9753 case SEEK_SET
: /* Go from beginning of source. */
9757 case SEEK_END
: /* Go from end of source. */
9758 idx
= src
->len
+ off
;
9761 case SEEK_CUR
: /* Go from current position. */
9762 idx
= src
->index
+ off
;
9765 default: /* Invalid `whence'. */
9769 if (idx
> src
->len
|| idx
< 0)
9778 tiff_close_memory (data
)
9787 tiff_mmap_memory (data
, pbase
, psize
)
9792 /* It is already _IN_ memory. */
9798 tiff_unmap_memory (data
, base
, size
)
9803 /* We don't need to do this. */
9808 tiff_size_of_memory (data
)
9811 return ((tiff_memory_source
*) data
)->len
;
9816 tiff_error_handler (title
, format
, ap
)
9817 const char *title
, *format
;
9823 len
= sprintf (buf
, "TIFF error: %s ", title
);
9824 vsprintf (buf
+ len
, format
, ap
);
9825 add_to_log (buf
, Qnil
, Qnil
);
9830 tiff_warning_handler (title
, format
, ap
)
9831 const char *title
, *format
;
9837 len
= sprintf (buf
, "TIFF warning: %s ", title
);
9838 vsprintf (buf
+ len
, format
, ap
);
9839 add_to_log (buf
, Qnil
, Qnil
);
9843 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9851 Lisp_Object file
, specified_file
;
9852 Lisp_Object specified_data
;
9854 int width
, height
, x
, y
;
9858 struct gcpro gcpro1
;
9859 tiff_memory_source memsrc
;
9861 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9862 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9866 TIFFSetErrorHandler (tiff_error_handler
);
9867 TIFFSetWarningHandler (tiff_warning_handler
);
9869 if (NILP (specified_data
))
9871 /* Read from a file */
9872 file
= x_find_image_file (specified_file
);
9873 if (!STRINGP (file
))
9875 image_error ("Cannot find image file `%s'", file
, Qnil
);
9880 /* Try to open the image file. */
9881 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9884 image_error ("Cannot open `%s'", file
, Qnil
);
9891 /* Memory source! */
9892 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9893 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9896 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9897 (TIFFReadWriteProc
) tiff_read_from_memory
,
9898 (TIFFReadWriteProc
) tiff_write_from_memory
,
9899 tiff_seek_in_memory
,
9901 tiff_size_of_memory
,
9907 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9913 /* Get width and height of the image, and allocate a raster buffer
9914 of width x height 32-bit values. */
9915 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9916 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9917 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9919 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9923 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9929 /* Create the X image and pixmap. */
9930 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9937 /* Initialize the color table. */
9938 init_color_table ();
9940 /* Process the pixel raster. Origin is in the lower-left corner. */
9941 for (y
= 0; y
< height
; ++y
)
9943 uint32
*row
= buf
+ y
* width
;
9945 for (x
= 0; x
< width
; ++x
)
9947 uint32 abgr
= row
[x
];
9948 int r
= TIFFGetR (abgr
) << 8;
9949 int g
= TIFFGetG (abgr
) << 8;
9950 int b
= TIFFGetB (abgr
) << 8;
9951 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9955 /* Remember the colors allocated for the image. Free the color table. */
9956 img
->colors
= colors_in_color_table (&img
->ncolors
);
9957 free_color_table ();
9960 img
->height
= height
;
9962 /* Maybe fill in the background field while we have ximg handy. */
9963 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
9964 IMAGE_BACKGROUND (img
, f
, ximg
);
9966 /* Put the image into the pixmap, then free the X image and its buffer. */
9967 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9968 x_destroy_x_image (ximg
);
9975 #endif /* HAVE_TIFF != 0 */
9979 /***********************************************************************
9981 ***********************************************************************/
9985 #include <gif_lib.h>
9987 static int gif_image_p
P_ ((Lisp_Object object
));
9988 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9990 /* The symbol `gif' identifying images of this type. */
9994 /* Indices of image specification fields in gif_format, below. */
9996 enum gif_keyword_index
10005 GIF_HEURISTIC_MASK
,
10012 /* Vector of image_keyword structures describing the format
10013 of valid user-defined image specifications. */
10015 static struct image_keyword gif_format
[GIF_LAST
] =
10017 {":type", IMAGE_SYMBOL_VALUE
, 1},
10018 {":data", IMAGE_STRING_VALUE
, 0},
10019 {":file", IMAGE_STRING_VALUE
, 0},
10020 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10021 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10022 {":relief", IMAGE_INTEGER_VALUE
, 0},
10023 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10024 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10025 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10026 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
10027 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10030 /* Structure describing the image type `gif'. */
10032 static struct image_type gif_type
=
10042 /* Return non-zero if OBJECT is a valid GIF image specification. */
10045 gif_image_p (object
)
10046 Lisp_Object object
;
10048 struct image_keyword fmt
[GIF_LAST
];
10049 bcopy (gif_format
, fmt
, sizeof fmt
);
10051 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
10054 /* Must specify either the :data or :file keyword. */
10055 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
10059 /* Reading a GIF image from memory
10060 Based on the PNG memory stuff to a certain extent. */
10064 unsigned char *bytes
;
10071 /* Make the current memory source available to gif_read_from_memory.
10072 It's done this way because not all versions of libungif support
10073 a UserData field in the GifFileType structure. */
10074 static gif_memory_source
*current_gif_memory_src
;
10077 gif_read_from_memory (file
, buf
, len
)
10082 gif_memory_source
*src
= current_gif_memory_src
;
10084 if (len
> src
->len
- src
->index
)
10087 bcopy (src
->bytes
+ src
->index
, buf
, len
);
10093 /* Load GIF image IMG for use on frame F. Value is non-zero if
10101 Lisp_Object file
, specified_file
;
10102 Lisp_Object specified_data
;
10103 int rc
, width
, height
, x
, y
, i
;
10105 ColorMapObject
*gif_color_map
;
10106 unsigned long pixel_colors
[256];
10108 struct gcpro gcpro1
;
10110 int ino
, image_left
, image_top
, image_width
, image_height
;
10111 gif_memory_source memsrc
;
10112 unsigned char *raster
;
10114 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10115 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10119 if (NILP (specified_data
))
10121 file
= x_find_image_file (specified_file
);
10122 if (!STRINGP (file
))
10124 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
10129 /* Open the GIF file. */
10130 gif
= DGifOpenFileName (XSTRING (file
)->data
);
10133 image_error ("Cannot open `%s'", file
, Qnil
);
10140 /* Read from memory! */
10141 current_gif_memory_src
= &memsrc
;
10142 memsrc
.bytes
= XSTRING (specified_data
)->data
;
10143 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
10146 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
10149 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
10155 /* Read entire contents. */
10156 rc
= DGifSlurp (gif
);
10157 if (rc
== GIF_ERROR
)
10159 image_error ("Error reading `%s'", img
->spec
, Qnil
);
10160 DGifCloseFile (gif
);
10165 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
10166 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
10167 if (ino
>= gif
->ImageCount
)
10169 image_error ("Invalid image number `%s' in image `%s'",
10171 DGifCloseFile (gif
);
10176 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
10177 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
10179 /* Create the X image and pixmap. */
10180 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
10182 DGifCloseFile (gif
);
10187 /* Allocate colors. */
10188 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
10189 if (!gif_color_map
)
10190 gif_color_map
= gif
->SColorMap
;
10191 init_color_table ();
10192 bzero (pixel_colors
, sizeof pixel_colors
);
10194 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
10196 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
10197 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
10198 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
10199 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
10202 img
->colors
= colors_in_color_table (&img
->ncolors
);
10203 free_color_table ();
10205 /* Clear the part of the screen image that are not covered by
10206 the image from the GIF file. Full animated GIF support
10207 requires more than can be done here (see the gif89 spec,
10208 disposal methods). Let's simply assume that the part
10209 not covered by a sub-image is in the frame's background color. */
10210 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
10211 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
10212 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
10213 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
10215 for (y
= 0; y
< image_top
; ++y
)
10216 for (x
= 0; x
< width
; ++x
)
10217 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10219 for (y
= image_top
+ image_height
; y
< height
; ++y
)
10220 for (x
= 0; x
< width
; ++x
)
10221 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10223 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
10225 for (x
= 0; x
< image_left
; ++x
)
10226 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10227 for (x
= image_left
+ image_width
; x
< width
; ++x
)
10228 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
10231 /* Read the GIF image into the X image. We use a local variable
10232 `raster' here because RasterBits below is a char *, and invites
10233 problems with bytes >= 0x80. */
10234 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
10236 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
10238 static int interlace_start
[] = {0, 4, 2, 1};
10239 static int interlace_increment
[] = {8, 8, 4, 2};
10241 int row
= interlace_start
[0];
10245 for (y
= 0; y
< image_height
; y
++)
10247 if (row
>= image_height
)
10249 row
= interlace_start
[++pass
];
10250 while (row
>= image_height
)
10251 row
= interlace_start
[++pass
];
10254 for (x
= 0; x
< image_width
; x
++)
10256 int i
= raster
[(y
* image_width
) + x
];
10257 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
10261 row
+= interlace_increment
[pass
];
10266 for (y
= 0; y
< image_height
; ++y
)
10267 for (x
= 0; x
< image_width
; ++x
)
10269 int i
= raster
[y
* image_width
+ x
];
10270 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
10274 DGifCloseFile (gif
);
10276 /* Maybe fill in the background field while we have ximg handy. */
10277 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
10278 IMAGE_BACKGROUND (img
, f
, ximg
);
10280 /* Put the image into the pixmap, then free the X image and its buffer. */
10281 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10282 x_destroy_x_image (ximg
);
10288 #endif /* HAVE_GIF != 0 */
10292 /***********************************************************************
10294 ***********************************************************************/
10296 static int gs_image_p
P_ ((Lisp_Object object
));
10297 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
10298 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
10300 /* The symbol `postscript' identifying images of this type. */
10302 Lisp_Object Qpostscript
;
10304 /* Keyword symbols. */
10306 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
10308 /* Indices of image specification fields in gs_format, below. */
10310 enum gs_keyword_index
10328 /* Vector of image_keyword structures describing the format
10329 of valid user-defined image specifications. */
10331 static struct image_keyword gs_format
[GS_LAST
] =
10333 {":type", IMAGE_SYMBOL_VALUE
, 1},
10334 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10335 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
10336 {":file", IMAGE_STRING_VALUE
, 1},
10337 {":loader", IMAGE_FUNCTION_VALUE
, 0},
10338 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
10339 {":ascent", IMAGE_ASCENT_VALUE
, 0},
10340 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
10341 {":relief", IMAGE_INTEGER_VALUE
, 0},
10342 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10343 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10344 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10345 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
10348 /* Structure describing the image type `ghostscript'. */
10350 static struct image_type gs_type
=
10360 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10363 gs_clear_image (f
, img
)
10367 /* IMG->data.ptr_val may contain a recorded colormap. */
10368 xfree (img
->data
.ptr_val
);
10369 x_clear_image (f
, img
);
10373 /* Return non-zero if OBJECT is a valid Ghostscript image
10377 gs_image_p (object
)
10378 Lisp_Object object
;
10380 struct image_keyword fmt
[GS_LAST
];
10384 bcopy (gs_format
, fmt
, sizeof fmt
);
10386 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
10389 /* Bounding box must be a list or vector containing 4 integers. */
10390 tem
= fmt
[GS_BOUNDING_BOX
].value
;
10393 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
10394 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
10399 else if (VECTORP (tem
))
10401 if (XVECTOR (tem
)->size
!= 4)
10403 for (i
= 0; i
< 4; ++i
)
10404 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
10414 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10423 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
10424 struct gcpro gcpro1
, gcpro2
;
10426 double in_width
, in_height
;
10427 Lisp_Object pixel_colors
= Qnil
;
10429 /* Compute pixel size of pixmap needed from the given size in the
10430 image specification. Sizes in the specification are in pt. 1 pt
10431 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10433 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
10434 in_width
= XFASTINT (pt_width
) / 72.0;
10435 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
10436 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
10437 in_height
= XFASTINT (pt_height
) / 72.0;
10438 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
10440 /* Create the pixmap. */
10441 xassert (img
->pixmap
== None
);
10442 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10443 img
->width
, img
->height
,
10444 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
10448 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
10452 /* Call the loader to fill the pixmap. It returns a process object
10453 if successful. We do not record_unwind_protect here because
10454 other places in redisplay like calling window scroll functions
10455 don't either. Let the Lisp loader use `unwind-protect' instead. */
10456 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
10458 sprintf (buffer
, "%lu %lu",
10459 (unsigned long) FRAME_X_WINDOW (f
),
10460 (unsigned long) img
->pixmap
);
10461 window_and_pixmap_id
= build_string (buffer
);
10463 sprintf (buffer
, "%lu %lu",
10464 FRAME_FOREGROUND_PIXEL (f
),
10465 FRAME_BACKGROUND_PIXEL (f
));
10466 pixel_colors
= build_string (buffer
);
10468 XSETFRAME (frame
, f
);
10469 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
10471 loader
= intern ("gs-load-image");
10473 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
10474 make_number (img
->width
),
10475 make_number (img
->height
),
10476 window_and_pixmap_id
,
10479 return PROCESSP (img
->data
.lisp_val
);
10483 /* Kill the Ghostscript process that was started to fill PIXMAP on
10484 frame F. Called from XTread_socket when receiving an event
10485 telling Emacs that Ghostscript has finished drawing. */
10488 x_kill_gs_process (pixmap
, f
)
10492 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
10496 /* Find the image containing PIXMAP. */
10497 for (i
= 0; i
< c
->used
; ++i
)
10498 if (c
->images
[i
]->pixmap
== pixmap
)
10501 /* Should someone in between have cleared the image cache, for
10502 instance, give up. */
10506 /* Kill the GS process. We should have found PIXMAP in the image
10507 cache and its image should contain a process object. */
10508 img
= c
->images
[i
];
10509 xassert (PROCESSP (img
->data
.lisp_val
));
10510 Fkill_process (img
->data
.lisp_val
, Qnil
);
10511 img
->data
.lisp_val
= Qnil
;
10513 /* On displays with a mutable colormap, figure out the colors
10514 allocated for the image by looking at the pixels of an XImage for
10516 class = FRAME_X_VISUAL (f
)->class;
10517 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
10523 /* Try to get an XImage for img->pixmep. */
10524 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
10525 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
10530 /* Initialize the color table. */
10531 init_color_table ();
10533 /* For each pixel of the image, look its color up in the
10534 color table. After having done so, the color table will
10535 contain an entry for each color used by the image. */
10536 for (y
= 0; y
< img
->height
; ++y
)
10537 for (x
= 0; x
< img
->width
; ++x
)
10539 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
10540 lookup_pixel_color (f
, pixel
);
10543 /* Record colors in the image. Free color table and XImage. */
10544 img
->colors
= colors_in_color_table (&img
->ncolors
);
10545 free_color_table ();
10546 XDestroyImage (ximg
);
10548 #if 0 /* This doesn't seem to be the case. If we free the colors
10549 here, we get a BadAccess later in x_clear_image when
10550 freeing the colors. */
10551 /* We have allocated colors once, but Ghostscript has also
10552 allocated colors on behalf of us. So, to get the
10553 reference counts right, free them once. */
10555 x_free_colors (f
, img
->colors
, img
->ncolors
);
10559 image_error ("Cannot get X image of `%s'; colors will not be freed",
10565 /* Now that we have the pixmap, compute mask and transform the
10566 image if requested. */
10568 postprocess_image (f
, img
);
10574 /***********************************************************************
10576 ***********************************************************************/
10578 DEFUN ("x-change-window-property", Fx_change_window_property
,
10579 Sx_change_window_property
, 2, 3, 0,
10580 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
10581 PROP and VALUE must be strings. FRAME nil or omitted means use the
10582 selected frame. Value is VALUE. */)
10583 (prop
, value
, frame
)
10584 Lisp_Object frame
, prop
, value
;
10586 struct frame
*f
= check_x_frame (frame
);
10589 CHECK_STRING (prop
);
10590 CHECK_STRING (value
);
10593 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10594 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10595 prop_atom
, XA_STRING
, 8, PropModeReplace
,
10596 XSTRING (value
)->data
, XSTRING (value
)->size
);
10598 /* Make sure the property is set when we return. */
10599 XFlush (FRAME_X_DISPLAY (f
));
10606 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
10607 Sx_delete_window_property
, 1, 2, 0,
10608 doc
: /* Remove window property PROP from X window of FRAME.
10609 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10611 Lisp_Object prop
, frame
;
10613 struct frame
*f
= check_x_frame (frame
);
10616 CHECK_STRING (prop
);
10618 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10619 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
10621 /* Make sure the property is removed when we return. */
10622 XFlush (FRAME_X_DISPLAY (f
));
10629 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
10631 doc
: /* Value is the value of window property PROP on FRAME.
10632 If FRAME is nil or omitted, use the selected frame. Value is nil
10633 if FRAME hasn't a property with name PROP or if PROP has no string
10636 Lisp_Object prop
, frame
;
10638 struct frame
*f
= check_x_frame (frame
);
10641 Lisp_Object prop_value
= Qnil
;
10642 char *tmp_data
= NULL
;
10645 unsigned long actual_size
, bytes_remaining
;
10647 CHECK_STRING (prop
);
10649 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10650 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10651 prop_atom
, 0, 0, False
, XA_STRING
,
10652 &actual_type
, &actual_format
, &actual_size
,
10653 &bytes_remaining
, (unsigned char **) &tmp_data
);
10656 int size
= bytes_remaining
;
10661 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10662 prop_atom
, 0, bytes_remaining
,
10664 &actual_type
, &actual_format
,
10665 &actual_size
, &bytes_remaining
,
10666 (unsigned char **) &tmp_data
);
10667 if (rc
== Success
&& tmp_data
)
10668 prop_value
= make_string (tmp_data
, size
);
10679 /***********************************************************************
10681 ***********************************************************************/
10683 /* If non-null, an asynchronous timer that, when it expires, displays
10684 an hourglass cursor on all frames. */
10686 static struct atimer
*hourglass_atimer
;
10688 /* Non-zero means an hourglass cursor is currently shown. */
10690 static int hourglass_shown_p
;
10692 /* Number of seconds to wait before displaying an hourglass cursor. */
10694 static Lisp_Object Vhourglass_delay
;
10696 /* Default number of seconds to wait before displaying an hourglass
10699 #define DEFAULT_HOURGLASS_DELAY 1
10701 /* Function prototypes. */
10703 static void show_hourglass
P_ ((struct atimer
*));
10704 static void hide_hourglass
P_ ((void));
10707 /* Cancel a currently active hourglass timer, and start a new one. */
10713 int secs
, usecs
= 0;
10715 cancel_hourglass ();
10717 if (INTEGERP (Vhourglass_delay
)
10718 && XINT (Vhourglass_delay
) > 0)
10719 secs
= XFASTINT (Vhourglass_delay
);
10720 else if (FLOATP (Vhourglass_delay
)
10721 && XFLOAT_DATA (Vhourglass_delay
) > 0)
10724 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
10725 secs
= XFASTINT (tem
);
10726 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
10729 secs
= DEFAULT_HOURGLASS_DELAY
;
10731 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10732 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10733 show_hourglass
, NULL
);
10737 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10741 cancel_hourglass ()
10743 if (hourglass_atimer
)
10745 cancel_atimer (hourglass_atimer
);
10746 hourglass_atimer
= NULL
;
10749 if (hourglass_shown_p
)
10754 /* Timer function of hourglass_atimer. TIMER is equal to
10757 Display an hourglass pointer on all frames by mapping the frames'
10758 hourglass_window. Set the hourglass_p flag in the frames'
10759 output_data.x structure to indicate that an hourglass cursor is
10760 shown on the frames. */
10763 show_hourglass (timer
)
10764 struct atimer
*timer
;
10766 /* The timer implementation will cancel this timer automatically
10767 after this function has run. Set hourglass_atimer to null
10768 so that we know the timer doesn't have to be canceled. */
10769 hourglass_atimer
= NULL
;
10771 if (!hourglass_shown_p
)
10773 Lisp_Object rest
, frame
;
10777 FOR_EACH_FRAME (rest
, frame
)
10779 struct frame
*f
= XFRAME (frame
);
10781 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
) && FRAME_X_DISPLAY (f
))
10783 Display
*dpy
= FRAME_X_DISPLAY (f
);
10785 #ifdef USE_X_TOOLKIT
10786 if (f
->output_data
.x
->widget
)
10788 if (FRAME_OUTER_WINDOW (f
))
10791 f
->output_data
.x
->hourglass_p
= 1;
10793 if (!f
->output_data
.x
->hourglass_window
)
10795 unsigned long mask
= CWCursor
;
10796 XSetWindowAttributes attrs
;
10798 attrs
.cursor
= f
->output_data
.x
->hourglass_cursor
;
10800 f
->output_data
.x
->hourglass_window
10801 = XCreateWindow (dpy
, FRAME_OUTER_WINDOW (f
),
10802 0, 0, 32000, 32000, 0, 0,
10808 XMapRaised (dpy
, f
->output_data
.x
->hourglass_window
);
10814 hourglass_shown_p
= 1;
10820 /* Hide the hourglass pointer on all frames, if it is currently
10826 if (hourglass_shown_p
)
10828 Lisp_Object rest
, frame
;
10831 FOR_EACH_FRAME (rest
, frame
)
10833 struct frame
*f
= XFRAME (frame
);
10836 /* Watch out for newly created frames. */
10837 && f
->output_data
.x
->hourglass_window
)
10839 XUnmapWindow (FRAME_X_DISPLAY (f
),
10840 f
->output_data
.x
->hourglass_window
);
10841 /* Sync here because XTread_socket looks at the
10842 hourglass_p flag that is reset to zero below. */
10843 XSync (FRAME_X_DISPLAY (f
), False
);
10844 f
->output_data
.x
->hourglass_p
= 0;
10848 hourglass_shown_p
= 0;
10855 /***********************************************************************
10857 ***********************************************************************/
10859 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10860 Lisp_Object
, Lisp_Object
));
10861 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
10862 Lisp_Object
, int, int, int *, int *));
10864 /* The frame of a currently visible tooltip. */
10866 Lisp_Object tip_frame
;
10868 /* If non-nil, a timer started that hides the last tooltip when it
10871 Lisp_Object tip_timer
;
10874 /* If non-nil, a vector of 3 elements containing the last args
10875 with which x-show-tip was called. See there. */
10877 Lisp_Object last_show_tip_args
;
10879 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10881 Lisp_Object Vx_max_tooltip_size
;
10885 unwind_create_tip_frame (frame
)
10888 Lisp_Object deleted
;
10890 deleted
= unwind_create_frame (frame
);
10891 if (EQ (deleted
, Qt
))
10901 /* Create a frame for a tooltip on the display described by DPYINFO.
10902 PARMS is a list of frame parameters. TEXT is the string to
10903 display in the tip frame. Value is the frame.
10905 Note that functions called here, esp. x_default_parameter can
10906 signal errors, for instance when a specified color name is
10907 undefined. We have to make sure that we're in a consistent state
10908 when this happens. */
10911 x_create_tip_frame (dpyinfo
, parms
, text
)
10912 struct x_display_info
*dpyinfo
;
10913 Lisp_Object parms
, text
;
10916 Lisp_Object frame
, tem
;
10918 long window_prompting
= 0;
10920 int count
= BINDING_STACK_SIZE ();
10921 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10923 int face_change_count_before
= face_change_count
;
10924 Lisp_Object buffer
;
10925 struct buffer
*old_buffer
;
10929 /* Use this general default value to start with until we know if
10930 this frame has a specified name. */
10931 Vx_resource_name
= Vinvocation_name
;
10933 #ifdef MULTI_KBOARD
10934 kb
= dpyinfo
->kboard
;
10936 kb
= &the_only_kboard
;
10939 /* Get the name of the frame to use for resource lookup. */
10940 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10941 if (!STRINGP (name
)
10942 && !EQ (name
, Qunbound
)
10944 error ("Invalid frame name--not a string or nil");
10945 Vx_resource_name
= name
;
10948 GCPRO3 (parms
, name
, frame
);
10949 f
= make_frame (1);
10950 XSETFRAME (frame
, f
);
10952 buffer
= Fget_buffer_create (build_string (" *tip*"));
10953 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10954 old_buffer
= current_buffer
;
10955 set_buffer_internal_1 (XBUFFER (buffer
));
10956 current_buffer
->truncate_lines
= Qnil
;
10958 Finsert (1, &text
);
10959 set_buffer_internal_1 (old_buffer
);
10961 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10962 record_unwind_protect (unwind_create_tip_frame
, frame
);
10964 /* By setting the output method, we're essentially saying that
10965 the frame is live, as per FRAME_LIVE_P. If we get a signal
10966 from this point on, x_destroy_window might screw up reference
10968 f
->output_method
= output_x_window
;
10969 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10970 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10971 f
->output_data
.x
->icon_bitmap
= -1;
10972 f
->output_data
.x
->fontset
= -1;
10973 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10974 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10975 #ifdef USE_TOOLKIT_SCROLL_BARS
10976 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= -1;
10977 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= -1;
10978 #endif /* USE_TOOLKIT_SCROLL_BARS */
10979 f
->icon_name
= Qnil
;
10980 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10982 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
10983 dpyinfo_refcount
= dpyinfo
->reference_count
;
10984 #endif /* GLYPH_DEBUG */
10985 #ifdef MULTI_KBOARD
10986 FRAME_KBOARD (f
) = kb
;
10988 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10989 f
->output_data
.x
->explicit_parent
= 0;
10991 /* These colors will be set anyway later, but it's important
10992 to get the color reference counts right, so initialize them! */
10995 struct gcpro gcpro1
;
10997 black
= build_string ("black");
10999 f
->output_data
.x
->foreground_pixel
11000 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11001 f
->output_data
.x
->background_pixel
11002 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11003 f
->output_data
.x
->cursor_pixel
11004 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11005 f
->output_data
.x
->cursor_foreground_pixel
11006 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11007 f
->output_data
.x
->border_pixel
11008 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11009 f
->output_data
.x
->mouse_pixel
11010 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
11014 /* Set the name; the functions to which we pass f expect the name to
11016 if (EQ (name
, Qunbound
) || NILP (name
))
11018 f
->name
= build_string (dpyinfo
->x_id_name
);
11019 f
->explicit_name
= 0;
11024 f
->explicit_name
= 1;
11025 /* use the frame's title when getting resources for this frame. */
11026 specbind (Qx_resource_name
, name
);
11029 /* Extract the window parameters from the supplied values that are
11030 needed to determine window geometry. */
11034 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
11037 /* First, try whatever font the caller has specified. */
11038 if (STRINGP (font
))
11040 tem
= Fquery_fontset (font
, Qnil
);
11042 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
11044 font
= x_new_font (f
, XSTRING (font
)->data
);
11047 /* Try out a font which we hope has bold and italic variations. */
11048 if (!STRINGP (font
))
11049 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
11050 if (!STRINGP (font
))
11051 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11052 if (! STRINGP (font
))
11053 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11054 if (! STRINGP (font
))
11055 /* This was formerly the first thing tried, but it finds too many fonts
11056 and takes too long. */
11057 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
11058 /* If those didn't work, look for something which will at least work. */
11059 if (! STRINGP (font
))
11060 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
11062 if (! STRINGP (font
))
11063 font
= build_string ("fixed");
11065 x_default_parameter (f
, parms
, Qfont
, font
,
11066 "font", "Font", RES_TYPE_STRING
);
11069 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
11070 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
11072 /* This defaults to 2 in order to match xterm. We recognize either
11073 internalBorderWidth or internalBorder (which is what xterm calls
11075 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11079 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
11080 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
11081 if (! EQ (value
, Qunbound
))
11082 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
11086 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
11087 "internalBorderWidth", "internalBorderWidth",
11090 /* Also do the stuff which must be set before the window exists. */
11091 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
11092 "foreground", "Foreground", RES_TYPE_STRING
);
11093 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
11094 "background", "Background", RES_TYPE_STRING
);
11095 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
11096 "pointerColor", "Foreground", RES_TYPE_STRING
);
11097 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
11098 "cursorColor", "Foreground", RES_TYPE_STRING
);
11099 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
11100 "borderColor", "BorderColor", RES_TYPE_STRING
);
11102 /* Init faces before x_default_parameter is called for scroll-bar
11103 parameters because that function calls x_set_scroll_bar_width,
11104 which calls change_frame_size, which calls Fset_window_buffer,
11105 which runs hooks, which call Fvertical_motion. At the end, we
11106 end up in init_iterator with a null face cache, which should not
11108 init_frame_faces (f
);
11110 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
11111 window_prompting
= x_figure_window_size (f
, parms
);
11113 if (window_prompting
& XNegative
)
11115 if (window_prompting
& YNegative
)
11116 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
11118 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
11122 if (window_prompting
& YNegative
)
11123 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
11125 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11128 f
->output_data
.x
->size_hint_flags
= window_prompting
;
11130 XSetWindowAttributes attrs
;
11131 unsigned long mask
;
11134 mask
= CWBackPixel
| CWOverrideRedirect
| CWEventMask
;
11135 if (DoesSaveUnders (dpyinfo
->screen
))
11136 mask
|= CWSaveUnder
;
11138 /* Window managers look at the override-redirect flag to determine
11139 whether or net to give windows a decoration (Xlib spec, chapter
11141 attrs
.override_redirect
= True
;
11142 attrs
.save_under
= True
;
11143 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
11144 /* Arrange for getting MapNotify and UnmapNotify events. */
11145 attrs
.event_mask
= StructureNotifyMask
;
11147 = FRAME_X_WINDOW (f
)
11148 = XCreateWindow (FRAME_X_DISPLAY (f
),
11149 FRAME_X_DISPLAY_INFO (f
)->root_window
,
11150 /* x, y, width, height */
11154 CopyFromParent
, InputOutput
, CopyFromParent
,
11161 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
11162 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11163 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
11164 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
11165 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
11166 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
11168 /* Dimensions, especially f->height, must be done via change_frame_size.
11169 Change will not be effected unless different from the current
11172 height
= f
->height
;
11174 SET_FRAME_WIDTH (f
, 0);
11175 change_frame_size (f
, height
, width
, 1, 0, 0);
11177 /* Set up faces after all frame parameters are known. This call
11178 also merges in face attributes specified for new frames.
11180 Frame parameters may be changed if .Xdefaults contains
11181 specifications for the default font. For example, if there is an
11182 `Emacs.default.attributeBackground: pink', the `background-color'
11183 attribute of the frame get's set, which let's the internal border
11184 of the tooltip frame appear in pink. Prevent this. */
11186 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
11188 /* Set tip_frame here, so that */
11190 call1 (Qface_set_after_frame_default
, frame
);
11192 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
11193 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
11201 /* It is now ok to make the frame official even if we get an error
11202 below. And the frame needs to be on Vframe_list or making it
11203 visible won't work. */
11204 Vframe_list
= Fcons (frame
, Vframe_list
);
11206 /* Now that the frame is official, it counts as a reference to
11208 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
11210 /* Setting attributes of faces of the tooltip frame from resources
11211 and similar will increment face_change_count, which leads to the
11212 clearing of all current matrices. Since this isn't necessary
11213 here, avoid it by resetting face_change_count to the value it
11214 had before we created the tip frame. */
11215 face_change_count
= face_change_count_before
;
11217 /* Discard the unwind_protect. */
11218 return unbind_to (count
, frame
);
11222 /* Compute where to display tip frame F. PARMS is the list of frame
11223 parameters for F. DX and DY are specified offsets from the current
11224 location of the mouse. WIDTH and HEIGHT are the width and height
11225 of the tooltip. Return coordinates relative to the root window of
11226 the display in *ROOT_X, and *ROOT_Y. */
11229 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
11231 Lisp_Object parms
, dx
, dy
;
11233 int *root_x
, *root_y
;
11235 Lisp_Object left
, top
;
11237 Window root
, child
;
11240 /* User-specified position? */
11241 left
= Fcdr (Fassq (Qleft
, parms
));
11242 top
= Fcdr (Fassq (Qtop
, parms
));
11244 /* Move the tooltip window where the mouse pointer is. Resize and
11246 if (!INTEGERP (left
) || !INTEGERP (top
))
11249 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
11250 &root
, &child
, root_x
, root_y
, &win_x
, &win_y
, &pmask
);
11254 if (INTEGERP (top
))
11255 *root_y
= XINT (top
);
11256 else if (*root_y
+ XINT (dy
) - height
< 0)
11257 *root_y
-= XINT (dy
);
11261 *root_y
+= XINT (dy
);
11264 if (INTEGERP (left
))
11265 *root_x
= XINT (left
);
11266 else if (*root_x
+ XINT (dx
) + width
<= FRAME_X_DISPLAY_INFO (f
)->width
)
11267 /* It fits to the right of the pointer. */
11268 *root_x
+= XINT (dx
);
11269 else if (width
+ XINT (dx
) <= *root_x
)
11270 /* It fits to the left of the pointer. */
11271 *root_x
-= width
+ XINT (dx
);
11273 /* Put it left-justified on the screen--it ought to fit that way. */
11278 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
11279 doc
: /* Show STRING in a "tooltip" window on frame FRAME.
11280 A tooltip window is a small X window displaying a string.
11282 FRAME nil or omitted means use the selected frame.
11284 PARMS is an optional list of frame parameters which can be used to
11285 change the tooltip's appearance.
11287 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11288 means use the default timeout of 5 seconds.
11290 If the list of frame parameters PARAMS contains a `left' parameters,
11291 the tooltip is displayed at that x-position. Otherwise it is
11292 displayed at the mouse position, with offset DX added (default is 5 if
11293 DX isn't specified). Likewise for the y-position; if a `top' frame
11294 parameter is specified, it determines the y-position of the tooltip
11295 window, otherwise it is displayed at the mouse position, with offset
11296 DY added (default is -10).
11298 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11299 Text larger than the specified size is clipped. */)
11300 (string
, frame
, parms
, timeout
, dx
, dy
)
11301 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
11305 int root_x
, root_y
;
11306 struct buffer
*old_buffer
;
11307 struct text_pos pos
;
11308 int i
, width
, height
;
11309 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
11310 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
11311 int count
= BINDING_STACK_SIZE ();
11313 specbind (Qinhibit_redisplay
, Qt
);
11315 GCPRO4 (string
, parms
, frame
, timeout
);
11317 CHECK_STRING (string
);
11318 f
= check_x_frame (frame
);
11319 if (NILP (timeout
))
11320 timeout
= make_number (5);
11322 CHECK_NATNUM (timeout
);
11325 dx
= make_number (5);
11330 dy
= make_number (-10);
11334 if (NILP (last_show_tip_args
))
11335 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
11337 if (!NILP (tip_frame
))
11339 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
11340 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
11341 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
11343 if (EQ (frame
, last_frame
)
11344 && !NILP (Fequal (last_string
, string
))
11345 && !NILP (Fequal (last_parms
, parms
)))
11347 struct frame
*f
= XFRAME (tip_frame
);
11349 /* Only DX and DY have changed. */
11350 if (!NILP (tip_timer
))
11352 Lisp_Object timer
= tip_timer
;
11354 call1 (Qcancel_timer
, timer
);
11358 compute_tip_xy (f
, parms
, dx
, dy
, PIXEL_WIDTH (f
),
11359 PIXEL_HEIGHT (f
), &root_x
, &root_y
);
11360 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11367 /* Hide a previous tip, if any. */
11370 ASET (last_show_tip_args
, 0, string
);
11371 ASET (last_show_tip_args
, 1, frame
);
11372 ASET (last_show_tip_args
, 2, parms
);
11374 /* Add default values to frame parameters. */
11375 if (NILP (Fassq (Qname
, parms
)))
11376 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
11377 if (NILP (Fassq (Qinternal_border_width
, parms
)))
11378 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
11379 if (NILP (Fassq (Qborder_width
, parms
)))
11380 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
11381 if (NILP (Fassq (Qborder_color
, parms
)))
11382 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
11383 if (NILP (Fassq (Qbackground_color
, parms
)))
11384 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
11387 /* Create a frame for the tooltip, and record it in the global
11388 variable tip_frame. */
11389 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
, string
);
11390 f
= XFRAME (frame
);
11392 /* Set up the frame's root window. */
11393 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
11394 w
->left
= w
->top
= make_number (0);
11396 if (CONSP (Vx_max_tooltip_size
)
11397 && INTEGERP (XCAR (Vx_max_tooltip_size
))
11398 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
11399 && INTEGERP (XCDR (Vx_max_tooltip_size
))
11400 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
11402 w
->width
= XCAR (Vx_max_tooltip_size
);
11403 w
->height
= XCDR (Vx_max_tooltip_size
);
11407 w
->width
= make_number (80);
11408 w
->height
= make_number (40);
11411 f
->window_width
= XINT (w
->width
);
11413 w
->pseudo_window_p
= 1;
11415 /* Display the tooltip text in a temporary buffer. */
11416 old_buffer
= current_buffer
;
11417 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
11418 current_buffer
->truncate_lines
= Qnil
;
11419 clear_glyph_matrix (w
->desired_matrix
);
11420 clear_glyph_matrix (w
->current_matrix
);
11421 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
11422 try_window (FRAME_ROOT_WINDOW (f
), pos
);
11424 /* Compute width and height of the tooltip. */
11425 width
= height
= 0;
11426 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
11428 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
11429 struct glyph
*last
;
11432 /* Stop at the first empty row at the end. */
11433 if (!row
->enabled_p
|| !row
->displays_text_p
)
11436 /* Let the row go over the full width of the frame. */
11437 row
->full_width_p
= 1;
11439 /* There's a glyph at the end of rows that is used to place
11440 the cursor there. Don't include the width of this glyph. */
11441 if (row
->used
[TEXT_AREA
])
11443 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
11444 row_width
= row
->pixel_width
- last
->pixel_width
;
11447 row_width
= row
->pixel_width
;
11449 height
+= row
->height
;
11450 width
= max (width
, row_width
);
11453 /* Add the frame's internal border to the width and height the X
11454 window should have. */
11455 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11456 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
11458 /* Move the tooltip window where the mouse pointer is. Resize and
11460 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
11463 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11464 root_x
, root_y
, width
, height
);
11465 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11468 /* Draw into the window. */
11469 w
->must_be_updated_p
= 1;
11470 update_single_window (w
, 1);
11472 /* Restore original current buffer. */
11473 set_buffer_internal_1 (old_buffer
);
11474 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
11477 /* Let the tip disappear after timeout seconds. */
11478 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
11479 intern ("x-hide-tip"));
11482 return unbind_to (count
, Qnil
);
11486 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
11487 doc
: /* Hide the current tooltip window, if there is any.
11488 Value is t if tooltip was open, nil otherwise. */)
11492 Lisp_Object deleted
, frame
, timer
;
11493 struct gcpro gcpro1
, gcpro2
;
11495 /* Return quickly if nothing to do. */
11496 if (NILP (tip_timer
) && NILP (tip_frame
))
11501 GCPRO2 (frame
, timer
);
11502 tip_frame
= tip_timer
= deleted
= Qnil
;
11504 count
= BINDING_STACK_SIZE ();
11505 specbind (Qinhibit_redisplay
, Qt
);
11506 specbind (Qinhibit_quit
, Qt
);
11509 call1 (Qcancel_timer
, timer
);
11511 if (FRAMEP (frame
))
11513 Fdelete_frame (frame
, Qnil
);
11517 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11518 redisplay procedure is not called when a tip frame over menu
11519 items is unmapped. Redisplay the menu manually... */
11521 struct frame
*f
= SELECTED_FRAME ();
11522 Widget w
= f
->output_data
.x
->menubar_widget
;
11523 extern void xlwmenu_redisplay
P_ ((Widget
));
11525 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f
)->screen
)
11529 xlwmenu_redisplay (w
);
11533 #endif /* USE_LUCID */
11537 return unbind_to (count
, deleted
);
11542 /***********************************************************************
11543 File selection dialog
11544 ***********************************************************************/
11548 /* Callback for "OK" and "Cancel" on file selection dialog. */
11551 file_dialog_cb (widget
, client_data
, call_data
)
11553 XtPointer call_data
, client_data
;
11555 int *result
= (int *) client_data
;
11556 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
11557 *result
= cb
->reason
;
11561 /* Callback for unmapping a file selection dialog. This is used to
11562 capture the case where a dialog is closed via a window manager's
11563 closer button, for example. Using a XmNdestroyCallback didn't work
11567 file_dialog_unmap_cb (widget
, client_data
, call_data
)
11569 XtPointer call_data
, client_data
;
11571 int *result
= (int *) client_data
;
11572 *result
= XmCR_CANCEL
;
11576 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
11577 doc
: /* Read file name, prompting with PROMPT in directory DIR.
11578 Use a file selection dialog.
11579 Select DEFAULT-FILENAME in the dialog's file selection box, if
11580 specified. Don't let the user enter a file name in the file
11581 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11582 (prompt
, dir
, default_filename
, mustmatch
)
11583 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
11586 struct frame
*f
= SELECTED_FRAME ();
11587 Lisp_Object file
= Qnil
;
11588 Widget dialog
, text
, list
, help
;
11591 extern XtAppContext Xt_app_con
;
11592 XmString dir_xmstring
, pattern_xmstring
;
11593 int count
= specpdl_ptr
- specpdl
;
11594 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
11596 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
11597 CHECK_STRING (prompt
);
11598 CHECK_STRING (dir
);
11600 /* Prevent redisplay. */
11601 specbind (Qinhibit_redisplay
, Qt
);
11605 /* Create the dialog with PROMPT as title, using DIR as initial
11606 directory and using "*" as pattern. */
11607 dir
= Fexpand_file_name (dir
, Qnil
);
11608 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
11609 pattern_xmstring
= XmStringCreateLocalized ("*");
11611 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
11612 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
11613 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
11614 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
11615 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
11616 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
11618 XmStringFree (dir_xmstring
);
11619 XmStringFree (pattern_xmstring
);
11621 /* Add callbacks for OK and Cancel. */
11622 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
11623 (XtPointer
) &result
);
11624 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
11625 (XtPointer
) &result
);
11626 XtAddCallback (dialog
, XmNunmapCallback
, file_dialog_unmap_cb
,
11627 (XtPointer
) &result
);
11629 /* Disable the help button since we can't display help. */
11630 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
11631 XtSetSensitive (help
, False
);
11633 /* Mark OK button as default. */
11634 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
11635 XmNshowAsDefault
, True
, NULL
);
11637 /* If MUSTMATCH is non-nil, disable the file entry field of the
11638 dialog, so that the user must select a file from the files list
11639 box. We can't remove it because we wouldn't have a way to get at
11640 the result file name, then. */
11641 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
11642 if (!NILP (mustmatch
))
11645 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
11646 XtSetSensitive (text
, False
);
11647 XtSetSensitive (label
, False
);
11650 /* Manage the dialog, so that list boxes get filled. */
11651 XtManageChild (dialog
);
11653 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11654 must include the path for this to work. */
11655 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
11656 if (STRINGP (default_filename
))
11658 XmString default_xmstring
;
11662 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
11664 if (!XmListItemExists (list
, default_xmstring
))
11666 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11667 XmListAddItem (list
, default_xmstring
, 0);
11671 item_pos
= XmListItemPos (list
, default_xmstring
);
11672 XmStringFree (default_xmstring
);
11674 /* Select the item and scroll it into view. */
11675 XmListSelectPos (list
, item_pos
, True
);
11676 XmListSetPos (list
, item_pos
);
11679 /* Process events until the user presses Cancel or OK. Block
11680 and unblock input here so that we get a chance of processing
11684 while (result
== 0)
11687 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
11692 /* Get the result. */
11693 if (result
== XmCR_OK
)
11698 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
11699 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
11700 XmStringFree (text
);
11701 file
= build_string (data
);
11708 XtUnmanageChild (dialog
);
11709 XtDestroyWidget (dialog
);
11713 /* Make "Cancel" equivalent to C-g. */
11715 Fsignal (Qquit
, Qnil
);
11717 return unbind_to (count
, file
);
11720 #endif /* USE_MOTIF */
11724 /***********************************************************************
11726 ***********************************************************************/
11728 #ifdef HAVE_XKBGETKEYBOARD
11729 #include <X11/XKBlib.h>
11730 #include <X11/keysym.h>
11733 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p
,
11734 Sx_backspace_delete_keys_p
, 0, 1, 0,
11735 doc
: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11736 FRAME nil means use the selected frame.
11737 Value is t if we know that both keys are present, and are mapped to the
11738 usual X keysyms. */)
11742 #ifdef HAVE_XKBGETKEYBOARD
11744 struct frame
*f
= check_x_frame (frame
);
11745 Display
*dpy
= FRAME_X_DISPLAY (f
);
11746 Lisp_Object have_keys
;
11747 int major
, minor
, op
, event
, error
;
11751 /* Check library version in case we're dynamically linked. */
11752 major
= XkbMajorVersion
;
11753 minor
= XkbMinorVersion
;
11754 if (!XkbLibraryVersion (&major
, &minor
))
11760 /* Check that the server supports XKB. */
11761 major
= XkbMajorVersion
;
11762 minor
= XkbMinorVersion
;
11763 if (!XkbQueryExtension (dpy
, &op
, &event
, &error
, &major
, &minor
))
11770 kb
= XkbGetMap (dpy
, XkbAllMapComponentsMask
, XkbUseCoreKbd
);
11773 int delete_keycode
= 0, backspace_keycode
= 0, i
;
11775 if (XkbGetNames (dpy
, XkbAllNamesMask
, kb
) == Success
)
11777 for (i
= kb
->min_key_code
;
11778 (i
< kb
->max_key_code
11779 && (delete_keycode
== 0 || backspace_keycode
== 0));
11782 /* The XKB symbolic key names can be seen most easily in
11783 the PS file generated by `xkbprint -label name
11785 if (bcmp ("DELE", kb
->names
->keys
[i
].name
, 4) == 0)
11786 delete_keycode
= i
;
11787 else if (bcmp ("BKSP", kb
->names
->keys
[i
].name
, 4) == 0)
11788 backspace_keycode
= i
;
11791 XkbFreeNames (kb
, 0, True
);
11794 XkbFreeClientMap (kb
, 0, True
);
11797 && backspace_keycode
11798 && XKeysymToKeycode (dpy
, XK_Delete
) == delete_keycode
11799 && XKeysymToKeycode (dpy
, XK_BackSpace
) == backspace_keycode
)
11804 #else /* not HAVE_XKBGETKEYBOARD */
11806 #endif /* not HAVE_XKBGETKEYBOARD */
11811 /***********************************************************************
11813 ***********************************************************************/
11818 /* This is zero if not using X windows. */
11821 /* The section below is built by the lisp expression at the top of the file,
11822 just above where these variables are declared. */
11823 /*&&& init symbols here &&&*/
11824 Qauto_raise
= intern ("auto-raise");
11825 staticpro (&Qauto_raise
);
11826 Qauto_lower
= intern ("auto-lower");
11827 staticpro (&Qauto_lower
);
11828 Qbar
= intern ("bar");
11830 Qborder_color
= intern ("border-color");
11831 staticpro (&Qborder_color
);
11832 Qborder_width
= intern ("border-width");
11833 staticpro (&Qborder_width
);
11834 Qbox
= intern ("box");
11836 Qcursor_color
= intern ("cursor-color");
11837 staticpro (&Qcursor_color
);
11838 Qcursor_type
= intern ("cursor-type");
11839 staticpro (&Qcursor_type
);
11840 Qgeometry
= intern ("geometry");
11841 staticpro (&Qgeometry
);
11842 Qicon_left
= intern ("icon-left");
11843 staticpro (&Qicon_left
);
11844 Qicon_top
= intern ("icon-top");
11845 staticpro (&Qicon_top
);
11846 Qicon_type
= intern ("icon-type");
11847 staticpro (&Qicon_type
);
11848 Qicon_name
= intern ("icon-name");
11849 staticpro (&Qicon_name
);
11850 Qinternal_border_width
= intern ("internal-border-width");
11851 staticpro (&Qinternal_border_width
);
11852 Qleft
= intern ("left");
11853 staticpro (&Qleft
);
11854 Qright
= intern ("right");
11855 staticpro (&Qright
);
11856 Qmouse_color
= intern ("mouse-color");
11857 staticpro (&Qmouse_color
);
11858 Qnone
= intern ("none");
11859 staticpro (&Qnone
);
11860 Qparent_id
= intern ("parent-id");
11861 staticpro (&Qparent_id
);
11862 Qscroll_bar_width
= intern ("scroll-bar-width");
11863 staticpro (&Qscroll_bar_width
);
11864 Qsuppress_icon
= intern ("suppress-icon");
11865 staticpro (&Qsuppress_icon
);
11866 Qundefined_color
= intern ("undefined-color");
11867 staticpro (&Qundefined_color
);
11868 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
11869 staticpro (&Qvertical_scroll_bars
);
11870 Qvisibility
= intern ("visibility");
11871 staticpro (&Qvisibility
);
11872 Qwindow_id
= intern ("window-id");
11873 staticpro (&Qwindow_id
);
11874 Qouter_window_id
= intern ("outer-window-id");
11875 staticpro (&Qouter_window_id
);
11876 Qx_frame_parameter
= intern ("x-frame-parameter");
11877 staticpro (&Qx_frame_parameter
);
11878 Qx_resource_name
= intern ("x-resource-name");
11879 staticpro (&Qx_resource_name
);
11880 Quser_position
= intern ("user-position");
11881 staticpro (&Quser_position
);
11882 Quser_size
= intern ("user-size");
11883 staticpro (&Quser_size
);
11884 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
11885 staticpro (&Qscroll_bar_foreground
);
11886 Qscroll_bar_background
= intern ("scroll-bar-background");
11887 staticpro (&Qscroll_bar_background
);
11888 Qscreen_gamma
= intern ("screen-gamma");
11889 staticpro (&Qscreen_gamma
);
11890 Qline_spacing
= intern ("line-spacing");
11891 staticpro (&Qline_spacing
);
11892 Qcenter
= intern ("center");
11893 staticpro (&Qcenter
);
11894 Qcompound_text
= intern ("compound-text");
11895 staticpro (&Qcompound_text
);
11896 Qcancel_timer
= intern ("cancel-timer");
11897 staticpro (&Qcancel_timer
);
11898 Qwait_for_wm
= intern ("wait-for-wm");
11899 staticpro (&Qwait_for_wm
);
11900 Qfullscreen
= intern ("fullscreen");
11901 staticpro (&Qfullscreen
);
11902 Qfullwidth
= intern ("fullwidth");
11903 staticpro (&Qfullwidth
);
11904 Qfullheight
= intern ("fullheight");
11905 staticpro (&Qfullheight
);
11906 Qfullboth
= intern ("fullboth");
11907 staticpro (&Qfullboth
);
11908 /* This is the end of symbol initialization. */
11910 /* Text property `display' should be nonsticky by default. */
11911 Vtext_property_default_nonsticky
11912 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
11915 Qlaplace
= intern ("laplace");
11916 staticpro (&Qlaplace
);
11917 Qemboss
= intern ("emboss");
11918 staticpro (&Qemboss
);
11919 Qedge_detection
= intern ("edge-detection");
11920 staticpro (&Qedge_detection
);
11921 Qheuristic
= intern ("heuristic");
11922 staticpro (&Qheuristic
);
11923 QCmatrix
= intern (":matrix");
11924 staticpro (&QCmatrix
);
11925 QCcolor_adjustment
= intern (":color-adjustment");
11926 staticpro (&QCcolor_adjustment
);
11927 QCmask
= intern (":mask");
11928 staticpro (&QCmask
);
11930 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
11931 staticpro (&Qface_set_after_frame_default
);
11933 Fput (Qundefined_color
, Qerror_conditions
,
11934 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
11935 Fput (Qundefined_color
, Qerror_message
,
11936 build_string ("Undefined color"));
11938 init_x_parm_symbols ();
11940 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
11941 doc
: /* Non-nil means always draw a cross over disabled images.
11942 Disabled images are those having an `:conversion disabled' property.
11943 A cross is always drawn on black & white displays. */);
11944 cross_disabled_images
= 0;
11946 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11947 doc
: /* List of directories to search for bitmap files for X. */);
11948 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11950 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11951 doc
: /* The shape of the pointer when over text.
11952 Changing the value does not affect existing frames
11953 unless you set the mouse color. */);
11954 Vx_pointer_shape
= Qnil
;
11956 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11957 doc
: /* The name Emacs uses to look up X resources.
11958 `x-get-resource' uses this as the first component of the instance name
11959 when requesting resource values.
11960 Emacs initially sets `x-resource-name' to the name under which Emacs
11961 was invoked, or to the value specified with the `-name' or `-rn'
11962 switches, if present.
11964 It may be useful to bind this variable locally around a call
11965 to `x-get-resource'. See also the variable `x-resource-class'. */);
11966 Vx_resource_name
= Qnil
;
11968 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11969 doc
: /* The class Emacs uses to look up X resources.
11970 `x-get-resource' uses this as the first component of the instance class
11971 when requesting resource values.
11973 Emacs initially sets `x-resource-class' to "Emacs".
11975 Setting this variable permanently is not a reasonable thing to do,
11976 but binding this variable locally around a call to `x-get-resource'
11977 is a reasonable practice. See also the variable `x-resource-name'. */);
11978 Vx_resource_class
= build_string (EMACS_CLASS
);
11980 #if 0 /* This doesn't really do anything. */
11981 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11982 doc
: /* The shape of the pointer when not over text.
11983 This variable takes effect when you create a new frame
11984 or when you set the mouse color. */);
11986 Vx_nontext_pointer_shape
= Qnil
;
11988 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
11989 doc
: /* The shape of the pointer when Emacs is busy.
11990 This variable takes effect when you create a new frame
11991 or when you set the mouse color. */);
11992 Vx_hourglass_pointer_shape
= Qnil
;
11994 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
11995 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
11996 display_hourglass_p
= 1;
11998 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
11999 doc
: /* *Seconds to wait before displaying an hourglass pointer.
12000 Value must be an integer or float. */);
12001 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
12003 #if 0 /* This doesn't really do anything. */
12004 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
12005 doc
: /* The shape of the pointer when over the mode line.
12006 This variable takes effect when you create a new frame
12007 or when you set the mouse color. */);
12009 Vx_mode_pointer_shape
= Qnil
;
12011 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
12012 &Vx_sensitive_text_pointer_shape
,
12013 doc
: /* The shape of the pointer when over mouse-sensitive text.
12014 This variable takes effect when you create a new frame
12015 or when you set the mouse color. */);
12016 Vx_sensitive_text_pointer_shape
= Qnil
;
12018 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
12019 &Vx_window_horizontal_drag_shape
,
12020 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
12021 This variable takes effect when you create a new frame
12022 or when you set the mouse color. */);
12023 Vx_window_horizontal_drag_shape
= Qnil
;
12025 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
12026 doc
: /* A string indicating the foreground color of the cursor box. */);
12027 Vx_cursor_fore_pixel
= Qnil
;
12029 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
12030 doc
: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
12031 Text larger than this is clipped. */);
12032 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
12034 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
12035 doc
: /* Non-nil if no X window manager is in use.
12036 Emacs doesn't try to figure this out; this is always nil
12037 unless you set it to something else. */);
12038 /* We don't have any way to find this out, so set it to nil
12039 and maybe the user would like to set it to t. */
12040 Vx_no_window_manager
= Qnil
;
12042 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
12043 &Vx_pixel_size_width_font_regexp
,
12044 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
12046 Since Emacs gets width of a font matching with this regexp from
12047 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12048 such a font. This is especially effective for such large fonts as
12049 Chinese, Japanese, and Korean. */);
12050 Vx_pixel_size_width_font_regexp
= Qnil
;
12052 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
12053 doc
: /* Time after which cached images are removed from the cache.
12054 When an image has not been displayed this many seconds, remove it
12055 from the image cache. Value must be an integer or nil with nil
12056 meaning don't clear the cache. */);
12057 Vimage_cache_eviction_delay
= make_number (30 * 60);
12059 #ifdef USE_X_TOOLKIT
12060 Fprovide (intern ("x-toolkit"), Qnil
);
12062 Fprovide (intern ("motif"), Qnil
);
12064 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string
,
12065 doc
: /* Version info for LessTif/Motif. */);
12066 Vmotif_version_string
= build_string (XmVERSION_STRING
);
12067 #endif /* USE_MOTIF */
12068 #endif /* USE_X_TOOLKIT */
12070 defsubr (&Sx_get_resource
);
12072 /* X window properties. */
12073 defsubr (&Sx_change_window_property
);
12074 defsubr (&Sx_delete_window_property
);
12075 defsubr (&Sx_window_property
);
12077 defsubr (&Sxw_display_color_p
);
12078 defsubr (&Sx_display_grayscale_p
);
12079 defsubr (&Sxw_color_defined_p
);
12080 defsubr (&Sxw_color_values
);
12081 defsubr (&Sx_server_max_request_size
);
12082 defsubr (&Sx_server_vendor
);
12083 defsubr (&Sx_server_version
);
12084 defsubr (&Sx_display_pixel_width
);
12085 defsubr (&Sx_display_pixel_height
);
12086 defsubr (&Sx_display_mm_width
);
12087 defsubr (&Sx_display_mm_height
);
12088 defsubr (&Sx_display_screens
);
12089 defsubr (&Sx_display_planes
);
12090 defsubr (&Sx_display_color_cells
);
12091 defsubr (&Sx_display_visual_class
);
12092 defsubr (&Sx_display_backing_store
);
12093 defsubr (&Sx_display_save_under
);
12094 defsubr (&Sx_parse_geometry
);
12095 defsubr (&Sx_create_frame
);
12096 defsubr (&Sx_open_connection
);
12097 defsubr (&Sx_close_connection
);
12098 defsubr (&Sx_display_list
);
12099 defsubr (&Sx_synchronize
);
12100 defsubr (&Sx_focus_frame
);
12101 defsubr (&Sx_backspace_delete_keys_p
);
12103 /* Setting callback functions for fontset handler. */
12104 get_font_info_func
= x_get_font_info
;
12106 #if 0 /* This function pointer doesn't seem to be used anywhere.
12107 And the pointer assigned has the wrong type, anyway. */
12108 list_fonts_func
= x_list_fonts
;
12111 load_font_func
= x_load_font
;
12112 find_ccl_program_func
= x_find_ccl_program
;
12113 query_font_func
= x_query_font
;
12114 set_frame_fontset_func
= x_set_font
;
12115 check_window_system_func
= check_x
;
12118 Qxbm
= intern ("xbm");
12120 QCtype
= intern (":type");
12121 staticpro (&QCtype
);
12122 QCconversion
= intern (":conversion");
12123 staticpro (&QCconversion
);
12124 QCheuristic_mask
= intern (":heuristic-mask");
12125 staticpro (&QCheuristic_mask
);
12126 QCcolor_symbols
= intern (":color-symbols");
12127 staticpro (&QCcolor_symbols
);
12128 QCascent
= intern (":ascent");
12129 staticpro (&QCascent
);
12130 QCmargin
= intern (":margin");
12131 staticpro (&QCmargin
);
12132 QCrelief
= intern (":relief");
12133 staticpro (&QCrelief
);
12134 Qpostscript
= intern ("postscript");
12135 staticpro (&Qpostscript
);
12136 QCloader
= intern (":loader");
12137 staticpro (&QCloader
);
12138 QCbounding_box
= intern (":bounding-box");
12139 staticpro (&QCbounding_box
);
12140 QCpt_width
= intern (":pt-width");
12141 staticpro (&QCpt_width
);
12142 QCpt_height
= intern (":pt-height");
12143 staticpro (&QCpt_height
);
12144 QCindex
= intern (":index");
12145 staticpro (&QCindex
);
12146 Qpbm
= intern ("pbm");
12150 Qxpm
= intern ("xpm");
12155 Qjpeg
= intern ("jpeg");
12156 staticpro (&Qjpeg
);
12160 Qtiff
= intern ("tiff");
12161 staticpro (&Qtiff
);
12165 Qgif
= intern ("gif");
12170 Qpng
= intern ("png");
12174 defsubr (&Sclear_image_cache
);
12175 defsubr (&Simage_size
);
12176 defsubr (&Simage_mask_p
);
12178 hourglass_atimer
= NULL
;
12179 hourglass_shown_p
= 0;
12181 defsubr (&Sx_show_tip
);
12182 defsubr (&Sx_hide_tip
);
12184 staticpro (&tip_timer
);
12186 staticpro (&tip_frame
);
12188 last_show_tip_args
= Qnil
;
12189 staticpro (&last_show_tip_args
);
12192 defsubr (&Sx_file_dialog
);
12200 image_types
= NULL
;
12201 Vimage_types
= Qnil
;
12203 define_image_type (&xbm_type
);
12204 define_image_type (&gs_type
);
12205 define_image_type (&pbm_type
);
12208 define_image_type (&xpm_type
);
12212 define_image_type (&jpeg_type
);
12216 define_image_type (&tiff_type
);
12220 define_image_type (&gif_type
);
12224 define_image_type (&png_type
);
12228 #endif /* HAVE_X_WINDOWS */