Mercurial > hg > xemacs-beta
comparison src/glyphs-gtk.c @ 2082:16489ca72b3d
[xemacs-hg @ 2004-05-15 07:43:05 by malcolmp]
Improvements to the rendering of GTK glyph backgrounds.
author | malcolmp |
---|---|
date | Sat, 15 May 2004 07:43:09 +0000 |
parents | 91d4c8c65a0f |
children | 95fee4a1420e |
comparison
equal
deleted
inserted
replaced
2081:e8db6a10ad42 | 2082:16489ca72b3d |
---|---|
69 #include "ui-gtk.h" | 69 #include "ui-gtk.h" |
70 | 70 |
71 #include "sysfile.h" | 71 #include "sysfile.h" |
72 | 72 |
73 #include <setjmp.h> | 73 #include <setjmp.h> |
74 | |
75 #if defined (HAVE_XPM) | |
76 #include <X11/xpm.h> | |
77 #endif | |
74 | 78 |
75 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); | 79 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); |
76 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); | 80 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); |
77 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); | 81 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); |
78 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); | 82 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); |
1058 | 1062 |
1059 #ifdef HAVE_XPM | 1063 #ifdef HAVE_XPM |
1060 /********************************************************************** | 1064 /********************************************************************** |
1061 * XPM * | 1065 * XPM * |
1062 **********************************************************************/ | 1066 **********************************************************************/ |
1063 static Lisp_Object | |
1064 write_lisp_string_to_temp_file (Lisp_Object string) | |
1065 { | |
1066 Lisp_Object instream, outstream; | |
1067 Lstream *istr, *ostr; | |
1068 Char_Binary tempbuf[1024]; /* some random amount */ | |
1069 int fubar = 0; | |
1070 FILE *tmpfil; | |
1071 static Extbyte_dynarr *conversion_out_dynarr; | |
1072 Bytecount bstart, bend; | |
1073 Lisp_Object tempfile; | |
1074 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
1075 Lisp_Object conv_out_stream; | |
1076 Lstream *costr; | |
1077 | |
1078 /* This function can GC */ | |
1079 if (!conversion_out_dynarr) | |
1080 conversion_out_dynarr = Dynarr_new (Extbyte); | |
1081 else | |
1082 Dynarr_reset (conversion_out_dynarr); | |
1083 | |
1084 /* Create the temporary file ... */ | |
1085 tempfile = Fmake_temp_name (build_string ("/tmp/emacs")); | |
1086 tmpfil = qxe_fopen (XSTRING_DATA (tempfile), "w"); | |
1087 if (!tmpfil) | |
1088 { | |
1089 if (tmpfil) | |
1090 { | |
1091 int old_errno = errno; | |
1092 retry_fclose (tmpfil); | |
1093 qxe_unlink (XSTRING_DATA (tempfile)); | |
1094 errno = old_errno; | |
1095 } | |
1096 report_file_error ("Creating temp file", tempfile); | |
1097 } | |
1098 | |
1099 CHECK_STRING (string); | |
1100 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend, | |
1101 GB_HISTORICAL_STRING_BEHAVIOR); | |
1102 instream = make_lisp_string_input_stream (string, bstart, bend); | |
1103 istr = XLSTREAM (instream); | |
1104 /* setup the out stream */ | |
1105 outstream = | |
1106 make_dynarr_output_stream ((unsigned_char_dynarr *) conversion_out_dynarr); | |
1107 ostr = XLSTREAM (outstream); | |
1108 /* setup the conversion stream */ | |
1109 conv_out_stream = | |
1110 make_coding_output_stream (ostr, Qbinary, CODING_ENCODE, 0); | |
1111 costr = XLSTREAM (conv_out_stream); | |
1112 GCPRO4 (tempfile, instream, outstream, conv_out_stream); | |
1113 | |
1114 /* Get the data while doing the conversion */ | |
1115 while (1) | |
1116 { | |
1117 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf)); | |
1118 if (!size_in_bytes) | |
1119 break; | |
1120 /* It does seem the flushes are necessary... */ | |
1121 Lstream_write (costr, tempbuf, size_in_bytes); | |
1122 Lstream_flush (costr); | |
1123 Lstream_flush (ostr); | |
1124 if (retry_fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0), | |
1125 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1) | |
1126 { | |
1127 fubar = 1; | |
1128 break; | |
1129 } | |
1130 /* reset the dynarr */ | |
1131 Lstream_rewind(ostr); | |
1132 } | |
1133 | |
1134 if (retry_fclose (tmpfil) != 0) | |
1135 fubar = 1; | |
1136 Lstream_close (istr); | |
1137 Lstream_close (costr); | |
1138 Lstream_close (ostr); | |
1139 | |
1140 Lstream_delete (istr); | |
1141 Lstream_delete (ostr); | |
1142 Lstream_delete (costr); | |
1143 | |
1144 if (fubar) | |
1145 report_file_error ("Writing temp file", tempfile); | |
1146 | |
1147 UNGCPRO; | |
1148 return tempfile; | |
1149 } | |
1150 | 1067 |
1151 struct color_symbol | 1068 struct color_symbol |
1152 { | 1069 { |
1153 Ibyte* name; | 1070 Ibyte* name; |
1154 GdkColor color; | 1071 GdkColor color; |
1232 GdkPixmap *pixmap; | 1149 GdkPixmap *pixmap; |
1233 GdkPixmap *mask = 0; | 1150 GdkPixmap *mask = 0; |
1234 GdkWindow *window = 0; | 1151 GdkWindow *window = 0; |
1235 int nsymbols = 0, i = 0; | 1152 int nsymbols = 0, i = 0; |
1236 struct color_symbol *color_symbols = NULL; | 1153 struct color_symbol *color_symbols = NULL; |
1237 GdkColor *transparent_color = NULL; | |
1238 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator, | 1154 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator, |
1239 Q_color_symbols); | 1155 Q_color_symbols); |
1240 enum image_instance_type type; | 1156 enum image_instance_type type; |
1241 int force_mono; | 1157 int force_mono; |
1242 gint w, h; | 1158 gint w, h; |
1243 Lisp_Object tempfile = Qnil; | 1159 struct gcpro gcpro1, gcpro2, gcpro3; |
1244 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 1160 const UChar_Binary * volatile dstring; |
1245 | 1161 |
1246 if (!DEVICE_GTK_P (XDEVICE (device))) | 1162 if (!DEVICE_GTK_P (XDEVICE (device))) |
1247 gui_error ("Not a Gtk device", device); | 1163 gui_error ("Not a Gtk device", device); |
1248 | 1164 |
1249 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | 1165 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) |
1256 incompatible_image_types (instantiator, dest_mask, | 1172 incompatible_image_types (instantiator, dest_mask, |
1257 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | 1173 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK |
1258 | IMAGE_POINTER_MASK); | 1174 | IMAGE_POINTER_MASK); |
1259 force_mono = (type != IMAGE_COLOR_PIXMAP); | 1175 force_mono = (type != IMAGE_COLOR_PIXMAP); |
1260 | 1176 |
1261 GCPRO4 (device, data, color_symbol_alist, tempfile); | 1177 GCPRO3 (device, data, color_symbol_alist); |
1262 | 1178 |
1263 window = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); | 1179 window = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); |
1264 cmap = DEVICE_GTK_COLORMAP (XDEVICE (device)); | 1180 cmap = DEVICE_GTK_COLORMAP (XDEVICE (device)); |
1265 depth = DEVICE_GTK_DEPTH (XDEVICE (device)); | 1181 depth = DEVICE_GTK_DEPTH (XDEVICE (device)); |
1266 visual = DEVICE_GTK_VISUAL (XDEVICE (device)); | 1182 visual = DEVICE_GTK_VISUAL (XDEVICE (device)); |
1267 | 1183 |
1268 gtk_initialize_pixmap_image_instance (ii, 1, type); | 1184 gtk_initialize_pixmap_image_instance (ii, 1, type); |
1269 | 1185 |
1270 assert (!NILP (data)); | 1186 assert (!NILP (data)); |
1271 | 1187 |
1272 /* Need to get the transparent color here */ | 1188 /* Extract all the entries from xpm-color-symbols */ |
1273 color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, | 1189 color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, |
1274 &nsymbols); | 1190 &nsymbols); |
1275 for (i = 0; i < nsymbols; i++) | 1191 assert (!NILP (data)); |
1276 { | 1192 |
1277 if (!qxestrcasecmp_c (color_symbols[i].name, "BgColor") || | 1193 LISP_STRING_TO_EXTERNAL(data, dstring, Qbinary); |
1278 !qxestrcasecmp_c (color_symbols[i].name, "None")) | 1194 |
1279 { | 1195 /* |
1280 transparent_color = &color_symbols[i].color; | 1196 * GTK only uses the 'c' color entry of an XPM and doesn't use the symbolic |
1281 } | 1197 * color names at all. This is unfortunate because the way to change the |
1282 } | 1198 * colors from lisp is by adding the symbolic names, and the new colors, to |
1283 | 1199 * the variable xpm-color-symbols. |
1284 tempfile = write_lisp_string_to_temp_file (data); | 1200 * |
1201 * To get around this decode the XPM, add a 'c' entry of the desired color | |
1202 * for each matching symbolic color, recode the XPM and pass it to GTK. The | |
1203 * decode and recode stages aren't too bad because this also performs the | |
1204 * external to internal format translation, which avoids contortions like | |
1205 * writing the XPM back to disk in order to get it processed. | |
1206 */ | |
1285 { | 1207 { |
1286 Extbyte *tempfileout; | 1208 XpmImage image; |
1287 | 1209 XpmInfo info; |
1288 LISP_STRING_TO_EXTERNAL (tempfile, tempfileout, Qfile_name); | 1210 char** data; |
1289 pixmap = gdk_pixmap_create_from_xpm (window, &mask, transparent_color, | 1211 |
1290 tempfileout); | 1212 XpmCreateXpmImageFromBuffer ((char*) dstring, &image, &info); |
1213 | |
1214 for (i = 0; i < nsymbols; i++) | |
1215 { | |
1216 unsigned j; | |
1217 | |
1218 for (j = 0; j < image.ncolors; j++) | |
1219 { | |
1220 if (image.colorTable[j].symbolic != NULL && | |
1221 !qxestrcasecmp_c(color_symbols[i].name, image.colorTable[j].symbolic)) | |
1222 { | |
1223 image.colorTable[j].c_color = (char*) xmalloc(16); | |
1224 | |
1225 sprintf(image.colorTable[j].c_color, "#%.4x%.4x%.4x", | |
1226 color_symbols[i].color.red, color_symbols[i].color.green, | |
1227 color_symbols[i].color.blue); | |
1228 } | |
1229 } | |
1230 } | |
1231 | |
1232 XpmCreateDataFromXpmImage (&data, &image, &info); | |
1233 | |
1234 pixmap = gdk_pixmap_create_from_xpm_d (window, &mask, NULL, | |
1235 data); | |
1291 } | 1236 } |
1292 qxe_unlink (XSTRING_DATA (tempfile)); | |
1293 | 1237 |
1294 if (color_symbols) | 1238 if (color_symbols) |
1295 xfree (color_symbols, struct color_symbol *); | 1239 xfree (color_symbols, struct color_symbol *); |
1296 | 1240 |
1297 if (!pixmap) | 1241 if (!pixmap) |
1298 signal_image_error ("Error reading pixmap", data); | 1242 signal_image_error ("Error reading pixmap", data); |
1299 | 1243 |
1300 gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth); | 1244 gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth); |
1301 | 1245 |
1302 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap; | 1246 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap; |
1303 IMAGE_INSTANCE_GTK_MASK (ii) = mask; | 1247 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask; |
1304 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap; | 1248 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap; |
1305 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0; | 1249 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0; |
1306 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0; | 1250 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0; |
1307 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w; | 1251 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w; |
1308 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h; | 1252 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h; |