summaryrefslogtreecommitdiff
path: root/grid.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:49:22 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:49:22 +0000
commit7c4135cb4b16908b54a07ee14a7ef03727102c78 (patch)
treed941faa69a7da1ac3eff60f02f35e770aad60b73 /grid.c
parent961d4493f519b5b093581e111997f894b1675d48 (diff)
Diffstat (limited to 'grid.c')
-rw-r--r--grid.c619
1 files changed, 533 insertions, 86 deletions
diff --git a/grid.c b/grid.c
index 7d41f3d..f2125c1 100644
--- a/grid.c
+++ b/grid.c
@@ -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);