diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/xfns.c | 230 |
1 files changed, 213 insertions, 17 deletions
diff --git a/src/xfns.c b/src/xfns.c index 02cc0ade3d2..c91e49549a4 100644 --- a/src/xfns.c +++ b/src/xfns.c | |||
| @@ -781,6 +781,13 @@ static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *, | |||
| 781 | static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object)); | 781 | static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object)); |
| 782 | static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object, | 782 | static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object, |
| 783 | Lisp_Object)); | 783 | Lisp_Object)); |
| 784 | static void init_color_table P_ ((void)); | ||
| 785 | static void free_color_table P_ ((void)); | ||
| 786 | static unsigned long *colors_in_color_table P_ ((int *n)); | ||
| 787 | static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b)); | ||
| 788 | static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p)); | ||
| 789 | |||
| 790 | |||
| 784 | 791 | ||
| 785 | static struct x_frame_parm_table x_frame_parms[] = | 792 | static struct x_frame_parm_table x_frame_parms[] = |
| 786 | { | 793 | { |
| @@ -3833,7 +3840,7 @@ x_icon (f, parms) | |||
| 3833 | UNBLOCK_INPUT; | 3840 | UNBLOCK_INPUT; |
| 3834 | } | 3841 | } |
| 3835 | 3842 | ||
| 3836 | /* Make the GC's needed for this window, setting the | 3843 | /* Make the GCs needed for this window, setting the |
| 3837 | background, border and mouse colors; also create the | 3844 | background, border and mouse colors; also create the |
| 3838 | mouse cursor and the gray border tile. */ | 3845 | mouse cursor and the gray border tile. */ |
| 3839 | 3846 | ||
| @@ -3853,7 +3860,7 @@ x_make_gc (f) | |||
| 3853 | 3860 | ||
| 3854 | BLOCK_INPUT; | 3861 | BLOCK_INPUT; |
| 3855 | 3862 | ||
| 3856 | /* Create the GC's of this frame. | 3863 | /* Create the GCs of this frame. |
| 3857 | Note that many default values are used. */ | 3864 | Note that many default values are used. */ |
| 3858 | 3865 | ||
| 3859 | /* Normal video */ | 3866 | /* Normal video */ |
| @@ -5369,6 +5376,31 @@ or omitted means use the selected frame.") | |||
| 5369 | } | 5376 | } |
| 5370 | 5377 | ||
| 5371 | 5378 | ||
| 5379 | DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0, | ||
| 5380 | "Return t if image SPEC has a mask bitmap.\n\ | ||
| 5381 | FRAME is the frame on which the image will be displayed. FRAME nil\n\ | ||
| 5382 | or omitted means use the selected frame.") | ||
| 5383 | (spec, frame) | ||
| 5384 | Lisp_Object spec, frame; | ||
| 5385 | { | ||
| 5386 | Lisp_Object mask; | ||
| 5387 | |||
| 5388 | mask = Qnil; | ||
| 5389 | if (valid_image_p (spec)) | ||
| 5390 | { | ||
| 5391 | struct frame *f = check_x_frame (frame); | ||
| 5392 | int id = lookup_image (f, spec); | ||
| 5393 | struct image *img = IMAGE_FROM_ID (f, id); | ||
| 5394 | if (img->mask) | ||
| 5395 | mask = Qt; | ||
| 5396 | } | ||
| 5397 | else | ||
| 5398 | error ("Invalid image specification"); | ||
| 5399 | |||
| 5400 | return mask; | ||
| 5401 | } | ||
| 5402 | |||
| 5403 | |||
| 5372 | 5404 | ||
| 5373 | /*********************************************************************** | 5405 | /*********************************************************************** |
| 5374 | Image type independent image structures | 5406 | Image type independent image structures |
| @@ -5776,7 +5808,7 @@ lookup_image (f, spec) | |||
| 5776 | means build a mask heuristically. | 5808 | means build a mask heuristically. |
| 5777 | `:heuristic-mask (R G B)' | 5809 | `:heuristic-mask (R G B)' |
| 5778 | `:mask (heuristic (R G B))' | 5810 | `:mask (heuristic (R G B))' |
| 5779 | measn build a mask from color (R G B) in the | 5811 | means build a mask from color (R G B) in the |
| 5780 | image. | 5812 | image. |
| 5781 | `:mask nil' | 5813 | `:mask nil' |
| 5782 | means remove a mask, if any. */ | 5814 | means remove a mask, if any. */ |
| @@ -6018,7 +6050,7 @@ x_find_image_file (file) | |||
| 6018 | 6050 | ||
| 6019 | /* Read FILE into memory. Value is a pointer to a buffer allocated | 6051 | /* Read FILE into memory. Value is a pointer to a buffer allocated |
| 6020 | with xmalloc holding FILE's contents. Value is null if an error | 6052 | with xmalloc holding FILE's contents. Value is null if an error |
| 6021 | occured. *SIZE is set to the size of the file. */ | 6053 | occurred. *SIZE is set to the size of the file. */ |
| 6022 | 6054 | ||
| 6023 | static char * | 6055 | static char * |
| 6024 | slurp_file (file, size) | 6056 | slurp_file (file, size) |
| @@ -6329,7 +6361,7 @@ xbm_scan (s, end, sval, ival) | |||
| 6329 | buffer's end. Set *WIDTH and *HEIGHT to the width and height of | 6361 | buffer's end. Set *WIDTH and *HEIGHT to the width and height of |
| 6330 | the image. Return in *DATA the bitmap data allocated with xmalloc. | 6362 | the image. Return in *DATA the bitmap data allocated with xmalloc. |
| 6331 | Value is non-zero if successful. DATA null means just test if | 6363 | Value is non-zero if successful. DATA null means just test if |
| 6332 | CONTENTS looks like an im-memory XBM file. */ | 6364 | CONTENTS looks like an in-memory XBM file. */ |
| 6333 | 6365 | ||
| 6334 | static int | 6366 | static int |
| 6335 | xbm_read_bitmap_data (contents, end, width, height, data) | 6367 | xbm_read_bitmap_data (contents, end, width, height, data) |
| @@ -6747,6 +6779,156 @@ static struct image_type xpm_type = | |||
| 6747 | }; | 6779 | }; |
| 6748 | 6780 | ||
| 6749 | 6781 | ||
| 6782 | /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation | ||
| 6783 | functions for allocating image colors. Our own functions handle | ||
| 6784 | color allocation failures more gracefully than the ones on the XPM | ||
| 6785 | lib. */ | ||
| 6786 | |||
| 6787 | #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure | ||
| 6788 | #define ALLOC_XPM_COLORS | ||
| 6789 | #endif | ||
| 6790 | |||
| 6791 | #ifdef ALLOC_XPM_COLORS | ||
| 6792 | |||
| 6793 | static void xpm_init_color_cache P_ ((void)); | ||
| 6794 | static void xpm_free_color_cache P_ ((void)); | ||
| 6795 | static int xpm_lookup_color P_ ((struct frame *, char *, XColor *)); | ||
| 6796 | |||
| 6797 | /* An entry in a hash table used to cache color definitions of named | ||
| 6798 | colors. This cache is necessary to speed up XPM image loading in | ||
| 6799 | case we do color allocations ourselves. Without it, we would need | ||
| 6800 | a call to XParseColor per pixel in the image. */ | ||
| 6801 | |||
| 6802 | struct xpm_cached_color | ||
| 6803 | { | ||
| 6804 | /* Next in collision chain. */ | ||
| 6805 | struct xpm_cached_color *next; | ||
| 6806 | |||
| 6807 | /* Color definition (RGB and pixel color). */ | ||
| 6808 | XColor color; | ||
| 6809 | |||
| 6810 | /* Color name. */ | ||
| 6811 | char name[1]; | ||
| 6812 | }; | ||
| 6813 | |||
| 6814 | /* The hash table used for the color cache, and its bucket vector | ||
| 6815 | size. */ | ||
| 6816 | |||
| 6817 | #define XPM_COLOR_CACHE_BUCKETS 1001 | ||
| 6818 | struct xpm_cached_color **xpm_color_cache; | ||
| 6819 | |||
| 6820 | |||
| 6821 | /* Initialize the color cache. */ | ||
| 6822 | |||
| 6823 | static void | ||
| 6824 | xpm_init_color_cache () | ||
| 6825 | { | ||
| 6826 | size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache; | ||
| 6827 | xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes); | ||
| 6828 | memset (xpm_color_cache, 0, nbytes); | ||
| 6829 | init_color_table (); | ||
| 6830 | } | ||
| 6831 | |||
| 6832 | |||
| 6833 | /* Free the color cache. */ | ||
| 6834 | |||
| 6835 | static void | ||
| 6836 | xpm_free_color_cache () | ||
| 6837 | { | ||
| 6838 | struct xpm_cached_color *p, *next; | ||
| 6839 | int i; | ||
| 6840 | |||
| 6841 | for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i) | ||
| 6842 | for (p = xpm_color_cache[i]; p; p = next) | ||
| 6843 | { | ||
| 6844 | next = p->next; | ||
| 6845 | xfree (p); | ||
| 6846 | } | ||
| 6847 | |||
| 6848 | xfree (xpm_color_cache); | ||
| 6849 | xpm_color_cache = NULL; | ||
| 6850 | free_color_table (); | ||
| 6851 | } | ||
| 6852 | |||
| 6853 | |||
| 6854 | /* Look up color COLOR_NAME for frame F in the color cache. If found, | ||
| 6855 | return the cached definition in *COLOR. Otherwise, make a new | ||
| 6856 | entry in the cache and allocate the color. Value is zero if color | ||
| 6857 | allocation failed. */ | ||
| 6858 | |||
| 6859 | static int | ||
| 6860 | xpm_lookup_color (f, color_name, color) | ||
| 6861 | struct frame *f; | ||
| 6862 | char *color_name; | ||
| 6863 | XColor *color; | ||
| 6864 | { | ||
| 6865 | unsigned h = 0; | ||
| 6866 | const char *s; | ||
| 6867 | struct xpm_cached_color *p; | ||
| 6868 | |||
| 6869 | for (s = color_name; *s; ++s) | ||
| 6870 | h = (h << 2) ^ *s; | ||
| 6871 | h %= XPM_COLOR_CACHE_BUCKETS; | ||
| 6872 | |||
| 6873 | for (p = xpm_color_cache[h]; p; p = p->next) | ||
| 6874 | if (strcmp (p->name, color_name) == 0) | ||
| 6875 | break; | ||
| 6876 | |||
| 6877 | if (p != NULL) | ||
| 6878 | *color = p->color; | ||
| 6879 | else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), | ||
| 6880 | color_name, color)) | ||
| 6881 | { | ||
| 6882 | size_t nbytes; | ||
| 6883 | color->pixel = lookup_rgb_color (f, color->red, color->green, | ||
| 6884 | color->blue); | ||
| 6885 | nbytes = sizeof *p + strlen (color_name); | ||
| 6886 | p = (struct xpm_cached_color *) xmalloc (nbytes); | ||
| 6887 | strcpy (p->name, color_name); | ||
| 6888 | p->color = *color; | ||
| 6889 | p->next = xpm_color_cache[h]; | ||
| 6890 | xpm_color_cache[h] = p; | ||
| 6891 | } | ||
| 6892 | |||
| 6893 | return p != NULL; | ||
| 6894 | } | ||
| 6895 | |||
| 6896 | |||
| 6897 | /* Callback for allocating color COLOR_NAME. Called from the XPM lib. | ||
| 6898 | CLOSURE is a pointer to the frame on which we allocate the | ||
| 6899 | color. Return in *COLOR the allocated color. Value is non-zero | ||
| 6900 | if successful. */ | ||
| 6901 | |||
| 6902 | static int | ||
| 6903 | xpm_alloc_color (dpy, cmap, color_name, color, closure) | ||
| 6904 | Display *dpy; | ||
| 6905 | Colormap cmap; | ||
| 6906 | char *color_name; | ||
| 6907 | XColor *color; | ||
| 6908 | void *closure; | ||
| 6909 | { | ||
| 6910 | return xpm_lookup_color ((struct frame *) closure, color_name, color); | ||
| 6911 | } | ||
| 6912 | |||
| 6913 | |||
| 6914 | /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE | ||
| 6915 | is a pointer to the frame on which we allocate the color. Value is | ||
| 6916 | non-zero if successful. */ | ||
| 6917 | |||
| 6918 | static int | ||
| 6919 | xpm_free_colors (dpy, cmap, pixels, npixels, closure) | ||
| 6920 | Display *dpy; | ||
| 6921 | Colormap cmap; | ||
| 6922 | Pixel *pixels; | ||
| 6923 | int npixels; | ||
| 6924 | void *closure; | ||
| 6925 | { | ||
| 6926 | return 1; | ||
| 6927 | } | ||
| 6928 | |||
| 6929 | #endif /* ALLOC_XPM_COLORS */ | ||
| 6930 | |||
| 6931 | |||
| 6750 | /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list | 6932 | /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list |
| 6751 | for XPM images. Such a list must consist of conses whose car and | 6933 | for XPM images. Such a list must consist of conses whose car and |
| 6752 | cdr are strings. */ | 6934 | cdr are strings. */ |
| @@ -6806,14 +6988,25 @@ xpm_load (f, img) | |||
| 6806 | attrs.colormap = FRAME_X_COLORMAP (f); | 6988 | attrs.colormap = FRAME_X_COLORMAP (f); |
| 6807 | attrs.valuemask |= XpmVisual; | 6989 | attrs.valuemask |= XpmVisual; |
| 6808 | attrs.valuemask |= XpmColormap; | 6990 | attrs.valuemask |= XpmColormap; |
| 6991 | |||
| 6992 | #ifdef ALLOC_XPM_COLORS | ||
| 6993 | /* Allocate colors with our own functions which handle | ||
| 6994 | failing color allocation more gracefully. */ | ||
| 6995 | attrs.color_closure = f; | ||
| 6996 | attrs.alloc_color = xpm_alloc_color; | ||
| 6997 | attrs.free_colors = xpm_free_colors; | ||
| 6998 | attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure; | ||
| 6999 | #else /* not ALLOC_XPM_COLORS */ | ||
| 7000 | /* Let the XPM lib allocate colors. */ | ||
| 6809 | attrs.valuemask |= XpmReturnAllocPixels; | 7001 | attrs.valuemask |= XpmReturnAllocPixels; |
| 6810 | #ifdef XpmAllocCloseColors | 7002 | #ifdef XpmAllocCloseColors |
| 6811 | attrs.alloc_close_colors = 1; | 7003 | attrs.alloc_close_colors = 1; |
| 6812 | attrs.valuemask |= XpmAllocCloseColors; | 7004 | attrs.valuemask |= XpmAllocCloseColors; |
| 6813 | #else | 7005 | #else /* not XpmAllocCloseColors */ |
| 6814 | attrs.closeness = 600; | 7006 | attrs.closeness = 600; |
| 6815 | attrs.valuemask |= XpmCloseness; | 7007 | attrs.valuemask |= XpmCloseness; |
| 6816 | #endif | 7008 | #endif /* not XpmAllocCloseColors */ |
| 7009 | #endif /* ALLOC_XPM_COLORS */ | ||
| 6817 | 7010 | ||
| 6818 | /* If image specification contains symbolic color definitions, add | 7011 | /* If image specification contains symbolic color definitions, add |
| 6819 | these to `attrs'. */ | 7012 | these to `attrs'. */ |
| @@ -6854,6 +7047,11 @@ xpm_load (f, img) | |||
| 6854 | /* Create a pixmap for the image, either from a file, or from a | 7047 | /* Create a pixmap for the image, either from a file, or from a |
| 6855 | string buffer containing data in the same format as an XPM file. */ | 7048 | string buffer containing data in the same format as an XPM file. */ |
| 6856 | BLOCK_INPUT; | 7049 | BLOCK_INPUT; |
| 7050 | |||
| 7051 | #ifdef ALLOC_XPM_COLORS | ||
| 7052 | xpm_init_color_cache (); | ||
| 7053 | #endif | ||
| 7054 | |||
| 6857 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 7055 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 6858 | if (STRINGP (specified_file)) | 7056 | if (STRINGP (specified_file)) |
| 6859 | { | 7057 | { |
| @@ -6881,7 +7079,9 @@ xpm_load (f, img) | |||
| 6881 | 7079 | ||
| 6882 | if (rc == XpmSuccess) | 7080 | if (rc == XpmSuccess) |
| 6883 | { | 7081 | { |
| 6884 | /* Remember allocated colors. */ | 7082 | #ifdef ALLOC_XPM_COLORS |
| 7083 | img->colors = colors_in_color_table (&img->ncolors); | ||
| 7084 | #else /* not ALLOC_XPM_COLORS */ | ||
| 6885 | img->ncolors = attrs.nalloc_pixels; | 7085 | img->ncolors = attrs.nalloc_pixels; |
| 6886 | img->colors = (unsigned long *) xmalloc (img->ncolors | 7086 | img->colors = (unsigned long *) xmalloc (img->ncolors |
| 6887 | * sizeof *img->colors); | 7087 | * sizeof *img->colors); |
| @@ -6892,6 +7092,7 @@ xpm_load (f, img) | |||
| 6892 | register_color (img->colors[i]); | 7092 | register_color (img->colors[i]); |
| 6893 | #endif | 7093 | #endif |
| 6894 | } | 7094 | } |
| 7095 | #endif /* not ALLOC_XPM_COLORS */ | ||
| 6895 | 7096 | ||
| 6896 | img->width = attrs.width; | 7097 | img->width = attrs.width; |
| 6897 | img->height = attrs.height; | 7098 | img->height = attrs.height; |
| @@ -6928,6 +7129,9 @@ xpm_load (f, img) | |||
| 6928 | } | 7129 | } |
| 6929 | } | 7130 | } |
| 6930 | 7131 | ||
| 7132 | #ifdef ALLOC_XPM_COLORS | ||
| 7133 | xpm_free_color_cache (); | ||
| 7134 | #endif | ||
| 6931 | return rc == XpmSuccess; | 7135 | return rc == XpmSuccess; |
| 6932 | } | 7136 | } |
| 6933 | 7137 | ||
| @@ -6965,15 +7169,6 @@ struct ct_color **ct_table; | |||
| 6965 | 7169 | ||
| 6966 | int ct_colors_allocated; | 7170 | int ct_colors_allocated; |
| 6967 | 7171 | ||
| 6968 | /* Function prototypes. */ | ||
| 6969 | |||
| 6970 | static void init_color_table P_ ((void)); | ||
| 6971 | static void free_color_table P_ ((void)); | ||
| 6972 | static unsigned long *colors_in_color_table P_ ((int *n)); | ||
| 6973 | static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b)); | ||
| 6974 | static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p)); | ||
| 6975 | |||
| 6976 | |||
| 6977 | /* Initialize the color table. */ | 7172 | /* Initialize the color table. */ |
| 6978 | 7173 | ||
| 6979 | static void | 7174 | static void |
| @@ -10855,6 +11050,7 @@ meaning don't clear the cache."); | |||
| 10855 | 11050 | ||
| 10856 | defsubr (&Sclear_image_cache); | 11051 | defsubr (&Sclear_image_cache); |
| 10857 | defsubr (&Simage_size); | 11052 | defsubr (&Simage_size); |
| 11053 | defsubr (&Simage_mask_p); | ||
| 10858 | 11054 | ||
| 10859 | busy_cursor_atimer = NULL; | 11055 | busy_cursor_atimer = NULL; |
| 10860 | busy_cursor_shown_p = 0; | 11056 | busy_cursor_shown_p = 0; |