428
+ − 1 /* X-specific Lisp objects.
+ − 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+ − 3 Copyright (C) 1995 Board of Trustees, University of Illinois.
+ − 4 Copyright (C) 1995 Tinker Systems.
800
+ − 5 Copyright (C) 1995, 1996, 2000, 2001, 2002 Ben Wing.
428
+ − 6 Copyright (C) 1995 Sun Microsystems, Inc.
+ − 7
+ − 8 This file is part of XEmacs.
+ − 9
+ − 10 XEmacs is free software; you can redistribute it and/or modify it
+ − 11 under the terms of the GNU General Public License as published by the
+ − 12 Free Software Foundation; either version 2, or (at your option) any
+ − 13 later version.
+ − 14
+ − 15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ − 16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ − 17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ − 18 for more details.
+ − 19
+ − 20 You should have received a copy of the GNU General Public License
+ − 21 along with XEmacs; see the file COPYING. If not, write to
+ − 22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 23 Boston, MA 02111-1307, USA. */
+ − 24
+ − 25 /* Synched up with: Not in FSF. */
+ − 26
+ − 27 /* Authors: Jamie Zawinski, Chuck Thompson, Ben Wing */
+ − 28
442
+ − 29 /* This file Mule-ized by Ben Wing, 7-10-00. */
+ − 30
428
+ − 31 #include <config.h>
+ − 32 #include "lisp.h"
+ − 33
872
+ − 34 #include "charset.h"
+ − 35 #include "device-impl.h"
+ − 36 #include "insdel.h"
428
+ − 37
872
+ − 38 #include "console-x-impl.h"
+ − 39 #include "objects-x-impl.h"
428
+ − 40
+ − 41 int x_handle_non_fully_specified_fonts;
+ − 42
+ − 43
+ − 44 /************************************************************************/
+ − 45 /* color instances */
+ − 46 /************************************************************************/
+ − 47
+ − 48 /* Replacement for XAllocColor() that tries to return the nearest
+ − 49 available color if the colormap is full. Original was from FSFmacs,
+ − 50 but rewritten by Jareth Hein <jareth@camelot-soft.com> 97/11/25
+ − 51 Modified by Lee Kindness <lkindness@csl.co.uk> 31/08/99 to handle previous
+ − 52 total failure which was due to a read/write colorcell being the nearest
+ − 53 match - tries the next nearest...
+ − 54
+ − 55 Return value is 1 for normal success, 2 for nearest color success,
442
+ − 56 3 for Non-deallocable success. */
428
+ − 57 int
+ − 58 allocate_nearest_color (Display *display, Colormap colormap, Visual *visual,
+ − 59 XColor *color_def)
+ − 60 {
+ − 61 int status;
+ − 62
+ − 63 if (visual->class == DirectColor || visual->class == TrueColor)
+ − 64 {
+ − 65 if (XAllocColor (display, colormap, color_def) != 0)
+ − 66 {
+ − 67 status = 1;
+ − 68 }
+ − 69 else
+ − 70 {
+ − 71 /* We're dealing with a TrueColor/DirectColor visual, so play games
+ − 72 with the RGB values in the XColor struct. */
440
+ − 73 /* #### JH: I'm not sure how a call to XAllocColor can fail in a
428
+ − 74 TrueColor or DirectColor visual, so I will just reformat the
+ − 75 request to match the requirements of the visual, and re-issue
+ − 76 the request. If this fails for anybody, I wanna know about it
+ − 77 so I can come up with a better plan */
+ − 78
+ − 79 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
+ − 80 junk = visual->red_mask;
+ − 81 rshift = 0;
+ − 82 while ((junk & 0x1) == 0) {
+ − 83 junk = junk >> 1;
+ − 84 rshift ++;
+ − 85 }
+ − 86 rbits = 0;
+ − 87 while (junk != 0) {
+ − 88 junk = junk >> 1;
+ − 89 rbits++;
+ − 90 }
+ − 91 junk = visual->green_mask;
+ − 92 gshift = 0;
+ − 93 while ((junk & 0x1) == 0) {
+ − 94 junk = junk >> 1;
+ − 95 gshift ++;
+ − 96 }
+ − 97 gbits = 0;
+ − 98 while (junk != 0) {
+ − 99 junk = junk >> 1;
+ − 100 gbits++;
+ − 101 }
+ − 102 junk = visual->blue_mask;
+ − 103 bshift = 0;
+ − 104 while ((junk & 0x1) == 0) {
+ − 105 junk = junk >> 1;
+ − 106 bshift ++;
+ − 107 }
+ − 108 bbits = 0;
+ − 109 while (junk != 0) {
+ − 110 junk = junk >> 1;
+ − 111 bbits++;
+ − 112 }
+ − 113
+ − 114 color_def->red = color_def->red >> (16 - rbits);
+ − 115 color_def->green = color_def->green >> (16 - gbits);
+ − 116 color_def->blue = color_def->blue >> (16 - bbits);
+ − 117 if (XAllocColor (display, colormap, color_def) != 0)
+ − 118 status = 1;
+ − 119 else
+ − 120 {
+ − 121 int rd, gr, bl;
440
+ − 122 /* #### JH: I'm punting here, knowing that doing this will at
428
+ − 123 least draw the color correctly. However, unless we convert
+ − 124 all of the functions that allocate colors (graphics
+ − 125 libraries, etc) to use this function doing this is very
+ − 126 likely to cause problems later... */
+ − 127
+ − 128 if (rbits > 8)
+ − 129 rd = color_def->red << (rbits - 8);
+ − 130 else
+ − 131 rd = color_def->red >> (8 - rbits);
+ − 132 if (gbits > 8)
+ − 133 gr = color_def->green << (gbits - 8);
+ − 134 else
+ − 135 gr = color_def->green >> (8 - gbits);
+ − 136 if (bbits > 8)
+ − 137 bl = color_def->blue << (bbits - 8);
+ − 138 else
+ − 139 bl = color_def->blue >> (8 - bbits);
442
+ − 140 color_def->pixel = (rd << rshift) | (gr << gshift) | (bl <<
+ − 141 bshift);
428
+ − 142 status = 3;
+ − 143 }
+ − 144 }
+ − 145 }
+ − 146 else
+ − 147 {
+ − 148 XColor *cells = NULL;
+ − 149 /* JH: I can't believe there's no way to go backwards from a
+ − 150 colormap ID and get its visual and number of entries, but X
+ − 151 apparently isn't built that way... */
+ − 152 int no_cells = visual->map_entries;
+ − 153 status = 0;
+ − 154
+ − 155 if (XAllocColor (display, colormap, color_def) != 0)
+ − 156 status = 1;
+ − 157 else while( status != 2 )
+ − 158 {
+ − 159 /* If we got to this point, the colormap is full, so we're
+ − 160 going to try and get the next closest color. The algorithm used
+ − 161 is a least-squares matching, which is what X uses for closest
+ − 162 color matching with StaticColor visuals. */
+ − 163 int nearest;
+ − 164 long nearest_delta, trial_delta;
+ − 165 int x;
+ − 166
+ − 167 if( cells == NULL )
442
+ − 168 {
+ − 169 cells = alloca_array (XColor, no_cells);
+ − 170 for (x = 0; x < no_cells; x++)
+ − 171 cells[x].pixel = x;
428
+ − 172
442
+ − 173 /* read the current colormap */
+ − 174 XQueryColors (display, colormap, cells, no_cells);
+ − 175 }
428
+ − 176
+ − 177 nearest = 0;
+ − 178 /* I'm assuming CSE so I'm not going to condense this. */
+ − 179 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
+ − 180 * ((color_def->red >> 8) - (cells[0].red >> 8)))
+ − 181 +
+ − 182 (((color_def->green >> 8) - (cells[0].green >> 8))
442
+ − 183 * ((color_def->green >> 8) - (cells[0].green >>
+ − 184 8)))
428
+ − 185 +
+ − 186 (((color_def->blue >> 8) - (cells[0].blue >> 8))
442
+ − 187 * ((color_def->blue >> 8) - (cells[0].blue >>
+ − 188 8))));
428
+ − 189 for (x = 1; x < no_cells; x++)
+ − 190 {
+ − 191 trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
+ − 192 * ((color_def->red >> 8) - (cells[x].red >> 8)))
+ − 193 +
+ − 194 (((color_def->green >> 8) - (cells[x].green >> 8))
442
+ − 195 * ((color_def->green >> 8) - (cells[x].green >>
+ − 196 8)))
428
+ − 197 +
+ − 198 (((color_def->blue >> 8) - (cells[x].blue >> 8))
442
+ − 199 * ((color_def->blue >> 8) - (cells[x].blue >>
+ − 200 8))));
428
+ − 201
+ − 202 /* less? Ignore cells marked as previously failing */
+ − 203 if( (trial_delta < nearest_delta) &&
+ − 204 (cells[x].pixel != ULONG_MAX) )
+ − 205 {
+ − 206 nearest = x;
+ − 207 nearest_delta = trial_delta;
+ − 208 }
+ − 209 }
+ − 210 color_def->red = cells[nearest].red;
+ − 211 color_def->green = cells[nearest].green;
+ − 212 color_def->blue = cells[nearest].blue;
+ − 213 if (XAllocColor (display, colormap, color_def) != 0)
442
+ − 214 status = 2;
428
+ − 215 else
442
+ − 216 /* LSK: Either the colour map has changed since
+ − 217 * we read it, or the colour is allocated
+ − 218 * read/write... Mark this cmap entry so it's
+ − 219 * ignored in the next iteration.
+ − 220 */
+ − 221 cells[nearest].pixel = ULONG_MAX;
428
+ − 222 }
+ − 223 }
+ − 224 return status;
+ − 225 }
+ − 226
442
+ − 227 static int
+ − 228 x_parse_nearest_color (struct device *d, XColor *color, Lisp_Object name,
578
+ − 229 Error_Behavior errb)
428
+ − 230 {
+ − 231 Display *dpy = DEVICE_X_DISPLAY (d);
+ − 232 Colormap cmap = DEVICE_X_COLORMAP (d);
+ − 233 Visual *visual = DEVICE_X_VISUAL (d);
+ − 234 int result;
+ − 235
+ − 236 xzero (*color);
+ − 237 {
442
+ − 238 const Extbyte *extname;
428
+ − 239
442
+ − 240 LISP_STRING_TO_EXTERNAL (name, extname, Qx_color_name_encoding);
+ − 241 result = XParseColor (dpy, cmap, extname, color);
428
+ − 242 }
+ − 243 if (!result)
+ − 244 {
563
+ − 245 maybe_signal_error (Qgui_error, "Unrecognized color",
+ − 246 name, Qcolor, errb);
428
+ − 247 return 0;
+ − 248 }
+ − 249 result = allocate_nearest_color (dpy, cmap, visual, color);
+ − 250 if (!result)
+ − 251 {
563
+ − 252 maybe_signal_error (Qgui_error, "Couldn't allocate color",
+ − 253 name, Qcolor, errb);
428
+ − 254 return 0;
+ − 255 }
+ − 256
+ − 257 return result;
+ − 258 }
+ − 259
+ − 260 static int
440
+ − 261 x_initialize_color_instance (Lisp_Color_Instance *c, Lisp_Object name,
578
+ − 262 Lisp_Object device, Error_Behavior errb)
428
+ − 263 {
+ − 264 XColor color;
+ − 265 int result;
+ − 266
442
+ − 267 result = x_parse_nearest_color (XDEVICE (device), &color, name, errb);
428
+ − 268
+ − 269 if (!result)
+ − 270 return 0;
+ − 271
+ − 272 /* Don't allocate the data until we're sure that we will succeed,
+ − 273 or the finalize method may get fucked. */
+ − 274 c->data = xnew (struct x_color_instance_data);
+ − 275 if (result == 3)
+ − 276 COLOR_INSTANCE_X_DEALLOC (c) = 0;
+ − 277 else
+ − 278 COLOR_INSTANCE_X_DEALLOC (c) = 1;
+ − 279 COLOR_INSTANCE_X_COLOR (c) = color;
+ − 280 return 1;
+ − 281 }
+ − 282
+ − 283 static void
440
+ − 284 x_print_color_instance (Lisp_Color_Instance *c,
428
+ − 285 Lisp_Object printcharfun,
+ − 286 int escapeflag)
+ − 287 {
+ − 288 XColor color = COLOR_INSTANCE_X_COLOR (c);
800
+ − 289 write_fmt_string (printcharfun, " %ld=(%X,%X,%X)",
+ − 290 color.pixel, color.red, color.green, color.blue);
428
+ − 291 }
+ − 292
+ − 293 static void
440
+ − 294 x_finalize_color_instance (Lisp_Color_Instance *c)
428
+ − 295 {
+ − 296 if (c->data)
+ − 297 {
+ − 298 if (DEVICE_LIVE_P (XDEVICE (c->device)))
+ − 299 {
+ − 300 if (COLOR_INSTANCE_X_DEALLOC (c))
+ − 301 {
442
+ − 302 XFreeColors (DEVICE_X_DISPLAY (XDEVICE (c->device)),
+ − 303 DEVICE_X_COLORMAP (XDEVICE (c->device)),
428
+ − 304 &COLOR_INSTANCE_X_COLOR (c).pixel, 1, 0);
+ − 305 }
+ − 306 }
+ − 307 xfree (c->data);
+ − 308 c->data = 0;
+ − 309 }
+ − 310 }
+ − 311
+ − 312 /* Color instances are equal if they resolve to the same color on the
+ − 313 screen (have the same RGB values). I imagine that
+ − 314 "same RGB values" == "same cell in the colormap." Arguably we should
+ − 315 be comparing their names or pixel values instead. */
+ − 316
+ − 317 static int
440
+ − 318 x_color_instance_equal (Lisp_Color_Instance *c1,
+ − 319 Lisp_Color_Instance *c2,
428
+ − 320 int depth)
+ − 321 {
+ − 322 XColor color1 = COLOR_INSTANCE_X_COLOR (c1);
+ − 323 XColor color2 = COLOR_INSTANCE_X_COLOR (c2);
+ − 324 return ((color1.red == color2.red) &&
+ − 325 (color1.green == color2.green) &&
+ − 326 (color1.blue == color2.blue));
+ − 327 }
+ − 328
+ − 329 static unsigned long
440
+ − 330 x_color_instance_hash (Lisp_Color_Instance *c, int depth)
428
+ − 331 {
+ − 332 XColor color = COLOR_INSTANCE_X_COLOR (c);
+ − 333 return HASH3 (color.red, color.green, color.blue);
+ − 334 }
+ − 335
+ − 336 static Lisp_Object
440
+ − 337 x_color_instance_rgb_components (Lisp_Color_Instance *c)
428
+ − 338 {
+ − 339 XColor color = COLOR_INSTANCE_X_COLOR (c);
+ − 340 return (list3 (make_int (color.red),
+ − 341 make_int (color.green),
+ − 342 make_int (color.blue)));
+ − 343 }
+ − 344
+ − 345 static int
+ − 346 x_valid_color_name_p (struct device *d, Lisp_Object color)
+ − 347 {
+ − 348 XColor c;
+ − 349 Display *dpy = DEVICE_X_DISPLAY (d);
+ − 350 Colormap cmap = DEVICE_X_COLORMAP (d);
442
+ − 351 const Extbyte *extname;
428
+ − 352
442
+ − 353 LISP_STRING_TO_EXTERNAL (color, extname, Qx_color_name_encoding);
428
+ − 354
440
+ − 355 return XParseColor (dpy, cmap, extname, &c);
428
+ − 356 }
+ − 357
+ − 358
+ − 359 /************************************************************************/
+ − 360 /* font instances */
+ − 361 /************************************************************************/
+ − 362
+ − 363 static int
440
+ − 364 x_initialize_font_instance (Lisp_Font_Instance *f, Lisp_Object name,
578
+ − 365 Lisp_Object device, Error_Behavior errb)
428
+ − 366 {
440
+ − 367 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (device));
428
+ − 368 XFontStruct *xf;
442
+ − 369 const Extbyte *extname;
428
+ − 370
442
+ − 371 LISP_STRING_TO_EXTERNAL (f->name, extname, Qx_font_name_encoding);
428
+ − 372 xf = XLoadQueryFont (dpy, extname);
+ − 373
+ − 374 if (!xf)
+ − 375 {
563
+ − 376 maybe_signal_error (Qgui_error, "Couldn't load font", f->name, Qfont,
+ − 377 errb);
428
+ − 378 return 0;
+ − 379 }
+ − 380
+ − 381 if (!xf->max_bounds.width)
+ − 382 {
+ − 383 /* yes, this has been known to happen. */
+ − 384 XFreeFont (dpy, xf);
563
+ − 385 maybe_signal_error (Qgui_error, "X font is too small", f->name, Qfont,
+ − 386 errb);
428
+ − 387 return 0;
+ − 388 }
+ − 389
+ − 390 /* Don't allocate the data until we're sure that we will succeed,
+ − 391 or the finalize method may get fucked. */
+ − 392 f->data = xnew (struct x_font_instance_data);
+ − 393 FONT_INSTANCE_X_FONT (f) = xf;
+ − 394 f->ascent = xf->ascent;
+ − 395 f->descent = xf->descent;
+ − 396 f->height = xf->ascent + xf->descent;
+ − 397 {
+ − 398 /* following change suggested by Ted Phelps <phelps@dstc.edu.au> */
647
+ − 399 int def_char = 'n'; /*xf->default_char;*/
+ − 400 int byte1, byte2;
428
+ − 401
+ − 402 once_more:
+ − 403 byte1 = def_char >> 8;
+ − 404 byte2 = def_char & 0xFF;
+ − 405
+ − 406 if (xf->per_char)
+ − 407 {
+ − 408 /* Old versions of the R5 font server have garbage (>63k) as
+ − 409 def_char. 'n' might not be a valid character. */
647
+ − 410 if (byte1 < (int) xf->min_byte1 ||
+ − 411 byte1 > (int) xf->max_byte1 ||
+ − 412 byte2 < (int) xf->min_char_or_byte2 ||
+ − 413 byte2 > (int) xf->max_char_or_byte2)
428
+ − 414 f->width = 0;
+ − 415 else
+ − 416 f->width = xf->per_char[(byte1 - xf->min_byte1) *
+ − 417 (xf->max_char_or_byte2 -
+ − 418 xf->min_char_or_byte2 + 1) +
+ − 419 (byte2 - xf->min_char_or_byte2)].width;
+ − 420 }
+ − 421 else
+ − 422 f->width = xf->max_bounds.width;
+ − 423
+ − 424 /* Some fonts have a default char whose width is 0. This is no good.
+ − 425 If that's the case, first try 'n' as the default char, and if n has
+ − 426 0 width too (unlikely) then just use the max width. */
+ − 427 if (f->width == 0)
+ − 428 {
647
+ − 429 if (def_char == (int) xf->default_char)
428
+ − 430 f->width = xf->max_bounds.width;
+ − 431 else
+ − 432 {
+ − 433 def_char = xf->default_char;
+ − 434 goto once_more;
+ − 435 }
+ − 436 }
+ − 437 }
+ − 438 /* If all characters don't exist then there could potentially be
+ − 439 0-width characters lurking out there. Not setting this flag
+ − 440 trips an optimization that would make them appear to have width
+ − 441 to redisplay. This is bad. So we set it if not all characters
+ − 442 have the same width or if not all characters are defined.
+ − 443 */
+ − 444 /* #### This sucks. There is a measurable performance increase
+ − 445 when using proportional width fonts if this flag is not set.
+ − 446 Unfortunately so many of the fucking X fonts are not fully
+ − 447 defined that we could almost just get rid of this damn flag and
+ − 448 make it an assertion. */
+ − 449 f->proportional_p = (xf->min_bounds.width != xf->max_bounds.width ||
+ − 450 (x_handle_non_fully_specified_fonts &&
+ − 451 !xf->all_chars_exist));
+ − 452
+ − 453 return 1;
+ − 454 }
+ − 455
+ − 456 static void
440
+ − 457 x_print_font_instance (Lisp_Font_Instance *f,
428
+ − 458 Lisp_Object printcharfun,
+ − 459 int escapeflag)
+ − 460 {
800
+ − 461 write_fmt_string (printcharfun, " 0x%lx",
+ − 462 (unsigned long) FONT_INSTANCE_X_FONT (f)->fid);
428
+ − 463 }
+ − 464
+ − 465 static void
440
+ − 466 x_finalize_font_instance (Lisp_Font_Instance *f)
428
+ − 467 {
+ − 468
+ − 469 if (f->data)
+ − 470 {
+ − 471 if (DEVICE_LIVE_P (XDEVICE (f->device)))
+ − 472 {
+ − 473 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (f->device));
+ − 474
+ − 475 XFreeFont (dpy, FONT_INSTANCE_X_FONT (f));
+ − 476 }
+ − 477 xfree (f->data);
+ − 478 f->data = 0;
+ − 479 }
+ − 480 }
+ − 481
+ − 482 /* Determining the truename of a font is hard. (Big surprise.)
+ − 483
+ − 484 By "truename" we mean an XLFD-form name which contains no wildcards, yet
+ − 485 which resolves to *exactly* the same font as the one which we already have
+ − 486 the (probably wildcarded) name and `XFontStruct' of.
+ − 487
+ − 488 One might think that the first font returned by XListFonts would be the one
+ − 489 that XOpenFont would pick. Apparently this is the case on some servers,
+ − 490 but not on others. It would seem not to be specified.
+ − 491
+ − 492 The MIT R5 server sometimes appears to be picking the lexicographically
+ − 493 smallest font which matches the name (thus picking "adobe" fonts before
+ − 494 "bitstream" fonts even if the bitstream fonts are earlier in the path, and
+ − 495 also picking 100dpi adobe fonts over 75dpi adobe fonts even though the
+ − 496 75dpi are in the path earlier) but sometimes appears to be doing something
442
+ − 497 else entirely (for example, removing the bitstream fonts from the path will
428
+ − 498 cause the 75dpi adobe fonts to be used instead of the 100dpi, even though
+ − 499 their relative positions in the path (and their names!) have not changed).
+ − 500
+ − 501 The documentation for XSetFontPath() seems to indicate that the order of
442
+ − 502 entries in the font path means something, but it's pretty noncommittal about
428
+ − 503 it, and the spirit of the law is apparently not being obeyed...
+ − 504
+ − 505 All the fonts I've seen have a property named `FONT' which contains the
+ − 506 truename of the font. However, there are two problems with using this: the
+ − 507 first is that the X Protocol Document is quite explicit that all properties
+ − 508 are optional, so we can't depend on it being there. The second is that
+ − 509 it's conceivable that this alleged truename isn't actually accessible as a
+ − 510 font, due to some difference of opinion between the font designers and
+ − 511 whoever installed the font on the system.
+ − 512
+ − 513 So, our first attempt is to look for a FONT property, and then verify that
+ − 514 the name there is a valid name by running XListFonts on it. There's still
+ − 515 the potential that this could be true but we could still be being lied to,
+ − 516 but that seems pretty remote.
+ − 517
+ − 518 Late breaking news: I've gotten reports that SunOS 4.1.3U1
+ − 519 with OpenWound 3.0 has a font whose truename is really
+ − 520 "-Adobe-Courier-Medium-R-Normal--12-120-75-75-M-70-ISO8859-1"
+ − 521 but whose FONT property contains "Courier".
+ − 522
+ − 523 So we disbelieve the FONT property unless it begins with a dash and
+ − 524 is more than 30 characters long. X Windows: The defacto substandard.
+ − 525 X Windows: Complex nonsolutions to simple nonproblems. X Windows:
+ − 526 Live the nightmare.
+ − 527
+ − 528 If the FONT property doesn't exist, then we try and construct an XLFD name
+ − 529 out of the other font properties (FOUNDRY, FAMILY_NAME, WEIGHT_NAME, etc).
+ − 530 This is necessary at least for some versions of OpenWound. But who knows
+ − 531 what the future will bring.
+ − 532
+ − 533 If that doesn't work, then we use XListFonts and either take the first font
+ − 534 (which I think is the most sensible thing) or we find the lexicographically
+ − 535 least, depending on whether the preprocessor constant `XOPENFONT_SORTS' is
+ − 536 defined. This sucks because the two behaviors are a property of the server
+ − 537 being used, not the architecture on which emacs has been compiled. Also,
+ − 538 as I described above, sorting isn't ALWAYS what the server does. Really it
+ − 539 does something seemingly random. There is no reliable way to win if the
+ − 540 FONT property isn't present.
+ − 541
+ − 542 Another possibility which I haven't bothered to implement would be to map
+ − 543 over all of the matching fonts and find the first one that has the same
+ − 544 character metrics as the font we already have loaded. Even if this didn't
+ − 545 return exactly the same font, it would at least return one whose characters
+ − 546 were the same sizes, which would probably be good enough.
+ − 547
+ − 548 More late-breaking news: on RS/6000 AIX 3.2.4, the expression
+ − 549 XLoadQueryFont (dpy, "-*-Fixed-Medium-R-*-*-*-130-75-75-*-*-ISO8859-1")
+ − 550 actually returns the font
+ − 551 -Misc-Fixed-Medium-R-Normal--13-120-75-75-C-80-ISO8859-1
+ − 552 which is crazy, because that font doesn't even match that pattern! It is
+ − 553 also not included in the output produced by `xlsfonts' with that pattern.
+ − 554
+ − 555 So this is yet another example of XListFonts() and XOpenFont() using
+ − 556 completely different algorithms. This, however, is a goofier example of
+ − 557 this bug, because in this case, it's not just the search order that is
+ − 558 different -- the sets don't even intersect.
+ − 559
+ − 560 If anyone has any better ideas how to do this, or any insights on what it is
+ − 561 that the various servers are actually doing, please let me know! -- jwz. */
+ − 562
+ − 563 static int
442
+ − 564 valid_x_font_name_p (Display *dpy, Extbyte *name)
428
+ − 565 {
+ − 566 /* Maybe this should be implemented by calling XLoadFont and trapping
+ − 567 the error. That would be a lot of work, and wasteful as hell, but
+ − 568 might be more correct.
+ − 569 */
+ − 570 int nnames = 0;
444
+ − 571 Extbyte **names = 0;
428
+ − 572 if (! name)
+ − 573 return 0;
+ − 574 names = XListFonts (dpy, name, 1, &nnames);
+ − 575 if (names)
+ − 576 XFreeFontNames (names);
+ − 577 return (nnames != 0);
+ − 578 }
+ − 579
442
+ − 580 static Extbyte *
428
+ − 581 truename_via_FONT_prop (Display *dpy, XFontStruct *font)
+ − 582 {
+ − 583 unsigned long value = 0;
442
+ − 584 Extbyte *result = 0;
428
+ − 585 if (XGetFontProperty (font, XA_FONT, &value))
+ − 586 result = XGetAtomName (dpy, value);
+ − 587 /* result is now 0, or the string value of the FONT property. */
+ − 588 if (result)
+ − 589 {
+ − 590 /* Verify that result is an XLFD name (roughly...) */
647
+ − 591 if (result [0] != '-' || strlen (result) < 30)
428
+ − 592 {
+ − 593 XFree (result);
+ − 594 result = 0;
+ − 595 }
+ − 596 }
+ − 597 return result; /* this must be freed by caller if non-0 */
+ − 598 }
+ − 599
442
+ − 600 static Extbyte *
428
+ − 601 truename_via_random_props (Display *dpy, XFontStruct *font)
+ − 602 {
+ − 603 struct device *d = get_device_from_display (dpy);
+ − 604 unsigned long value = 0;
442
+ − 605 Extbyte *foundry, *family, *weight, *slant, *setwidth, *add_style;
428
+ − 606 unsigned long pixel, point, res_x, res_y;
442
+ − 607 Extbyte *spacing;
428
+ − 608 unsigned long avg_width;
442
+ − 609 Extbyte *registry, *encoding;
+ − 610 Extbyte composed_name [2048];
428
+ − 611 int ok = 0;
442
+ − 612 Extbyte *result;
428
+ − 613
+ − 614 #define get_string(atom,var) \
+ − 615 if (XGetFontProperty (font, (atom), &value)) \
+ − 616 var = XGetAtomName (dpy, value); \
+ − 617 else { \
+ − 618 var = 0; \
+ − 619 goto FAIL; }
+ − 620 #define get_number(atom,var) \
+ − 621 if (!XGetFontProperty (font, (atom), &var) || \
+ − 622 var > 999) \
+ − 623 goto FAIL;
+ − 624
+ − 625 foundry = family = weight = slant = setwidth = 0;
+ − 626 add_style = spacing = registry = encoding = 0;
+ − 627
+ − 628 get_string (DEVICE_XATOM_FOUNDRY (d), foundry);
+ − 629 get_string (DEVICE_XATOM_FAMILY_NAME (d), family);
+ − 630 get_string (DEVICE_XATOM_WEIGHT_NAME (d), weight);
+ − 631 get_string (DEVICE_XATOM_SLANT (d), slant);
+ − 632 get_string (DEVICE_XATOM_SETWIDTH_NAME (d), setwidth);
+ − 633 get_string (DEVICE_XATOM_ADD_STYLE_NAME (d), add_style);
+ − 634 get_number (DEVICE_XATOM_PIXEL_SIZE (d), pixel);
+ − 635 get_number (DEVICE_XATOM_POINT_SIZE (d), point);
+ − 636 get_number (DEVICE_XATOM_RESOLUTION_X (d), res_x);
+ − 637 get_number (DEVICE_XATOM_RESOLUTION_Y (d), res_y);
+ − 638 get_string (DEVICE_XATOM_SPACING (d), spacing);
+ − 639 get_number (DEVICE_XATOM_AVERAGE_WIDTH (d), avg_width);
+ − 640 get_string (DEVICE_XATOM_CHARSET_REGISTRY (d), registry);
+ − 641 get_string (DEVICE_XATOM_CHARSET_ENCODING (d), encoding);
+ − 642 #undef get_number
+ − 643 #undef get_string
+ − 644
+ − 645 sprintf (composed_name,
+ − 646 "-%s-%s-%s-%s-%s-%s-%ld-%ld-%ld-%ld-%s-%ld-%s-%s",
+ − 647 foundry, family, weight, slant, setwidth, add_style, pixel,
+ − 648 point, res_x, res_y, spacing, avg_width, registry, encoding);
+ − 649 ok = 1;
+ − 650
+ − 651 FAIL:
+ − 652 if (ok)
+ − 653 {
+ − 654 int L = strlen (composed_name) + 1;
442
+ − 655 result = (Extbyte *) xmalloc (L);
428
+ − 656 strncpy (result, composed_name, L);
+ − 657 }
+ − 658 else
+ − 659 result = 0;
+ − 660
+ − 661 if (foundry) XFree (foundry);
+ − 662 if (family) XFree (family);
+ − 663 if (weight) XFree (weight);
+ − 664 if (slant) XFree (slant);
+ − 665 if (setwidth) XFree (setwidth);
+ − 666 if (add_style) XFree (add_style);
+ − 667 if (spacing) XFree (spacing);
+ − 668 if (registry) XFree (registry);
+ − 669 if (encoding) XFree (encoding);
+ − 670
+ − 671 return result;
+ − 672 }
+ − 673
+ − 674 /* Unbounded, for sufficiently small values of infinity... */
+ − 675 #define MAX_FONT_COUNT 5000
+ − 676
442
+ − 677 static Extbyte *
+ − 678 truename_via_XListFonts (Display *dpy, Extbyte *font_name)
428
+ − 679 {
442
+ − 680 Extbyte *result = 0;
444
+ − 681 Extbyte **names;
428
+ − 682 int count = 0;
+ − 683
+ − 684 #ifndef XOPENFONT_SORTS
+ − 685 /* In a sensible world, the first font returned by XListFonts()
+ − 686 would be the font that XOpenFont() would use. */
+ − 687 names = XListFonts (dpy, font_name, 1, &count);
+ − 688 if (count) result = names [0];
+ − 689 #else
+ − 690 /* But the world I live in is much more perverse. */
+ − 691 names = XListFonts (dpy, font_name, MAX_FONT_COUNT, &count);
+ − 692 while (count--)
442
+ − 693 /* !!#### Not Mule-friendly */
428
+ − 694 /* If names[count] is lexicographically less than result, use it.
+ − 695 (#### Should we be comparing case-insensitively?) */
+ − 696 if (result == 0 || (strcmp (result, names [count]) < 0))
+ − 697 result = names [count];
+ − 698 #endif
+ − 699
+ − 700 if (result)
+ − 701 result = xstrdup (result);
+ − 702 if (names)
+ − 703 XFreeFontNames (names);
+ − 704
+ − 705 return result; /* this must be freed by caller if non-0 */
+ − 706 }
+ − 707
+ − 708 static Lisp_Object
442
+ − 709 x_font_truename (Display *dpy, Extbyte *name, XFontStruct *font)
428
+ − 710 {
442
+ − 711 Extbyte *truename_FONT = 0;
+ − 712 Extbyte *truename_random = 0;
+ − 713 Extbyte *truename = 0;
428
+ − 714
+ − 715 /* The search order is:
+ − 716 - if FONT property exists, and is a valid name, return it.
+ − 717 - if the other props exist, and add up to a valid name, return it.
+ − 718 - if we find a matching name with XListFonts, return it.
+ − 719 - if FONT property exists, return it regardless.
+ − 720 - if other props exist, return the resultant name regardless.
+ − 721 - else return 0.
+ − 722 */
+ − 723
+ − 724 truename = truename_FONT = truename_via_FONT_prop (dpy, font);
+ − 725 if (truename && !valid_x_font_name_p (dpy, truename))
+ − 726 truename = 0;
+ − 727 if (!truename)
+ − 728 truename = truename_random = truename_via_random_props (dpy, font);
+ − 729 if (truename && !valid_x_font_name_p (dpy, truename))
+ − 730 truename = 0;
+ − 731 if (!truename && name)
+ − 732 truename = truename_via_XListFonts (dpy, name);
+ − 733
+ − 734 if (!truename)
+ − 735 {
+ − 736 /* Gag - we weren't able to find a seemingly-valid truename.
+ − 737 Well, maybe we're on one of those braindead systems where
+ − 738 XListFonts() and XLoadFont() are in violent disagreement.
+ − 739 If we were able to compute a truename, try using that even
+ − 740 if evidence suggests that it's not a valid name - because
+ − 741 maybe it is, really, and that's better than nothing.
+ − 742 X Windows: You'll envy the dead.
+ − 743 */
+ − 744 if (truename_FONT)
+ − 745 truename = truename_FONT;
+ − 746 else if (truename_random)
+ − 747 truename = truename_random;
+ − 748 }
+ − 749
+ − 750 /* One or both of these are not being used - free them. */
+ − 751 if (truename_FONT && truename_FONT != truename)
+ − 752 XFree (truename_FONT);
+ − 753 if (truename_random && truename_random != truename)
+ − 754 XFree (truename_random);
+ − 755
+ − 756 if (truename)
+ − 757 {
442
+ − 758 Lisp_Object result = build_ext_string (truename, Qx_font_name_encoding);
428
+ − 759 XFree (truename);
+ − 760 return result;
+ − 761 }
+ − 762 else
+ − 763 return Qnil;
+ − 764 }
+ − 765
+ − 766 static Lisp_Object
578
+ − 767 x_font_instance_truename (Lisp_Font_Instance *f, Error_Behavior errb)
428
+ − 768 {
+ − 769 struct device *d = XDEVICE (f->device);
+ − 770
872
+ − 771 if (NILP (FONT_INSTANCE_TRUENAME (f)))
428
+ − 772 {
+ − 773 Display *dpy = DEVICE_X_DISPLAY (d);
+ − 774 {
442
+ − 775 Extbyte *nameext;
+ − 776
+ − 777 LISP_STRING_TO_EXTERNAL (f->name, nameext, Qx_font_name_encoding);
872
+ − 778 FONT_INSTANCE_TRUENAME (f) =
442
+ − 779 x_font_truename (dpy, nameext, FONT_INSTANCE_X_FONT (f));
428
+ − 780 }
872
+ − 781 if (NILP (FONT_INSTANCE_TRUENAME (f)))
428
+ − 782 {
793
+ − 783 Lisp_Object font_instance = wrap_font_instance (f);
+ − 784
428
+ − 785
563
+ − 786 maybe_signal_error (Qgui_error, "Couldn't determine font truename",
+ − 787 font_instance, Qfont, errb);
428
+ − 788 /* Ok, just this once, return the font name as the truename.
+ − 789 (This is only used by Fequal() right now.) */
+ − 790 return f->name;
+ − 791 }
+ − 792 }
872
+ − 793 return FONT_INSTANCE_TRUENAME (f);
428
+ − 794 }
+ − 795
+ − 796 static Lisp_Object
440
+ − 797 x_font_instance_properties (Lisp_Font_Instance *f)
428
+ − 798 {
+ − 799 struct device *d = XDEVICE (f->device);
+ − 800 int i;
+ − 801 Lisp_Object result = Qnil;
444
+ − 802 Display *dpy = DEVICE_X_DISPLAY (d);
+ − 803 XFontProp *props = FONT_INSTANCE_X_FONT (f)->properties;
428
+ − 804
+ − 805 for (i = FONT_INSTANCE_X_FONT (f)->n_properties - 1; i >= 0; i--)
+ − 806 {
+ − 807 Lisp_Object name, value;
+ − 808 Atom atom = props [i].name;
867
+ − 809 Ibyte *name_str = 0;
647
+ − 810 Bytecount name_len;
442
+ − 811 Extbyte *namestrext = XGetAtomName (dpy, atom);
+ − 812
+ − 813 if (namestrext)
444
+ − 814 TO_INTERNAL_FORMAT (C_STRING, namestrext,
+ − 815 ALLOCA, (name_str, name_len),
+ − 816 Qx_atom_name_encoding);
442
+ − 817
771
+ − 818 name = (name_str ? intern_int (name_str) : Qnil);
428
+ − 819 if (name_str &&
+ − 820 (atom == XA_FONT ||
+ − 821 atom == DEVICE_XATOM_FOUNDRY (d) ||
+ − 822 atom == DEVICE_XATOM_FAMILY_NAME (d) ||
+ − 823 atom == DEVICE_XATOM_WEIGHT_NAME (d) ||
+ − 824 atom == DEVICE_XATOM_SLANT (d) ||
+ − 825 atom == DEVICE_XATOM_SETWIDTH_NAME (d) ||
+ − 826 atom == DEVICE_XATOM_ADD_STYLE_NAME (d) ||
+ − 827 atom == DEVICE_XATOM_SPACING (d) ||
+ − 828 atom == DEVICE_XATOM_CHARSET_REGISTRY (d) ||
+ − 829 atom == DEVICE_XATOM_CHARSET_ENCODING (d) ||
826
+ − 830 !qxestrcmp_c (name_str, "CHARSET_COLLECTIONS") ||
+ − 831 !qxestrcmp_c (name_str, "FONTNAME_REGISTRY") ||
+ − 832 !qxestrcmp_c (name_str, "CLASSIFICATION") ||
+ − 833 !qxestrcmp_c (name_str, "COPYRIGHT") ||
+ − 834 !qxestrcmp_c (name_str, "DEVICE_FONT_NAME") ||
+ − 835 !qxestrcmp_c (name_str, "FULL_NAME") ||
+ − 836 !qxestrcmp_c (name_str, "MONOSPACED") ||
+ − 837 !qxestrcmp_c (name_str, "QUALITY") ||
+ − 838 !qxestrcmp_c (name_str, "RELATIVE_SET") ||
+ − 839 !qxestrcmp_c (name_str, "RELATIVE_WEIGHT") ||
+ − 840 !qxestrcmp_c (name_str, "STYLE")))
428
+ − 841 {
442
+ − 842 Extbyte *val_str = XGetAtomName (dpy, props [i].card32);
+ − 843
+ − 844 value = (val_str ? build_ext_string (val_str, Qx_atom_name_encoding)
+ − 845 : Qnil);
428
+ − 846 }
+ − 847 else
+ − 848 value = make_int (props [i].card32);
442
+ − 849 if (namestrext) XFree (namestrext);
428
+ − 850 result = Fcons (Fcons (name, value), result);
+ − 851 }
+ − 852 return result;
+ − 853 }
+ − 854
+ − 855 static Lisp_Object
+ − 856 x_list_fonts (Lisp_Object pattern, Lisp_Object device)
+ − 857 {
444
+ − 858 Extbyte **names;
428
+ − 859 int count = 0;
+ − 860 Lisp_Object result = Qnil;
442
+ − 861 const Extbyte *patternext;
428
+ − 862
442
+ − 863 LISP_STRING_TO_EXTERNAL (pattern, patternext, Qx_font_name_encoding);
428
+ − 864
+ − 865 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
+ − 866 patternext, MAX_FONT_COUNT, &count);
+ − 867 while (count--)
442
+ − 868 result = Fcons (build_ext_string (names[count], Qx_font_name_encoding),
+ − 869 result);
428
+ − 870 if (names)
+ − 871 XFreeFontNames (names);
+ − 872 return result;
+ − 873 }
+ − 874
+ − 875 #ifdef MULE
+ − 876
+ − 877 static int
+ − 878 x_font_spec_matches_charset (struct device *d, Lisp_Object charset,
867
+ − 879 const Ibyte *nonreloc, Lisp_Object reloc,
872
+ − 880 Bytecount offset, Bytecount length,
+ − 881 int stage)
428
+ − 882 {
872
+ − 883 if (stage)
+ − 884 return 0;
+ − 885
428
+ − 886 if (UNBOUNDP (charset))
+ − 887 return 1;
+ − 888 /* Hack! Short font names don't have the registry in them,
+ − 889 so we just assume the user knows what they're doing in the
+ − 890 case of ASCII. For other charsets, you gotta give the
+ − 891 long form; sorry buster.
+ − 892 */
+ − 893 if (EQ (charset, Vcharset_ascii))
+ − 894 {
867
+ − 895 const Ibyte *the_nonreloc = nonreloc;
428
+ − 896 int i;
+ − 897 Bytecount the_length = length;
+ − 898
+ − 899 if (!the_nonreloc)
+ − 900 the_nonreloc = XSTRING_DATA (reloc);
+ − 901 fixup_internal_substring (nonreloc, reloc, offset, &the_length);
+ − 902 the_nonreloc += offset;
+ − 903 if (!memchr (the_nonreloc, '*', the_length))
+ − 904 {
+ − 905 for (i = 0;; i++)
+ − 906 {
867
+ − 907 const Ibyte *new_nonreloc = (const Ibyte *)
428
+ − 908 memchr (the_nonreloc, '-', the_length);
+ − 909 if (!new_nonreloc)
+ − 910 break;
+ − 911 new_nonreloc++;
+ − 912 the_length -= new_nonreloc - the_nonreloc;
+ − 913 the_nonreloc = new_nonreloc;
+ − 914 }
+ − 915
+ − 916 /* If it has less than 5 dashes, it's a short font.
+ − 917 Of course, long fonts always have 14 dashes or so, but short
+ − 918 fonts never have more than 1 or 2 dashes, so this is some
+ − 919 sort of reasonable heuristic. */
+ − 920 if (i < 5)
+ − 921 return 1;
+ − 922 }
+ − 923 }
+ − 924
+ − 925 return (fast_string_match (XCHARSET_REGISTRY (charset),
+ − 926 nonreloc, reloc, offset, length, 1,
+ − 927 ERROR_ME, 0) >= 0);
+ − 928 }
+ − 929
+ − 930 /* find a font spec that matches font spec FONT and also matches
+ − 931 (the registry of) CHARSET. */
+ − 932 static Lisp_Object
872
+ − 933 x_find_charset_font (Lisp_Object device, Lisp_Object font, Lisp_Object charset,
+ − 934 int stage)
428
+ − 935 {
444
+ − 936 Extbyte **names;
428
+ − 937 int count = 0;
+ − 938 Lisp_Object result = Qnil;
442
+ − 939 const Extbyte *patternext;
428
+ − 940 int i;
+ − 941
872
+ − 942 if (stage)
+ − 943 return Qnil;
+ − 944
442
+ − 945 LISP_STRING_TO_EXTERNAL (font, patternext, Qx_font_name_encoding);
428
+ − 946
+ − 947 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
+ − 948 patternext, MAX_FONT_COUNT, &count);
440
+ − 949 /* #### This code seems awfully bogus -- mrb */
428
+ − 950 for (i = 0; i < count; i ++)
+ − 951 {
867
+ − 952 const Ibyte *intname;
444
+ − 953 Bytecount intlen;
428
+ − 954
444
+ − 955 TO_INTERNAL_FORMAT (C_STRING, names[i],
+ − 956 ALLOCA, (intname, intlen),
+ − 957 Qx_font_name_encoding);
428
+ − 958 if (x_font_spec_matches_charset (XDEVICE (device), charset,
872
+ − 959 intname, Qnil, 0, -1, 0))
428
+ − 960 {
444
+ − 961 result = make_string (intname, intlen);
428
+ − 962 break;
+ − 963 }
+ − 964 }
+ − 965
+ − 966 if (names)
+ − 967 XFreeFontNames (names);
+ − 968
+ − 969 /* Check for a short font name. */
+ − 970 if (NILP (result)
+ − 971 && x_font_spec_matches_charset (XDEVICE (device), charset, 0,
872
+ − 972 font, 0, -1, 0))
428
+ − 973 return font;
+ − 974
+ − 975 return result;
+ − 976 }
+ − 977
+ − 978 #endif /* MULE */
+ − 979
+ − 980
+ − 981 /************************************************************************/
+ − 982 /* initialization */
+ − 983 /************************************************************************/
+ − 984
+ − 985 void
+ − 986 syms_of_objects_x (void)
+ − 987 {
+ − 988 }
+ − 989
+ − 990 void
+ − 991 console_type_create_objects_x (void)
+ − 992 {
+ − 993 /* object methods */
+ − 994
+ − 995 CONSOLE_HAS_METHOD (x, initialize_color_instance);
+ − 996 CONSOLE_HAS_METHOD (x, print_color_instance);
+ − 997 CONSOLE_HAS_METHOD (x, finalize_color_instance);
+ − 998 CONSOLE_HAS_METHOD (x, color_instance_equal);
+ − 999 CONSOLE_HAS_METHOD (x, color_instance_hash);
+ − 1000 CONSOLE_HAS_METHOD (x, color_instance_rgb_components);
+ − 1001 CONSOLE_HAS_METHOD (x, valid_color_name_p);
+ − 1002
+ − 1003 CONSOLE_HAS_METHOD (x, initialize_font_instance);
+ − 1004 CONSOLE_HAS_METHOD (x, print_font_instance);
+ − 1005 CONSOLE_HAS_METHOD (x, finalize_font_instance);
+ − 1006 CONSOLE_HAS_METHOD (x, font_instance_truename);
+ − 1007 CONSOLE_HAS_METHOD (x, font_instance_properties);
+ − 1008 CONSOLE_HAS_METHOD (x, list_fonts);
+ − 1009 #ifdef MULE
+ − 1010 CONSOLE_HAS_METHOD (x, find_charset_font);
+ − 1011 CONSOLE_HAS_METHOD (x, font_spec_matches_charset);
+ − 1012 #endif
+ − 1013 }
+ − 1014
+ − 1015 void
+ − 1016 vars_of_objects_x (void)
+ − 1017 {
+ − 1018 DEFVAR_BOOL ("x-handle-non-fully-specified-fonts",
+ − 1019 &x_handle_non_fully_specified_fonts /*
+ − 1020 If this is true then fonts which do not have all characters specified
+ − 1021 will be considered to be proportional width even if they are actually
+ − 1022 fixed-width. If this is not done then characters which are supposed to
+ − 1023 have 0 width may appear to actually have some width.
+ − 1024
+ − 1025 Note: While setting this to t guarantees correct output in all
+ − 1026 circumstances, it also causes a noticeable performance hit when using
+ − 1027 fixed-width fonts. Since most people don't use characters which could
+ − 1028 cause problems this is set to nil by default.
+ − 1029 */ );
+ − 1030 x_handle_non_fully_specified_fonts = 0;
+ − 1031 }
+ − 1032
+ − 1033 void
+ − 1034 Xatoms_of_objects_x (struct device *d)
+ − 1035 {
+ − 1036 Display *D = DEVICE_X_DISPLAY (d);
+ − 1037
+ − 1038 DEVICE_XATOM_FOUNDRY (d) = XInternAtom (D, "FOUNDRY", False);
+ − 1039 DEVICE_XATOM_FAMILY_NAME (d) = XInternAtom (D, "FAMILY_NAME", False);
+ − 1040 DEVICE_XATOM_WEIGHT_NAME (d) = XInternAtom (D, "WEIGHT_NAME", False);
+ − 1041 DEVICE_XATOM_SLANT (d) = XInternAtom (D, "SLANT", False);
+ − 1042 DEVICE_XATOM_SETWIDTH_NAME (d) = XInternAtom (D, "SETWIDTH_NAME", False);
+ − 1043 DEVICE_XATOM_ADD_STYLE_NAME (d) = XInternAtom (D, "ADD_STYLE_NAME", False);
+ − 1044 DEVICE_XATOM_PIXEL_SIZE (d) = XInternAtom (D, "PIXEL_SIZE", False);
+ − 1045 DEVICE_XATOM_POINT_SIZE (d) = XInternAtom (D, "POINT_SIZE", False);
+ − 1046 DEVICE_XATOM_RESOLUTION_X (d) = XInternAtom (D, "RESOLUTION_X", False);
+ − 1047 DEVICE_XATOM_RESOLUTION_Y (d) = XInternAtom (D, "RESOLUTION_Y", False);
+ − 1048 DEVICE_XATOM_SPACING (d) = XInternAtom (D, "SPACING", False);
+ − 1049 DEVICE_XATOM_AVERAGE_WIDTH (d) = XInternAtom (D, "AVERAGE_WIDTH", False);
+ − 1050 DEVICE_XATOM_CHARSET_REGISTRY(d) = XInternAtom (D, "CHARSET_REGISTRY",False);
+ − 1051 DEVICE_XATOM_CHARSET_ENCODING(d) = XInternAtom (D, "CHARSET_ENCODING",False);
+ − 1052 }