aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog10
-rw-r--r--src/image.c475
2 files changed, 482 insertions, 3 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 0fddb274d55..16cb680e455 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
12004-05-11 Steven Tamm <tamm@Steven-Tamms-Computer.local>
2
3 * image.c (xpm_scan, xpm_make_color_table_v, xpm_put_color_table_v)
4 (xpm_get_color_table_v, xpm_make_color_table_h)
5 (xpm_put_color_table_h, xpm_get_color_table_h)
6 (xpm_str_to_color_key, xpm_load_image, xpm_load)
7 (syms_of_image): Support XPM on Carbon Emacs. Does not
8 depend on libXpm, but only supports XPM version 3 without
9 extensions.
10
12004-05-11 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> 112004-05-11 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
2 12
3 * macterm.c (x_flush, XTframe_up_to_date): use FRAME_MAC_P 13 * macterm.c (x_flush, XTframe_up_to_date): use FRAME_MAC_P
diff --git a/src/image.c b/src/image.c
index c7bedb5de32..700ab3fa2d9 100644
--- a/src/image.c
+++ b/src/image.c
@@ -3184,12 +3184,15 @@ xbm_load (f, img)
3184 XPM images 3184 XPM images
3185 ***********************************************************************/ 3185 ***********************************************************************/
3186 3186
3187#ifdef HAVE_XPM 3187#if defined (HAVE_XPM) || defined (MAC_OS)
3188 3188
3189static int xpm_image_p P_ ((Lisp_Object object)); 3189static int xpm_image_p P_ ((Lisp_Object object));
3190static int xpm_load P_ ((struct frame *f, struct image *img)); 3190static int xpm_load P_ ((struct frame *f, struct image *img));
3191static int xpm_valid_color_symbols_p P_ ((Lisp_Object)); 3191static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3192 3192
3193#endif /* HAVE_XPM || MAC_OS */
3194
3195#ifdef HAVE_XPM
3193#ifdef HAVE_NTGUI 3196#ifdef HAVE_NTGUI
3194/* Indicate to xpm.h that we don't have Xlib. */ 3197/* Indicate to xpm.h that we don't have Xlib. */
3195#define FOR_MSW 3198#define FOR_MSW
@@ -3208,7 +3211,9 @@ static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3208#else 3211#else
3209#include "X11/xpm.h" 3212#include "X11/xpm.h"
3210#endif /* HAVE_NTGUI */ 3213#endif /* HAVE_NTGUI */
3214#endif /* HAVE_XPM */
3211 3215
3216#if defined (HAVE_XPM) || defined (MAC_OS)
3212/* The symbol `xpm' identifying XPM-format images. */ 3217/* The symbol `xpm' identifying XPM-format images. */
3213 3218
3214Lisp_Object Qxpm; 3219Lisp_Object Qxpm;
@@ -3536,10 +3541,13 @@ xpm_image_p (object)
3536 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); 3541 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3537} 3542}
3538 3543
3544#endif /* HAVE_XPM || MAC_OS */
3539 3545
3540/* Load image IMG which will be displayed on frame F. Value is 3546/* Load image IMG which will be displayed on frame F. Value is
3541 non-zero if successful. */ 3547 non-zero if successful. */
3542 3548
3549#ifdef HAVE_XPM
3550
3543static int 3551static int
3544xpm_load (f, img) 3552xpm_load (f, img)
3545 struct frame *f; 3553 struct frame *f;
@@ -3771,6 +3779,467 @@ xpm_load (f, img)
3771 3779
3772#endif /* HAVE_XPM */ 3780#endif /* HAVE_XPM */
3773 3781
3782#ifdef MAC_OS
3783
3784/* XPM support functions for Mac OS where libxpm is not available.
3785 Only XPM version 3 (without any extensions) is supported. */
3786
3787static int xpm_scan P_ ((unsigned char **, unsigned char *,
3788 unsigned char **, int *));
3789static Lisp_Object xpm_make_color_table_v
3790 P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
3791 Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
3792static void xpm_put_color_table_v P_ ((Lisp_Object, unsigned char *,
3793 int, Lisp_Object));
3794static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
3795 unsigned char *, int));
3796static Lisp_Object xpm_make_color_table_h
3797 P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
3798 Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
3799static void xpm_put_color_table_h P_ ((Lisp_Object, unsigned char *,
3800 int, Lisp_Object));
3801static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
3802 unsigned char *, int));
3803static int xpm_str_to_color_key P_ ((char *));
3804static int xpm_load_image P_ ((struct frame *, struct image *,
3805 unsigned char *, unsigned char *));
3806
3807/* Tokens returned from xpm_scan. */
3808
3809enum xpm_token
3810{
3811 XPM_TK_IDENT = 256,
3812 XPM_TK_STRING,
3813 XPM_TK_EOF
3814};
3815
3816/* Scan an XPM data and return a character (< 256) or a token defined
3817 by enum xpm_token above. *S and END are the start (inclusive) and
3818 the end (exclusive) addresses of the data, respectively. Advance
3819 *S while scanning. If token is either XPM_TK_IDENT or
3820 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3821 length of the corresponding token, respectively. */
3822
3823static int
3824xpm_scan (s, end, beg, len)
3825 unsigned char **s, *end, **beg;
3826 int *len;
3827{
3828 int c;
3829
3830 while (*s < end)
3831 {
3832 /* Skip white-space. */
3833 while (*s < end && (c = *(*s)++, isspace (c)))
3834 ;
3835
3836 /* gnus-pointer.xpm uses '-' in its identifier.
3837 sb-dir-plus.xpm uses '+' in its identifier. */
3838 if (isalpha (c) || c == '_' || c == '-' || c == '+')
3839 {
3840 *beg = *s - 1;
3841 while (*s < end &&
3842 (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
3843 ++*s;
3844 *len = *s - *beg;
3845 return XPM_TK_IDENT;
3846 }
3847 else if (c == '"')
3848 {
3849 *beg = *s;
3850 while (*s < end && **s != '"')
3851 ++*s;
3852 *len = *s - *beg;
3853 if (*s < end)
3854 ++*s;
3855 return XPM_TK_STRING;
3856 }
3857 else if (c == '/')
3858 {
3859 if (*s < end && **s == '*')
3860 {
3861 /* C-style comment. */
3862 ++*s;
3863 do
3864 {
3865 while (*s < end && *(*s)++ != '*')
3866 ;
3867 }
3868 while (*s < end && **s != '/');
3869 if (*s < end)
3870 ++*s;
3871 }
3872 else
3873 return c;
3874 }
3875 else
3876 return c;
3877 }
3878
3879 return XPM_TK_EOF;
3880}
3881
3882/* Functions for color table lookup in XPM data. A Key is a string
3883 specifying the color of each pixel in XPM data. A value is either
3884 an integer that specifies a pixel color, Qt that specifies
3885 transparency, or Qnil for the unspecified color. If the length of
3886 the key string is one, a vector is used as a table. Otherwise, a
3887 hash table is used. */
3888
3889static Lisp_Object
3890xpm_make_color_table_v (put_func, get_func)
3891 void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
3892 Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
3893{
3894 *put_func = xpm_put_color_table_v;
3895 *get_func = xpm_get_color_table_v;
3896 return Fmake_vector (make_number (256), Qnil);
3897}
3898
3899static void
3900xpm_put_color_table_v (color_table, chars_start, chars_len, color)
3901 Lisp_Object color_table;
3902 unsigned char *chars_start;
3903 int chars_len;
3904 Lisp_Object color;
3905{
3906 XVECTOR (color_table)->contents[*chars_start] = color;
3907}
3908
3909static Lisp_Object
3910xpm_get_color_table_v (color_table, chars_start, chars_len)
3911 Lisp_Object color_table;
3912 unsigned char *chars_start;
3913 int chars_len;
3914{
3915 return XVECTOR (color_table)->contents[*chars_start];
3916}
3917
3918static Lisp_Object
3919xpm_make_color_table_h (put_func, get_func)
3920 void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
3921 Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
3922{
3923 *put_func = xpm_put_color_table_h;
3924 *get_func = xpm_get_color_table_h;
3925 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
3926 make_float (DEFAULT_REHASH_SIZE),
3927 make_float (DEFAULT_REHASH_THRESHOLD),
3928 Qnil, Qnil, Qnil);
3929}
3930
3931static void
3932xpm_put_color_table_h (color_table, chars_start, chars_len, color)
3933 Lisp_Object color_table;
3934 unsigned char *chars_start;
3935 int chars_len;
3936 Lisp_Object color;
3937{
3938 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
3939 unsigned hash_code;
3940 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
3941
3942 hash_lookup (table, chars, &hash_code);
3943 hash_put (table, chars, color, hash_code);
3944}
3945
3946static Lisp_Object
3947xpm_get_color_table_h (color_table, chars_start, chars_len)
3948 Lisp_Object color_table;
3949 unsigned char *chars_start;
3950 int chars_len;
3951{
3952 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
3953 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
3954 NULL);
3955
3956 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
3957}
3958
3959enum xpm_color_key {
3960 XPM_COLOR_KEY_S,
3961 XPM_COLOR_KEY_M,
3962 XPM_COLOR_KEY_G4,
3963 XPM_COLOR_KEY_G,
3964 XPM_COLOR_KEY_C
3965};
3966
3967static char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
3968
3969static int
3970xpm_str_to_color_key (s)
3971 char *s;
3972{
3973 int i;
3974
3975 for (i = 0;
3976 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
3977 i++)
3978 if (strcmp (xpm_color_key_strings[i], s) == 0)
3979 return i;
3980 return -1;
3981}
3982
3983static int
3984xpm_load_image (f, img, contents, end)
3985 struct frame *f;
3986 struct image *img;
3987 unsigned char *contents, *end;
3988{
3989 unsigned char *s = contents, *beg, *str;
3990 unsigned char buffer[BUFSIZ];
3991 int width, height, x, y;
3992 int num_colors, chars_per_pixel;
3993 int len, LA1;
3994 void (*put_color_table) (Lisp_Object, unsigned char *, int, Lisp_Object);
3995 Lisp_Object (*get_color_table) (Lisp_Object, unsigned char *, int);
3996 Lisp_Object frame, color_symbols, color_table;
3997 int best_key, have_mask = 0;
3998 XImagePtr ximg = NULL, mask_img = NULL;
3999
4000#define match() \
4001 LA1 = xpm_scan (&s, end, &beg, &len)
4002
4003#define expect(TOKEN) \
4004 if (LA1 != (TOKEN)) \
4005 goto failure; \
4006 else \
4007 match ()
4008
4009#define expect_ident(IDENT) \
4010 if (LA1 == XPM_TK_IDENT \
4011 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4012 match (); \
4013 else \
4014 goto failure
4015
4016 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4017 goto failure;
4018 s += 9;
4019 match();
4020 expect_ident ("static");
4021 expect_ident ("char");
4022 expect ('*');
4023 expect (XPM_TK_IDENT);
4024 expect ('[');
4025 expect (']');
4026 expect ('=');
4027 expect ('{');
4028 expect (XPM_TK_STRING);
4029 if (len >= BUFSIZ)
4030 goto failure;
4031 memcpy (buffer, beg, len);
4032 buffer[len] = '\0';
4033 if (sscanf (buffer, "%d %d %d %d", &width, &height,
4034 &num_colors, &chars_per_pixel) != 4
4035 || width <= 0 || height <= 0
4036 || num_colors <= 0 || chars_per_pixel <= 0)
4037 goto failure;
4038 expect (',');
4039
4040 XSETFRAME (frame, f);
4041 if (!NILP (Fxw_display_color_p (frame)))
4042 best_key = XPM_COLOR_KEY_C;
4043 else if (!NILP (Fx_display_grayscale_p (frame)))
4044 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4045 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4046 else
4047 best_key = XPM_COLOR_KEY_M;
4048
4049 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4050 if (chars_per_pixel == 1)
4051 color_table = xpm_make_color_table_v (&put_color_table,
4052 &get_color_table);
4053 else
4054 color_table = xpm_make_color_table_h (&put_color_table,
4055 &get_color_table);
4056
4057 while (num_colors-- > 0)
4058 {
4059 unsigned char *color, *max_color;
4060 int key, next_key, max_key = 0;
4061 Lisp_Object symbol_color = Qnil, color_val;
4062 XColor cdef;
4063
4064 expect (XPM_TK_STRING);
4065 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4066 goto failure;
4067 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4068 buffer[len - chars_per_pixel] = '\0';
4069
4070 str = strtok (buffer, " \t");
4071 if (str == NULL)
4072 goto failure;
4073 key = xpm_str_to_color_key (str);
4074 if (key < 0)
4075 goto failure;
4076 do
4077 {
4078 color = strtok (NULL, " \t");
4079 if (color == NULL)
4080 goto failure;
4081
4082 while (str = strtok (NULL, " \t"))
4083 {
4084 next_key = xpm_str_to_color_key (str);
4085 if (next_key >= 0)
4086 break;
4087 color[strlen (color)] = ' ';
4088 }
4089
4090 if (key == XPM_COLOR_KEY_S)
4091 {
4092 if (NILP (symbol_color))
4093 symbol_color = build_string (color);
4094 }
4095 else if (max_key < key && key <= best_key)
4096 {
4097 max_key = key;
4098 max_color = color;
4099 }
4100 key = next_key;
4101 }
4102 while (str);
4103
4104 color_val = Qnil;
4105 if (!NILP (color_symbols) && !NILP (symbol_color))
4106 {
4107 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4108
4109 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4110 if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
4111 color_val = Qt;
4112 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4113 &cdef, 0))
4114 color_val = make_number (cdef.pixel);
4115 }
4116 if (NILP (color_val) && max_key > 0)
4117 if (xstricmp (max_color, "None") == 0)
4118 color_val = Qt;
4119 else if (x_defined_color (f, max_color, &cdef, 0))
4120 color_val = make_number (cdef.pixel);
4121 if (!NILP (color_val))
4122 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4123
4124 expect (',');
4125 }
4126
4127 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4128 &ximg, &img->pixmap)
4129 || !x_create_x_image_and_pixmap (f, width, height, 1,
4130 &mask_img, &img->mask))
4131 {
4132 image_error ("Out of memory (%s)", img->spec, Qnil);
4133 goto error;
4134 }
4135
4136 for (y = 0; y < height; y++)
4137 {
4138 expect (XPM_TK_STRING);
4139 str = beg;
4140 if (len < width * chars_per_pixel)
4141 goto failure;
4142 for (x = 0; x < width; x++, str += chars_per_pixel)
4143 {
4144 Lisp_Object color_val =
4145 (*get_color_table) (color_table, str, chars_per_pixel);
4146
4147 XPutPixel (ximg, x, y,
4148 (INTEGERP (color_val) ? XINT (color_val)
4149 : FRAME_FOREGROUND_PIXEL (f)));
4150 XPutPixel (mask_img, x, y,
4151 (!EQ (color_val, Qt) ? PIX_MASK_DRAW (f)
4152 : (have_mask = 1, PIX_MASK_RETAIN (f))));
4153 }
4154 if (y + 1 < height)
4155 expect (',');
4156 }
4157
4158 img->width = width;
4159 img->height = height;
4160
4161 x_put_x_image (f, ximg, img->pixmap, width, height);
4162 x_destroy_x_image (ximg);
4163 if (have_mask)
4164 {
4165 x_put_x_image (f, mask_img, img->mask, width, height);
4166 x_destroy_x_image (mask_img);
4167 }
4168 else
4169 {
4170 x_destroy_x_image (mask_img);
4171 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4172 img->mask = NO_PIXMAP;
4173 }
4174
4175 return 1;
4176
4177 failure:
4178 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4179 error:
4180 x_destroy_x_image (ximg);
4181 x_destroy_x_image (mask_img);
4182 x_clear_image (f, img);
4183 return 0;
4184
4185#undef match
4186#undef expect
4187#undef expect_ident
4188}
4189
4190static int
4191xpm_load (f, img)
4192 struct frame *f;
4193 struct image *img;
4194{
4195 int success_p = 0;
4196 Lisp_Object file_name;
4197
4198 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4199 file_name = image_spec_value (img->spec, QCfile, NULL);
4200 if (STRINGP (file_name))
4201 {
4202 Lisp_Object file;
4203 unsigned char *contents;
4204 int size;
4205 struct gcpro gcpro1;
4206
4207 file = x_find_image_file (file_name);
4208 GCPRO1 (file);
4209 if (!STRINGP (file))
4210 {
4211 image_error ("Cannot find image file `%s'", file_name, Qnil);
4212 UNGCPRO;
4213 return 0;
4214 }
4215
4216 contents = slurp_file (SDATA (file), &size);
4217 if (contents == NULL)
4218 {
4219 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4220 UNGCPRO;
4221 return 0;
4222 }
4223
4224 success_p = xpm_load_image (f, img, contents, contents + size);
4225 xfree (contents);
4226 UNGCPRO;
4227 }
4228 else
4229 {
4230 Lisp_Object data;
4231
4232 data = image_spec_value (img->spec, QCdata, NULL);
4233 success_p = xpm_load_image (f, img, SDATA (data),
4234 SDATA (data) + SBYTES (data));
4235 }
4236
4237 return success_p;
4238}
4239
4240#endif /* MAC_OS */
4241
4242
3774 4243
3775/*********************************************************************** 4244/***********************************************************************
3776 Color table 4245 Color table
@@ -7447,7 +7916,7 @@ syms_of_image ()
7447 Qxbm = intern ("xbm"); 7916 Qxbm = intern ("xbm");
7448 staticpro (&Qxbm); 7917 staticpro (&Qxbm);
7449 7918
7450#ifdef HAVE_XPM 7919#if defined (HAVE_XPM) || defined (MAC_OS)
7451 Qxpm = intern ("xpm"); 7920 Qxpm = intern ("xpm");
7452 staticpro (&Qxpm); 7921 staticpro (&Qxpm);
7453#endif 7922#endif
@@ -7517,7 +7986,7 @@ init_image ()
7517 define_image_type (&xbm_type); 7986 define_image_type (&xbm_type);
7518 define_image_type (&pbm_type); 7987 define_image_type (&pbm_type);
7519 7988
7520#ifdef HAVE_XPM 7989#if defined (HAVE_XPM) || defined (MAC_OS)
7521 IF_LIB_AVAILABLE(init_xpm_functions) 7990 IF_LIB_AVAILABLE(init_xpm_functions)
7522 define_image_type (&xpm_type); 7991 define_image_type (&xpm_type);
7523#endif 7992#endif