diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:49:22 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:49:22 +0000 |
commit | 7c4135cb4b16908b54a07ee14a7ef03727102c78 (patch) | |
tree | d941faa69a7da1ac3eff60f02f35e770aad60b73 | |
parent | 961d4493f519b5b093581e111997f894b1675d48 (diff) |
XFree86 4.3.0.1xf86-4_3_0_1PRE_xf86-4_3_0_1
-rw-r--r-- | Xfd.ad | 15 | ||||
-rw-r--r-- | grid.c | 619 | ||||
-rw-r--r-- | grid.h | 28 | ||||
-rw-r--r-- | gridP.h | 45 | ||||
-rw-r--r-- | xfd.c | 269 | ||||
-rw-r--r-- | xfd.man | 7 |
6 files changed, 802 insertions, 181 deletions
@@ -1,12 +1,19 @@ ! $Xorg: Xfd.ad,v 1.3 2000/08/17 19:54:18 cpqbld Exp $ + + + +! $XFree86: xc/programs/xfd/Xfd.ad,v 1.3 2002/07/23 01:45:41 tsi Exp $ + *internalBorderWidth: 0 *showGrip: false *grid.borderWidth: 0 *quit.Label: Quit -*prev.Label: Prev Page -*next.Label: Next Page +*prev.Label: Prev +*next.Label: Next +*prev16.Label: -16 +*next16.Label: +16 *select.Label: Select a character *metrics.Label: @@ -17,10 +24,14 @@ *quit.Translations: #override \ <Btn1Down>,<Btn1Up>: Quit() unset() +*next16.Translations: #override \ + <Btn1Down>,<Btn1Up>: Next16() unset() *next.Translations: #override \ <Btn1Down>,<Btn1Up>: Next() unset() *prev.Translations: #override \ <Btn1Down>,<Btn1Up>: Prev() unset() +*prev16.Translations: #override \ + <Btn1Down>,<Btn1Up>: Prev16() unset() *Translations: #override \n\ <Key>q: Quit()\n\ @@ -26,6 +26,7 @@ in this Software without prior written authorization from The Open Group. * * * Author: Jim Fulton, MIT X Consortium */ +/* $XFree86: xc/programs/xfd/grid.c,v 1.9 2002/07/06 00:46:42 keithp Exp $ */ #include <X11/IntrinsicP.h> @@ -47,10 +48,21 @@ in this Software without prior written authorization from The Open Group. #define Bell(w,n) XBell(XtDisplay(w), 0) #endif - -static void ClassInitialize(), Initialize(), Realize(), Redisplay(), Notify(); -static void Destroy(), Resize(), paint_grid(); -static Boolean SetValues(); +static GC get_gc(FontGridWidget fgw, Pixel fore); +static void ClassInitialize(void); +static void Initialize(Widget request, Widget new, ArgList args, + Cardinal *num_args); +static void Realize(Widget gw, Mask *valueMask, + XSetWindowAttributes *attributes); +static void Destroy(Widget gw); +static void Resize(Widget gw); +static void Redisplay(Widget gw, XEvent *event, Region region); +static void paint_grid(FontGridWidget fgw, int col, int row, + int ncols, int nrows); +static Boolean SetValues(Widget current, Widget request, Widget new, + ArgList args, Cardinal *num_args); +static void Notify(Widget gw, XEvent *event, String *params, + Cardinal *nparams); #define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field) @@ -65,10 +77,12 @@ static XtResource resources[] = { Offset(cell_width), XtRImmediate, (XtPointer) 0 }, { XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int), Offset(cell_height), XtRImmediate, (XtPointer) 0 }, - { XtNstartChar, XtCStartChar, XtRDimension, sizeof(Dimension), - Offset(start_char), XtRImmediate, (XtPointer) 0xffff }, + { XtNstartChar, XtCStartChar, XtRLong, sizeof(long), + Offset(start_char), XtRImmediate, (XtPointer) 0xffffffff }, +#ifndef XRENDER { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground }, +#endif { XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean), Offset(center_chars), XtRImmediate, (XtPointer) FALSE }, { XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean), @@ -81,6 +95,12 @@ static XtResource resources[] = { Offset(internal_pad), XtRImmediate, (XtPointer) 4 }, { XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int), Offset(grid_width), XtRImmediate, (XtPointer) 1 }, +#ifdef XRENDER + {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor), + Offset(fg_color), XtRString, XtDefaultForeground}, + {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *), + Offset (text_face), XtRString, 0}, +#endif }; #undef Offset @@ -135,34 +155,193 @@ FontGridClassRec fontgridClassRec = { WidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec; +long +GridFirstChar (Widget w) +{ + FontGridWidget fgw = (FontGridWidget) w; + XFontStruct *fs = fgw->fontgrid.text_font; +#ifdef XRENDER + XftFont *xft = fgw->fontgrid.text_face; + if (xft) + { + FcChar32 map[FC_CHARSET_MAP_SIZE]; + FcChar32 next; + FcChar32 first; + int i; + + first = FcCharSetFirstPage (xft->charset, map, &next); + for (i = 0; i < FC_CHARSET_MAP_SIZE; i++) + if (map[i]) + { + FcChar32 bits = map[i]; + first += i * 32; + while (!(bits & 0x1)) + { + bits >>= 1; + first++; + } + break; + } + return first; + } + else +#endif + if (fs) + { + return (fs->min_byte1 << 8) | (fs->min_char_or_byte2); + } + else + return 0; +} + +long +GridLastChar (Widget w) +{ + FontGridWidget fgw = (FontGridWidget) w; + XFontStruct *fs = fgw->fontgrid.text_font; +#ifdef XRENDER + XftFont *xft = fgw->fontgrid.text_face; + if (xft) + { + FcChar32 this, last, next; + FcChar32 map[FC_CHARSET_MAP_SIZE]; + int i; + last = FcCharSetFirstPage (xft->charset, map, &next); + while ((this = FcCharSetNextPage (xft->charset, map, &next)) != FC_CHARSET_DONE) + last = this; + last &= ~0xff; + for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--) + if (map[i]) + { + FcChar32 bits = map[i]; + last += i * 32 + 31; + while (!(bits & 0x80000000)) + { + last--; + bits <<= 1; + } + break; + } + return (long) last; + } + else +#endif + if (fs) + { + return (fs->max_byte1 << 8) | (fs->max_char_or_byte2); + } + else + return 0; +} + +/* + * CI_GET_CHAR_INFO_1D - return the charinfo struct for the indicated 8bit + * character. If the character is in the column and exists, then return the + * appropriate metrics (note that fonts with common per-character metrics will + * return min_bounds). + */ + +#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ + (((cs)->rbearing|(cs)->lbearing| \ + (cs)->ascent|(cs)->descent) == 0)) + +#define CI_GET_CHAR_INFO_1D(fs,col,cs) \ +{ \ + cs = 0; \ + if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ + if (fs->per_char == NULL) { \ + cs = &fs->min_bounds; \ + } else { \ + cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ + } \ + if (CI_NONEXISTCHAR(cs)) \ + cs = 0; \ + } \ +} + +/* + * CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and + * column. This is used for fonts that have more than row zero. + */ +#define CI_GET_CHAR_INFO_2D(fs,row,col,cs) \ +{ \ + cs = 0; \ + if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ + col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ + if (fs->per_char == NULL) { \ + cs = &fs->min_bounds; \ + } else { \ + cs = &fs->per_char[((row - fs->min_byte1) * \ + (fs->max_char_or_byte2 - \ + fs->min_char_or_byte2 + 1)) + \ + (col - fs->min_char_or_byte2)]; \ + } \ + if (CI_NONEXISTCHAR(cs)) \ + cs = 0; \ + } \ +} + +static Boolean +GridHasChar (Widget w, long ch) +{ + FontGridWidget fgw = (FontGridWidget) w; +#ifdef XRENDER + XftFont *xft = fgw->fontgrid.text_face; + if (xft) + { + return FcCharSetHasChar (xft->charset, (FcChar32) ch); + } + else +#endif + { + XFontStruct *fs = fgw->fontgrid.text_font; + XCharStruct *cs; + + if (!fs) + return False; + if (fs->max_byte1 == 0) + { + CI_GET_CHAR_INFO_1D (fs, ch, cs); + } + else + { + unsigned int r = (ch >> 8); + unsigned int c = (ch & 0xff); + CI_GET_CHAR_INFO_2D (fs, r, c, cs); + } + return cs != 0; + } +} + /* * public routines */ -void GetFontGridCellDimensions (w, startp, ncolsp, nrowsp) - Widget w; - Dimension *startp; - int *ncolsp, *nrowsp; +void +GetFontGridCellDimensions(Widget w, long *startp, + int *ncolsp, int *nrowsp) { FontGridWidget fgw = (FontGridWidget) w; - *startp = (long)fgw->fontgrid.start_char; + *startp = fgw->fontgrid.start_char; *ncolsp = fgw->fontgrid.cell_cols; *nrowsp = fgw->fontgrid.cell_rows; } -void GetPrevNextStates (w, prevvalidp, nextvalidp) - Widget w; - Bool *prevvalidp, *nextvalidp; +void +GetPrevNextStates(Widget w, Bool *prevvalidp, Bool *nextvalidp, + Bool *prev16validp, Bool *next16validp) { FontGridWidget fgw = (FontGridWidget) w; + long minn = (long) GridFirstChar (w); + long maxn = (long) GridLastChar (w); - XFontStruct *fs = fgw->fontgrid.text_font; - long minn = (long) ((fs->min_byte1 << 0) | fs->min_char_or_byte2); - long maxn = (long) ((fs->max_byte1 << 8) | fs->max_char_or_byte2); - - *prevvalidp = ((long)fgw->fontgrid.start_char > minn); - *nextvalidp = (((long)fgw->fontgrid.start_char + + *prev16validp = (fgw->fontgrid.start_char - 0xf00 > minn); + *prevvalidp = (fgw->fontgrid.start_char > minn); + *nextvalidp = (fgw->fontgrid.start_char + + (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows) + < maxn); + *next16validp =((fgw->fontgrid.start_char + 0xf00 + (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows)) < maxn); } @@ -174,18 +353,21 @@ void GetPrevNextStates (w, prevvalidp, nextvalidp) */ -static GC get_gc (fgw, fore) - FontGridWidget fgw; - Pixel fore; +static GC +get_gc(FontGridWidget fgw, Pixel fore) { XtGCMask mask; XGCValues gcv; - mask = (GCForeground | GCBackground | GCFunction | GCFont); + mask = (GCForeground | GCBackground | GCFunction); gcv.foreground = fore; gcv.background = fgw->core.background_pixel; gcv.function = GXcopy; - gcv.font = fgw->fontgrid.text_font->fid; + if (fgw->fontgrid.text_font) + { + mask |= GCFont; + gcv.font = fgw->fontgrid.text_font->fid; + } gcv.cap_style = CapProjecting; mask |= GCCapStyle; if (fgw->fontgrid.grid_width > 0) { @@ -197,26 +379,219 @@ static GC get_gc (fgw, fore) } -static void ClassInitialize () +#ifdef XRENDER +XtConvertArgRec xftColorConvertArgs[] = { + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)}, + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), + sizeof(Colormap)} +}; + +#define donestr(type, value, tstr) \ + { \ + if (toVal->addr != NULL) { \ + if (toVal->size < sizeof(type)) { \ + toVal->size = sizeof(type); \ + XtDisplayStringConversionWarning(dpy, \ + (char*) fromVal->addr, tstr); \ + return False; \ + } \ + *(type*)(toVal->addr) = (value); \ + } \ + else { \ + static type static_val; \ + static_val = (value); \ + toVal->addr = (XPointer)&static_val; \ + } \ + toVal->size = sizeof(type); \ + return True; \ + } + +static void +XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure, + XrmValuePtr args, Cardinal *num_args) +{ + Screen *screen; + Colormap colormap; + XftColor *color; + + if (*num_args != 2) + { + XtAppErrorMsg (app, + "freeXftColor", "wrongParameters", + "XtToolkitError", + "Freeing an XftColor requires screen and colormap arguments", + (String *) NULL, (Cardinal *)NULL); + return; + } + + screen = *((Screen **) args[0].addr); + colormap = *((Colormap *) args[1].addr); + color = (XftColor *) toVal->addr; + XftColorFree (DisplayOfScreen (screen), + DefaultVisual (DisplayOfScreen (screen), + XScreenNumberOfScreen (screen)), + colormap, color); +} + +static Boolean +XmuCvtStringToXftColor(Display *dpy, + XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + char *spec; + XRenderColor renderColor; + XftColor xftColor; + Screen *screen; + Colormap colormap; + + if (*num_args != 2) + { + XtAppErrorMsg (XtDisplayToApplicationContext (dpy), + "cvtStringToXftColor", "wrongParameters", + "XtToolkitError", + "String to render color conversion needs screen and colormap arguments", + (String *) NULL, (Cardinal *)NULL); + return False; + } + + screen = *((Screen **) args[0].addr); + colormap = *((Colormap *) args[1].addr); + + spec = (char *) fromVal->addr; + if (strcasecmp (spec, XtDefaultForeground) == 0) + { + renderColor.red = 0; + renderColor.green = 0; + renderColor.blue = 0; + renderColor.alpha = 0xffff; + } + else if (strcasecmp (spec, XtDefaultBackground) == 0) + { + renderColor.red = 0xffff; + renderColor.green = 0xffff; + renderColor.blue = 0xffff; + renderColor.alpha = 0xffff; + } + else if (!XRenderParseColor (dpy, spec, &renderColor)) + return False; + if (!XftColorAllocValue (dpy, + DefaultVisual (dpy, + XScreenNumberOfScreen (screen)), + colormap, + &renderColor, + &xftColor)) + return False; + + donestr (XftColor, xftColor, XtRXftColor); +} + +static void +XmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure, + XrmValuePtr args, Cardinal *num_args) +{ + Screen *screen; + XftFont *font; + + if (*num_args != 1) + { + XtAppErrorMsg (app, + "freeXftFont", "wrongParameters", + "XtToolkitError", + "Freeing an XftFont requires screen argument", + (String *) NULL, (Cardinal *)NULL); + return; + } + + screen = *((Screen **) args[0].addr); + font = *((XftFont **) toVal->addr); + if (font) + XftFontClose (DisplayOfScreen (screen), font); +} + +static Boolean +XmuCvtStringToXftFont(Display *dpy, + XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + char *name; + XftFont *font; + Screen *screen; + + if (*num_args != 1) + { + XtAppErrorMsg (XtDisplayToApplicationContext (dpy), + "cvtStringToXftFont", "wrongParameters", + "XtToolkitError", + "String to XftFont conversion needs screen argument", + (String *) NULL, (Cardinal *)NULL); + return False; + } + + screen = *((Screen **) args[0].addr); + name = (char *) fromVal->addr; + + font = 0; + if (name) + { + font = XftFontOpenName (dpy, + XScreenNumberOfScreen (screen), + name); + if (!font) + { + XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont); + return False; + } + } + donestr (XftFont *, font, XtRXftFont); +} + +static XtConvertArgRec xftFontConvertArgs[] = { + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)}, +}; + +#endif + +static void +ClassInitialize(void) { XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0); +#ifdef XRENDER + XtSetTypeConverter (XtRString, XtRXftColor, + XmuCvtStringToXftColor, + xftColorConvertArgs, XtNumber(xftColorConvertArgs), + XtCacheByDisplay, XmuFreeXftColor); + XtSetTypeConverter (XtRString, XtRXftFont, + XmuCvtStringToXftFont, + xftFontConvertArgs, XtNumber(xftFontConvertArgs), + XtCacheByDisplay, XmuFreeXftFont); +#endif } -static void Initialize (request, new, args, num_args) - Widget request, new; - ArgList args; - Cardinal *num_args; +static void +Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args) { FontGridWidget reqfg = (FontGridWidget) request; FontGridWidget newfg = (FontGridWidget) new; XFontStruct *fs = newfg->fontgrid.text_font; +#ifdef XRENDER + XftFont *xft = newfg->fontgrid.text_face; +#endif unsigned maxn; if (reqfg->fontgrid.cell_cols <= 0) newfg->fontgrid.cell_cols = 16; if (reqfg->fontgrid.cell_rows <= 0) { +#ifdef XRENDER + if (xft) + newfg->fontgrid.cell_rows = 16; + else +#endif if (fs && fs->max_byte1 == 0) { newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 / newfg->fontgrid.cell_cols) + 1; @@ -227,9 +602,9 @@ static void Initialize (request, new, args, num_args) } if (reqfg->fontgrid.cell_width <= 0) - newfg->fontgrid.cell_width = (fs ? DefaultCellWidth (newfg) : 1); + newfg->fontgrid.cell_width = DefaultCellWidth (newfg); if (reqfg->fontgrid.cell_height <= 0) - newfg->fontgrid.cell_height = (fs ? DefaultCellHeight (newfg) : 1); + newfg->fontgrid.cell_height = DefaultCellHeight (newfg); /* give a nice size that fits one screen full */ if (newfg->core.width == 0) @@ -248,38 +623,39 @@ static void Initialize (request, new, args, num_args) * select the first character */ - if (newfg->fontgrid.start_char == 0xffff) { - newfg->fontgrid.start_char = (fs ? (unsigned)(fs->min_byte1 << 8) : 0); - } - if (fs) { - maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2); - if (newfg->fontgrid.start_char > maxn) - newfg->fontgrid.start_char = (maxn + 1 - - (newfg->fontgrid.cell_cols * - newfg->fontgrid.cell_rows)); - } + if (newfg->fontgrid.start_char == 0xffffffff) + newfg->fontgrid.start_char = GridFirstChar(new) & ~0xff; + maxn = GridLastChar (new); + if (newfg->fontgrid.start_char > maxn) + newfg->fontgrid.start_char = (maxn + 1 - + (newfg->fontgrid.cell_cols * + newfg->fontgrid.cell_rows)); } -static void Realize (gw, valueMask, attributes) - Widget gw; - Mask *valueMask; - XSetWindowAttributes *attributes; +static void +Realize(Widget gw, Mask *valueMask, XSetWindowAttributes *attributes) { FontGridWidget fgw = (FontGridWidget) gw; FontGridPart *p = &fgw->fontgrid; - p->text_gc = get_gc (fgw, p->foreground_pixel); + p->text_gc = get_gc (fgw, GridForeground (fgw)); p->box_gc = get_gc (fgw, p->box_pixel); Resize (gw); (*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes); +#ifdef XRENDER + p->draw = XftDrawCreate (XtDisplay (gw), XtWindow (gw), + DefaultVisual (XtDisplay (gw), + DefaultScreen(XtDisplay (gw))), + fgw->core.colormap); +#endif return; } -static void Destroy (gw) - Widget gw; +static void +Destroy(Widget gw) { FontGridWidget fgw = (FontGridWidget) gw; @@ -288,8 +664,8 @@ static void Destroy (gw) } -static void Resize (gw) - Widget gw; +static void +Resize(Widget gw) { FontGridWidget fgw = (FontGridWidget) gw; @@ -309,16 +685,17 @@ static void Resize (gw) /* ARGSUSED */ -static void Redisplay (gw, event, region) - Widget gw; - XEvent *event; - Region region; +static void +Redisplay(Widget gw, XEvent *event, Region region) { FontGridWidget fgw = (FontGridWidget) gw; XRectangle rect; /* bounding rect for region */ int left, right, top, bottom; /* which cells were damaged */ int cw, ch; /* cell size */ +#ifdef XRENDER + if (!fgw->fontgrid.text_face) +#endif if (!fgw->fontgrid.text_font) { Bell (gw, XkbBI_BadValue); return; @@ -339,10 +716,10 @@ static void Redisplay (gw, event, region) } -static void paint_grid (fgw, col, row, ncols, nrows) - FontGridWidget fgw; /* widget in which to draw */ - int col, row; /* where to start */ - int ncols, nrows; /* number of cells */ +static void +paint_grid(FontGridWidget fgw, /* widget in which to draw */ + int col, int row, /* where to start */ + int ncols, int nrows) /* number of cells */ { FontGridPart *p = &fgw->fontgrid; int i, j; @@ -353,8 +730,7 @@ static void paint_grid (fgw, col, row, ncols, nrows) int tcols = p->cell_cols; int trows = p->cell_rows; int x1, y1, x2, y2, x, y; - unsigned maxn = ((p->text_font->max_byte1 << 8) | - p->text_font->max_char_or_byte2); + unsigned maxn = GridLastChar ((Widget) fgw); unsigned n, prevn; int startx; @@ -384,8 +760,6 @@ static void paint_grid (fgw, col, row, ncols, nrows) XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); } } - - /* * Draw a character in every box; treat all fonts as if they were 16bit * fonts. Store the high eight bits in byte1 and the low eight bits in @@ -394,15 +768,45 @@ static void paint_grid (fgw, col, row, ncols, nrows) prevn = p->start_char + col + row * tcols; startx = col * cw + p->internal_pad + p->grid_width; for (j = 0, - y = row * ch + p->internal_pad + p->grid_width + p->text_font->ascent; + y = row * ch + p->internal_pad + p->grid_width + GridFontAscent (fgw); j < nrows; j++, y += ch) { n = prevn; for (i = 0, x = startx; i < ncols; i++, x += cw) { - XChar2b thechar; int xoff = p->xoff, yoff = p->yoff; - if (n > maxn) goto done; /* no break out of nested */ +#ifdef XRENDER + if (fgw->fontgrid.text_face) + { + XftFont *xft = p->text_face; + FcChar32 c = n; + XGlyphInfo extents; + XftTextExtents32 (dpy, xft, &c, 1, &extents); + if (p->center_chars) + { + xoff = (p->cell_width - extents.width) / 2 - extents.x; + yoff = (p->cell_height - extents.height) / 2 - extents.y; + } + if (extents.width && extents.height) + { + XClearArea (dpy, wind, x + xoff - extents.x, + y + yoff - extents.y, + extents.width, extents.height, False); + if (p->box_chars) + XDrawRectangle (dpy, wind, p->box_gc, + x + xoff - extents.x, + y + yoff - extents.y, + extents.width - 1, + extents.height - 1); + } + XftDrawString32 (p->draw, &p->fg_color, xft, + x + xoff, y + yoff, &c, 1); + } + else +#endif + { + XChar2b thechar; + thechar.byte1 = (n >> 8); /* high eight bits */ thechar.byte2 = (n & 255); /* low eight bits */ if (p->box_chars || p->center_chars) { @@ -436,20 +840,50 @@ static void paint_grid (fgw, col, row, ncols, nrows) } XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff, &thechar, 1); + } n++; } prevn += tcols; } done: + /* + * paint the grid lines for the indicated rows + */ + if (p->grid_width > 0) { + int half_grid_width = p->grid_width >> 1; + x1 = col * cw + half_grid_width; + y1 = row * ch + half_grid_width; + x2 = x1 + ncols * cw; + y2 = y1 + nrows * ch; + for (i = 0, x = x1; i <= ncols; i++, x += cw) { + XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2); + } + for (i = 0, y = y1; i <= nrows; i++, y += ch) { + XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); + } + } + + return; } +static Boolean +PageBlank (Widget w, long first, long last) +{ + while (first <= last) + { + if (GridHasChar (w, first)) + return False; + first++; + } + return True; +} + /*ARGSUSED*/ -static Boolean SetValues (current, request, new, args, num_args) - Widget current, request, new; - ArgList args; - Cardinal *num_args; +static Boolean +SetValues(Widget current, Widget request, Widget new, + ArgList args, Cardinal *num_args) { FontGridWidget curfg = (FontGridWidget) current; FontGridWidget newfg = (FontGridWidget) new; @@ -462,10 +896,9 @@ static Boolean SetValues (current, request, new, args, num_args) redisplay = TRUE; } - if (curfg->fontgrid.foreground_pixel != newfg->fontgrid.foreground_pixel) { + if (GridForeground(curfg) != GridForeground (newfg)) { XtReleaseGC (new, curfg->fontgrid.text_gc); - newfg->fontgrid.text_gc = get_gc (newfg, - newfg->fontgrid.foreground_pixel); + newfg->fontgrid.text_gc = get_gc (newfg, GridForeground (newfg)); redisplay = TRUE; } @@ -480,14 +913,29 @@ static Boolean SetValues (current, request, new, args, num_args) redisplay = TRUE; if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) { - XFontStruct *fs = newfg->fontgrid.text_font; - unsigned maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2); + long maxn = GridLastChar (new); + long page = newfg->fontgrid.cell_cols * newfg->fontgrid.cell_rows; + long dir = page; + long start = newfg->fontgrid.start_char; + + if (start < curfg->fontgrid.start_char) + dir = -page; + + if (start < 0) + start = 0; + if (start > maxn) + start = (maxn / page) * page; + + while (PageBlank (new, start, start + page - 1)) + { + long next = start + dir; - if (newfg->fontgrid.start_char > maxn) - newfg->fontgrid.start_char = (maxn + 1 - - (newfg->fontgrid.cell_cols * - newfg->fontgrid.cell_rows)); + if (next < 0 || maxn < next) + break; + start = next; + } + newfg->fontgrid.start_char = start; redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char); } @@ -496,11 +944,8 @@ static Boolean SetValues (current, request, new, args, num_args) /* ARGSUSED */ -static void Notify (gw, event, params, nparams) - Widget gw; - XEvent *event; - String *params; - Cardinal *nparams; +static void +Notify(Widget gw, XEvent *event, String *params, Cardinal *nparams) { FontGridWidget fgw = (FontGridWidget) gw; int x, y; /* where the event happened */ @@ -546,8 +991,10 @@ static void Notify (gw, event, params, nparams) ((y / ch) * fgw->fontgrid.cell_cols) + (x / cw)); rec.thefont = fgw->fontgrid.text_font; - rec.thechar.byte1 = (n >> 8); - rec.thechar.byte2 = (n & 255); +#ifdef XRENDER + rec.theface = fgw->fontgrid.text_face; +#endif + rec.thechar = n; } XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec); @@ -26,10 +26,16 @@ other dealings in this Software without prior written authorization from The Open Group. */ +/* $XFree86: xc/programs/xfd/grid.h,v 1.4 2002/07/23 01:45:41 tsi Exp $ */ #ifndef _FontGrid_h_ #define _FontGrid_h_ +#ifdef XRENDER +#include <X11/Xft/Xft.h> +#include <X11/extensions/Xrender.h> +#endif + typedef struct _FontGridRec *FontGridWidget; extern WidgetClass fontgridWidgetClass; @@ -60,15 +66,24 @@ extern WidgetClass fontgridWidgetClass; #define XtNgridWidth "gridWidth" #define XtCGridWidth "GridWidth" +#define XtRXftColor "XftColor" + +#define XtNface "face" +#define XtCFace "Face" +#define XtRXftFont "XftFont" + typedef struct _FontGridCharRec { +#ifdef XRENDER + XftFont * theface; +#endif XFontStruct * thefont; - XChar2b thechar; + long thechar; } FontGridCharRec; extern void GetFontGridCellDimensions( #if NeedFunctionPrototypes Widget, - Dimension *, + long *, int *, int * #endif @@ -78,8 +93,17 @@ extern void GetPrevNextStates( #if NeedFunctionPrototypes Widget, Bool *, + Bool *, + Bool *, Bool * #endif ); +long +GridFirstChar (Widget w); + +long +GridLastChar (Widget w); + + #endif /* _FontGrid_h_ */ @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ - +/* $XFree86: xc/programs/xfd/gridP.h,v 1.4 2002/07/23 01:45:41 tsi Exp $ */ #ifndef _FontGridP_h_ #define _FontGridP_h_ @@ -46,18 +46,25 @@ typedef struct _FontGridPart { XFontStruct * text_font; /* font to display */ int cell_cols, cell_rows; /* number of cells */ int cell_width, cell_height; /* size of cell */ +#ifndef XRENDER Pixel foreground_pixel; /* color of text */ +#endif Pixel box_pixel; /* for box_chars */ Boolean center_chars; /* center characters in grid */ Boolean box_chars; /* put box around logical width */ XtCallbackList callbacks; /* for notifying caller */ int internal_pad; /* extra padding inside grid */ - Dimension start_char; /* first character of grid */ + long start_char; /* first character of grid */ int grid_width; /* width of grid lines */ /* private data */ GC text_gc; /* printing text */ GC box_gc; /* for box_chars */ int xoff, yoff; /* extra offsets within grid */ +#ifdef XRENDER + XftDraw *draw; + XftColor fg_color; + XftFont *text_face; +#endif } FontGridPart; typedef struct _FontGridRec { @@ -66,13 +73,39 @@ typedef struct _FontGridRec { FontGridPart fontgrid; } FontGridRec; -#define DefaultCellWidth(fgw) (((fgw)->fontgrid.text_font->max_bounds.width) \ +#ifdef XRENDER + +#define GridFontHeight(g) ((g)->fontgrid.text_face ? \ + (g)->fontgrid.text_face->height : \ + (g)->fontgrid.text_font ? \ + (g)->fontgrid.text_font->ascent + \ + (g)->fontgrid.text_font->descent : 1) +#define GridFontAscent(g) ((g)->fontgrid.text_face ? \ + (g)->fontgrid.text_face->ascent : \ + (g)->fontgrid.text_font ? \ + (g)->fontgrid.text_font->ascent: 1) +#define GridFontWidth(g) ((g)->fontgrid.text_face ? \ + (g)->fontgrid.text_face->max_advance_width : \ + (g)->fontgrid.text_font ? \ + (g)->fontgrid.text_font->max_bounds.width : 1) +#define GridForeground(g) ((g)->fontgrid.fg_color.pixel) + +#else /* XRENDER */ + +#define GridFontHeight(g) ((g)->fontgrid.text_font->ascent + \ + (g)->fontgrid.text_font->descent) +#define GridFontAscent(g) ((g)->fontgrid.text_font ? \ + (g)->fontgrid.text_font->ascent: 1) +#define GridFontWidth(g) ((g)->fontgrid.text_font->max_bounds.width) +#define GridForeground(g) ((g)->fontgrid.foreground_pixel) + +#endif /* else XRENDER */ + +#define DefaultCellWidth(fgw) (GridFontWidth(fgw) \ + ((fgw)->fontgrid.internal_pad * 2)) -#define DefaultCellHeight(fgw) ((fgw)->fontgrid.text_font->ascent + \ - (fgw)->fontgrid.text_font->descent + \ +#define DefaultCellHeight(fgw) (GridFontHeight(fgw) + \ ((fgw)->fontgrid.internal_pad * 2)) - #define CellWidth(fgw) (((int)(fgw)->core.width - (fgw)->fontgrid.grid_width) \ / (fgw)->fontgrid.cell_cols \ - (fgw)->fontgrid.grid_width) @@ -26,6 +26,7 @@ in this Software without prior written authorization from The Open Group. * * * Author: Jim Fulton, MIT X Consortium */ +/* $XFree86: xc/programs/xfd/xfd.c,v 1.8 2003/02/20 02:56:40 dawes Exp $ */ #include <X11/Intrinsic.h> #include <X11/StringDefs.h> @@ -38,12 +39,20 @@ in this Software without prior written authorization from The Open Group. #include <X11/Xaw/Form.h> #include <X11/Xaw/Command.h> #include <stdio.h> +#include <stdlib.h> #include "grid.h" +#ifdef XRENDER +#include <X11/Xft/Xft.h> +#include <X11/extensions/Xrender.h> +#endif char *ProgramName; static XrmOptionDescRec xfd_options[] = { {"-fn", "*grid.font", XrmoptionSepArg, (caddr_t) NULL }, +#ifdef XRENDER +{"-fa", "*grid.face", XrmoptionSepArg, (caddr_t) NULL }, +#endif {"-start", "*startChar", XrmoptionSepArg, (caddr_t) NULL }, {"-box", "*grid.boxChars", XrmoptionNoArg, (caddr_t) "on" }, {"-bc", "*grid.boxColor", XrmoptionSepArg, (caddr_t) NULL }, @@ -52,27 +61,43 @@ static XrmOptionDescRec xfd_options[] = { {"-columns", "*grid.cellColumns", XrmoptionSepArg, (caddr_t) NULL }, }; -static void do_quit(), do_next(), do_prev(); -static void change_page (), set_button_state (); -static char *get_font_name(); -static void SelectChar(); +static void usage(void); +static void SelectChar(Widget w, XtPointer closure, XtPointer data); +static void do_quit(Widget w, XEvent *event, String *params, + Cardinal *num_params); +static void change_page(int page); +static void set_button_state(void); +static void do_prev(Widget w, XEvent *event, String *params, + Cardinal *num_params); +static void do_next(Widget w, XEvent *event, String *params, + Cardinal *num_params); +static void do_prev16(Widget w, XEvent *event, String *params, + Cardinal *num_params); +static void do_next16(Widget w, XEvent *event, String *params, + Cardinal *num_params); +static char *get_font_name(Display *dpy, XFontStruct *fs); +static void CatchFontConversionWarning(String name, String type, String class, + String defaultp, String *params, + Cardinal *np); static XtActionsRec xfd_actions[] = { { "Quit", do_quit }, + { "Prev16", do_prev16 }, { "Prev", do_prev }, { "Next", do_next }, + { "Next16", do_next16 }, }; static Atom wm_delete_window; -Widget quitButton, prevButton, nextButton; +Widget quitButton, prev16Button, prevButton, nextButton, next16Button; -#define DEF_SELECT_FORMAT "character 0x%02x%02x (%u,%u) (%#o,%#o)" +#define DEF_SELECT_FORMAT "character 0x%04x%02x (%u,%u) (%#o,%#o)" #define DEF_METRICS_FORMAT "width %d; left %d, right %d; ascent %d, descent %d (font %d, %d)" -#define DEF_RANGE_FORMAT "range: 0x%02x%02x (%u,%u) thru 0x%02x%02x (%u,%u)" -#define DEF_START_FORMAT "upper left: 0x%04x (%d,%d)" -#define DEF_NOCHAR_FORMAT "no such character 0x%02x%02x (%u,%u) (%#o,%#o)" +#define DEF_RANGE_FORMAT "range: 0x%04x%02x (%u,%u) thru 0x%04x%02x (%u,%u)" +#define DEF_START_FORMAT "upper left: 0x%06x (%d,%d)" +#define DEF_NOCHAR_FORMAT "no such character 0x%04x%02x (%u,%u) (%#o,%#o)" static struct _xfd_resources { char *select_format; @@ -99,7 +124,8 @@ static XtResource Resources[] = { #undef Offset -usage() +static void +usage(void) { fprintf (stderr, "usage: %s [-options ...] -fn font\n\n", ProgramName); fprintf (stderr, "where options include:\n"); @@ -125,12 +151,10 @@ usage() static Widget selectLabel, metricsLabel, rangeLabel, startLabel, fontGrid; static Boolean fontConversionFailed = False; -static void (*oldWarningHandler)(); -static void CatchFontConversionWarning(); +static XtErrorMsgHandler oldWarningHandler; -main (argc, argv) - int argc; - char **argv; +int +main(int argc, char *argv[]) { XtAppContext xtcontext; Widget toplevel, pane, toplabel, box, form; @@ -139,7 +163,11 @@ main (argc, argv) Cardinal i; static XtCallbackRec cb[2] = { { SelectChar, NULL }, { NULL, NULL } }; XFontStruct *fs; +#ifdef XRENDER + XftFont *xft; +#endif char *fontname; + long minn, maxn; ProgramName = argv[0]; @@ -167,10 +195,14 @@ main (argc, argv) box = XtCreateManagedWidget ("box", boxWidgetClass, pane, NULL, ZERO); quitButton = XtCreateManagedWidget ("quit", commandWidgetClass, box, NULL, ZERO); + prev16Button = XtCreateManagedWidget ("prev16", commandWidgetClass, box, + NULL, ZERO); prevButton = XtCreateManagedWidget ("prev", commandWidgetClass, box, NULL, ZERO); nextButton = XtCreateManagedWidget ("next", commandWidgetClass, box, NULL, ZERO); + next16Button = XtCreateManagedWidget ("next16", commandWidgetClass, box, + NULL, ZERO); /* and labels in which to put information */ @@ -205,26 +237,56 @@ main (argc, argv) XtAppSetWarningMsgHandler(xtcontext, oldWarningHandler); /* set the label at the top to tell us which font this is */ +#ifdef XRENDER i = 0; - XtSetArg (av[i], XtNfont, &fs); i++; + XtSetArg (av[i], XtNface, &xft); i++; XtGetValues (fontGrid, av, i); - if (!fs || fontConversionFailed) { - fprintf (stderr, "%s: no font to display\n", ProgramName); - exit (1); + if (xft) + { + FcChar8 *family; + FcChar8 *style; + FcPattern *p; + double size; + family = (FcChar8 *) ""; + FcPatternGetString (xft->pattern, FC_FAMILY, 0, &family); + style = (FcChar8 *) ""; + FcPatternGetString (xft->pattern, FC_STYLE, 0, &style); + size = 0; + FcPatternGetDouble (xft->pattern, FC_SIZE, 0, &size); + p = FcPatternBuild (0, + FC_FAMILY, FcTypeString, family, + FC_STYLE, FcTypeString, style, + FC_SIZE, FcTypeDouble, size, + NULL); + fontname = (char *) FcNameUnparse (p); + FcPatternDestroy (p); + } + else +#endif + { + i = 0; + XtSetArg (av[i], XtNfont, &fs); i++; + XtGetValues (fontGrid, av, i); + if (!fs || fontConversionFailed) { + fprintf (stderr, "%s: no font to display\n", ProgramName); + exit (1); + } + fontname = get_font_name (XtDisplay(toplevel), fs); } - fontname = get_font_name (XtDisplay(toplevel), fs); - if (!fontname) fontname = "unknown font!"; i = 0; XtSetArg (av[i], XtNlabel, fontname); i++; XtSetValues (toplabel, av, i); + minn = GridFirstChar (fontGrid); + maxn = GridLastChar (fontGrid); + sprintf (buf, xfd_resources.range_format, + minn >> 8, minn & 0xff, + minn >> 8, minn & 0xff, + maxn >> 8, maxn & 0xff, + maxn >> 8, maxn & 0xff); + i = 0; XtSetArg (av[i], XtNlabel, buf); i++; - sprintf (buf, xfd_resources.range_format, - fs->min_byte1, fs->min_char_or_byte2, - fs->min_byte1, fs->min_char_or_byte2, - fs->max_byte1, fs->max_char_or_byte2, - fs->max_byte1, fs->max_char_or_byte2); XtSetValues (rangeLabel, av, i); XtRealizeWidget (toplevel); @@ -236,70 +298,98 @@ main (argc, argv) change_page (0); XtAppMainLoop (xtcontext); + exit(0); } /*ARGSUSED*/ -static void SelectChar (w, closure, data) - Widget w; - XtPointer closure, data; +static void +SelectChar(Widget w, XtPointer closure, XtPointer data) { FontGridCharRec *p = (FontGridCharRec *) data; XFontStruct *fs = p->thefont; - unsigned n = ((((unsigned) p->thechar.byte1) << 8) | - ((unsigned) p->thechar.byte2)); + long n = p->thechar; int direction, fontascent, fontdescent; XCharStruct metrics; char buf[256]; Arg arg; + Boolean has_char = 1; XtSetArg (arg, XtNlabel, buf); - if ((!fs->min_byte1 && !fs->max_byte1) ? - (n < fs->min_char_or_byte2 || n > fs->max_char_or_byte2) : - (p->thechar.byte1 < fs->min_byte1 || p->thechar.byte1 > fs->max_byte1 || - p->thechar.byte2 < fs->min_char_or_byte2 || - p->thechar.byte2 > fs->max_char_or_byte2)) { - sprintf (buf, xfd_resources.nochar_format, - (unsigned) p->thechar.byte1, (unsigned) p->thechar.byte2, - (unsigned) p->thechar.byte1, (unsigned) p->thechar.byte2, - (unsigned) p->thechar.byte1, (unsigned) p->thechar.byte2); - XtSetValues (selectLabel, &arg, ONE); - buf[0] = '\0'; - XtSetValues (metricsLabel, &arg, ONE); - return; + buf[0] = '\0'; +#ifdef XRENDER + if (p->theface) + { + XftFont *xft = p->theface; + FcChar32 c = (FcChar32) n; + has_char = (Boolean) FcCharSetHasChar (xft->charset, n); + if (has_char) + { + XGlyphInfo extents; + XftTextExtents32 (XtDisplay (w), xft, &c, 1, &extents); + sprintf (buf, xfd_resources.metrics_format, + extents.xOff, - extents.x, + extents.xOff - extents.width + extents.x, + extents.y, extents.height - extents.y, + xft->ascent, xft->descent); + } + } + else +#endif + { + if ((!fs->min_byte1 && !fs->max_byte1) ? + (n < fs->min_char_or_byte2 || n > fs->max_char_or_byte2) : + (n >> 8 < fs->min_byte1 || n >> 8 > fs->max_byte1 || + (n & 0xff) < fs->min_char_or_byte2 || + (n & 0xff) > fs->max_char_or_byte2)) + { + has_char = 0; + } + else + { + XChar2b char2b; + char2b.byte1 = p->thechar >> 8; + char2b.byte2 = p->thechar & 0xff; + XTextExtents16 (fs, &char2b, 1, &direction, &fontascent, &fontdescent, + &metrics); + sprintf (buf, xfd_resources.metrics_format, + metrics.width, metrics.lbearing, metrics.rbearing, + metrics.ascent, metrics.descent, fontascent, fontdescent); + } } + XtSetValues (metricsLabel, &arg, ONE); - XTextExtents16 (fs, &p->thechar, 1, &direction, &fontascent, &fontdescent, - &metrics); - sprintf (buf, xfd_resources.select_format, - (unsigned) p->thechar.byte1, (unsigned) p->thechar.byte2, - (unsigned) p->thechar.byte1, (unsigned) p->thechar.byte2, - (unsigned) p->thechar.byte1, (unsigned) p->thechar.byte2); + if (has_char) + { + sprintf (buf, xfd_resources.select_format, + n >> 8, n & 0xff, + n >> 8, n & 0xff, + n >> 8, n & 0xff); + } + else + { + sprintf (buf, xfd_resources.nochar_format, + n >> 8, n & 0xff, + n >> 8, n & 0xff, + n >> 8, n & 0xff); + } XtSetValues (selectLabel, &arg, ONE); - sprintf (buf, xfd_resources.metrics_format, - metrics.width, metrics.lbearing, metrics.rbearing, - metrics.ascent, metrics.descent, fontascent, fontdescent); - XtSetValues (metricsLabel, &arg, ONE); - return; } /*ARGSUSED*/ -static void do_quit (w, event, params, num_params) - Widget w; - XEvent *event; - String *params; - Cardinal *num_params; +static void +do_quit (Widget w, XEvent *event, String *params, Cardinal *num_params) { exit (0); } -static void change_page (page) - int page; +static void +change_page(int page) { - Dimension oldstart, newstart; + long oldstart, newstart; int ncols, nrows; char buf[256]; Arg arg; @@ -335,45 +425,58 @@ static void change_page (page) } -static void set_button_state () +static void +set_button_state(void) { - Bool prevvalid, nextvalid; + Bool prevvalid, nextvalid, prev16valid, next16valid; Arg arg; - GetPrevNextStates (fontGrid, &prevvalid, &nextvalid); + GetPrevNextStates (fontGrid, &prevvalid, &nextvalid, &prev16valid, &next16valid); arg.name = XtNsensitive; arg.value = (XtArgVal) (prevvalid ? TRUE : FALSE); XtSetValues (prevButton, &arg, ONE); arg.value = (XtArgVal) (nextvalid ? TRUE : FALSE); XtSetValues (nextButton, &arg, ONE); + arg.name = XtNsensitive; + arg.value = (XtArgVal) (prev16valid ? TRUE : FALSE); + XtSetValues (prev16Button, &arg, ONE); + arg.value = (XtArgVal) (next16valid ? TRUE : FALSE); + XtSetValues (next16Button, &arg, ONE); } /* ARGSUSED */ -static void do_prev (w, event, params, num_params) - Widget w; - XEvent *event; - String *params; - Cardinal *num_params; +static void +do_prev16(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + change_page (-16); +} + + +static void +do_prev(Widget w, XEvent *event, String *params, Cardinal *num_params) { change_page (-1); } /* ARGSUSED */ -static void do_next (w, event, params, num_params) - Widget w; - XEvent *event; - String *params; - Cardinal *num_params; +static void +do_next(Widget w, XEvent *event, String *params, Cardinal *num_params) { change_page (1); } +/* ARGSUSED */ +static void +do_next16(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + change_page (16); +} + -static char *get_font_name (dpy, fs) - Display *dpy; - XFontStruct *fs; +static char * +get_font_name(Display *dpy, XFontStruct *fs) { register XFontProp *fp; register int i; @@ -388,11 +491,11 @@ static char *get_font_name (dpy, fs) } -static void CatchFontConversionWarning(name, type, class, defaultp, params, np) - String name, type, class, defaultp, *params; - Cardinal *np; +static void +CatchFontConversionWarning(String name, String type, String class, + String defaultp, String *params, Cardinal *np) { - if (np && *np > 1 & + if (np && *np > 1 && strcmp(name, "conversionError") == 0 && strcmp(type, "string") == 0 && strcmp(class, "XtToolkitError") == 0 && @@ -22,7 +22,10 @@ .\" not be used in advertising or otherwise to promote the sale, use or .\" other dealings in this Software without prior written authorization .\" from The Open Group. -.TH XFD 1 "Release 6.4" "X Version 11" +.\" +.\" $XFree86: xc/programs/xfd/xfd.man,v 1.8 2001/12/14 20:01:31 dawes Exp $ +.\" +.TH XFD 1 __xorgversion__ .SH NAME xfd \- display all the characters in an X font .SH SYNOPSIS @@ -177,7 +180,7 @@ character does not exist. The default is "no such character 0x%02x%02x (%u,%u) (%#o,%#o)". The arguments that will come after the format string are the same as for the \fBselectFormat\fP resource. .SH "SEE ALSO" -X(1), xlsfonts(1), xrdb(1), xfontsel(1), +X(__miscmansuffix__), xlsfonts(1), xrdb(1), xfontsel(1), .I "X Logical Font Description Conventions" .SH "BUGS" The program should skip over pages full of non-existent characters. |