void clear ();
rxvt_fontprop properties ();
- rxvt_fontprop properties (XFontStruct *f);
bool load (const rxvt_fontprop &prop);
bool enc2b, encm;
const char *get_property (XFontStruct *f, const char *property, const char *repl) const;
+ bool set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth);
+ bool set_properties (rxvt_fontprop &p, XFontStruct *f);
+ bool set_properties (rxvt_fontprop &p, const char *name);
};
const char *
rxvt_fontprop
rxvt_font_x11::properties ()
{
- return properties (f);
+ rxvt_fontprop p;
+ set_properties (p, f);
+ return p;
}
-rxvt_fontprop
-rxvt_font_x11::properties (XFontStruct *f)
+bool
+rxvt_font_x11::set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth)
{
- rxvt_fontprop p;
+ p.width = avgwidth ? (avgwidth + 1) / 10 : (height + 1) / 2;
+ p.height = height;
+ p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium;
+ p.slant = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic;
+ return true;
+}
+
+bool
+rxvt_font_x11::set_properties (rxvt_fontprop &p, XFontStruct *f)
+{
const char *weight = get_property (f, "WEIGHT_NAME", "medium");
const char *slant = get_property (f, "SLANT", "r");
+ unsigned long height;
+ if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
+ return false;
+
unsigned long avgwidth;
- p.width = XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth)
- ? avgwidth / 10
- : (height + 1) / 2;
- p.height = height;
- p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium;
- p.slant = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic;
+ if (!XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth))
+ avgwidth = 0;
- return p;
+ return set_properties (p, height, weight, slant, avgwidth);
+}
+
+bool
+rxvt_font_x11::set_properties (rxvt_fontprop &p, const char *name)
+{
+ int slashes = 0;
+ const char *comp[12];
+
+ for (const char *c = name; *c; c++)
+ if (*c == '-')
+ {
+ comp[slashes++] = c + 1;
+ if (slashes >= 13)
+ break;
+ }
+
+ /* can we short-circuit the costly XLoadQueryFont? */
+ if (slashes >= 13
+ && (*comp[ 6] >= '1' && *comp[ 6] <= '9')
+ && (*comp[11] >= '0' && *comp[11] <= '9'))
+ return set_properties (p, atoi (comp[6]), comp[2], comp[3], atoi (comp[11]));
+
+ XFontStruct *f = XLoadQueryFont (DISPLAY, name);
+
+ if (f)
+ {
+ // the font should really exists now. if not, we have a problem
+ // (e.g. if the user did xset fp rehash just when we were searching fonts).
+ // in that case, just return garbage.
+ bool ret = set_properties (p, f);
+ XFreeFont (DISPLAY, f);
+ return ret;
+ }
+ else
+ return false;
+}
+
+// fix the size of scalable fonts
+static void
+fix_scalable (char *buf, const char *name, const rxvt_fontprop &prop)
+{
+ int slashes = 0;
+ const char *size;
+
+ for (const char *c = name; *c; c++)
+ if (*c == '-')
+ {
+ if (slashes == 6)
+ size = c + 1;
+
+ if (++slashes >= 13)
+ break;
+ }
+
+ if (slashes >= 13 && size[0] == '0')
+ {
+ strncpy (buf, name, size - name);
+ buf += size - name;
+ buf += sprintf (buf, "%d", prop.height);
+ strcpy (buf, size + 1);
+ }
+ else
+ strcpy (buf, name);
}
bool
char **list;
int count;
- XFontStruct *info;
- list = XListFontsWithInfo (DISPLAY, name, 128, &count, &info);
+ list = XListFonts (DISPLAY, name, 512, &count);
+ set_name (0);
if (!list)
return false;
int bestdiff = 0x7fffffff;
- XFontStruct *best = 0;
for (int i = 0; i < count; i++)
{
- XFontStruct *f = info + i;
+ rxvt_fontprop p;
+ char fname[1024];
+ fix_scalable (fname, list[i], prop);
- if (f->ascent + f->descent <= prop.height) // weed out too large fonts
- {
- rxvt_fontprop p = properties (f);
- int diff = (prop.height - f->ascent + f->descent) * 32
- + abs (prop.weight - p.weight)
- + abs (prop.slant - p.slant );
+ if (!set_properties (p, fname))
+ continue;
- if (!best // compare against best found so far
- || diff < bestdiff)
- {
- best = f;
- bestdiff = diff;
- }
+ if (p.height > prop.height) // weed out too large fonts
+ continue;
+
+ int diff = (prop.height - p.height) * 32
+ + abs (prop.weight - p.weight)
+ + abs (prop.slant - p.slant );
+
+ if (!name // compare against best found so far
+ || diff < bestdiff)
+ {
+ set_name (strdup (fname));
+ bestdiff = diff;
}
}
- if (!best)
- return false;
-
- set_name (strdup (list[best - info]));
+ XFreeFontNames (list);
- XFreeFontInfo (list, info, count);
+ if (!name)
+ return false;
f = XLoadQueryFont (DISPLAY, name);
else
clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
- if (!slow && width == r->TermWin.fwidth)
+ if (!slow && width == r->TermWin.fwidth && 0)
{
if (sizeof (text_t) == sizeof (FcChar16))
XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, len);
{
if (*text != NOCHAR && *text != ' ')
{
+ XGlyphInfo extents;
if (sizeof (text_t) == sizeof (FcChar16))
- XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, 1);
+ {
+ XftTextExtents16 (DISPLAY, f, (const FcChar16 *)text, 1, &extents);
+ XftDrawString16 (d, &r->PixColors[fg].c, f, x + extents.x + (r->TermWin.fwidth - extents.width) / 2,
+ y + r->TermWin.fbase, (const FcChar16 *)text, 1);
+ }
else
- XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, 1);
+ {
+ XGlyphInfo extents;
+ XftTextExtents32 (DISPLAY, f, (const FcChar32 *)text, 1, &extents);
+ XftDrawString32 (d, &r->PixColors[fg].c, f, x + extents.x + (r->TermWin.fwidth - extents.width) / 2,
+ y + r->TermWin.fbase, (const FcChar32 *)text, 1);
+ }
}
x += r->TermWin.fwidth;
/*--------------------------------*-C-*--------------------------------------*
* File: screen.c
*---------------------------------------------------------------------------*
- * $Id: screen.C,v 1.13 2003-12-24 09:22:29 pcg Exp $
+ * $Id: screen.C,v 1.14 2003-12-26 07:42:23 pcg Exp $
*
* Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com>
*
}
rend_t rend = SET_FONT (R->rstyle, R->TermWin.fontset->find_font (c));
+ // rely on wcwidth to tell us the character width, at least for non-ascii
+ int width = c <= 128 ? 1 : wcwidth (c);
- stp[R->screen.cur.col] = c;
- srp[R->screen.cur.col] = rend;
-
- if (c > 255)
+ // width 0 characters (e.g. combining chars) are ignored. your problem, really
+ while (width-- > 0)
{
- // rely on wcwidth to tell us the character width, at least for non iso-8859-1
- int width = wcwidth (c);
-
- if (width > 1)
- {
- while (--width > 0 && R->screen.cur.col < last_col - 1)
- {
+ stp[R->screen.cur.col] = c;
+ srp[R->screen.cur.col] = rend;
- srp[R->screen.cur.col] |= RS_wide;
-
- R->screen.cur.col++;
- stp[R->screen.cur.col] = NOCHAR;
- srp[R->screen.cur.col] = rend;
- }
+ if (R->screen.cur.col < last_col - 1)
+ R->screen.cur.col++;
+ else
+ {
+ R->screen.tlen[row] = last_col;
+ if (R->screen.flags & Screen_Autowrap)
+ R->screen.flags |= Screen_WrapNext;
+ break;
}
- }
- if (R->screen.cur.col < last_col - 1)
- R->screen.cur.col++;
- else {
- R->screen.tlen[row] = last_col;
- if (R->screen.flags & Screen_Autowrap)
- R->screen.flags |= Screen_WrapNext;
- }
+ c = NOCHAR;
+ }
}
if (R->screen.tlen[row] != -1) /* XXX: think about this */
MAX_IT(R->screen.tlen[row], R->screen.cur.col);