1 /*--------------------------------*-C-*---------------------------------*;
3 *----------------------------------------------------------------------*
4 * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *---------------------------------------------------------------------*/
22 #include "../config.h"
24 #include "defaultfont.h"
28 #define DISPLAY r->display->display
29 #define GC r->TermWin.gc
31 const struct rxvt_fallback_font {
34 } fallback_fonts[] = {
35 { CS_ISO8859_1, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-1" },
36 { CS_ISO8859_15, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-15" },
37 { CS_ISO8859_15, "-*-*-*-r-*--*-*-*-*-c-*-fcd8859-15" },
41 { CS_KOI8_R, "-*-*-*-r-*--*-*-*-*-c-*-koi8-r" },
42 { CS_KOI8_U, "-*-*-*-r-*--*-*-*-*-c-*-koi8-u" },
44 { CS_ISO8859_2, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-2" },
45 { CS_ISO8859_3, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-3" },
46 { CS_ISO8859_4, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-4" },
47 { CS_ISO8859_5, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-5" },
48 { CS_ISO8859_6, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-6" },
49 { CS_ISO8859_7, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-7" },
50 { CS_ISO8859_8, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-8" },
51 { CS_ISO8859_9, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-9" },
52 { CS_ISO8859_10, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-10" },
53 { CS_ISO8859_11, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-11" },
54 { CS_ISO8859_13, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-13" },
55 { CS_ISO8859_14, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-14" },
56 { CS_ISO8859_16, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-16" },
60 #if ENCODING_JP || ENCODING_JP_EXT
62 // prefer xft for complex scripts
63 { CS_UNICODE, "xft:Kochi Gothic:antialias=false" },
65 { CS_JIS0201_1976_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0201*-0" },
66 { CS_JIS0208_1983_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0208*-0" },
67 { CS_JIS0212_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0212*-0" },
70 #if ENCODING_CN || ENCODING_CN_EXT
72 { CS_BIG5_EXT, "xft:AR PL Mingti2L Big5" },
73 { CS_BIG5_EXT, "xft:AR PL KaitiM Big5" },
74 { CS_GB2312_1980_0, "xft:AR PL KaitiM GB" },
75 { CS_GB2312_1980_0, "xft:AR PL SungtiL GB" },
77 { CS_BIG5_EXT, "-*-*-*-*-*-*-*-*-*-*-c-*-big5*-0" },
78 { CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-gb2312*-0" },
79 { CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-1" },
80 { CS_CNS11643_1992_2, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-2" },
81 { CS_CNS11643_1992_3, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-3" },
82 { CS_CNS11643_1992_4, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-4" },
83 { CS_CNS11643_1992_5, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-5" },
84 { CS_CNS11643_1992_6, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-6" },
85 { CS_CNS11643_1992_7, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-7" },
86 { CS_CNS11643_1992_F, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-f" },
90 { CS_UNICODE, "xft:Andale Mono" },
91 { CS_UNICODE, "xft:Arial Unicode MS" },
93 { CS_UNICODE, "-*-lucidatypewriter-*-*-*-*-*-*-*-*-m-*-iso10646-1" },
94 { CS_UNICODE, "xft:FreeMono" },
95 { CS_UNICODE, "-*-unifont-*-*-*-*-*-*-*-*-c-*-iso10646-1" },
96 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-c-*-iso10646-1" },
97 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" },
102 /////////////////////////////////////////////////////////////////////////////
105 rxvt_drawable::~rxvt_drawable ()
108 XftDrawDestroy (xftdrawable);
111 rxvt_drawable::operator XftDraw *()
114 xftdrawable = XftDrawCreate (display->display, drawable, display->visual, display->cmap);
120 /////////////////////////////////////////////////////////////////////////////
122 static void *enc_buf;
123 static uint32_t enc_len;
126 get_enc_buf (uint32_t len)
131 enc_buf = malloc (len);
138 enc_char (const text_t *text, uint32_t len, codeset cs, bool &zero)
140 uint8_t *buf = (uint8_t *)get_enc_buf (len);
144 uint32_t c = FROM_UNICODE (cs, *text++);
155 return (const char *)enc_buf;
158 static const XChar2b *
159 enc_xchar2b (const text_t *text, uint32_t len, codeset cs, bool &zero)
161 XChar2b *buf = (XChar2b *)get_enc_buf (len * sizeof (XChar2b));
165 uint32_t c = FROM_UNICODE (cs, *text++);
178 return (XChar2b *)enc_buf;
181 /////////////////////////////////////////////////////////////////////////////
184 rxvt_font::clear_rect (rxvt_drawable &d, int x, int y, int w, int h, int color)
186 if (color == Color_bg)
187 XClearArea (d.display->display, d, x, y, w, h, FALSE);
191 XftDrawRect (d, &r->PixColors[color].c, x, y, w, h);
193 XSetForeground (d.display->display, GC, r->PixColors[color]);
194 XFillRectangle (d.display->display, d, GC, x, y, w, h);
199 static const char *linedraw_cmds[128] = {
200 "1hH", "2hH", "1vV", "2vV",
203 "1HV", "2H1V", "1H2V", "2HV",
206 "1hV", "2h1V", "1h2V", "2hV",
207 "1Hv", "2H1v", "1H2v", "2Hv",
208 "1hv", "2h1v", "1h2v", "2hv",
209 "1HvV", "2H1vV", "1HV2v", "1Hv2V",
212 "1H2vV", "2Hv1V", "2HV1v", "2HvV",
213 "1hvV", "2h1vV", "1hV2v", "1hv2V",
214 "1h2vV", "2hv1V", "1v2hV", "2hvV",
215 "1hHV", "2h1HV", "2H1hV", "2hH1V",
218 "1hH2V", "2hV1H", "1h2HV", "2hHV",
219 "1hHv", "1vH2h", "1hv2H", "1v2hH",
220 "1hH2v", "1H2hv", "1h2Hv", "2hHv",
221 "1hHvV", "1vVH2h", "1hvV2H", "1vV2hH",
224 "1hHV2v", "1hHv2V", "1hH2vV", "1HV2hv",
225 "1hV2Hv", "1Hv2hV", "1hv2HV", "1V2hHv",
226 "1v2hHV", "1H2hvV", "1h2HvV", "2hHvV",
242 0, "1a", "1b", "1ab",
243 "1h", "1v", "1H", "1V",
244 "2h", "2v", "2H", "2V",
245 "1h2H", "1v2V", "1H2h", "1V2v"
250 struct rxvt_font_default : rxvt_font {
251 rxvt_fontprop properties ()
255 p.width = p.height = 1;
256 p.weight = rxvt_fontprop::medium;
257 p.slant = rxvt_fontprop::roman;
262 bool load (const rxvt_fontprop &prop)
264 width = 1; height = 1;
265 ascent = 1; descent = 0;
270 bool has_codepoint (uint32_t unicode)
272 if (unicode <= 0x001f)
274 if (unicode >= 0x0080 && unicode <= 0x009f)
277 if (unicode >= 0x2500 && unicode <= 0x257f
278 && linedraw_cmds[unicode - 0x2500])
283 case ZERO_WIDTH_CHAR:
290 void draw (rxvt_drawable &d, int x, int y,
291 const text_t *text, int len,
296 rxvt_font_default::draw (rxvt_drawable &d, int x, int y,
297 const text_t *text, int len,
300 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
302 XSetForeground (d.display->display, GC, r->PixColors[fg]);
308 // is it in our linedrawing table?
309 if (t >= 0x2500 & t <= 0x2580 && linedraw_cmds[t - 0x2500])
311 const char *p = linedraw_cmds[t - 0x2500];
313 int x0 = x, x1 = x + r->TermWin.fwidth / 2, x2 = x + r->TermWin.fwidth - 1;
314 int y0 = y, y1 = y + r->TermWin.fheight / 2, y2 = y + r->TermWin.fheight - 1;
324 XChangeGC (d.display->display, GC, GCLineWidth, &gcv);
329 XChangeGC (d.display->display, GC, GCLineWidth, &gcv);
332 case 'h': XDrawLine (d.display->display, d, GC, x0, y1, x1, y1); break;
333 case 'H': XDrawLine (d.display->display, d, GC, x1, y1, x2, y1); break;
334 case 'v': XDrawLine (d.display->display, d, GC, x1, y0, x1, y1); break;
335 case 'V': XDrawLine (d.display->display, d, GC, x1, y1, x1, y2); break;
336 case 'a': XDrawLine (d.display->display, d, GC, x0, y2, x2, y0); break;
337 case 'b': XDrawLine (d.display->display, d, GC, x0, y0, x2, y2); break;
342 XChangeGC (d.display->display, GC, GCLineWidth, &gcv);
347 case ZERO_WIDTH_CHAR:
351 while (len > 0 && *text == NOCHAR)
355 w += r->TermWin.fwidth;
358 XDrawRectangle (d.display->display, d, GC, x + 2, y + 2,
359 w + r->TermWin.fwidth - 5, r->TermWin.fheight - 5);
363 x += r->TermWin.fwidth;
367 /////////////////////////////////////////////////////////////////////////////
369 struct rxvt_font_x11 : rxvt_font {
370 rxvt_font_x11 () { f = 0; }
374 rxvt_fontprop properties ();
376 bool load (const rxvt_fontprop &prop);
378 bool has_codepoint (uint32_t unicode);
380 void draw (rxvt_drawable &d, int x, int y,
381 const text_t *text, int len,
388 const char *get_property (XFontStruct *f, const char *property, const char *repl) const;
389 bool set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth);
390 bool set_properties (rxvt_fontprop &p, XFontStruct *f);
391 bool set_properties (rxvt_fontprop &p, const char *name);
395 rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const
399 if (XGetFontProperty (f, XInternAtom (DISPLAY, property, 0), &value))
400 return XGetAtomName (DISPLAY, value);
406 rxvt_font_x11::properties ()
409 set_properties (p, f);
414 rxvt_font_x11::set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth)
416 p.width = avgwidth ? (avgwidth + 1) / 10 : (height + 1) / 2;
418 p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium;
419 p.slant = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic;
425 rxvt_font_x11::set_properties (rxvt_fontprop &p, XFontStruct *f)
427 const char *weight = get_property (f, "WEIGHT_NAME", "medium");
428 const char *slant = get_property (f, "SLANT", "r");
430 unsigned long height;
431 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
434 unsigned long avgwidth;
435 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth))
438 return set_properties (p, height, weight, slant, avgwidth);
442 rxvt_font_x11::set_properties (rxvt_fontprop &p, const char *name)
445 const char *comp[12];
447 for (const char *c = name; *c; c++)
450 comp[slashes++] = c + 1;
455 /* can we short-circuit the costly XLoadQueryFont? */
457 && (*comp[ 6] >= '1' && *comp[ 6] <= '9')
458 && (*comp[11] >= '0' && *comp[11] <= '9'))
459 return set_properties (p, atoi (comp[6]), comp[2], comp[3], atoi (comp[11]));
461 XFontStruct *f = XLoadQueryFont (DISPLAY, name);
465 // the font should really exist now. if not, we have a problem
466 // (e.g. if the user did xset fp rehash just when we were searching fonts).
467 // in that case, just return garbage.
468 bool ret = set_properties (p, f);
469 XFreeFont (DISPLAY, f);
476 // fix the size of scalable fonts
478 fix_scalable (char *buf, const char *name, const rxvt_fontprop &prop)
483 for (const char *c = name; *c; c++)
493 if (slashes >= 13 && size[0] == '0')
495 strncpy (buf, name, size - name);
497 buf += sprintf (buf, "%d", prop.height);
498 strcpy (buf, size + 1);
505 rxvt_font_x11::load (const rxvt_fontprop &prop)
511 list = XListFonts (DISPLAY, name, 512, &count);
517 int bestdiff = 0x7fffffff;
518 for (int i = 0; i < count; i++)
522 fix_scalable (fname, list[i], prop);
524 if (!set_properties (p, fname))
527 if (p.height > prop.height) // weed out too large fonts
530 int diff = (prop.height - p.height) * 32
531 + abs (prop.weight - p.weight)
532 + abs (prop.slant - p.slant );
534 if (!name // compare against best found so far
537 set_name (strdup (fname));
542 XFreeFontNames (list);
547 f = XLoadQueryFont (DISPLAY, name);
552 const char *registry = get_property (f, "CHARSET_REGISTRY", 0);
553 const char *encoding = get_property (f, "CHARSET_ENCODING", 0);
555 if (registry && encoding)
558 snprintf (charset, 64, "%s-%s", registry, encoding);
560 cs = codeset_from_name (charset);
564 const char *charset = get_property (f, "FONT", 0);
571 if (*charset++ == '-' && !--count)
574 cs = codeset_from_name (charset);
577 if (cs == CS_UNICODE)
578 cs = CS_UNICODE_16; // X11 can have a max. of 65536 chars per font
580 encm = f->min_byte1 != 0 || f->max_byte1 != 0;
581 enc2b = encm || f->max_char_or_byte2 > 255;
584 descent = f->descent;
585 height = ascent + descent;
589 if (f->min_bounds.width == f->max_bounds.width)
590 width = f->min_bounds.width;
591 else if (f->per_char == NULL)
592 width = f->max_bounds.width;
597 int N = f->max_char_or_byte2 - f->min_char_or_byte2;
600 N += (f->max_byte1 - f->min_byte1)
601 * (f->max_char_or_byte2 - f->min_char_or_byte2 + 1);
605 if (f->per_char[N].width > width)
606 width = f->per_char[N].width;
612 if (cs == CS_UNKNOWN)
614 fprintf (stderr, "unable to deduce codeset, ignoring font '%s'\n", name);
625 rxvt_font_x11::clear ()
629 XFreeFont (DISPLAY, f);
635 rxvt_font_x11::has_codepoint (uint32_t unicode)
637 uint32_t ch = FROM_UNICODE (cs, unicode);
642 /* check wether the character exists in _this_ font. horrible. */
647 unsigned char byte1 = ch >> 8;
648 unsigned char byte2 = ch & 255;
650 if (byte1 < f->min_byte1 || byte1 > f->max_byte1
651 || byte2 < f->min_char_or_byte2 || byte2 > f->max_char_or_byte2)
657 int D = f->max_char_or_byte2 - f->min_char_or_byte2 + 1;
658 int N = (byte1 - f->min_byte1) * D + byte2 - f->min_char_or_byte2;
660 xcs = f->per_char + N;
664 if (ch < f->min_char_or_byte2 || ch > f->max_char_or_byte2)
670 xcs = f->per_char + (ch - f->min_char_or_byte2);
673 if (xcs->lbearing == 0 && xcs->rbearing == 0 && xcs->width == 0
674 && xcs->ascent == 0 && xcs->descent == 0)
681 rxvt_font_x11::draw (rxvt_drawable &d, int x, int y,
682 const text_t *text, int len,
685 // this looks like a mess /.
686 // and it is a mess /.
687 // yet we are trying to be perfect /.
688 // but the result still isn't perfect /.
690 bool slow = this->slow
691 || width != r->TermWin.fwidth
692 || height != r->TermWin.fheight;
694 int base = r->TermWin.fbase;
697 v.foreground = r->PixColors[fg];
698 v.background = r->PixColors[bg];
703 const XChar2b *xc = enc_xchar2b (text, len, cs, slow);
705 if (bg == Color_bg && !slow)
707 XChangeGC (d.display->display, GC, GCForeground | GCBackground | GCFont, &v);
708 XDrawImageString16 (d.display->display, d, GC, x, y + base, xc, len);
712 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
714 XChangeGC (d.display->display, GC, GCForeground | GCFont, &v);
720 if (xc->byte1 || xc->byte2)
721 XDrawString16 (d.display->display, d, GC, x, y + base, xc, 1);
723 x += r->TermWin.fwidth;
729 XDrawString16 (d.display->display, d, GC, x, y + base, xc, len);
734 const char *xc = enc_char (text, len, cs, slow);
736 if (bg == Color_bg && !slow)
738 XChangeGC (d.display->display, GC, GCForeground | GCBackground | GCFont, &v);
739 XDrawImageString (d.display->display, d, GC, x, y + base, xc, len);
743 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
745 XChangeGC (d.display->display, GC, GCForeground | GCFont, &v);
752 XDrawString (d.display->display, d, GC, x, y + base, xc, 1);
754 x += r->TermWin.fwidth;
760 XDrawString (d.display->display, d, GC, x, y + base, xc, len);
765 /////////////////////////////////////////////////////////////////////////////
770 //#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables
774 struct rxvt_font_xft : rxvt_font {
775 rxvt_font_xft () { f = 0; }
779 rxvt_fontprop properties ();
781 bool load (const rxvt_fontprop &prop);
783 void draw (rxvt_drawable &d, int x, int y,
784 const text_t *text, int len,
787 bool has_codepoint (uint32_t unicode);
794 rxvt_font_xft::clear ()
798 XftFontClose (DISPLAY, f);
804 rxvt_font_xft::properties ()
808 FT_Face face = XftLockFace (f);
810 p.width = width; p.height = height;
811 p.weight = face->style_flags & FT_STYLE_FLAG_BOLD ? rxvt_fontprop::bold : rxvt_fontprop::medium;
812 p.slant = face->style_flags & FT_STYLE_FLAG_ITALIC ? rxvt_fontprop::italic : rxvt_fontprop::roman;
820 rxvt_font_xft::load (const rxvt_fontprop &prop)
823 for (int i = 0; i < SWATHCOUNT; i++)
829 FcPattern *p = FcNameParse ((FcChar8 *) name);
836 if (FcPatternGet (p, FC_WEIGHT, 0, &v) != FcResultMatch)
837 FcPatternAddInteger (p, FC_WEIGHT, prop.weight);
839 if (FcPatternGet (p, FC_SLANT, 0, &v) != FcResultMatch)
840 FcPatternAddInteger (p, FC_SLANT, prop.slant);
842 #if 0 // clipping unfortunately destroys our precious double-width-characters
843 // clip width, we can't do better, or can we?
844 if (FcPatternGet (p, FC_CHAR_WIDTH, 0, &v) != FcResultMatch)
845 FcPatternAddInteger (p, FC_CHAR_WIDTH, prop.width);
848 //FcPatternAddBool (p, FC_MINSPACE, 1);
851 FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result);
853 FcPatternDestroy (p);
858 f = XftFontOpenPattern (DISPLAY, match);
862 FcPatternDestroy (match);
866 FT_Face face = XftLockFace (f);
868 slow = !FT_IS_FIXED_WIDTH (face);
877 c = 'i'; XftTextExtents8 (DISPLAY, f, &c, 1, &g1);
878 c = 'W'; XftTextExtents8 (DISPLAY, f, &c, 1, &g2);
880 if (g1.xOff != g2.xOff) // don't simply trust the font
884 ascent = (face->size->metrics.ascender + 63) >> 6;
885 descent = (-face->size->metrics.descender + 63) >> 6;
886 height = ascent + descent;
888 if (height <= prop.height || !prop.height)
893 // take smaller steps near the end
894 if (height > prop.height + 1) ftheight++;
895 if (height > prop.height + 2) ftheight++;
896 if (height > prop.height + 3) ftheight++;
898 FT_Set_Pixel_Sizes (face, 0, ftheight -= height - prop.height);
901 FT_Set_Pixel_Sizes (face, 0, ftheight = prop.height);
910 rxvt_font_xft::has_codepoint (uint32_t unicode)
912 return XftCharExists (DISPLAY, f, unicode);
916 rxvt_font_xft::draw (rxvt_drawable &d, int x, int y,
917 const text_t *text, int len,
920 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
922 if (!slow && width == r->TermWin.fwidth && 0)
924 if (sizeof (text_t) == sizeof (FcChar16))
925 XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, len);
927 XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, len);
933 if (*text != NOCHAR && *text != ' ')
935 int fwidth = r->TermWin.fwidth;
936 if (len >= 2 && text[1] == NOCHAR)
940 if (sizeof (text_t) == sizeof (FcChar16))
942 XftTextExtents16 (d.display->display, f, (const FcChar16 *)text, 1, &extents);
943 XftDrawString16 (d, &r->PixColors[fg].c, f, x + extents.x + (fwidth - extents.width) / 2,
944 y + r->TermWin.fbase, (const FcChar16 *)text, 1);
949 XftTextExtents32 (d.display->display, f, (const FcChar32 *)text, 1, &extents);
950 XftDrawString32 (d, &r->PixColors[fg].c, f, x + extents.x + (fwidth - extents.width) / 2,
951 y + r->TermWin.fbase, (const FcChar32 *)text, 1);
955 x += r->TermWin.fwidth;
963 /////////////////////////////////////////////////////////////////////////////
965 rxvt_fontset::rxvt_fontset (rxvt_t r)
971 rxvt_fontset::~rxvt_fontset ()
977 rxvt_fontset::clear ()
979 for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++)
984 base_prop.height = 0x7fffffff;
985 base_prop.weight = rxvt_fontprop::medium;
986 base_prop.slant = rxvt_fontprop::roman;
988 fallback = fallback_fonts;
992 rxvt_fontset::new_font (const char *name, codeset cs)
999 f = new rxvt_font_default;
1002 else if (!strncmp (name, "xft:", 4))
1005 f = new rxvt_font_xft;
1008 else if (!strncmp (name, "x:", 2))
1011 f = new rxvt_font_x11;
1014 f = new rxvt_font_x11;
1017 f->set_name (strdup (name));
1025 /////////////////////////////////////////////////////////////////////////////
1028 rxvt_fontset::add_fonts (const char *desc)
1037 while (*desc <= ' ') desc++;
1041 fprintf (stderr, "extra font parameters not yet supported, skipping.\n");
1043 //const char *extra = desc++; // not yet used
1045 desc = strchr (desc, ']');
1049 fprintf (stderr, "ERROR: opening '[' without closing ']' in font specification.\n");
1054 while (*desc <= ' ') desc++;
1057 end = strchr (desc, ',');
1059 end = desc + strlen (desc);
1061 if (end - desc < 511)
1063 strncpy (buf, desc, end - desc);
1064 buf[end - desc] = 0;
1066 fonts.push_back (new_font (buf, CS_UNICODE));
1076 rxvt_fontset::realize_font (int i)
1078 if (fonts[i]->loaded)
1081 fonts[i]->loaded = true;
1083 if (!fonts[i]->load (base_prop))
1085 fonts[i]->cs = CS_UNKNOWN;
1093 rxvt_fontset::populate (const char *desc)
1097 fonts.push_back (new_font (0, CS_UNICODE));
1105 // we currently need a base-font, no matter what
1106 if ((int)fonts.size () <= base_id || !realize_font (base_id))
1108 puts ("unable to load specified font (s), falling back to 'fixed'\n");
1109 add_fonts ("fixed");
1110 base_id = fonts.size () - 1;
1113 if ((int)fonts.size () <= base_id || !realize_font (base_id))
1116 base_prop = fonts[base_id]->properties ();
1122 rxvt_fontset::find_font (uint32_t unicode)
1124 for (unsigned int i = 0; i < fonts.size (); i++)
1126 rxvt_font *f = fonts[i];
1130 if (FROM_UNICODE (f->cs, unicode) == NOCHAR)
1133 if (!realize_font (i))
1137 if (f->cs != CS_UNKNOWN && f->has_codepoint (unicode))
1141 if (i == fonts.size () - 1 && fallback->name)
1143 fonts.push_back (new_font (fallback->name, fallback->cs));
1149 return 0; /* we must return SOME font */