2
* $Xorg: grid.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $
5
Copyright 1989, 1998 The Open Group
7
Permission to use, copy, modify, distribute, and sell this software and its
8
documentation for any purpose is hereby granted without fee, provided that
9
the above copyright notice appear in all copies and that both that
10
copyright notice and this permission notice appear in supporting
13
The above copyright notice and this permission notice shall be included in
14
all copies or substantial portions of the Software.
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
Except as contained in this notice, the name of The Open Group shall not be
24
used in advertising or otherwise to promote the sale, use or other dealings
25
in this Software without prior written authorization from The Open Group.
27
* Author: Jim Fulton, MIT X Consortium
29
/* $XFree86: xc/programs/xfd/grid.c,v 1.9 2002/07/06 00:46:42 keithp Exp $ */
32
#include <X11/IntrinsicP.h>
33
#include <X11/StringDefs.h>
34
#include <X11/Xaw/SimpleP.h>
35
#include <X11/Xmu/Converters.h>
39
#include <X11/extensions/XKBbells.h>
41
#define XkbBI_MinorError 2
42
#define XkbBI_Ignore 11
46
#define Bell(w,n) XkbStdBell(XtDisplay(w), XtWindow(w), 50, n)
48
#define Bell(w,n) XBell(XtDisplay(w), 0)
51
static GC get_gc(FontGridWidget fgw, Pixel fore);
52
static void ClassInitialize(void);
53
static void Initialize(Widget request, Widget new, ArgList args,
55
static void Realize(Widget gw, Mask *valueMask,
56
XSetWindowAttributes *attributes);
57
static void Destroy(Widget gw);
58
static void Resize(Widget gw);
59
static void Redisplay(Widget gw, XEvent *event, Region region);
60
static void paint_grid(FontGridWidget fgw, int col, int row,
61
int ncols, int nrows);
62
static Boolean SetValues(Widget current, Widget request, Widget new,
63
ArgList args, Cardinal *num_args);
64
static void Notify(Widget gw, XEvent *event, String *params,
67
#define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field)
69
static XtResource resources[] = {
70
{ XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
71
Offset(text_font), XtRString, (XtPointer) NULL },
72
{ XtNcellColumns, XtCCellColumns, XtRInt, sizeof(int),
73
Offset(cell_cols), XtRImmediate, (XtPointer) 0 },
74
{ XtNcellRows, XtCCellRows, XtRInt, sizeof(int),
75
Offset(cell_rows), XtRImmediate, (XtPointer) 0 },
76
{ XtNcellWidth, XtCCellWidth, XtRInt, sizeof(int),
77
Offset(cell_width), XtRImmediate, (XtPointer) 0 },
78
{ XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int),
79
Offset(cell_height), XtRImmediate, (XtPointer) 0 },
80
{ XtNstartChar, XtCStartChar, XtRLong, sizeof(long),
81
Offset(start_char), XtRImmediate, (XtPointer) 0xffffffff },
83
{ XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
84
Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground },
86
{ XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean),
87
Offset(center_chars), XtRImmediate, (XtPointer) FALSE },
88
{ XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean),
89
Offset(box_chars), XtRImmediate, (XtPointer) FALSE },
90
{ XtNboxColor, XtCForeground, XtRPixel, sizeof(Pixel),
91
Offset(box_pixel), XtRString, (XtPointer) XtDefaultForeground },
92
{ XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
93
Offset(callbacks), XtRCallback, (XtPointer) NULL },
94
{ XtNinternalPad, XtCInternalPad, XtRInt, sizeof(int),
95
Offset(internal_pad), XtRImmediate, (XtPointer) 4 },
96
{ XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int),
97
Offset(grid_width), XtRImmediate, (XtPointer) 1 },
99
{XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor),
100
Offset(fg_color), XtRString, XtDefaultForeground},
101
{XtNface, XtCFace, XtRXftFont, sizeof (XftFont *),
102
Offset (text_face), XtRString, 0},
108
static char defaultTranslations[] =
109
"<ButtonPress>: notify()";
111
static XtActionsRec actions_list[] = {
112
{ "notify", Notify },
115
FontGridClassRec fontgridClassRec = {
117
/* superclass */ (WidgetClass) &simpleClassRec,
118
/* class_name */ "FontGrid",
119
/* widget_size */ sizeof(FontGridRec),
120
/* class_initialize */ ClassInitialize,
121
/* class_part_initialize */ NULL,
122
/* class_inited */ FALSE,
123
/* initialize */ Initialize,
124
/* initialize_hook */ NULL,
125
/* realize */ Realize,
126
/* actions */ actions_list,
127
/* num_actions */ XtNumber(actions_list),
128
/* resources */ resources,
129
/* num_resources */ XtNumber(resources),
130
/* xrm_class */ NULLQUARK,
131
/* compress_motion */ TRUE,
132
/* compress_exposure */ TRUE,
133
/* compress_enterleave */ TRUE,
134
/* visible_interest */ FALSE,
135
/* destroy */ Destroy,
137
/* expose */ Redisplay,
138
/* set_values */ SetValues,
139
/* set_values_hook */ NULL,
140
/* set_values_almost */ XtInheritSetValuesAlmost,
141
/* get_values_hook */ NULL,
142
/* accept_focus */ NULL,
143
/* version */ XtVersion,
144
/* callback_private */ NULL,
145
/* tm_table */ defaultTranslations,
146
/* query_geometry */ XtInheritQueryGeometry,
147
/* display_accelerator */ XtInheritDisplayAccelerator,
150
{ /* simple fields */
151
/* change_sensitive */ XtInheritChangeSensitive
155
WidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec;
159
GridFirstChar (Widget w)
161
FontGridWidget fgw = (FontGridWidget) w;
162
XFontStruct *fs = fgw->fontgrid.text_font;
164
XftFont *xft = fgw->fontgrid.text_face;
167
FcChar32 map[FC_CHARSET_MAP_SIZE];
172
first = FcCharSetFirstPage (xft->charset, map, &next);
173
for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
176
FcChar32 bits = map[i];
178
while (!(bits & 0x1))
191
return (fs->min_byte1 << 8) | (fs->min_char_or_byte2);
198
GridLastChar (Widget w)
200
FontGridWidget fgw = (FontGridWidget) w;
201
XFontStruct *fs = fgw->fontgrid.text_font;
203
XftFont *xft = fgw->fontgrid.text_face;
206
FcChar32 this, last, next;
207
FcChar32 map[FC_CHARSET_MAP_SIZE];
209
last = FcCharSetFirstPage (xft->charset, map, &next);
210
while ((this = FcCharSetNextPage (xft->charset, map, &next)) != FC_CHARSET_DONE)
213
for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--)
216
FcChar32 bits = map[i];
218
while (!(bits & 0x80000000))
231
return (fs->max_byte1 << 8) | (fs->max_char_or_byte2);
238
* CI_GET_CHAR_INFO_1D - return the charinfo struct for the indicated 8bit
239
* character. If the character is in the column and exists, then return the
240
* appropriate metrics (note that fonts with common per-character metrics will
241
* return min_bounds).
244
#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
245
(((cs)->rbearing|(cs)->lbearing| \
246
(cs)->ascent|(cs)->descent) == 0))
248
#define CI_GET_CHAR_INFO_1D(fs,col,cs) \
251
if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
252
if (fs->per_char == NULL) { \
253
cs = &fs->min_bounds; \
255
cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
257
if (CI_NONEXISTCHAR(cs)) \
263
* CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and
264
* column. This is used for fonts that have more than row zero.
266
#define CI_GET_CHAR_INFO_2D(fs,row,col,cs) \
269
if (row >= fs->min_byte1 && row <= fs->max_byte1 && \
270
col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
271
if (fs->per_char == NULL) { \
272
cs = &fs->min_bounds; \
274
cs = &fs->per_char[((row - fs->min_byte1) * \
275
(fs->max_char_or_byte2 - \
276
fs->min_char_or_byte2 + 1)) + \
277
(col - fs->min_char_or_byte2)]; \
279
if (CI_NONEXISTCHAR(cs)) \
285
GridHasChar (Widget w, long ch)
287
FontGridWidget fgw = (FontGridWidget) w;
289
XftFont *xft = fgw->fontgrid.text_face;
292
return FcCharSetHasChar (xft->charset, (FcChar32) ch);
297
XFontStruct *fs = fgw->fontgrid.text_font;
302
if (fs->max_byte1 == 0)
304
CI_GET_CHAR_INFO_1D (fs, ch, cs);
308
unsigned int r = (ch >> 8);
309
unsigned int c = (ch & 0xff);
310
CI_GET_CHAR_INFO_2D (fs, r, c, cs);
321
GetFontGridCellDimensions(Widget w, long *startp,
322
int *ncolsp, int *nrowsp)
324
FontGridWidget fgw = (FontGridWidget) w;
325
*startp = fgw->fontgrid.start_char;
326
*ncolsp = fgw->fontgrid.cell_cols;
327
*nrowsp = fgw->fontgrid.cell_rows;
332
GetPrevNextStates(Widget w, Bool *prevvalidp, Bool *nextvalidp,
333
Bool *prev16validp, Bool *next16validp)
335
FontGridWidget fgw = (FontGridWidget) w;
336
long minn = (long) GridFirstChar (w);
337
long maxn = (long) GridLastChar (w);
339
*prev16validp = (fgw->fontgrid.start_char - 0xf00 > minn);
340
*prevvalidp = (fgw->fontgrid.start_char > minn);
341
*nextvalidp = (fgw->fontgrid.start_char +
342
(fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows)
344
*next16validp =((fgw->fontgrid.start_char + 0xf00 +
345
(fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows))
352
* private routines and methods
357
get_gc(FontGridWidget fgw, Pixel fore)
362
mask = (GCForeground | GCBackground | GCFunction);
363
gcv.foreground = fore;
364
gcv.background = fgw->core.background_pixel;
365
gcv.function = GXcopy;
366
if (fgw->fontgrid.text_font)
369
gcv.font = fgw->fontgrid.text_font->fid;
371
gcv.cap_style = CapProjecting;
373
if (fgw->fontgrid.grid_width > 0) {
375
gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 :
376
fgw->fontgrid.grid_width);
378
return (XtGetGC ((Widget) fgw, mask, &gcv));
383
XtConvertArgRec xftColorConvertArgs[] = {
384
{XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
386
{XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
390
#define donestr(type, value, tstr) \
392
if (toVal->addr != NULL) { \
393
if (toVal->size < sizeof(type)) { \
394
toVal->size = sizeof(type); \
395
XtDisplayStringConversionWarning(dpy, \
396
(char*) fromVal->addr, tstr); \
399
*(type*)(toVal->addr) = (value); \
402
static type static_val; \
403
static_val = (value); \
404
toVal->addr = (XPointer)&static_val; \
406
toVal->size = sizeof(type); \
411
XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
412
XrmValuePtr args, Cardinal *num_args)
421
"freeXftColor", "wrongParameters",
423
"Freeing an XftColor requires screen and colormap arguments",
424
(String *) NULL, (Cardinal *)NULL);
428
screen = *((Screen **) args[0].addr);
429
colormap = *((Colormap *) args[1].addr);
430
color = (XftColor *) toVal->addr;
431
XftColorFree (DisplayOfScreen (screen),
432
DefaultVisual (DisplayOfScreen (screen),
433
XScreenNumberOfScreen (screen)),
438
XmuCvtStringToXftColor(Display *dpy,
439
XrmValue *args, Cardinal *num_args,
440
XrmValue *fromVal, XrmValue *toVal,
441
XtPointer *converter_data)
444
XRenderColor renderColor;
451
XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
452
"cvtStringToXftColor", "wrongParameters",
454
"String to render color conversion needs screen and colormap arguments",
455
(String *) NULL, (Cardinal *)NULL);
459
screen = *((Screen **) args[0].addr);
460
colormap = *((Colormap *) args[1].addr);
462
spec = (char *) fromVal->addr;
463
if (strcasecmp (spec, XtDefaultForeground) == 0)
466
renderColor.green = 0;
467
renderColor.blue = 0;
468
renderColor.alpha = 0xffff;
470
else if (strcasecmp (spec, XtDefaultBackground) == 0)
472
renderColor.red = 0xffff;
473
renderColor.green = 0xffff;
474
renderColor.blue = 0xffff;
475
renderColor.alpha = 0xffff;
477
else if (!XRenderParseColor (dpy, spec, &renderColor))
479
if (!XftColorAllocValue (dpy,
481
XScreenNumberOfScreen (screen)),
487
donestr (XftColor, xftColor, XtRXftColor);
491
XmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
492
XrmValuePtr args, Cardinal *num_args)
500
"freeXftFont", "wrongParameters",
502
"Freeing an XftFont requires screen argument",
503
(String *) NULL, (Cardinal *)NULL);
507
screen = *((Screen **) args[0].addr);
508
font = *((XftFont **) toVal->addr);
510
XftFontClose (DisplayOfScreen (screen), font);
514
XmuCvtStringToXftFont(Display *dpy,
515
XrmValue *args, Cardinal *num_args,
516
XrmValue *fromVal, XrmValue *toVal,
517
XtPointer *converter_data)
525
XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
526
"cvtStringToXftFont", "wrongParameters",
528
"String to XftFont conversion needs screen argument",
529
(String *) NULL, (Cardinal *)NULL);
533
screen = *((Screen **) args[0].addr);
534
name = (char *) fromVal->addr;
539
font = XftFontOpenName (dpy,
540
XScreenNumberOfScreen (screen),
544
XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
548
donestr (XftFont *, font, XtRXftFont);
551
static XtConvertArgRec xftFontConvertArgs[] = {
552
{XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
559
ClassInitialize(void)
561
XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0);
563
XtSetTypeConverter (XtRString, XtRXftColor,
564
XmuCvtStringToXftColor,
565
xftColorConvertArgs, XtNumber(xftColorConvertArgs),
566
XtCacheByDisplay, XmuFreeXftColor);
567
XtSetTypeConverter (XtRString, XtRXftFont,
568
XmuCvtStringToXftFont,
569
xftFontConvertArgs, XtNumber(xftFontConvertArgs),
570
XtCacheByDisplay, XmuFreeXftFont);
576
Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
578
FontGridWidget reqfg = (FontGridWidget) request;
579
FontGridWidget newfg = (FontGridWidget) new;
580
XFontStruct *fs = newfg->fontgrid.text_font;
582
XftFont *xft = newfg->fontgrid.text_face;
586
if (reqfg->fontgrid.cell_cols <= 0)
587
newfg->fontgrid.cell_cols = 16;
589
if (reqfg->fontgrid.cell_rows <= 0) {
592
newfg->fontgrid.cell_rows = 16;
595
if (fs && fs->max_byte1 == 0) {
596
newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 /
597
newfg->fontgrid.cell_cols) + 1;
598
if (newfg->fontgrid.cell_rows > 16)
599
newfg->fontgrid.cell_rows = 16;
601
newfg->fontgrid.cell_rows = 16;
604
if (reqfg->fontgrid.cell_width <= 0)
605
newfg->fontgrid.cell_width = DefaultCellWidth (newfg);
606
if (reqfg->fontgrid.cell_height <= 0)
607
newfg->fontgrid.cell_height = DefaultCellHeight (newfg);
609
/* give a nice size that fits one screen full */
610
if (newfg->core.width == 0)
611
newfg->core.width = (newfg->fontgrid.cell_width *
612
newfg->fontgrid.cell_cols +
613
newfg->fontgrid.grid_width *
614
(newfg->fontgrid.cell_cols + 1));
616
if (newfg->core.height == 0)
617
newfg->core.height = (newfg->fontgrid.cell_height *
618
newfg->fontgrid.cell_rows +
619
newfg->fontgrid.grid_width *
620
(newfg->fontgrid.cell_rows + 1));
623
* select the first character
626
if (newfg->fontgrid.start_char == 0xffffffff)
627
newfg->fontgrid.start_char = GridFirstChar(new) & ~0xff;
628
maxn = GridLastChar (new);
629
if (newfg->fontgrid.start_char > maxn)
630
newfg->fontgrid.start_char = (maxn + 1 -
631
(newfg->fontgrid.cell_cols *
632
newfg->fontgrid.cell_rows));
636
Realize(Widget gw, Mask *valueMask, XSetWindowAttributes *attributes)
638
FontGridWidget fgw = (FontGridWidget) gw;
639
FontGridPart *p = &fgw->fontgrid;
641
p->text_gc = get_gc (fgw, GridForeground (fgw));
642
p->box_gc = get_gc (fgw, p->box_pixel);
645
(*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes);
647
p->draw = XftDrawCreate (XtDisplay (gw), XtWindow (gw),
648
DefaultVisual (XtDisplay (gw),
649
DefaultScreen(XtDisplay (gw))),
660
FontGridWidget fgw = (FontGridWidget) gw;
662
XtReleaseGC (gw, fgw->fontgrid.text_gc);
663
XtReleaseGC (gw, fgw->fontgrid.box_gc);
670
FontGridWidget fgw = (FontGridWidget) gw;
672
/* recompute in case we've changed size */
673
fgw->fontgrid.cell_width = CellWidth (fgw);
674
if (fgw->fontgrid.cell_width <= 0)
675
fgw->fontgrid.cell_width = 1;
676
fgw->fontgrid.cell_height = CellHeight (fgw);
677
if (fgw->fontgrid.cell_height <= 0)
678
fgw->fontgrid.cell_height = 1;
679
fgw->fontgrid.xoff = (fgw->fontgrid.cell_width -
680
DefaultCellWidth (fgw)) / 2;
681
fgw->fontgrid.yoff = (fgw->fontgrid.cell_height -
682
DefaultCellHeight (fgw)) / 2;
689
Redisplay(Widget gw, XEvent *event, Region region)
691
FontGridWidget fgw = (FontGridWidget) gw;
692
XRectangle rect; /* bounding rect for region */
693
int left, right, top, bottom; /* which cells were damaged */
694
int cw, ch; /* cell size */
697
if (!fgw->fontgrid.text_face)
699
if (!fgw->fontgrid.text_font) {
700
Bell (gw, XkbBI_BadValue);
705
* compute the left, right, top, and bottom cells that were damaged
707
XClipBox (region, &rect);
708
cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width;
709
ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width;
710
if ((left = (((int) rect.x) / cw)) < 0) left = 0;
711
right = (((int) (rect.x + rect.width - 1)) / cw);
712
if ((top = (((int) rect.y) / ch)) < 0) top = 0;
713
bottom = (((int) (rect.y + rect.height - 1)) / ch);
715
paint_grid (fgw, left, top, right - left + 1, bottom - top + 1);
720
paint_grid(FontGridWidget fgw, /* widget in which to draw */
721
int col, int row, /* where to start */
722
int ncols, int nrows) /* number of cells */
724
FontGridPart *p = &fgw->fontgrid;
726
Display *dpy = XtDisplay(fgw);
727
Window wind = XtWindow(fgw);
728
int cw = p->cell_width + p->grid_width;
729
int ch = p->cell_height + p->grid_width;
730
int tcols = p->cell_cols;
731
int trows = p->cell_rows;
732
int x1, y1, x2, y2, x, y;
733
unsigned maxn = GridLastChar ((Widget) fgw);
737
if (col + ncols >= tcols) {
739
if (ncols < 1) return;
742
if (row + nrows >= trows) {
744
if (nrows < 1) return;
748
* paint the grid lines for the indicated rows
750
if (p->grid_width > 0) {
751
int half_grid_width = p->grid_width >> 1;
752
x1 = col * cw + half_grid_width;
753
y1 = row * ch + half_grid_width;
754
x2 = x1 + ncols * cw;
755
y2 = y1 + nrows * ch;
756
for (i = 0, x = x1; i <= ncols; i++, x += cw) {
757
XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2);
759
for (i = 0, y = y1; i <= nrows; i++, y += ch) {
760
XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y);
764
* Draw a character in every box; treat all fonts as if they were 16bit
765
* fonts. Store the high eight bits in byte1 and the low eight bits in
768
prevn = p->start_char + col + row * tcols;
769
startx = col * cw + p->internal_pad + p->grid_width;
771
y = row * ch + p->internal_pad + p->grid_width + GridFontAscent (fgw);
772
j < nrows; j++, y += ch) {
774
for (i = 0, x = startx; i < ncols; i++, x += cw) {
775
int xoff = p->xoff, yoff = p->yoff;
776
if (n > maxn) goto done; /* no break out of nested */
779
if (fgw->fontgrid.text_face)
781
XftFont *xft = p->text_face;
784
XftTextExtents32 (dpy, xft, &c, 1, &extents);
787
xoff = (p->cell_width - extents.width) / 2 - extents.x;
788
yoff = (p->cell_height - extents.height) / 2 - extents.y;
790
if (extents.width && extents.height)
792
XClearArea (dpy, wind, x + xoff - extents.x,
793
y + yoff - extents.y,
794
extents.width, extents.height, False);
796
XDrawRectangle (dpy, wind, p->box_gc,
797
x + xoff - extents.x,
798
y + yoff - extents.y,
802
XftDrawString32 (p->draw, &p->fg_color, xft,
803
x + xoff, y + yoff, &c, 1);
810
thechar.byte1 = (n >> 8); /* high eight bits */
811
thechar.byte2 = (n & 255); /* low eight bits */
812
if (p->box_chars || p->center_chars) {
814
int direction, fontascent, fontdescent;
816
XTextExtents16 (p->text_font, &thechar, 1, &direction,
817
&fontascent, &fontdescent, &metrics);
819
if (p->center_chars) {
821
* We want to move the origin by enough to center the ink
822
* within the cell. The left edge will then be at
823
* (cell_width - (rbearing - lbearing)) / 2; so we subtract
824
* the lbearing to find the origin. Ditto for vertical.
826
xoff = (((p->cell_width -
827
(metrics.rbearing - metrics.lbearing)) / 2) -
828
p->internal_pad - metrics.lbearing);
829
yoff = (((p->cell_height -
830
(metrics.descent + metrics.ascent)) / 2) -
832
p->text_font->ascent + metrics.ascent);
835
XDrawRectangle (dpy, wind, p->box_gc,
836
x + xoff, y + yoff - p->text_font->ascent,
838
fontascent + fontdescent - 1);
841
XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff,
851
* paint the grid lines for the indicated rows
853
if (p->grid_width > 0) {
854
int half_grid_width = p->grid_width >> 1;
855
x1 = col * cw + half_grid_width;
856
y1 = row * ch + half_grid_width;
857
x2 = x1 + ncols * cw;
858
y2 = y1 + nrows * ch;
859
for (i = 0, x = x1; i <= ncols; i++, x += cw) {
860
XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2);
862
for (i = 0, y = y1; i <= nrows; i++, y += ch) {
863
XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y);
872
PageBlank (Widget w, long first, long last)
874
while (first <= last)
876
if (GridHasChar (w, first))
885
SetValues(Widget current, Widget request, Widget new,
886
ArgList args, Cardinal *num_args)
888
FontGridWidget curfg = (FontGridWidget) current;
889
FontGridWidget newfg = (FontGridWidget) new;
890
Boolean redisplay = FALSE;
892
if (curfg->fontgrid.text_font != newfg->fontgrid.text_font ||
893
curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) {
894
newfg->fontgrid.cell_width = DefaultCellWidth (newfg);
895
newfg->fontgrid.cell_height = DefaultCellHeight (newfg);
899
if (GridForeground(curfg) != GridForeground (newfg)) {
900
XtReleaseGC (new, curfg->fontgrid.text_gc);
901
newfg->fontgrid.text_gc = get_gc (newfg, GridForeground (newfg));
905
if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) {
906
XtReleaseGC (new, curfg->fontgrid.text_gc);
907
newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel);
911
if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars ||
912
curfg->fontgrid.box_chars != newfg->fontgrid.box_chars)
915
if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) {
916
long maxn = GridLastChar (new);
917
long page = newfg->fontgrid.cell_cols * newfg->fontgrid.cell_rows;
919
long start = newfg->fontgrid.start_char;
921
if (start < curfg->fontgrid.start_char)
927
start = (maxn / page) * page;
929
while (PageBlank (new, start, start + page - 1))
931
long next = start + dir;
933
if (next < 0 || maxn < next)
938
newfg->fontgrid.start_char = start;
939
redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char);
948
Notify(Widget gw, XEvent *event, String *params, Cardinal *nparams)
950
FontGridWidget fgw = (FontGridWidget) gw;
951
int x, y; /* where the event happened */
952
FontGridCharRec rec; /* callback data */
955
* only allow events with (x,y)
957
switch (event->type) {
965
x = event->xbutton.x;
966
y = event->xbutton.y;
969
x = event->xmotion.x;
970
y = event->xmotion.y;
973
Bell (gw, XkbBI_Ignore);
978
* compute the callback data
981
int cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width;
982
int ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width;
985
if (x > (fgw->fontgrid.cell_cols * cw)) {
986
Bell (gw, XkbBI_InvalidLocation);
990
n= (fgw->fontgrid.start_char +
991
((y / ch) * fgw->fontgrid.cell_cols) + (x / cw));
993
rec.thefont = fgw->fontgrid.text_font;
995
rec.theface = fgw->fontgrid.text_face;
1000
XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec);