Mercurial > hg > xemacs-beta
diff src/objects-x.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/objects-x.c Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,832 @@ +/* X-specific Lisp objects. + Copyright (C) 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1995 Board of Trustees, University of Illinois. + Copyright (C) 1995 Tinker Systems. + Copyright (C) 1995, 1996 Ben Wing. + Copyright (C) 1995 Sun Microsystems, Inc. + +This file is part of XEmacs. + +XEmacs is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +XEmacs is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: Not in FSF. */ + +/* Authors: Jamie Zawinski, Chuck Thompson, Ben Wing */ + +#include <config.h> +#include "lisp.h" + +#include "console-x.h" +#include "objects-x.h" + +#include "buffer.h" +#include "device.h" +#include "insdel.h" + +int handle_nonfull_spec_fonts; + + +/************************************************************************/ +/* color instances */ +/************************************************************************/ + +/* Replacement for XAllocColor() that tries to return the nearest + available color if the colormap is full. From FSF Emacs. */ + +int +allocate_nearest_color (Display *display, Colormap screen_colormap, + XColor *color_def) +{ + int status; + + status = XAllocColor (display, screen_colormap, color_def); + if (!status) + { + /* If we got to this point, the colormap is full, so we're + going to try and get the next closest color. + The algorithm used is a least-squares matching, which is + what X uses for closest color matching with StaticColor visuals. */ + + XColor *cells; + int no_cells; + int nearest; + long nearest_delta, trial_delta; + int x; + + no_cells = XDisplayCells (display, XDefaultScreen (display)); + cells = (XColor *) alloca (sizeof (XColor) * no_cells); + + for (x = 0; x < no_cells; x++) + cells[x].pixel = x; + + XQueryColors (display, screen_colormap, cells, no_cells); + nearest = 0; + /* I'm assuming CSE so I'm not going to condense this. */ + nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8)) + * ((color_def->red >> 8) - (cells[0].red >> 8))) + + + (((color_def->green >> 8) - (cells[0].green >> 8)) + * ((color_def->green >> 8) - (cells[0].green >> 8))) + + + (((color_def->blue >> 8) - (cells[0].blue >> 8)) + * ((color_def->blue >> 8) - (cells[0].blue >> 8)))); + for (x = 1; x < no_cells; x++) + { + trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8)) + * ((color_def->red >> 8) - (cells[x].red >> 8))) + + + (((color_def->green >> 8) - (cells[x].green >> 8)) + * ((color_def->green >> 8) - (cells[x].green >> 8))) + + + (((color_def->blue >> 8) - (cells[x].blue >> 8)) + * ((color_def->blue >> 8) - (cells[x].blue >> 8)))); + if (trial_delta < nearest_delta) + { + nearest = x; + nearest_delta = trial_delta; + } + } + color_def->red = cells[nearest].red; + color_def->green = cells[nearest].green; + color_def->blue = cells[nearest].blue; + status = XAllocColor (display, screen_colormap, color_def); + } + + return status; +} + +int +x_parse_nearest_color (struct device *d, XColor *color, Bufbyte *name, + Bytecount len, Error_behavior errb) +{ + Display *dpy; + Screen *xs; + Colormap cmap; + int result; + + dpy = DEVICE_X_DISPLAY (d); + xs = DefaultScreenOfDisplay (dpy); + cmap = DefaultColormapOfScreen (xs); + + memset (color, 0, sizeof (*color)); + { + CONST Extbyte *extname; + Extcount extnamelen; + + GET_CHARPTR_EXT_BINARY_DATA_ALLOCA (name, len, extname, extnamelen); + result = XParseColor (dpy, cmap, (char *) extname, color); + } + if (!result) + { + maybe_signal_simple_error ("unrecognized color", make_string (name, len), + Qcolor, errb); + return 0; + } + result = allocate_nearest_color (dpy, cmap, color); + if (!result) + { + maybe_signal_simple_error ("couldn't allocate color", + make_string (name, len), Qcolor, errb); + return 0; + } + + return 1; +} + +static int +x_initialize_color_instance (struct Lisp_Color_Instance *c, Lisp_Object name, + Lisp_Object device, Error_behavior errb) +{ + XColor color; + int result; + + result = x_parse_nearest_color (XDEVICE (device), &color, + string_data (XSTRING (name)), + string_length (XSTRING (name)), + errb); + + if (!result) + return 0; + + /* Don't allocate the data until we're sure that we will succeed, + or the finalize method may get fucked. */ + c->data = malloc_type (struct x_color_instance_data); + COLOR_INSTANCE_X_COLOR (c) = color; + return 1; +} + +static void +x_print_color_instance (struct Lisp_Color_Instance *c, + Lisp_Object printcharfun, + int escapeflag) +{ + char buf[100]; + XColor color = COLOR_INSTANCE_X_COLOR (c); + sprintf (buf, " %ld=(%X,%X,%X)", + color.pixel, color.red, color.green, color.blue); + write_c_string (buf, printcharfun); +} + +static void +x_finalize_color_instance (struct Lisp_Color_Instance *c) +{ + if (c->data) + { + if (DEVICE_LIVE_P (XDEVICE (c->device))) + { + Display *dpy = DEVICE_X_DISPLAY (XDEVICE (c->device)); + + XFreeColors (dpy, + DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy)), + &COLOR_INSTANCE_X_COLOR (c).pixel, 1, 0); + } + xfree (c->data); + c->data = 0; + } +} + +/* Color instances are equal if they resolve to the same color on the + screen (have the same RGB values). I imagine that + "same RGV values" == "same cell in the colormap." Arguably we should + be comparing their names instead. */ + +static int +x_color_instance_equal (struct Lisp_Color_Instance *c1, + struct Lisp_Color_Instance *c2, + int depth) +{ + XColor color1 = COLOR_INSTANCE_X_COLOR (c1); + XColor color2 = COLOR_INSTANCE_X_COLOR (c2); + return ((color1.red == color2.red) && + (color1.green == color2.green) && + (color1.blue == color2.blue)); +} + +static unsigned long +x_color_instance_hash (struct Lisp_Color_Instance *c, int depth) +{ + XColor color = COLOR_INSTANCE_X_COLOR (c); + return HASH3 (color.red, color.green, color.blue); +} + +static Lisp_Object +x_color_instance_rgb_components (struct Lisp_Color_Instance *c) +{ + XColor color = COLOR_INSTANCE_X_COLOR (c); + return (list3 (make_int (color.red), + make_int (color.green), + make_int (color.blue))); +} + +static int +x_valid_color_name_p (struct device *d, Lisp_Object color) +{ + XColor c; + Display *dpy = DEVICE_X_DISPLAY (d); + CONST char *extname; + + GET_C_STRING_CTEXT_DATA_ALLOCA (color, extname); + + return XParseColor (dpy, + DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy)), + extname, &c); +} + + +/************************************************************************/ +/* font instances */ +/************************************************************************/ + +static int +x_initialize_font_instance (struct Lisp_Font_Instance *f, Lisp_Object name, + Lisp_Object device, Error_behavior errb) +{ + Display *dpy; + XFontStruct *xf; + CONST char *extname; + + dpy = DEVICE_X_DISPLAY (XDEVICE (device)); + GET_C_STRING_CTEXT_DATA_ALLOCA (f->name, extname); + xf = XLoadQueryFont (dpy, extname); + + if (!xf) + { + maybe_signal_simple_error ("couldn't load font", f->name, + Qfont, errb); + return 0; + } + + if (!xf->max_bounds.width) + { + /* yes, this has been known to happen. */ + XFreeFont (dpy, xf); + maybe_signal_simple_error ("X font is too small", f->name, + Qfont, errb); + return 0; + } + + /* Don't allocate the data until we're sure that we will succeed, + or the finalize method may get fucked. */ + f->data = malloc_type (struct x_font_instance_data); + FONT_INSTANCE_X_TRUENAME (f) = Qnil; + FONT_INSTANCE_X_FONT (f) = xf; + f->ascent = xf->ascent; + f->descent = xf->descent; + f->height = xf->ascent + xf->descent; + { + unsigned int def_char = xf->default_char; + int byte1, byte2; + + once_more: + byte1 = def_char >> 8; + byte2 = def_char & 0xFF; + + if (xf->per_char) + { + /* Old versions of the R5 font server have garbage (>63k) as + def_char. 'n' might not be a valid character. */ + if (byte1 < xf->min_byte1 || byte1 > xf->max_byte1 || + byte2 < xf->min_char_or_byte2 || byte2 > xf->max_char_or_byte2) + f->width = 0; + else + f->width = xf->per_char[(byte1 - xf->min_byte1) * + (xf->max_char_or_byte2 - + xf->min_char_or_byte2 + 1) + + (byte2 - xf->min_char_or_byte2)].width; + } + else + f->width = xf->max_bounds.width; + + /* Some fonts have a default char whose width is 0. This is no good. + If that's the case, first try 'n' as the default char, and if n has + 0 width too (unlikely) then just use the max width. */ + if (f->width == 0) + { + if (def_char == 'n') + f->width = xf->max_bounds.width; + else + { + def_char = 'n'; + goto once_more; + } + } + } + /* If all characters don't exist then there could potentially be + 0-width characters lurking out there. Not setting this flag + trips an optimization that would make them appear to have width + to redisplay. This is bad. So we set it if not all characters + have the same width or if not all characters are defined. + */ + /* #### This sucks. There is a measurable performance increase + when using proportional width fonts if this flag is not set. + Unfortunately so many of the fucking X fonts are not fully + defined that we could almost just get rid of this damn flag and + make it an assertion. */ + f->proportional_p = (xf->min_bounds.width != xf->max_bounds.width || + (handle_nonfull_spec_fonts && + !xf->all_chars_exist)); + + return 1; +} + +static void +x_mark_font_instance (struct Lisp_Font_Instance *f, + void (*markobj) (Lisp_Object)) +{ + ((markobj) (FONT_INSTANCE_X_TRUENAME (f))); +} + +static void +x_print_font_instance (struct Lisp_Font_Instance *f, + Lisp_Object printcharfun, + int escapeflag) +{ + char buf[200]; + sprintf (buf, " 0x%lx", (unsigned long) FONT_INSTANCE_X_FONT (f)->fid); + write_c_string (buf, printcharfun); +} + +static void +x_finalize_font_instance (struct Lisp_Font_Instance *f) +{ + + if (f->data) + { + if (DEVICE_LIVE_P (XDEVICE (f->device))) + { + Display *dpy = DEVICE_X_DISPLAY (XDEVICE (f->device)); + + XFreeFont (dpy, FONT_INSTANCE_X_FONT (f)); + } + xfree (f->data); + f->data = 0; + } +} + +/* Determining the truename of a font is hard. (Big surprise.) + + By "truename" we mean an XLFD-form name which contains no wildcards, yet + which resolves to *exactly* the same font as the one which we already have + the (probably wildcarded) name and `XFontStruct' of. + + One might think that the first font returned by XListFonts would be the one + that XOpenFont would pick. Apparently this is the case on some servers, + but not on others. It would seem not to be specified. + + The MIT R5 server sometimes appears to be picking the lexicographically + smallest font which matches the name (thus picking "adobe" fonts before + "bitstream" fonts even if the bitstream fonts are earlier in the path, and + also picking 100dpi adobe fonts over 75dpi adobe fonts even though the + 75dpi are in the path earlier) but sometimes appears to be doing something + else entirely (for example, removing the bitsream fonts from the path will + cause the 75dpi adobe fonts to be used instead of the100dpi, even though + their relative positions in the path (and their names!) have not changed). + + The documentation for XSetFontPath() seems to indicate that the order of + entries in the font path means something, but it's pretty noncommital about + it, and the spirit of the law is apparently not being obeyed... + + All the fonts I've seen have a property named `FONT' which contains the + truename of the font. However, there are two problems with using this: the + first is that the X Protocol Document is quite explicit that all properties + are optional, so we can't depend on it being there. The second is that + it's concievable that this alleged truename isn't actually accessible as a + font, due to some difference of opinion between the font designers and + whoever installed the font on the system. + + So, our first attempt is to look for a FONT property, and then verify that + the name there is a valid name by running XListFonts on it. There's still + the potential that this could be true but we could still be being lied to, + but that seems pretty remote. + + Late breaking news: I've gotten reports that SunOS 4.1.3U1 + with OpenWound 3.0 has a font whose truename is really + "-Adobe-Courier-Medium-R-Normal--12-120-75-75-M-70-ISO8859-1" + but whose FONT property contains "Courier". + + So we disbelieve the FONT property unless it begins with a dash and + is more than 30 characters long. X Windows: The defacto substandard. + X Windows: Complex nonsolutions to simple nonproblems. X Windows: + Live the nightmare. + + If the FONT property doesn't exist, then we try and construct an XLFD name + out of the other font properties (FOUNDRY, FAMILY_NAME, WEIGHT_NAME, etc). + This is necessary at least for some versions of OpenWound. But who knows + what the future will bring. + + If that doesn't work, then we use XListFonts and either take the first font + (which I think is the most sensible thing) or we find the lexicographically + least, depending on whether the preprocessor constant `XOPENFONT_SORTS' is + defined. This sucks because the two behaviors are a property of the server + being used, not the architecture on which emacs has been compiled. Also, + as I described above, sorting isn't ALWAYS what the server does. Really it + does something seemingly random. There is no reliable way to win if the + FONT property isn't present. + + Another possibility which I haven't bothered to implement would be to map + over all of the matching fonts and find the first one that has the same + character metrics as the font we already have loaded. Even if this didn't + return exactly the same font, it would at least return one whose characters + were the same sizes, which would probably be good enough. + + More late-breaking news: on RS/6000 AIX 3.2.4, the expression + XLoadQueryFont (dpy, "-*-Fixed-Medium-R-*-*-*-130-75-75-*-*-ISO8859-1") + actually returns the font + -Misc-Fixed-Medium-R-Normal--13-120-75-75-C-80-ISO8859-1 + which is crazy, because that font doesn't even match that pattern! It is + also not included in the output produced by `xlsfonts' with that pattern. + + So this is yet another example of XListFonts() and XOpenFont() using + completely different algorithms. This, however, is a goofier example of + this bug, because in this case, it's not just the search order that is + different -- the sets don't even intersect. + + If anyone has any better ideas how to do this, or any insights on what it is + that the various servers are actually doing, please let me know! -- jwz. */ + +static int +valid_x_font_name_p (Display *dpy, char *name) +{ + /* Maybe this should be implemented by callign XLoadFont and trapping + the error. That would be a lot of work, and wasteful as hell, but + might be more correct. + */ + int nnames = 0; + char **names = 0; + if (! name) + return 0; + names = XListFonts (dpy, name, 1, &nnames); + if (names) + XFreeFontNames (names); + return (nnames != 0); +} + +static char * +truename_via_FONT_prop (Display *dpy, XFontStruct *font) +{ + unsigned long value = 0; + char *result = 0; + if (XGetFontProperty (font, XA_FONT, &value)) + result = XGetAtomName (dpy, value); + /* result is now 0, or the string value of the FONT property. */ + if (result) + { + /* Verify that result is an XLFD name (roughly...) */ + if (result [0] != '-' || strlen (result) < (unsigned int) 30) + { + XFree (result); + result = 0; + } + } + return result; /* this must be freed by caller if non-0 */ +} + +static char * +truename_via_random_props (Display *dpy, XFontStruct *font) +{ + struct device *d = get_device_from_display (dpy); + unsigned long value = 0; + char *foundry, *family, *weight, *slant, *setwidth, *add_style; + unsigned long pixel, point, res_x, res_y; + char *spacing; + unsigned long avg_width; + char *registry, *encoding; + char composed_name [2048]; + int ok = 0; + char *result; + +#define get_string(atom,var) \ + if (XGetFontProperty (font, (atom), &value)) \ + var = XGetAtomName (dpy, value); \ + else { \ + var = 0; \ + goto FAIL; } +#define get_number(atom,var) \ + if (!XGetFontProperty (font, (atom), &var) || \ + var > 999) \ + goto FAIL; + + foundry = family = weight = slant = setwidth = 0; + add_style = spacing = registry = encoding = 0; + + get_string (DEVICE_XATOM_FOUNDRY (d), foundry); + get_string (DEVICE_XATOM_FAMILY_NAME (d), family); + get_string (DEVICE_XATOM_WEIGHT_NAME (d), weight); + get_string (DEVICE_XATOM_SLANT (d), slant); + get_string (DEVICE_XATOM_SETWIDTH_NAME (d), setwidth); + get_string (DEVICE_XATOM_ADD_STYLE_NAME (d), add_style); + get_number (DEVICE_XATOM_PIXEL_SIZE (d), pixel); + get_number (DEVICE_XATOM_POINT_SIZE (d), point); + get_number (DEVICE_XATOM_RESOLUTION_X (d), res_x); + get_number (DEVICE_XATOM_RESOLUTION_Y (d), res_y); + get_string (DEVICE_XATOM_SPACING (d), spacing); + get_number (DEVICE_XATOM_AVERAGE_WIDTH (d), avg_width); + get_string (DEVICE_XATOM_CHARSET_REGISTRY (d), registry); + get_string (DEVICE_XATOM_CHARSET_ENCODING (d), encoding); +#undef get_number +#undef get_string + + sprintf (composed_name, + "-%s-%s-%s-%s-%s-%s-%ld-%ld-%ld-%ld-%s-%ld-%s-%s", + foundry, family, weight, slant, setwidth, add_style, pixel, + point, res_x, res_y, spacing, avg_width, registry, encoding); + ok = 1; + + FAIL: + if (ok) + { + int L = strlen (composed_name) + 1; + result = xmalloc (L); + strncpy (result, composed_name, L); + } + else + result = 0; + + if (foundry) XFree (foundry); + if (family) XFree (family); + if (weight) XFree (weight); + if (slant) XFree (slant); + if (setwidth) XFree (setwidth); + if (add_style) XFree (add_style); + if (spacing) XFree (spacing); + if (registry) XFree (registry); + if (encoding) XFree (encoding); + + return result; +} + +/* Unbounded, for sufficiently small values of infinity... */ +#define MAX_FONT_COUNT 5000 + +static char * +truename_via_XListFonts (Display *dpy, char *font_name) +{ + char *result = 0; + char **names; + int count = 0; + +#ifndef XOPENFONT_SORTS + /* In a sensible world, the first font returned by XListFonts() + would be the font that XOpenFont() would use. */ + names = XListFonts (dpy, font_name, 1, &count); + if (count) result = names [0]; +#else + /* But the world I live in is much more perverse. */ + names = XListFonts (dpy, font_name, MAX_FONT_COUNT, &count); + while (count--) + /* If names[count] is lexicographically less than result, use it. + (#### Should we be comparing case-insensitively?) */ + if (result == 0 || (strcmp (result, names [count]) < 0)) + result = names [count]; +#endif + + if (result) + result = xstrdup (result); + if (names) + XFreeFontNames (names); + + return result; /* this must be freed by caller if non-0 */ +} + +static Lisp_Object +x_font_truename (Display *dpy, char *name, XFontStruct *font) +{ + char *truename_FONT = 0; + char *truename_random = 0; + char *truename = 0; + + /* The search order is: + - if FONT property exists, and is a valid name, return it. + - if the other props exist, and add up to a valid name, return it. + - if we find a matching name with XListFonts, return it. + - if FONT property exists, return it regardless. + - if other props exist, return the resultant name regardless. + - else return 0. + */ + + truename = truename_FONT = truename_via_FONT_prop (dpy, font); + if (truename && !valid_x_font_name_p (dpy, truename)) + truename = 0; + if (!truename) + truename = truename_random = truename_via_random_props (dpy, font); + if (truename && !valid_x_font_name_p (dpy, truename)) + truename = 0; + if (!truename && name) + truename = truename_via_XListFonts (dpy, name); + + if (!truename) + { + /* Gag - we weren't able to find a seemingly-valid truename. + Well, maybe we're on one of those braindead systems where + XListFonts() and XLoadFont() are in violent disagreement. + If we were able to compute a truename, try using that even + if evidence suggests that it's not a valid name - because + maybe it is, really, and that's better than nothing. + X Windows: You'll envy the dead. + */ + if (truename_FONT) + truename = truename_FONT; + else if (truename_random) + truename = truename_random; + } + + /* One or both of these are not being used - free them. */ + if (truename_FONT && truename_FONT != truename) + XFree (truename_FONT); + if (truename_random && truename_random != truename) + XFree (truename_random); + + if (truename) + { + Lisp_Object result = build_string (truename); + xfree (truename); + return result; + } + else + return Qnil; +} + +static Lisp_Object +x_font_instance_truename (struct Lisp_Font_Instance *f, Error_behavior errb) +{ + struct device *d = XDEVICE (f->device); + + if (NILP (FONT_INSTANCE_X_TRUENAME (f))) + { + Display *dpy = DEVICE_X_DISPLAY (d); + char *name = + (char *) string_data (XSTRING (f->name)); + { + FONT_INSTANCE_X_TRUENAME (f) = + x_font_truename (dpy, name, FONT_INSTANCE_X_FONT (f)); + } + if (NILP (FONT_INSTANCE_X_TRUENAME (f))) + { + Lisp_Object font_instance = Qnil; + XSETFONT_INSTANCE (font_instance, f); + + maybe_signal_simple_error ("couldn't determine font truename", + font_instance, Qfont, errb); + /* Ok, just this once, return the font name as the truename. + (This is only used by Fequal() right now.) */ + return f->name; + } + } + return (FONT_INSTANCE_X_TRUENAME (f)); +} + +static Lisp_Object +x_font_instance_properties (struct Lisp_Font_Instance *f) +{ + struct device *d = XDEVICE (f->device); + int i; + Lisp_Object result = Qnil; + XFontProp *props; + Display *dpy; + + dpy = DEVICE_X_DISPLAY (d); + props = FONT_INSTANCE_X_FONT (f)->properties; + for (i = FONT_INSTANCE_X_FONT (f)->n_properties - 1; i >= 0; i--) + { + char *name_str = 0; + char *val_str = 0; + Lisp_Object name, value; + Atom atom = props [i].name; + name_str = XGetAtomName (dpy, atom); + name = (name_str ? intern (name_str) : Qnil); + if (name_str && + (atom == XA_FONT || + atom == DEVICE_XATOM_FOUNDRY (d) || + atom == DEVICE_XATOM_FAMILY_NAME (d) || + atom == DEVICE_XATOM_WEIGHT_NAME (d) || + atom == DEVICE_XATOM_SLANT (d) || + atom == DEVICE_XATOM_SETWIDTH_NAME (d) || + atom == DEVICE_XATOM_ADD_STYLE_NAME (d) || + atom == DEVICE_XATOM_SPACING (d) || + atom == DEVICE_XATOM_CHARSET_REGISTRY (d) || + atom == DEVICE_XATOM_CHARSET_ENCODING (d) || + !strcmp (name_str, "CHARSET_COLLECTIONS") || + !strcmp (name_str, "FONTNAME_REGISTRY") || + !strcmp (name_str, "CLASSIFICATION") || + !strcmp (name_str, "COPYRIGHT") || + !strcmp (name_str, "DEVICE_FONT_NAME") || + !strcmp (name_str, "FULL_NAME") || + !strcmp (name_str, "MONOSPACED") || + !strcmp (name_str, "QUALITY") || + !strcmp (name_str, "RELATIVE_SET") || + !strcmp (name_str, "RELATIVE_WEIGHT") || + !strcmp (name_str, "STYLE"))) + { + val_str = XGetAtomName (dpy, props [i].card32); + value = (val_str ? build_string (val_str) : Qnil); + } + else + value = make_int (props [i].card32); + if (name_str) XFree (name_str); + result = Fcons (Fcons (name, value), result); + } + return result; +} + +static Lisp_Object +x_list_fonts (Lisp_Object pattern, Lisp_Object device) +{ + char **names; + int count = 0; + Lisp_Object result = Qnil; + CONST char *patternext; + + GET_C_STRING_BINARY_DATA_ALLOCA (pattern, patternext); + + names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)), + patternext, MAX_FONT_COUNT, &count); + while (count--) + result = Fcons (build_ext_string (names [count], FORMAT_BINARY), result); + if (names) + XFreeFontNames (names); + return result; +} + + +/************************************************************************/ +/* initialization */ +/************************************************************************/ + +void +syms_of_objects_x (void) +{ +} + +void +console_type_create_objects_x (void) +{ + /* object methods */ + + CONSOLE_HAS_METHOD (x, initialize_color_instance); + CONSOLE_HAS_METHOD (x, print_color_instance); + CONSOLE_HAS_METHOD (x, finalize_color_instance); + CONSOLE_HAS_METHOD (x, color_instance_equal); + CONSOLE_HAS_METHOD (x, color_instance_hash); + CONSOLE_HAS_METHOD (x, color_instance_rgb_components); + CONSOLE_HAS_METHOD (x, valid_color_name_p); + + CONSOLE_HAS_METHOD (x, initialize_font_instance); + CONSOLE_HAS_METHOD (x, mark_font_instance); + CONSOLE_HAS_METHOD (x, print_font_instance); + CONSOLE_HAS_METHOD (x, finalize_font_instance); + CONSOLE_HAS_METHOD (x, font_instance_truename); + CONSOLE_HAS_METHOD (x, font_instance_properties); + CONSOLE_HAS_METHOD (x, list_fonts); +} + +void +vars_of_objects_x (void) +{ + DEFVAR_BOOL ("x-handle-non-fully-specified-fonts",&handle_nonfull_spec_fonts /* +If this is true then fonts which do not have all characters specified +will be considered to be proportional width even if they are actually +fixed-width. If this is not done then characters which are supposed to +have 0 width may appear to actually have some width. + +Note: While setting this to t guarantees correct output in all +circumstances, it also causes a noticeable performance hit when using +fixed-width fonts. Since most people don't use characters which could +cause problems this is set to nil by default. +*/ ); + handle_nonfull_spec_fonts = 0; +} + + +void +Xatoms_of_objects_x (struct device *d) +{ +#define ATOM(x) XInternAtom (DEVICE_X_DISPLAY (d), (x), False) + + DEVICE_XATOM_FOUNDRY (d) = ATOM ("FOUNDRY"); + DEVICE_XATOM_FAMILY_NAME (d) = ATOM ("FAMILY_NAME"); + DEVICE_XATOM_WEIGHT_NAME (d) = ATOM ("WEIGHT_NAME"); + DEVICE_XATOM_SLANT (d) = ATOM ("SLANT"); + DEVICE_XATOM_SETWIDTH_NAME (d) = ATOM ("SETWIDTH_NAME"); + DEVICE_XATOM_ADD_STYLE_NAME (d) = ATOM ("ADD_STYLE_NAME"); + DEVICE_XATOM_PIXEL_SIZE (d) = ATOM ("PIXEL_SIZE"); + DEVICE_XATOM_POINT_SIZE (d) = ATOM ("POINT_SIZE"); + DEVICE_XATOM_RESOLUTION_X (d) = ATOM ("RESOLUTION_X"); + DEVICE_XATOM_RESOLUTION_Y (d) = ATOM ("RESOLUTION_Y"); + DEVICE_XATOM_SPACING (d) = ATOM ("SPACING"); + DEVICE_XATOM_AVERAGE_WIDTH (d) = ATOM ("AVERAGE_WIDTH"); + DEVICE_XATOM_CHARSET_REGISTRY (d) = ATOM ("CHARSET_REGISTRY"); + DEVICE_XATOM_CHARSET_ENCODING (d) = ATOM ("CHARSET_ENCODING"); +}