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.
5 Copyright (C) 1995, 1996 Ben Wing.
6 Copyright (C) 1995 Sun Microsystems, Inc.
8 This file is part of SXEmacs
10 SXEmacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 SXEmacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 /* Synched up with: Not in FSF. */
26 /* Authors: Jamie Zawinski, Chuck Thompson, Ben Wing */
27 /* Gtk version by William Perry */
32 #include "console-gtk.h"
33 #include "objects-gtk.h"
36 #include "ui/device.h"
37 #include "ui/insdel.h"
42 /************************************************************************/
44 /************************************************************************/
46 /* Replacement for XAllocColor() that tries to return the nearest
47 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 Modified by Lee Kindness <lkindness@csl.co.uk> 31/08/99 to handle previous
50 total failure which was due to a read/write colorcell being the nearest
51 match - tries the next nearest...
53 Gdk takes care of all this behind the scenes, so we don't need to
56 Return value is 1 for normal success, 2 for nearest color success,
57 3 for Non-deallocable sucess. */
59 allocate_nearest_color(GdkColormap * colormap, GdkVisual * visual,
64 rc = gdk_colormap_alloc_color(colormap, color_def, FALSE, TRUE);
73 gtk_parse_nearest_color(struct device *d, GdkColor * color, Bufbyte * name,
74 Bytecount len, Error_behavior errb)
80 cmap = DEVICE_GTK_COLORMAP(d);
81 visual = DEVICE_GTK_VISUAL(d);
85 const Extbyte *extname;
88 TO_EXTERNAL_FORMAT(DATA, (name, len), ALLOCA,
89 (extname, extnamelen), Qbinary);
91 result = gdk_color_parse(extname, color);
94 if (result == FALSE) {
95 maybe_signal_simple_error("unrecognized color",
96 make_string(name, len), Qcolor, errb);
99 result = allocate_nearest_color(cmap, visual, color);
101 maybe_signal_simple_error("couldn't allocate color",
102 make_string(name, len), Qcolor, errb);
110 gtk_initialize_color_instance(struct Lisp_Color_Instance *c, Lisp_Object name,
111 Lisp_Object device, Error_behavior errb)
116 result = gtk_parse_nearest_color(XDEVICE(device), &color,
118 XSTRING_LENGTH(name), errb);
123 /* Don't allocate the data until we're sure that we will succeed,
124 or the finalize method may get fucked. */
125 c->data = xnew(struct gtk_color_instance_data);
127 COLOR_INSTANCE_GTK_DEALLOC(c) = 0;
129 COLOR_INSTANCE_GTK_DEALLOC(c) = 1;
130 COLOR_INSTANCE_GTK_COLOR(c) = gdk_color_copy(&color);
135 gtk_print_color_instance(struct Lisp_Color_Instance *c,
136 Lisp_Object printcharfun, int escapeflag)
138 GdkColor *color = COLOR_INSTANCE_GTK_COLOR(c);
139 write_fmt_str(printcharfun, " %ld=(%X,%X,%X)",
140 color->pixel, color->red, color->green, color->blue);
143 static void gtk_finalize_color_instance(struct Lisp_Color_Instance *c)
146 if (DEVICE_LIVE_P(XDEVICE(c->device))) {
147 if (COLOR_INSTANCE_GTK_DEALLOC(c)) {
148 gdk_colormap_free_colors(DEVICE_GTK_COLORMAP
149 (XDEVICE(c->device)),
150 COLOR_INSTANCE_GTK_COLOR
153 gdk_color_free(COLOR_INSTANCE_GTK_COLOR(c));
160 /* Color instances are equal if they resolve to the same color on the
161 screen (have the same RGB values). I imagine that
162 "same RGB values" == "same cell in the colormap." Arguably we should
163 be comparing their names or pixel values instead. */
166 gtk_color_instance_equal(struct Lisp_Color_Instance *c1,
167 struct Lisp_Color_Instance *c2, int depth)
169 return (gdk_color_equal(COLOR_INSTANCE_GTK_COLOR(c1),
170 COLOR_INSTANCE_GTK_COLOR(c2)));
174 gtk_color_instance_hash(struct Lisp_Color_Instance *c, int depth)
176 return (gdk_color_hash(COLOR_INSTANCE_GTK_COLOR(c), NULL));
180 gtk_color_instance_rgb_components(struct Lisp_Color_Instance *c)
182 GdkColor *color = COLOR_INSTANCE_GTK_COLOR(c);
183 return (list3(make_int(color->red),
184 make_int(color->green), make_int(color->blue)));
187 static int gtk_valid_color_name_p(struct device *d, Lisp_Object color)
192 TO_EXTERNAL_FORMAT(LISP_STRING, color, C_STRING_ALLOCA, extname,
195 if (gdk_color_parse(extname, &c) != TRUE)
200 /************************************************************************/
202 /************************************************************************/
205 gtk_initialize_font_instance(struct Lisp_Font_Instance *f, Lisp_Object name,
206 Lisp_Object device, Error_behavior errb)
212 TO_EXTERNAL_FORMAT(LISP_STRING, f->name, C_STRING_ALLOCA, extname,
215 gf = gdk_font_load(extname);
218 maybe_signal_simple_error("couldn't load font", f->name,
223 xf = GDK_FONT_XFONT(gf);
225 /* Don't allocate the data until we're sure that we will succeed,
226 or the finalize method may get fucked. */
227 f->data = xnew(struct gtk_font_instance_data);
228 FONT_INSTANCE_GTK_TRUENAME(f) = Qnil;
229 FONT_INSTANCE_GTK_FONT(f) = gf;
230 f->ascent = gf->ascent;
231 f->descent = gf->descent;
232 f->height = gf->ascent + gf->descent;
234 /* Now lets figure out the width of the font */
236 /* following change suggested by Ted Phelps <phelps@dstc.edu.au> */
237 unsigned int def_char = 'n'; /*xf->default_char; */
238 unsigned int byte1, byte2;
241 byte1 = def_char >> 8;
242 byte2 = def_char & 0xFF;
245 /* Old versions of the R5 font server have garbage (>63k) as
246 def_char. 'n' might not be a valid character. */
247 if (byte1 < xf->min_byte1 ||
248 byte1 > xf->max_byte1 ||
249 byte2 < xf->min_char_or_byte2 ||
250 byte2 > xf->max_char_or_byte2)
254 xf->per_char[(byte1 - xf->min_byte1) *
255 (xf->max_char_or_byte2 -
256 xf->min_char_or_byte2 + 1) +
258 xf->min_char_or_byte2)].width;
260 f->width = xf->max_bounds.width;
262 /* Some fonts have a default char whose width is 0. This is no good.
263 If that's the case, first try 'n' as the default char, and if n has
264 0 width too (unlikely) then just use the max width. */
266 if (def_char == xf->default_char)
267 f->width = xf->max_bounds.width;
269 def_char = xf->default_char;
275 /* If all characters don't exist then there could potentially be
276 0-width characters lurking out there. Not setting this flag
277 trips an optimization that would make them appear to have width
278 to redisplay. This is bad. So we set it if not all characters
279 have the same width or if not all characters are defined.
281 /* #### This sucks. There is a measurable performance increase
282 when using proportional width fonts if this flag is not set.
283 Unfortunately so many of the fucking X fonts are not fully
284 defined that we could almost just get rid of this damn flag and
285 make it an assertion. */
286 f->proportional_p = (xf->min_bounds.width != xf->max_bounds.width ||
287 ( /* x_handle_non_fully_specified_fonts */ 0 &&
288 !xf->all_chars_exist));
290 f->width = gdk_char_width(gf, 'n');
292 (gdk_char_width(gf, '|') != gdk_char_width(gf, 'W')) ? 1 : 0;
297 static void gtk_mark_font_instance(struct Lisp_Font_Instance *f)
299 mark_object(FONT_INSTANCE_GTK_TRUENAME(f));
303 gtk_print_font_instance(struct Lisp_Font_Instance *f,
304 Lisp_Object printcharfun, int escapeflag)
306 write_fmt_str(printcharfun, " 0x%lx",
307 (unsigned long)gdk_font_id(FONT_INSTANCE_GTK_FONT(f)));
310 static void gtk_finalize_font_instance(struct Lisp_Font_Instance *f)
313 if (DEVICE_LIVE_P(XDEVICE(f->device))) {
314 gdk_font_unref(FONT_INSTANCE_GTK_FONT(f));
321 /* Forward declarations for X specific functions at the end of the file */
322 Lisp_Object __get_gtk_font_truename(GdkFont * gdk_font, int expandp);
323 static Lisp_Object __gtk_list_fonts_internal(const char *pattern);
326 gtk_font_instance_truename(struct Lisp_Font_Instance *f, Error_behavior errb)
328 if (NILP(FONT_INSTANCE_GTK_TRUENAME(f))) {
329 FONT_INSTANCE_GTK_TRUENAME(f) =
330 __get_gtk_font_truename(FONT_INSTANCE_GTK_FONT(f), 1);
332 if (NILP(FONT_INSTANCE_GTK_TRUENAME(f))) {
333 /* Ok, just this once, return the font name as the truename.
334 (This is only used by Fequal() right now.) */
338 return (FONT_INSTANCE_GTK_TRUENAME(f));
341 static Lisp_Object gtk_font_instance_properties(struct Lisp_Font_Instance *f)
343 Lisp_Object result = Qnil;
346 /* There seems to be no way to get this information under Gtk */
350 static Lisp_Object gtk_list_fonts(Lisp_Object pattern, Lisp_Object device)
352 const char *patternext;
354 TO_EXTERNAL_FORMAT(LISP_STRING, pattern, C_STRING_ALLOCA, patternext,
357 return (__gtk_list_fonts_internal(patternext));
363 gtk_font_spec_matches_charset(struct device *d, Lisp_Object charset,
364 const Bufbyte * nonreloc, Lisp_Object reloc,
365 Bytecount offset, Bytecount length)
367 if (UNBOUNDP(charset))
369 /* Hack! Short font names don't have the registry in them,
370 so we just assume the user knows what they're doing in the
371 case of ASCII. For other charsets, you gotta give the
372 long form; sorry buster.
374 if (EQ(charset, Vcharset_ascii)) {
375 const Bufbyte *the_nonreloc = nonreloc;
377 Bytecount the_length = length;
380 the_nonreloc = XSTRING_DATA(reloc);
381 fixup_internal_substring(nonreloc, reloc, offset, &the_length);
382 the_nonreloc += offset;
383 if (!memchr(the_nonreloc, '*', the_length)) {
385 const Bufbyte *new_nonreloc = (const Bufbyte *)
386 memchr(the_nonreloc, '-', the_length);
390 the_length -= new_nonreloc - the_nonreloc;
391 the_nonreloc = new_nonreloc;
394 /* If it has less than 5 dashes, it's a short font.
395 Of course, long fonts always have 14 dashes or so, but short
396 fonts never have more than 1 or 2 dashes, so this is some
397 sort of reasonable heuristic. */
403 return (fast_string_match(XCHARSET_REGISTRY(charset),
404 nonreloc, reloc, offset, length, 1,
408 /* find a font spec that matches font spec FONT and also matches
409 (the registry of) CHARSET. */
410 static Lisp_Object gtk_find_charset_font(Lisp_Object device, Lisp_Object font,
411 Lisp_Object charset);
415 /************************************************************************/
417 /************************************************************************/
419 void syms_of_objects_gtk(void)
423 void console_type_create_objects_gtk(void)
427 CONSOLE_HAS_METHOD(gtk, initialize_color_instance);
428 CONSOLE_HAS_METHOD(gtk, print_color_instance);
429 CONSOLE_HAS_METHOD(gtk, finalize_color_instance);
430 CONSOLE_HAS_METHOD(gtk, color_instance_equal);
431 CONSOLE_HAS_METHOD(gtk, color_instance_hash);
432 CONSOLE_HAS_METHOD(gtk, color_instance_rgb_components);
433 CONSOLE_HAS_METHOD(gtk, valid_color_name_p);
435 CONSOLE_HAS_METHOD(gtk, initialize_font_instance);
436 CONSOLE_HAS_METHOD(gtk, mark_font_instance);
437 CONSOLE_HAS_METHOD(gtk, print_font_instance);
438 CONSOLE_HAS_METHOD(gtk, finalize_font_instance);
439 CONSOLE_HAS_METHOD(gtk, font_instance_truename);
440 CONSOLE_HAS_METHOD(gtk, font_instance_properties);
441 CONSOLE_HAS_METHOD(gtk, list_fonts);
443 CONSOLE_HAS_METHOD(gtk, find_charset_font);
444 CONSOLE_HAS_METHOD(gtk, font_spec_matches_charset);
448 void vars_of_objects_gtk(void)
452 /* #### BILL!!! Try to make this go away eventually */
453 /* X Specific stuff */
454 #include <X11/Xatom.h>
456 /* Unbounded, for sufficiently small values of infinity... */
457 #define MAX_FONT_COUNT 5000
460 /* find a font spec that matches font spec FONT and also matches
461 (the registry of) CHARSET. */
463 gtk_find_charset_font(Lisp_Object device, Lisp_Object font, Lisp_Object charset)
467 Lisp_Object result = Qnil;
468 const char *patternext;
471 TO_EXTERNAL_FORMAT(LISP_STRING, font, C_STRING_ALLOCA, patternext,
474 names = XListFonts(GDK_DISPLAY(), patternext, MAX_FONT_COUNT, &count);
475 /* ### This code seems awfully bogus -- mrb */
476 for (i = 0; i < count; i++) {
477 const Bufbyte *intname;
480 TO_INTERNAL_FORMAT(C_STRING, names[i], ALLOCA,
481 (intname, intlen), Qctext);
482 if (gtk_font_spec_matches_charset
483 (XDEVICE(device), charset, intname, Qnil, 0, -1)) {
484 result = make_string((char *)intname, intlen);
490 XFreeFontNames(names);
492 /* Check for a short font name. */
494 && gtk_font_spec_matches_charset(XDEVICE(device), charset, 0,
502 /* Unbounded, for sufficiently small values of infinity... */
503 #define MAX_FONT_COUNT 5000
505 static int valid_font_name_p(Display * dpy, char *name)
507 /* Maybe this should be implemented by callign XLoadFont and trapping
508 the error. That would be a lot of work, and wasteful as hell, but
509 might be more correct.
515 names = XListFonts(dpy, name, 1, &nnames);
517 XFreeFontNames(names);
518 return (nnames != 0);
521 Lisp_Object __get_gtk_font_truename(GdkFont * gdk_font, int expandp)
523 Display *dpy = GDK_FONT_XDISPLAY(gdk_font);
524 GSList *names = ((GdkFontPrivate *) gdk_font)->names;
525 Lisp_Object font_name = Qnil;
529 if (valid_font_name_p(dpy, names->data)) {
531 /* They want the wildcarded version */
532 font_name = build_string(names->data);
534 /* Need to expand out */
536 char **x_font_names = 0;
539 XListFonts(dpy, names->data, 1,
543 build_string(x_font_names
545 XFreeFontNames(x_font_names);
556 static Lisp_Object __gtk_list_fonts_internal(const char *pattern)
560 Lisp_Object result = Qnil;
562 names = XListFonts(GDK_DISPLAY(), pattern, MAX_FONT_COUNT, &count);
564 result = Fcons(build_ext_string(names[count], Qbinary), result);
566 XFreeFontNames(names);