comparison src/objects-x.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents 8626e4521993
children de805c49cfc1
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
26 26
27 /* Authors: Jamie Zawinski, Chuck Thompson, Ben Wing */ 27 /* Authors: Jamie Zawinski, Chuck Thompson, Ben Wing */
28 28
29 #include <config.h> 29 #include <config.h>
30 #include "lisp.h" 30 #include "lisp.h"
31 #include <limits.h>
31 32
32 #include "console-x.h" 33 #include "console-x.h"
33 #include "objects-x.h" 34 #include "objects-x.h"
34 35
35 #include "buffer.h" 36 #include "buffer.h"
43 /* color instances */ 44 /* color instances */
44 /************************************************************************/ 45 /************************************************************************/
45 46
46 /* Replacement for XAllocColor() that tries to return the nearest 47 /* Replacement for XAllocColor() that tries to return the nearest
47 available color if the colormap is full. Original was from FSFmacs, 48 available color if the colormap is full. Original was from FSFmacs,
48 but rewritten by Jareth Hein <jareth@camelot-soft.com> 97/11/25 */ 49 but rewritten by Jareth Hein <jareth@camelot-soft.com> 97/11/25
49 50 Modified by Lee Kindness <lkindness@csl.co.uk> 31/08/99 to handle previous
50 /* Return value is 1 for normal success, 2 for nearest color success, 51 total failure which was due to a read/write colorcell being the nearest
51 3 for Non-deallocable sucess, and 0 for absolute failure (shouldn't 52 match - tries the next nearest...
52 happen?) */ 53
54 Return value is 1 for normal success, 2 for nearest color success,
55 3 for Non-deallocable sucess. */
53 int 56 int
54 allocate_nearest_color (Display *display, Colormap colormap, Visual *visual, 57 allocate_nearest_color (Display *display, Colormap colormap, Visual *visual,
55 XColor *color_def) 58 XColor *color_def)
56 { 59 {
57 int status; 60 int status;
64 } 67 }
65 else 68 else
66 { 69 {
67 /* We're dealing with a TrueColor/DirectColor visual, so play games 70 /* We're dealing with a TrueColor/DirectColor visual, so play games
68 with the RGB values in the XColor struct. */ 71 with the RGB values in the XColor struct. */
69 /* ### JH: I'm not sure how a call to XAllocColor can fail in a 72 /* #### JH: I'm not sure how a call to XAllocColor can fail in a
70 TrueColor or DirectColor visual, so I will just reformat the 73 TrueColor or DirectColor visual, so I will just reformat the
71 request to match the requirements of the visual, and re-issue 74 request to match the requirements of the visual, and re-issue
72 the request. If this fails for anybody, I wanna know about it 75 the request. If this fails for anybody, I wanna know about it
73 so I can come up with a better plan */ 76 so I can come up with a better plan */
74 77
113 if (XAllocColor (display, colormap, color_def) != 0) 116 if (XAllocColor (display, colormap, color_def) != 0)
114 status = 1; 117 status = 1;
115 else 118 else
116 { 119 {
117 int rd, gr, bl; 120 int rd, gr, bl;
118 /* ### JH: I'm punting here, knowing that doing this will at 121 /* #### JH: I'm punting here, knowing that doing this will at
119 least draw the color correctly. However, unless we convert 122 least draw the color correctly. However, unless we convert
120 all of the functions that allocate colors (graphics 123 all of the functions that allocate colors (graphics
121 libraries, etc) to use this function doing this is very 124 libraries, etc) to use this function doing this is very
122 likely to cause problems later... */ 125 likely to cause problems later... */
123 126
138 } 141 }
139 } 142 }
140 } 143 }
141 else 144 else
142 { 145 {
146 XColor *cells = NULL;
147 /* JH: I can't believe there's no way to go backwards from a
148 colormap ID and get its visual and number of entries, but X
149 apparently isn't built that way... */
150 int no_cells = visual->map_entries;
151 status = 0;
152
143 if (XAllocColor (display, colormap, color_def) != 0) 153 if (XAllocColor (display, colormap, color_def) != 0)
144 status = 1; 154 status = 1;
145 else 155 else while( status != 2 )
146 { 156 {
147 /* If we got to this point, the colormap is full, so we're 157 /* If we got to this point, the colormap is full, so we're
148 going to try and get the next closest color. The algorithm used 158 going to try and get the next closest color. The algorithm used
149 is a least-squares matching, which is what X uses for closest 159 is a least-squares matching, which is what X uses for closest
150 color matching with StaticColor visuals. */ 160 color matching with StaticColor visuals. */
151 XColor *cells;
152 /* JH: I can't believe there's no way to go backwards from a
153 colormap ID and get its visual and number of entries, but X
154 apparently isn't built that way... */
155 int no_cells = visual->map_entries;
156 int nearest; 161 int nearest;
157 long nearest_delta, trial_delta; 162 long nearest_delta, trial_delta;
158 int x; 163 int x;
159 164
160 cells = alloca_array (XColor, no_cells); 165 if( cells == NULL )
161 166 {
162 for (x = 0; x < no_cells; x++) 167 cells = alloca_array (XColor, no_cells);
163 cells[x].pixel = x; 168 for (x = 0; x < no_cells; x++)
164 169 cells[x].pixel = x;
165 /* read the current colormap */ 170
166 XQueryColors (display, colormap, cells, no_cells); 171 /* read the current colormap */
172 XQueryColors (display, colormap, cells, no_cells);
173 }
174
167 nearest = 0; 175 nearest = 0;
168 /* I'm assuming CSE so I'm not going to condense this. */ 176 /* I'm assuming CSE so I'm not going to condense this. */
169 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8)) 177 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
170 * ((color_def->red >> 8) - (cells[0].red >> 8))) 178 * ((color_def->red >> 8) - (cells[0].red >> 8)))
171 + 179 +
182 (((color_def->green >> 8) - (cells[x].green >> 8)) 190 (((color_def->green >> 8) - (cells[x].green >> 8))
183 * ((color_def->green >> 8) - (cells[x].green >> 8))) 191 * ((color_def->green >> 8) - (cells[x].green >> 8)))
184 + 192 +
185 (((color_def->blue >> 8) - (cells[x].blue >> 8)) 193 (((color_def->blue >> 8) - (cells[x].blue >> 8))
186 * ((color_def->blue >> 8) - (cells[x].blue >> 8)))); 194 * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
187 if (trial_delta < nearest_delta) 195
196 /* less? Ignore cells marked as previously failing */
197 if( (trial_delta < nearest_delta) &&
198 (cells[x].pixel != ULONG_MAX) )
188 { 199 {
189 nearest = x; 200 nearest = x;
190 nearest_delta = trial_delta; 201 nearest_delta = trial_delta;
191 } 202 }
192 } 203 }
193 color_def->red = cells[nearest].red; 204 color_def->red = cells[nearest].red;
194 color_def->green = cells[nearest].green; 205 color_def->green = cells[nearest].green;
195 color_def->blue = cells[nearest].blue; 206 color_def->blue = cells[nearest].blue;
196 if (XAllocColor (display, colormap, color_def) != 0) { 207 if (XAllocColor (display, colormap, color_def) != 0)
197 status = 2; 208 status = 2;
198 } else { 209 else
199 status = 0; /* JH: how does this happen??? DOES this happen??? */ 210 /* LSK: Either the colour map has changed since
200 fprintf(stderr,"allocate_nearest_color returned 0!!!\n"); 211 * we read it, or the colour is allocated
201 } 212 * read/write... Mark this cmap entry so it's
213 * ignored in the next iteration.
214 */
215 cells[nearest].pixel = ULONG_MAX;
202 } 216 }
203 } 217 }
204 return status; 218 return status;
205 } 219 }
206 220
207 int 221 int
208 x_parse_nearest_color (struct device *d, XColor *color, Bufbyte *name, 222 x_parse_nearest_color (struct device *d, XColor *color, Bufbyte *name,
209 Bytecount len, Error_behavior errb) 223 Bytecount len, Error_behavior errb)
210 { 224 {
211 Display *dpy; 225 Display *dpy = DEVICE_X_DISPLAY (d);
212 Colormap cmap; 226 Colormap cmap = DEVICE_X_COLORMAP (d);
213 Visual *visual; 227 Visual *visual = DEVICE_X_VISUAL (d);
214 int result; 228 int result;
215
216 dpy = DEVICE_X_DISPLAY (d);
217 cmap = DEVICE_X_COLORMAP(d);
218 visual = DEVICE_X_VISUAL (d);
219 229
220 xzero (*color); 230 xzero (*color);
221 { 231 {
222 CONST Extbyte *extname; 232 const Extbyte *extname;
223 Extcount extnamelen; 233 Extcount extnamelen;
224 234
225 GET_CHARPTR_EXT_BINARY_DATA_ALLOCA (name, len, extname, extnamelen); 235 TO_EXTERNAL_FORMAT (DATA, (name, len),
236 ALLOCA, (extname, extnamelen),
237 Qbinary);
226 result = XParseColor (dpy, cmap, (char *) extname, color); 238 result = XParseColor (dpy, cmap, (char *) extname, color);
227 } 239 }
228 if (!result) 240 if (!result)
229 { 241 {
230 maybe_signal_simple_error ("Unrecognized color", make_string (name, len), 242 maybe_signal_simple_error ("Unrecognized color", make_string (name, len),
241 253
242 return result; 254 return result;
243 } 255 }
244 256
245 static int 257 static int
246 x_initialize_color_instance (struct Lisp_Color_Instance *c, Lisp_Object name, 258 x_initialize_color_instance (Lisp_Color_Instance *c, Lisp_Object name,
247 Lisp_Object device, Error_behavior errb) 259 Lisp_Object device, Error_behavior errb)
248 { 260 {
249 XColor color; 261 XColor color;
250 int result; 262 int result;
251 263
267 COLOR_INSTANCE_X_COLOR (c) = color; 279 COLOR_INSTANCE_X_COLOR (c) = color;
268 return 1; 280 return 1;
269 } 281 }
270 282
271 static void 283 static void
272 x_print_color_instance (struct Lisp_Color_Instance *c, 284 x_print_color_instance (Lisp_Color_Instance *c,
273 Lisp_Object printcharfun, 285 Lisp_Object printcharfun,
274 int escapeflag) 286 int escapeflag)
275 { 287 {
276 char buf[100]; 288 char buf[100];
277 XColor color = COLOR_INSTANCE_X_COLOR (c); 289 XColor color = COLOR_INSTANCE_X_COLOR (c);
279 color.pixel, color.red, color.green, color.blue); 291 color.pixel, color.red, color.green, color.blue);
280 write_c_string (buf, printcharfun); 292 write_c_string (buf, printcharfun);
281 } 293 }
282 294
283 static void 295 static void
284 x_finalize_color_instance (struct Lisp_Color_Instance *c) 296 x_finalize_color_instance (Lisp_Color_Instance *c)
285 { 297 {
286 if (c->data) 298 if (c->data)
287 { 299 {
288 if (DEVICE_LIVE_P (XDEVICE (c->device))) 300 if (DEVICE_LIVE_P (XDEVICE (c->device)))
289 { 301 {
302 screen (have the same RGB values). I imagine that 314 screen (have the same RGB values). I imagine that
303 "same RGB values" == "same cell in the colormap." Arguably we should 315 "same RGB values" == "same cell in the colormap." Arguably we should
304 be comparing their names or pixel values instead. */ 316 be comparing their names or pixel values instead. */
305 317
306 static int 318 static int
307 x_color_instance_equal (struct Lisp_Color_Instance *c1, 319 x_color_instance_equal (Lisp_Color_Instance *c1,
308 struct Lisp_Color_Instance *c2, 320 Lisp_Color_Instance *c2,
309 int depth) 321 int depth)
310 { 322 {
311 XColor color1 = COLOR_INSTANCE_X_COLOR (c1); 323 XColor color1 = COLOR_INSTANCE_X_COLOR (c1);
312 XColor color2 = COLOR_INSTANCE_X_COLOR (c2); 324 XColor color2 = COLOR_INSTANCE_X_COLOR (c2);
313 return ((color1.red == color2.red) && 325 return ((color1.red == color2.red) &&
314 (color1.green == color2.green) && 326 (color1.green == color2.green) &&
315 (color1.blue == color2.blue)); 327 (color1.blue == color2.blue));
316 } 328 }
317 329
318 static unsigned long 330 static unsigned long
319 x_color_instance_hash (struct Lisp_Color_Instance *c, int depth) 331 x_color_instance_hash (Lisp_Color_Instance *c, int depth)
320 { 332 {
321 XColor color = COLOR_INSTANCE_X_COLOR (c); 333 XColor color = COLOR_INSTANCE_X_COLOR (c);
322 return HASH3 (color.red, color.green, color.blue); 334 return HASH3 (color.red, color.green, color.blue);
323 } 335 }
324 336
325 static Lisp_Object 337 static Lisp_Object
326 x_color_instance_rgb_components (struct Lisp_Color_Instance *c) 338 x_color_instance_rgb_components (Lisp_Color_Instance *c)
327 { 339 {
328 XColor color = COLOR_INSTANCE_X_COLOR (c); 340 XColor color = COLOR_INSTANCE_X_COLOR (c);
329 return (list3 (make_int (color.red), 341 return (list3 (make_int (color.red),
330 make_int (color.green), 342 make_int (color.green),
331 make_int (color.blue))); 343 make_int (color.blue)));
336 { 348 {
337 XColor c; 349 XColor c;
338 Display *dpy = DEVICE_X_DISPLAY (d); 350 Display *dpy = DEVICE_X_DISPLAY (d);
339 Colormap cmap = DEVICE_X_COLORMAP (d); 351 Colormap cmap = DEVICE_X_COLORMAP (d);
340 352
341 CONST char *extname; 353 const char *extname;
342 354
343 GET_C_STRING_CTEXT_DATA_ALLOCA (color, extname); 355 TO_EXTERNAL_FORMAT (LISP_STRING, color, C_STRING_ALLOCA, extname, Qctext);
344 356
345 return XParseColor (dpy, cmap, 357 return XParseColor (dpy, cmap, extname, &c);
346 extname, &c);
347 } 358 }
348 359
349 360
350 /************************************************************************/ 361 /************************************************************************/
351 /* font instances */ 362 /* font instances */
352 /************************************************************************/ 363 /************************************************************************/
353 364
354 static int 365 static int
355 x_initialize_font_instance (struct Lisp_Font_Instance *f, Lisp_Object name, 366 x_initialize_font_instance (Lisp_Font_Instance *f, Lisp_Object name,
356 Lisp_Object device, Error_behavior errb) 367 Lisp_Object device, Error_behavior errb)
357 { 368 {
358 Display *dpy; 369 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (device));
359 XFontStruct *xf; 370 XFontStruct *xf;
360 CONST char *extname; 371 const char *extname;
361 372
362 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); 373 TO_EXTERNAL_FORMAT (LISP_STRING, f->name, C_STRING_ALLOCA, extname, Qctext);
363 GET_C_STRING_CTEXT_DATA_ALLOCA (f->name, extname);
364 xf = XLoadQueryFont (dpy, extname); 374 xf = XLoadQueryFont (dpy, extname);
365 375
366 if (!xf) 376 if (!xf)
367 { 377 {
368 maybe_signal_simple_error ("Couldn't load font", f->name, 378 maybe_signal_simple_error ("Couldn't load font", f->name,
445 455
446 return 1; 456 return 1;
447 } 457 }
448 458
449 static void 459 static void
450 x_mark_font_instance (struct Lisp_Font_Instance *f, 460 x_mark_font_instance (Lisp_Font_Instance *f)
451 void (*markobj) (Lisp_Object)) 461 {
452 { 462 mark_object (FONT_INSTANCE_X_TRUENAME (f));
453 markobj (FONT_INSTANCE_X_TRUENAME (f));
454 } 463 }
455 464
456 static void 465 static void
457 x_print_font_instance (struct Lisp_Font_Instance *f, 466 x_print_font_instance (Lisp_Font_Instance *f,
458 Lisp_Object printcharfun, 467 Lisp_Object printcharfun,
459 int escapeflag) 468 int escapeflag)
460 { 469 {
461 char buf[200]; 470 char buf[200];
462 sprintf (buf, " 0x%lx", (unsigned long) FONT_INSTANCE_X_FONT (f)->fid); 471 sprintf (buf, " 0x%lx", (unsigned long) FONT_INSTANCE_X_FONT (f)->fid);
463 write_c_string (buf, printcharfun); 472 write_c_string (buf, printcharfun);
464 } 473 }
465 474
466 static void 475 static void
467 x_finalize_font_instance (struct Lisp_Font_Instance *f) 476 x_finalize_font_instance (Lisp_Font_Instance *f)
468 { 477 {
469 478
470 if (f->data) 479 if (f->data)
471 { 480 {
472 if (DEVICE_LIVE_P (XDEVICE (f->device))) 481 if (DEVICE_LIVE_P (XDEVICE (f->device)))
762 else 771 else
763 return Qnil; 772 return Qnil;
764 } 773 }
765 774
766 static Lisp_Object 775 static Lisp_Object
767 x_font_instance_truename (struct Lisp_Font_Instance *f, Error_behavior errb) 776 x_font_instance_truename (Lisp_Font_Instance *f, Error_behavior errb)
768 { 777 {
769 struct device *d = XDEVICE (f->device); 778 struct device *d = XDEVICE (f->device);
770 779
771 if (NILP (FONT_INSTANCE_X_TRUENAME (f))) 780 if (NILP (FONT_INSTANCE_X_TRUENAME (f)))
772 { 781 {
790 } 799 }
791 return (FONT_INSTANCE_X_TRUENAME (f)); 800 return (FONT_INSTANCE_X_TRUENAME (f));
792 } 801 }
793 802
794 static Lisp_Object 803 static Lisp_Object
795 x_font_instance_properties (struct Lisp_Font_Instance *f) 804 x_font_instance_properties (Lisp_Font_Instance *f)
796 { 805 {
797 struct device *d = XDEVICE (f->device); 806 struct device *d = XDEVICE (f->device);
798 int i; 807 int i;
799 Lisp_Object result = Qnil; 808 Lisp_Object result = Qnil;
800 XFontProp *props; 809 XFontProp *props;
848 x_list_fonts (Lisp_Object pattern, Lisp_Object device) 857 x_list_fonts (Lisp_Object pattern, Lisp_Object device)
849 { 858 {
850 char **names; 859 char **names;
851 int count = 0; 860 int count = 0;
852 Lisp_Object result = Qnil; 861 Lisp_Object result = Qnil;
853 CONST char *patternext; 862 const char *patternext;
854 863
855 GET_C_STRING_BINARY_DATA_ALLOCA (pattern, patternext); 864 TO_EXTERNAL_FORMAT (LISP_STRING, pattern,
865 C_STRING_ALLOCA, patternext,
866 Qbinary);
856 867
857 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)), 868 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
858 patternext, MAX_FONT_COUNT, &count); 869 patternext, MAX_FONT_COUNT, &count);
859 while (count--) 870 while (count--)
860 result = Fcons (build_ext_string (names [count], FORMAT_BINARY), result); 871 result = Fcons (build_ext_string (names [count], Qbinary), result);
861 if (names) 872 if (names)
862 XFreeFontNames (names); 873 XFreeFontNames (names);
863 return result; 874 return result;
864 } 875 }
865 876
866 #ifdef MULE 877 #ifdef MULE
867 878
868 static int 879 static int
869 x_font_spec_matches_charset (struct device *d, Lisp_Object charset, 880 x_font_spec_matches_charset (struct device *d, Lisp_Object charset,
870 CONST Bufbyte *nonreloc, Lisp_Object reloc, 881 const Bufbyte *nonreloc, Lisp_Object reloc,
871 Bytecount offset, Bytecount length) 882 Bytecount offset, Bytecount length)
872 { 883 {
873 if (UNBOUNDP (charset)) 884 if (UNBOUNDP (charset))
874 return 1; 885 return 1;
875 /* Hack! Short font names don't have the registry in them, 886 /* Hack! Short font names don't have the registry in them,
877 case of ASCII. For other charsets, you gotta give the 888 case of ASCII. For other charsets, you gotta give the
878 long form; sorry buster. 889 long form; sorry buster.
879 */ 890 */
880 if (EQ (charset, Vcharset_ascii)) 891 if (EQ (charset, Vcharset_ascii))
881 { 892 {
882 CONST Bufbyte *the_nonreloc = nonreloc; 893 const Bufbyte *the_nonreloc = nonreloc;
883 int i; 894 int i;
884 Bytecount the_length = length; 895 Bytecount the_length = length;
885 896
886 if (!the_nonreloc) 897 if (!the_nonreloc)
887 the_nonreloc = XSTRING_DATA (reloc); 898 the_nonreloc = XSTRING_DATA (reloc);
889 the_nonreloc += offset; 900 the_nonreloc += offset;
890 if (!memchr (the_nonreloc, '*', the_length)) 901 if (!memchr (the_nonreloc, '*', the_length))
891 { 902 {
892 for (i = 0;; i++) 903 for (i = 0;; i++)
893 { 904 {
894 CONST Bufbyte *new_nonreloc = (CONST Bufbyte *) 905 const Bufbyte *new_nonreloc = (const Bufbyte *)
895 memchr (the_nonreloc, '-', the_length); 906 memchr (the_nonreloc, '-', the_length);
896 if (!new_nonreloc) 907 if (!new_nonreloc)
897 break; 908 break;
898 new_nonreloc++; 909 new_nonreloc++;
899 the_length -= new_nonreloc - the_nonreloc; 910 the_length -= new_nonreloc - the_nonreloc;
920 x_find_charset_font (Lisp_Object device, Lisp_Object font, Lisp_Object charset) 931 x_find_charset_font (Lisp_Object device, Lisp_Object font, Lisp_Object charset)
921 { 932 {
922 char **names; 933 char **names;
923 int count = 0; 934 int count = 0;
924 Lisp_Object result = Qnil; 935 Lisp_Object result = Qnil;
925 CONST char *patternext; 936 const char *patternext;
926 int i; 937 int i;
927 938
928 GET_C_STRING_BINARY_DATA_ALLOCA (font, patternext); 939 TO_EXTERNAL_FORMAT (LISP_STRING, font,
940 C_STRING_ALLOCA, patternext,
941 Qbinary);
929 942
930 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)), 943 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
931 patternext, MAX_FONT_COUNT, &count); 944 patternext, MAX_FONT_COUNT, &count);
932 /* ### This code seems awfully bogus -- mrb */ 945 /* #### This code seems awfully bogus -- mrb */
933 for (i = 0; i < count; i ++) 946 for (i = 0; i < count; i ++)
934 { 947 {
935 CONST Bufbyte *intname; 948 const char *intname;
936 949
937 GET_C_CHARPTR_INT_BINARY_DATA_ALLOCA (names[i], intname); 950 TO_INTERNAL_FORMAT (C_STRING, names[i],
951 C_STRING_ALLOCA, intname,
952 Qbinary);
938 if (x_font_spec_matches_charset (XDEVICE (device), charset, 953 if (x_font_spec_matches_charset (XDEVICE (device), charset,
939 intname, Qnil, 0, -1)) 954 (Bufbyte *) intname, Qnil, 0, -1))
940 { 955 {
941 result = build_string ((char *) intname); 956 result = build_string (intname);
942 break; 957 break;
943 } 958 }
944 } 959 }
945 960
946 if (names) 961 if (names)