grid.c revision 9e0146f7
1492e1cfeSmrg/* 2492e1cfeSmrg * $XdotOrg: grid.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $ 3492e1cfeSmrg * $Xorg: grid.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $ 4492e1cfeSmrg * 5492e1cfeSmrg * 6492e1cfeSmrgCopyright 1989, 1998 The Open Group 7492e1cfeSmrg 8492e1cfeSmrgPermission to use, copy, modify, distribute, and sell this software and its 9492e1cfeSmrgdocumentation for any purpose is hereby granted without fee, provided that 10492e1cfeSmrgthe above copyright notice appear in all copies and that both that 11492e1cfeSmrgcopyright notice and this permission notice appear in supporting 12492e1cfeSmrgdocumentation. 13492e1cfeSmrg 14492e1cfeSmrgThe above copyright notice and this permission notice shall be included in 15492e1cfeSmrgall copies or substantial portions of the Software. 16492e1cfeSmrg 17492e1cfeSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18492e1cfeSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19492e1cfeSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20492e1cfeSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21492e1cfeSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22492e1cfeSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23492e1cfeSmrg 24492e1cfeSmrgExcept as contained in this notice, the name of The Open Group shall not be 25492e1cfeSmrgused in advertising or otherwise to promote the sale, use or other dealings 26492e1cfeSmrgin this Software without prior written authorization from The Open Group. 27492e1cfeSmrg * * 28492e1cfeSmrg * Author: Jim Fulton, MIT X Consortium 29492e1cfeSmrg */ 30492e1cfeSmrg/* $XFree86: xc/programs/xfd/grid.c,v 1.9 2002/07/06 00:46:42 keithp Exp $ */ 31492e1cfeSmrg 32492e1cfeSmrg 33492e1cfeSmrg#include <X11/IntrinsicP.h> 34492e1cfeSmrg#include <X11/StringDefs.h> 35492e1cfeSmrg#include <X11/Xaw/SimpleP.h> 36492e1cfeSmrg#include <X11/Xmu/Converters.h> 37492e1cfeSmrg#include <X11/Xos.h> 38492e1cfeSmrg#include "gridP.h" 39492e1cfeSmrg 40492e1cfeSmrg#ifdef XKB 41492e1cfeSmrg#include <X11/extensions/XKBbells.h> 42492e1cfeSmrg#else 43492e1cfeSmrg#define XkbBI_MinorError 2 44492e1cfeSmrg#define XkbBI_Ignore 11 45492e1cfeSmrg#endif 46492e1cfeSmrg 47492e1cfeSmrg#ifdef XKB 48492e1cfeSmrg#define Bell(w,n) XkbStdBell(XtDisplay(w), XtWindow(w), 50, n) 49492e1cfeSmrg#else 50492e1cfeSmrg#define Bell(w,n) XBell(XtDisplay(w), 0) 51492e1cfeSmrg#endif 52492e1cfeSmrg 53492e1cfeSmrgstatic GC get_gc(FontGridWidget fgw, Pixel fore); 54492e1cfeSmrgstatic void ClassInitialize(void); 55492e1cfeSmrgstatic void Initialize(Widget request, Widget new, ArgList args, 56492e1cfeSmrg Cardinal *num_args); 57492e1cfeSmrgstatic void Realize(Widget gw, Mask *valueMask, 58492e1cfeSmrg XSetWindowAttributes *attributes); 59492e1cfeSmrgstatic void Destroy(Widget gw); 60492e1cfeSmrgstatic void Resize(Widget gw); 61492e1cfeSmrgstatic void Redisplay(Widget gw, XEvent *event, Region region); 62492e1cfeSmrgstatic void paint_grid(FontGridWidget fgw, int col, int row, 63492e1cfeSmrg int ncols, int nrows); 64492e1cfeSmrgstatic Boolean SetValues(Widget current, Widget request, Widget new, 65492e1cfeSmrg ArgList args, Cardinal *num_args); 66492e1cfeSmrgstatic void Notify(Widget gw, XEvent *event, String *params, 67492e1cfeSmrg Cardinal *nparams); 68492e1cfeSmrg 69492e1cfeSmrg#define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field) 70492e1cfeSmrg 71492e1cfeSmrgstatic XtResource resources[] = { 72492e1cfeSmrg { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 73492e1cfeSmrg Offset(text_font), XtRString, (XtPointer) NULL }, 74492e1cfeSmrg { XtNcellColumns, XtCCellColumns, XtRInt, sizeof(int), 75492e1cfeSmrg Offset(cell_cols), XtRImmediate, (XtPointer) 0 }, 76492e1cfeSmrg { XtNcellRows, XtCCellRows, XtRInt, sizeof(int), 77492e1cfeSmrg Offset(cell_rows), XtRImmediate, (XtPointer) 0 }, 78492e1cfeSmrg { XtNcellWidth, XtCCellWidth, XtRInt, sizeof(int), 79492e1cfeSmrg Offset(cell_width), XtRImmediate, (XtPointer) 0 }, 80492e1cfeSmrg { XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int), 81492e1cfeSmrg Offset(cell_height), XtRImmediate, (XtPointer) 0 }, 82492e1cfeSmrg { XtNstartChar, XtCStartChar, XtRLong, sizeof(long), 83492e1cfeSmrg Offset(start_char), XtRImmediate, (XtPointer) 0xffffffff }, 84492e1cfeSmrg#ifndef XRENDER 85492e1cfeSmrg { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 86492e1cfeSmrg Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground }, 87492e1cfeSmrg#endif 88492e1cfeSmrg { XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean), 89492e1cfeSmrg Offset(center_chars), XtRImmediate, (XtPointer) FALSE }, 90492e1cfeSmrg { XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean), 91492e1cfeSmrg Offset(box_chars), XtRImmediate, (XtPointer) FALSE }, 92492e1cfeSmrg { XtNboxColor, XtCForeground, XtRPixel, sizeof(Pixel), 93492e1cfeSmrg Offset(box_pixel), XtRString, (XtPointer) XtDefaultForeground }, 94492e1cfeSmrg { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), 95492e1cfeSmrg Offset(callbacks), XtRCallback, (XtPointer) NULL }, 96492e1cfeSmrg { XtNinternalPad, XtCInternalPad, XtRInt, sizeof(int), 97492e1cfeSmrg Offset(internal_pad), XtRImmediate, (XtPointer) 4 }, 98492e1cfeSmrg { XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int), 99492e1cfeSmrg Offset(grid_width), XtRImmediate, (XtPointer) 1 }, 100492e1cfeSmrg#ifdef XRENDER 101492e1cfeSmrg {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor), 102492e1cfeSmrg Offset(fg_color), XtRString, XtDefaultForeground}, 103492e1cfeSmrg {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *), 1049e0146f7Smrg Offset (text_face), XtRString, NULL}, 105492e1cfeSmrg#endif 106492e1cfeSmrg}; 107492e1cfeSmrg 108492e1cfeSmrg#undef Offset 109492e1cfeSmrg 110492e1cfeSmrgstatic char defaultTranslations[] = 111492e1cfeSmrg "<ButtonPress>: notify()"; 112492e1cfeSmrg 113492e1cfeSmrgstatic XtActionsRec actions_list[] = { 114492e1cfeSmrg { "notify", Notify }, 115492e1cfeSmrg}; 116492e1cfeSmrg 117492e1cfeSmrgFontGridClassRec fontgridClassRec = { 118492e1cfeSmrg { /* core fields */ 119492e1cfeSmrg /* superclass */ (WidgetClass) &simpleClassRec, 120492e1cfeSmrg /* class_name */ "FontGrid", 121492e1cfeSmrg /* widget_size */ sizeof(FontGridRec), 122492e1cfeSmrg /* class_initialize */ ClassInitialize, 123492e1cfeSmrg /* class_part_initialize */ NULL, 124492e1cfeSmrg /* class_inited */ FALSE, 125492e1cfeSmrg /* initialize */ Initialize, 126492e1cfeSmrg /* initialize_hook */ NULL, 127492e1cfeSmrg /* realize */ Realize, 128492e1cfeSmrg /* actions */ actions_list, 129492e1cfeSmrg /* num_actions */ XtNumber(actions_list), 130492e1cfeSmrg /* resources */ resources, 131492e1cfeSmrg /* num_resources */ XtNumber(resources), 132492e1cfeSmrg /* xrm_class */ NULLQUARK, 133492e1cfeSmrg /* compress_motion */ TRUE, 134492e1cfeSmrg /* compress_exposure */ TRUE, 135492e1cfeSmrg /* compress_enterleave */ TRUE, 136492e1cfeSmrg /* visible_interest */ FALSE, 137492e1cfeSmrg /* destroy */ Destroy, 138492e1cfeSmrg /* resize */ Resize, 139492e1cfeSmrg /* expose */ Redisplay, 140492e1cfeSmrg /* set_values */ SetValues, 141492e1cfeSmrg /* set_values_hook */ NULL, 142492e1cfeSmrg /* set_values_almost */ XtInheritSetValuesAlmost, 143492e1cfeSmrg /* get_values_hook */ NULL, 144492e1cfeSmrg /* accept_focus */ NULL, 145492e1cfeSmrg /* version */ XtVersion, 146492e1cfeSmrg /* callback_private */ NULL, 147492e1cfeSmrg /* tm_table */ defaultTranslations, 148492e1cfeSmrg /* query_geometry */ XtInheritQueryGeometry, 149492e1cfeSmrg /* display_accelerator */ XtInheritDisplayAccelerator, 150492e1cfeSmrg /* extension */ NULL 151492e1cfeSmrg }, 152492e1cfeSmrg { /* simple fields */ 153492e1cfeSmrg /* change_sensitive */ XtInheritChangeSensitive 154492e1cfeSmrg } 155492e1cfeSmrg}; 156492e1cfeSmrg 157492e1cfeSmrgWidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec; 158492e1cfeSmrg 159492e1cfeSmrg 160492e1cfeSmrglong 161492e1cfeSmrgGridFirstChar (Widget w) 162492e1cfeSmrg{ 163492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 164492e1cfeSmrg XFontStruct *fs = fgw->fontgrid.text_font; 165492e1cfeSmrg#ifdef XRENDER 166492e1cfeSmrg XftFont *xft = fgw->fontgrid.text_face; 167492e1cfeSmrg if (xft) 168492e1cfeSmrg { 169492e1cfeSmrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 170492e1cfeSmrg FcChar32 next; 171492e1cfeSmrg FcChar32 first; 172492e1cfeSmrg int i; 173492e1cfeSmrg 174492e1cfeSmrg first = FcCharSetFirstPage (xft->charset, map, &next); 175492e1cfeSmrg for (i = 0; i < FC_CHARSET_MAP_SIZE; i++) 176492e1cfeSmrg if (map[i]) 177492e1cfeSmrg { 178492e1cfeSmrg FcChar32 bits = map[i]; 179492e1cfeSmrg first += i * 32; 180492e1cfeSmrg while (!(bits & 0x1)) 181492e1cfeSmrg { 182492e1cfeSmrg bits >>= 1; 183492e1cfeSmrg first++; 184492e1cfeSmrg } 185492e1cfeSmrg break; 186492e1cfeSmrg } 187492e1cfeSmrg return first; 188492e1cfeSmrg } 189492e1cfeSmrg else 190492e1cfeSmrg#endif 191492e1cfeSmrg if (fs) 192492e1cfeSmrg { 193492e1cfeSmrg return (fs->min_byte1 << 8) | (fs->min_char_or_byte2); 194492e1cfeSmrg } 195492e1cfeSmrg else 196492e1cfeSmrg return 0; 197492e1cfeSmrg} 198492e1cfeSmrg 199492e1cfeSmrglong 200492e1cfeSmrgGridLastChar (Widget w) 201492e1cfeSmrg{ 202492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 203492e1cfeSmrg XFontStruct *fs = fgw->fontgrid.text_font; 204492e1cfeSmrg#ifdef XRENDER 205492e1cfeSmrg XftFont *xft = fgw->fontgrid.text_face; 206492e1cfeSmrg if (xft) 207492e1cfeSmrg { 208492e1cfeSmrg FcChar32 this, last, next; 209492e1cfeSmrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 210492e1cfeSmrg int i; 211492e1cfeSmrg last = FcCharSetFirstPage (xft->charset, map, &next); 212492e1cfeSmrg while ((this = FcCharSetNextPage (xft->charset, map, &next)) != FC_CHARSET_DONE) 213492e1cfeSmrg last = this; 214492e1cfeSmrg last &= ~0xff; 215492e1cfeSmrg for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--) 216492e1cfeSmrg if (map[i]) 217492e1cfeSmrg { 218492e1cfeSmrg FcChar32 bits = map[i]; 219492e1cfeSmrg last += i * 32 + 31; 220492e1cfeSmrg while (!(bits & 0x80000000)) 221492e1cfeSmrg { 222492e1cfeSmrg last--; 223492e1cfeSmrg bits <<= 1; 224492e1cfeSmrg } 225492e1cfeSmrg break; 226492e1cfeSmrg } 227492e1cfeSmrg return (long) last; 228492e1cfeSmrg } 229492e1cfeSmrg else 230492e1cfeSmrg#endif 231492e1cfeSmrg if (fs) 232492e1cfeSmrg { 233492e1cfeSmrg return (fs->max_byte1 << 8) | (fs->max_char_or_byte2); 234492e1cfeSmrg } 235492e1cfeSmrg else 236492e1cfeSmrg return 0; 237492e1cfeSmrg} 238492e1cfeSmrg 239492e1cfeSmrg/* 240492e1cfeSmrg * CI_GET_CHAR_INFO_1D - return the charinfo struct for the indicated 8bit 241492e1cfeSmrg * character. If the character is in the column and exists, then return the 242492e1cfeSmrg * appropriate metrics (note that fonts with common per-character metrics will 243492e1cfeSmrg * return min_bounds). 244492e1cfeSmrg */ 245492e1cfeSmrg 246492e1cfeSmrg#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ 247492e1cfeSmrg (((cs)->rbearing|(cs)->lbearing| \ 248492e1cfeSmrg (cs)->ascent|(cs)->descent) == 0)) 249492e1cfeSmrg 250492e1cfeSmrg#define CI_GET_CHAR_INFO_1D(fs,col,cs) \ 251492e1cfeSmrg{ \ 2529e0146f7Smrg cs = NULL; \ 253492e1cfeSmrg if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 254492e1cfeSmrg if (fs->per_char == NULL) { \ 255492e1cfeSmrg cs = &fs->min_bounds; \ 256492e1cfeSmrg } else { \ 257492e1cfeSmrg cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ 258492e1cfeSmrg } \ 259492e1cfeSmrg if (CI_NONEXISTCHAR(cs)) \ 2609e0146f7Smrg cs = NULL; \ 261492e1cfeSmrg } \ 262492e1cfeSmrg} 263492e1cfeSmrg 264492e1cfeSmrg/* 265492e1cfeSmrg * CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and 266492e1cfeSmrg * column. This is used for fonts that have more than row zero. 267492e1cfeSmrg */ 268492e1cfeSmrg#define CI_GET_CHAR_INFO_2D(fs,row,col,cs) \ 269492e1cfeSmrg{ \ 2709e0146f7Smrg cs = NULL; \ 271492e1cfeSmrg if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ 272492e1cfeSmrg col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 273492e1cfeSmrg if (fs->per_char == NULL) { \ 274492e1cfeSmrg cs = &fs->min_bounds; \ 275492e1cfeSmrg } else { \ 276492e1cfeSmrg cs = &fs->per_char[((row - fs->min_byte1) * \ 277492e1cfeSmrg (fs->max_char_or_byte2 - \ 278492e1cfeSmrg fs->min_char_or_byte2 + 1)) + \ 279492e1cfeSmrg (col - fs->min_char_or_byte2)]; \ 280492e1cfeSmrg } \ 281492e1cfeSmrg if (CI_NONEXISTCHAR(cs)) \ 2829e0146f7Smrg cs = NULL; \ 283492e1cfeSmrg } \ 284492e1cfeSmrg} 285492e1cfeSmrg 286492e1cfeSmrgstatic Boolean 287492e1cfeSmrgGridHasChar (Widget w, long ch) 288492e1cfeSmrg{ 289492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 290492e1cfeSmrg#ifdef XRENDER 291492e1cfeSmrg XftFont *xft = fgw->fontgrid.text_face; 292492e1cfeSmrg if (xft) 293492e1cfeSmrg { 294492e1cfeSmrg return FcCharSetHasChar (xft->charset, (FcChar32) ch); 295492e1cfeSmrg } 296492e1cfeSmrg else 297492e1cfeSmrg#endif 298492e1cfeSmrg { 299492e1cfeSmrg XFontStruct *fs = fgw->fontgrid.text_font; 300492e1cfeSmrg XCharStruct *cs; 301492e1cfeSmrg 302492e1cfeSmrg if (!fs) 303492e1cfeSmrg return False; 304492e1cfeSmrg if (fs->max_byte1 == 0) 305492e1cfeSmrg { 306492e1cfeSmrg CI_GET_CHAR_INFO_1D (fs, ch, cs); 307492e1cfeSmrg } 308492e1cfeSmrg else 309492e1cfeSmrg { 310492e1cfeSmrg unsigned int r = (ch >> 8); 311492e1cfeSmrg unsigned int c = (ch & 0xff); 312492e1cfeSmrg CI_GET_CHAR_INFO_2D (fs, r, c, cs); 313492e1cfeSmrg } 3149e0146f7Smrg return cs != NULL; 315492e1cfeSmrg } 316492e1cfeSmrg} 317492e1cfeSmrg 318492e1cfeSmrg/* 319492e1cfeSmrg * public routines 320492e1cfeSmrg */ 321492e1cfeSmrg 322492e1cfeSmrgvoid 323492e1cfeSmrgGetFontGridCellDimensions(Widget w, long *startp, 324492e1cfeSmrg int *ncolsp, int *nrowsp) 325492e1cfeSmrg{ 326492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 327492e1cfeSmrg *startp = fgw->fontgrid.start_char; 328492e1cfeSmrg *ncolsp = fgw->fontgrid.cell_cols; 329492e1cfeSmrg *nrowsp = fgw->fontgrid.cell_rows; 330492e1cfeSmrg} 331492e1cfeSmrg 332492e1cfeSmrg 333492e1cfeSmrgvoid 334492e1cfeSmrgGetPrevNextStates(Widget w, Bool *prevvalidp, Bool *nextvalidp, 335492e1cfeSmrg Bool *prev16validp, Bool *next16validp) 336492e1cfeSmrg{ 337492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 338492e1cfeSmrg long minn = (long) GridFirstChar (w); 339492e1cfeSmrg long maxn = (long) GridLastChar (w); 340492e1cfeSmrg 341492e1cfeSmrg *prev16validp = (fgw->fontgrid.start_char - 0xf00 > minn); 342492e1cfeSmrg *prevvalidp = (fgw->fontgrid.start_char > minn); 343492e1cfeSmrg *nextvalidp = (fgw->fontgrid.start_char + 344492e1cfeSmrg (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows) 345492e1cfeSmrg < maxn); 346492e1cfeSmrg *next16validp =((fgw->fontgrid.start_char + 0xf00 + 347492e1cfeSmrg (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows)) 348492e1cfeSmrg < maxn); 349492e1cfeSmrg} 350492e1cfeSmrg 351492e1cfeSmrg 352492e1cfeSmrg 353492e1cfeSmrg/* 354492e1cfeSmrg * private routines and methods 355492e1cfeSmrg */ 356492e1cfeSmrg 357492e1cfeSmrg 358492e1cfeSmrgstatic GC 359492e1cfeSmrgget_gc(FontGridWidget fgw, Pixel fore) 360492e1cfeSmrg{ 361492e1cfeSmrg XtGCMask mask; 362492e1cfeSmrg XGCValues gcv; 363492e1cfeSmrg 364492e1cfeSmrg mask = (GCForeground | GCBackground | GCFunction); 365492e1cfeSmrg gcv.foreground = fore; 366492e1cfeSmrg gcv.background = fgw->core.background_pixel; 367492e1cfeSmrg gcv.function = GXcopy; 368492e1cfeSmrg if (fgw->fontgrid.text_font) 369492e1cfeSmrg { 370492e1cfeSmrg mask |= GCFont; 371492e1cfeSmrg gcv.font = fgw->fontgrid.text_font->fid; 372492e1cfeSmrg } 373492e1cfeSmrg gcv.cap_style = CapProjecting; 374492e1cfeSmrg mask |= GCCapStyle; 375492e1cfeSmrg if (fgw->fontgrid.grid_width > 0) { 376492e1cfeSmrg mask |= GCLineWidth; 377492e1cfeSmrg gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 : 378492e1cfeSmrg fgw->fontgrid.grid_width); 379492e1cfeSmrg } 380492e1cfeSmrg return (XtGetGC ((Widget) fgw, mask, &gcv)); 381492e1cfeSmrg} 382492e1cfeSmrg 383492e1cfeSmrg 384492e1cfeSmrg#ifdef XRENDER 3859e0146f7Smrgstatic XtConvertArgRec xftColorConvertArgs[] = { 386492e1cfeSmrg {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 387492e1cfeSmrg sizeof(Screen *)}, 388492e1cfeSmrg {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), 389492e1cfeSmrg sizeof(Colormap)} 390492e1cfeSmrg}; 391492e1cfeSmrg 392492e1cfeSmrg#define donestr(type, value, tstr) \ 393492e1cfeSmrg { \ 394492e1cfeSmrg if (toVal->addr != NULL) { \ 395492e1cfeSmrg if (toVal->size < sizeof(type)) { \ 396492e1cfeSmrg toVal->size = sizeof(type); \ 397492e1cfeSmrg XtDisplayStringConversionWarning(dpy, \ 398492e1cfeSmrg (char*) fromVal->addr, tstr); \ 399492e1cfeSmrg return False; \ 400492e1cfeSmrg } \ 401492e1cfeSmrg *(type*)(toVal->addr) = (value); \ 402492e1cfeSmrg } \ 403492e1cfeSmrg else { \ 404492e1cfeSmrg static type static_val; \ 405492e1cfeSmrg static_val = (value); \ 406492e1cfeSmrg toVal->addr = (XPointer)&static_val; \ 407492e1cfeSmrg } \ 408492e1cfeSmrg toVal->size = sizeof(type); \ 409492e1cfeSmrg return True; \ 410492e1cfeSmrg } 411492e1cfeSmrg 412492e1cfeSmrgstatic void 413492e1cfeSmrgXmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure, 414492e1cfeSmrg XrmValuePtr args, Cardinal *num_args) 415492e1cfeSmrg{ 416492e1cfeSmrg Screen *screen; 417492e1cfeSmrg Colormap colormap; 418492e1cfeSmrg XftColor *color; 419492e1cfeSmrg 420492e1cfeSmrg if (*num_args != 2) 421492e1cfeSmrg { 422492e1cfeSmrg XtAppErrorMsg (app, 423492e1cfeSmrg "freeXftColor", "wrongParameters", 424492e1cfeSmrg "XtToolkitError", 425492e1cfeSmrg "Freeing an XftColor requires screen and colormap arguments", 426492e1cfeSmrg (String *) NULL, (Cardinal *)NULL); 427492e1cfeSmrg return; 428492e1cfeSmrg } 429492e1cfeSmrg 430492e1cfeSmrg screen = *((Screen **) args[0].addr); 431492e1cfeSmrg colormap = *((Colormap *) args[1].addr); 432492e1cfeSmrg color = (XftColor *) toVal->addr; 433492e1cfeSmrg XftColorFree (DisplayOfScreen (screen), 434492e1cfeSmrg DefaultVisual (DisplayOfScreen (screen), 435492e1cfeSmrg XScreenNumberOfScreen (screen)), 436492e1cfeSmrg colormap, color); 437492e1cfeSmrg} 438492e1cfeSmrg 439492e1cfeSmrgstatic Boolean 440492e1cfeSmrgXmuCvtStringToXftColor(Display *dpy, 441492e1cfeSmrg XrmValue *args, Cardinal *num_args, 442492e1cfeSmrg XrmValue *fromVal, XrmValue *toVal, 443492e1cfeSmrg XtPointer *converter_data) 444492e1cfeSmrg{ 445492e1cfeSmrg char *spec; 446492e1cfeSmrg XRenderColor renderColor; 447492e1cfeSmrg XftColor xftColor; 448492e1cfeSmrg Screen *screen; 449492e1cfeSmrg Colormap colormap; 450492e1cfeSmrg 451492e1cfeSmrg if (*num_args != 2) 452492e1cfeSmrg { 453492e1cfeSmrg XtAppErrorMsg (XtDisplayToApplicationContext (dpy), 454492e1cfeSmrg "cvtStringToXftColor", "wrongParameters", 455492e1cfeSmrg "XtToolkitError", 456492e1cfeSmrg "String to render color conversion needs screen and colormap arguments", 457492e1cfeSmrg (String *) NULL, (Cardinal *)NULL); 458492e1cfeSmrg return False; 459492e1cfeSmrg } 460492e1cfeSmrg 461492e1cfeSmrg screen = *((Screen **) args[0].addr); 462492e1cfeSmrg colormap = *((Colormap *) args[1].addr); 463492e1cfeSmrg 464492e1cfeSmrg spec = (char *) fromVal->addr; 465492e1cfeSmrg if (strcasecmp (spec, XtDefaultForeground) == 0) 466492e1cfeSmrg { 467492e1cfeSmrg renderColor.red = 0; 468492e1cfeSmrg renderColor.green = 0; 469492e1cfeSmrg renderColor.blue = 0; 470492e1cfeSmrg renderColor.alpha = 0xffff; 471492e1cfeSmrg } 472492e1cfeSmrg else if (strcasecmp (spec, XtDefaultBackground) == 0) 473492e1cfeSmrg { 474492e1cfeSmrg renderColor.red = 0xffff; 475492e1cfeSmrg renderColor.green = 0xffff; 476492e1cfeSmrg renderColor.blue = 0xffff; 477492e1cfeSmrg renderColor.alpha = 0xffff; 478492e1cfeSmrg } 479492e1cfeSmrg else if (!XRenderParseColor (dpy, spec, &renderColor)) 480492e1cfeSmrg return False; 481492e1cfeSmrg if (!XftColorAllocValue (dpy, 482492e1cfeSmrg DefaultVisual (dpy, 483492e1cfeSmrg XScreenNumberOfScreen (screen)), 484492e1cfeSmrg colormap, 485492e1cfeSmrg &renderColor, 486492e1cfeSmrg &xftColor)) 487492e1cfeSmrg return False; 488492e1cfeSmrg 489492e1cfeSmrg donestr (XftColor, xftColor, XtRXftColor); 490492e1cfeSmrg} 491492e1cfeSmrg 492492e1cfeSmrgstatic void 493492e1cfeSmrgXmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure, 494492e1cfeSmrg XrmValuePtr args, Cardinal *num_args) 495492e1cfeSmrg{ 496492e1cfeSmrg Screen *screen; 497492e1cfeSmrg XftFont *font; 498492e1cfeSmrg 499492e1cfeSmrg if (*num_args != 1) 500492e1cfeSmrg { 501492e1cfeSmrg XtAppErrorMsg (app, 502492e1cfeSmrg "freeXftFont", "wrongParameters", 503492e1cfeSmrg "XtToolkitError", 504492e1cfeSmrg "Freeing an XftFont requires screen argument", 505492e1cfeSmrg (String *) NULL, (Cardinal *)NULL); 506492e1cfeSmrg return; 507492e1cfeSmrg } 508492e1cfeSmrg 509492e1cfeSmrg screen = *((Screen **) args[0].addr); 510492e1cfeSmrg font = *((XftFont **) toVal->addr); 511492e1cfeSmrg if (font) 512492e1cfeSmrg XftFontClose (DisplayOfScreen (screen), font); 513492e1cfeSmrg} 514492e1cfeSmrg 515492e1cfeSmrgstatic Boolean 516492e1cfeSmrgXmuCvtStringToXftFont(Display *dpy, 517492e1cfeSmrg XrmValue *args, Cardinal *num_args, 518492e1cfeSmrg XrmValue *fromVal, XrmValue *toVal, 519492e1cfeSmrg XtPointer *converter_data) 520492e1cfeSmrg{ 521492e1cfeSmrg char *name; 522492e1cfeSmrg XftFont *font; 523492e1cfeSmrg Screen *screen; 524492e1cfeSmrg 525492e1cfeSmrg if (*num_args != 1) 526492e1cfeSmrg { 527492e1cfeSmrg XtAppErrorMsg (XtDisplayToApplicationContext (dpy), 528492e1cfeSmrg "cvtStringToXftFont", "wrongParameters", 529492e1cfeSmrg "XtToolkitError", 530492e1cfeSmrg "String to XftFont conversion needs screen argument", 531492e1cfeSmrg (String *) NULL, (Cardinal *)NULL); 532492e1cfeSmrg return False; 533492e1cfeSmrg } 534492e1cfeSmrg 535492e1cfeSmrg screen = *((Screen **) args[0].addr); 536492e1cfeSmrg name = (char *) fromVal->addr; 5379e0146f7Smrg 5389e0146f7Smrg font = NULL; 539492e1cfeSmrg if (name) 540492e1cfeSmrg { 541492e1cfeSmrg font = XftFontOpenName (dpy, 542492e1cfeSmrg XScreenNumberOfScreen (screen), 543492e1cfeSmrg name); 544492e1cfeSmrg if (!font) 545492e1cfeSmrg { 546492e1cfeSmrg XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont); 547492e1cfeSmrg return False; 548492e1cfeSmrg } 549492e1cfeSmrg } 550492e1cfeSmrg donestr (XftFont *, font, XtRXftFont); 551492e1cfeSmrg} 552492e1cfeSmrg 553492e1cfeSmrgstatic XtConvertArgRec xftFontConvertArgs[] = { 554492e1cfeSmrg {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 555492e1cfeSmrg sizeof(Screen *)}, 556492e1cfeSmrg}; 557492e1cfeSmrg 558492e1cfeSmrg#endif 559492e1cfeSmrg 560492e1cfeSmrgstatic void 561492e1cfeSmrgClassInitialize(void) 562492e1cfeSmrg{ 563492e1cfeSmrg XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0); 564492e1cfeSmrg#ifdef XRENDER 565492e1cfeSmrg XtSetTypeConverter (XtRString, XtRXftColor, 566492e1cfeSmrg XmuCvtStringToXftColor, 567492e1cfeSmrg xftColorConvertArgs, XtNumber(xftColorConvertArgs), 568492e1cfeSmrg XtCacheByDisplay, XmuFreeXftColor); 569492e1cfeSmrg XtSetTypeConverter (XtRString, XtRXftFont, 570492e1cfeSmrg XmuCvtStringToXftFont, 571492e1cfeSmrg xftFontConvertArgs, XtNumber(xftFontConvertArgs), 572492e1cfeSmrg XtCacheByDisplay, XmuFreeXftFont); 573492e1cfeSmrg#endif 574492e1cfeSmrg} 575492e1cfeSmrg 576492e1cfeSmrg 577492e1cfeSmrgstatic void 578492e1cfeSmrgInitialize(Widget request, Widget new, ArgList args, Cardinal *num_args) 579492e1cfeSmrg{ 580492e1cfeSmrg FontGridWidget reqfg = (FontGridWidget) request; 581492e1cfeSmrg FontGridWidget newfg = (FontGridWidget) new; 582492e1cfeSmrg XFontStruct *fs = newfg->fontgrid.text_font; 583492e1cfeSmrg#ifdef XRENDER 584492e1cfeSmrg XftFont *xft = newfg->fontgrid.text_face; 585492e1cfeSmrg#endif 586492e1cfeSmrg unsigned maxn; 587492e1cfeSmrg 588492e1cfeSmrg if (reqfg->fontgrid.cell_cols <= 0) 589492e1cfeSmrg newfg->fontgrid.cell_cols = 16; 590492e1cfeSmrg 591492e1cfeSmrg if (reqfg->fontgrid.cell_rows <= 0) { 592492e1cfeSmrg#ifdef XRENDER 593492e1cfeSmrg if (xft) 594492e1cfeSmrg newfg->fontgrid.cell_rows = 16; 595492e1cfeSmrg else 596492e1cfeSmrg#endif 597492e1cfeSmrg if (fs && fs->max_byte1 == 0) { 598492e1cfeSmrg newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 / 599492e1cfeSmrg newfg->fontgrid.cell_cols) + 1; 600492e1cfeSmrg if (newfg->fontgrid.cell_rows > 16) 601492e1cfeSmrg newfg->fontgrid.cell_rows = 16; 602492e1cfeSmrg } else 603492e1cfeSmrg newfg->fontgrid.cell_rows = 16; 604492e1cfeSmrg } 605492e1cfeSmrg 606492e1cfeSmrg if (reqfg->fontgrid.cell_width <= 0) 607492e1cfeSmrg newfg->fontgrid.cell_width = DefaultCellWidth (newfg); 608492e1cfeSmrg if (reqfg->fontgrid.cell_height <= 0) 609492e1cfeSmrg newfg->fontgrid.cell_height = DefaultCellHeight (newfg); 610492e1cfeSmrg 611492e1cfeSmrg /* give a nice size that fits one screen full */ 612492e1cfeSmrg if (newfg->core.width == 0) 613492e1cfeSmrg newfg->core.width = (newfg->fontgrid.cell_width * 614492e1cfeSmrg newfg->fontgrid.cell_cols + 615492e1cfeSmrg newfg->fontgrid.grid_width * 616492e1cfeSmrg (newfg->fontgrid.cell_cols + 1)); 617492e1cfeSmrg 618492e1cfeSmrg if (newfg->core.height == 0) 619492e1cfeSmrg newfg->core.height = (newfg->fontgrid.cell_height * 620492e1cfeSmrg newfg->fontgrid.cell_rows + 621492e1cfeSmrg newfg->fontgrid.grid_width * 622492e1cfeSmrg (newfg->fontgrid.cell_rows + 1)); 623492e1cfeSmrg 624492e1cfeSmrg /* 625492e1cfeSmrg * select the first character 626492e1cfeSmrg */ 627492e1cfeSmrg 628492e1cfeSmrg if (newfg->fontgrid.start_char == 0xffffffff) 629492e1cfeSmrg newfg->fontgrid.start_char = GridFirstChar(new) & ~0xff; 630492e1cfeSmrg maxn = GridLastChar (new); 631492e1cfeSmrg if (newfg->fontgrid.start_char > maxn) 632492e1cfeSmrg newfg->fontgrid.start_char = (maxn + 1 - 633492e1cfeSmrg (newfg->fontgrid.cell_cols * 634492e1cfeSmrg newfg->fontgrid.cell_rows)); 635492e1cfeSmrg} 636492e1cfeSmrg 637492e1cfeSmrgstatic void 638492e1cfeSmrgRealize(Widget gw, Mask *valueMask, XSetWindowAttributes *attributes) 639492e1cfeSmrg{ 640492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 641492e1cfeSmrg FontGridPart *p = &fgw->fontgrid; 642492e1cfeSmrg 643492e1cfeSmrg p->text_gc = get_gc (fgw, GridForeground (fgw)); 644492e1cfeSmrg p->box_gc = get_gc (fgw, p->box_pixel); 645492e1cfeSmrg Resize (gw); 646492e1cfeSmrg 647492e1cfeSmrg (*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes); 648492e1cfeSmrg#ifdef XRENDER 649492e1cfeSmrg p->draw = XftDrawCreate (XtDisplay (gw), XtWindow (gw), 650492e1cfeSmrg DefaultVisual (XtDisplay (gw), 651492e1cfeSmrg DefaultScreen(XtDisplay (gw))), 652492e1cfeSmrg fgw->core.colormap); 653492e1cfeSmrg#endif 654492e1cfeSmrg return; 655492e1cfeSmrg} 656492e1cfeSmrg 657492e1cfeSmrg 658492e1cfeSmrg 659492e1cfeSmrgstatic void 660492e1cfeSmrgDestroy(Widget gw) 661492e1cfeSmrg{ 662492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 663492e1cfeSmrg 664492e1cfeSmrg XtReleaseGC (gw, fgw->fontgrid.text_gc); 665492e1cfeSmrg XtReleaseGC (gw, fgw->fontgrid.box_gc); 666492e1cfeSmrg} 667492e1cfeSmrg 668492e1cfeSmrg 669492e1cfeSmrgstatic void 670492e1cfeSmrgResize(Widget gw) 671492e1cfeSmrg{ 672492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 673492e1cfeSmrg 674492e1cfeSmrg /* recompute in case we've changed size */ 675492e1cfeSmrg fgw->fontgrid.cell_width = CellWidth (fgw); 676492e1cfeSmrg if (fgw->fontgrid.cell_width <= 0) 677492e1cfeSmrg fgw->fontgrid.cell_width = 1; 678492e1cfeSmrg fgw->fontgrid.cell_height = CellHeight (fgw); 679492e1cfeSmrg if (fgw->fontgrid.cell_height <= 0) 680492e1cfeSmrg fgw->fontgrid.cell_height = 1; 681492e1cfeSmrg fgw->fontgrid.xoff = (fgw->fontgrid.cell_width - 682492e1cfeSmrg DefaultCellWidth (fgw)) / 2; 683492e1cfeSmrg fgw->fontgrid.yoff = (fgw->fontgrid.cell_height - 684492e1cfeSmrg DefaultCellHeight (fgw)) / 2; 685492e1cfeSmrg 686492e1cfeSmrg} 687492e1cfeSmrg 688492e1cfeSmrg 689492e1cfeSmrg/* ARGSUSED */ 690492e1cfeSmrgstatic void 691492e1cfeSmrgRedisplay(Widget gw, XEvent *event, Region region) 692492e1cfeSmrg{ 693492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 694492e1cfeSmrg XRectangle rect; /* bounding rect for region */ 695492e1cfeSmrg int left, right, top, bottom; /* which cells were damaged */ 696492e1cfeSmrg int cw, ch; /* cell size */ 697492e1cfeSmrg 698492e1cfeSmrg#ifdef XRENDER 699492e1cfeSmrg if (!fgw->fontgrid.text_face) 700492e1cfeSmrg#endif 701492e1cfeSmrg if (!fgw->fontgrid.text_font) { 702492e1cfeSmrg Bell (gw, XkbBI_BadValue); 703492e1cfeSmrg return; 704492e1cfeSmrg } 705492e1cfeSmrg 706492e1cfeSmrg /* 707492e1cfeSmrg * compute the left, right, top, and bottom cells that were damaged 708492e1cfeSmrg */ 709492e1cfeSmrg XClipBox (region, &rect); 710492e1cfeSmrg cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width; 711492e1cfeSmrg ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width; 712492e1cfeSmrg if ((left = (((int) rect.x) / cw)) < 0) left = 0; 713492e1cfeSmrg right = (((int) (rect.x + rect.width - 1)) / cw); 714492e1cfeSmrg if ((top = (((int) rect.y) / ch)) < 0) top = 0; 715492e1cfeSmrg bottom = (((int) (rect.y + rect.height - 1)) / ch); 716492e1cfeSmrg 717492e1cfeSmrg paint_grid (fgw, left, top, right - left + 1, bottom - top + 1); 718492e1cfeSmrg} 719492e1cfeSmrg 720492e1cfeSmrg 721492e1cfeSmrgstatic void 722492e1cfeSmrgpaint_grid(FontGridWidget fgw, /* widget in which to draw */ 723492e1cfeSmrg int col, int row, /* where to start */ 724492e1cfeSmrg int ncols, int nrows) /* number of cells */ 725492e1cfeSmrg{ 726492e1cfeSmrg FontGridPart *p = &fgw->fontgrid; 727492e1cfeSmrg int i, j; 728492e1cfeSmrg Display *dpy = XtDisplay(fgw); 729492e1cfeSmrg Window wind = XtWindow(fgw); 730492e1cfeSmrg int cw = p->cell_width + p->grid_width; 731492e1cfeSmrg int ch = p->cell_height + p->grid_width; 732492e1cfeSmrg int tcols = p->cell_cols; 733492e1cfeSmrg int trows = p->cell_rows; 734492e1cfeSmrg int x1, y1, x2, y2, x, y; 735492e1cfeSmrg unsigned maxn = GridLastChar ((Widget) fgw); 736492e1cfeSmrg unsigned n, prevn; 737492e1cfeSmrg int startx; 738492e1cfeSmrg 739492e1cfeSmrg if (col + ncols >= tcols) { 740492e1cfeSmrg ncols = tcols - col; 741492e1cfeSmrg if (ncols < 1) return; 742492e1cfeSmrg } 743492e1cfeSmrg 744492e1cfeSmrg if (row + nrows >= trows) { 745492e1cfeSmrg nrows = trows - row; 746492e1cfeSmrg if (nrows < 1) return; 747492e1cfeSmrg } 748492e1cfeSmrg 749492e1cfeSmrg /* 750492e1cfeSmrg * paint the grid lines for the indicated rows 751492e1cfeSmrg */ 752492e1cfeSmrg if (p->grid_width > 0) { 753492e1cfeSmrg int half_grid_width = p->grid_width >> 1; 754492e1cfeSmrg x1 = col * cw + half_grid_width; 755492e1cfeSmrg y1 = row * ch + half_grid_width; 756492e1cfeSmrg x2 = x1 + ncols * cw; 757492e1cfeSmrg y2 = y1 + nrows * ch; 758492e1cfeSmrg for (i = 0, x = x1; i <= ncols; i++, x += cw) { 759492e1cfeSmrg XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2); 760492e1cfeSmrg } 761492e1cfeSmrg for (i = 0, y = y1; i <= nrows; i++, y += ch) { 762492e1cfeSmrg XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); 763492e1cfeSmrg } 764492e1cfeSmrg } 765492e1cfeSmrg /* 766492e1cfeSmrg * Draw a character in every box; treat all fonts as if they were 16bit 767492e1cfeSmrg * fonts. Store the high eight bits in byte1 and the low eight bits in 768492e1cfeSmrg * byte2. 769492e1cfeSmrg */ 770492e1cfeSmrg prevn = p->start_char + col + row * tcols; 771492e1cfeSmrg startx = col * cw + p->internal_pad + p->grid_width; 772492e1cfeSmrg for (j = 0, 773492e1cfeSmrg y = row * ch + p->internal_pad + p->grid_width + GridFontAscent (fgw); 774492e1cfeSmrg j < nrows; j++, y += ch) { 775492e1cfeSmrg n = prevn; 776492e1cfeSmrg for (i = 0, x = startx; i < ncols; i++, x += cw) { 777492e1cfeSmrg int xoff = p->xoff, yoff = p->yoff; 778492e1cfeSmrg if (n > maxn) goto done; /* no break out of nested */ 779492e1cfeSmrg 780492e1cfeSmrg#ifdef XRENDER 781492e1cfeSmrg if (fgw->fontgrid.text_face) 782492e1cfeSmrg { 783492e1cfeSmrg XftFont *xft = p->text_face; 784492e1cfeSmrg FcChar32 c = n; 785492e1cfeSmrg XGlyphInfo extents; 786492e1cfeSmrg XftTextExtents32 (dpy, xft, &c, 1, &extents); 787492e1cfeSmrg if (p->center_chars) 788492e1cfeSmrg { 789492e1cfeSmrg xoff = (p->cell_width - extents.width) / 2 - extents.x; 790492e1cfeSmrg yoff = (p->cell_height - extents.height) / 2 - extents.y; 791492e1cfeSmrg } 792492e1cfeSmrg if (extents.width && extents.height) 793492e1cfeSmrg { 794492e1cfeSmrg XClearArea (dpy, wind, x + xoff - extents.x, 795492e1cfeSmrg y + yoff - extents.y, 796492e1cfeSmrg extents.width, extents.height, False); 797492e1cfeSmrg if (p->box_chars) 798492e1cfeSmrg XDrawRectangle (dpy, wind, p->box_gc, 799492e1cfeSmrg x + xoff - extents.x, 800492e1cfeSmrg y + yoff - extents.y, 801492e1cfeSmrg extents.width - 1, 802492e1cfeSmrg extents.height - 1); 803492e1cfeSmrg } 804492e1cfeSmrg XftDrawString32 (p->draw, &p->fg_color, xft, 805492e1cfeSmrg x + xoff, y + yoff, &c, 1); 806492e1cfeSmrg } 807492e1cfeSmrg else 808492e1cfeSmrg#endif 809492e1cfeSmrg { 810492e1cfeSmrg XChar2b thechar; 811492e1cfeSmrg 812492e1cfeSmrg thechar.byte1 = (n >> 8); /* high eight bits */ 813492e1cfeSmrg thechar.byte2 = (n & 255); /* low eight bits */ 814492e1cfeSmrg if (p->box_chars || p->center_chars) { 815492e1cfeSmrg XCharStruct metrics; 816492e1cfeSmrg int direction, fontascent, fontdescent; 817492e1cfeSmrg 818492e1cfeSmrg XTextExtents16 (p->text_font, &thechar, 1, &direction, 819492e1cfeSmrg &fontascent, &fontdescent, &metrics); 820492e1cfeSmrg 821492e1cfeSmrg if (p->center_chars) { 822492e1cfeSmrg /* 823492e1cfeSmrg * We want to move the origin by enough to center the ink 824492e1cfeSmrg * within the cell. The left edge will then be at 825492e1cfeSmrg * (cell_width - (rbearing - lbearing)) / 2; so we subtract 826492e1cfeSmrg * the lbearing to find the origin. Ditto for vertical. 827492e1cfeSmrg */ 828492e1cfeSmrg xoff = (((p->cell_width - 829492e1cfeSmrg (metrics.rbearing - metrics.lbearing)) / 2) - 830492e1cfeSmrg p->internal_pad - metrics.lbearing); 831492e1cfeSmrg yoff = (((p->cell_height - 832492e1cfeSmrg (metrics.descent + metrics.ascent)) / 2) - 833492e1cfeSmrg p->internal_pad - 834492e1cfeSmrg p->text_font->ascent + metrics.ascent); 835492e1cfeSmrg } 836492e1cfeSmrg if (p->box_chars) { 837492e1cfeSmrg XDrawRectangle (dpy, wind, p->box_gc, 838492e1cfeSmrg x + xoff, y + yoff - p->text_font->ascent, 839492e1cfeSmrg metrics.width - 1, 840492e1cfeSmrg fontascent + fontdescent - 1); 841492e1cfeSmrg } 842492e1cfeSmrg } 843492e1cfeSmrg XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff, 844492e1cfeSmrg &thechar, 1); 845492e1cfeSmrg } 846492e1cfeSmrg n++; 847492e1cfeSmrg } 848492e1cfeSmrg prevn += tcols; 849492e1cfeSmrg } 850492e1cfeSmrg 851492e1cfeSmrg done: 852492e1cfeSmrg /* 853492e1cfeSmrg * paint the grid lines for the indicated rows 854492e1cfeSmrg */ 855492e1cfeSmrg if (p->grid_width > 0) { 856492e1cfeSmrg int half_grid_width = p->grid_width >> 1; 857492e1cfeSmrg x1 = col * cw + half_grid_width; 858492e1cfeSmrg y1 = row * ch + half_grid_width; 859492e1cfeSmrg x2 = x1 + ncols * cw; 860492e1cfeSmrg y2 = y1 + nrows * ch; 861492e1cfeSmrg for (i = 0, x = x1; i <= ncols; i++, x += cw) { 862492e1cfeSmrg XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2); 863492e1cfeSmrg } 864492e1cfeSmrg for (i = 0, y = y1; i <= nrows; i++, y += ch) { 865492e1cfeSmrg XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); 866492e1cfeSmrg } 867492e1cfeSmrg } 868492e1cfeSmrg 869492e1cfeSmrg 870492e1cfeSmrg return; 871492e1cfeSmrg} 872492e1cfeSmrg 873492e1cfeSmrgstatic Boolean 874492e1cfeSmrgPageBlank (Widget w, long first, long last) 875492e1cfeSmrg{ 876492e1cfeSmrg while (first <= last) 877492e1cfeSmrg { 878492e1cfeSmrg if (GridHasChar (w, first)) 879492e1cfeSmrg return False; 880492e1cfeSmrg first++; 881492e1cfeSmrg } 882492e1cfeSmrg return True; 883492e1cfeSmrg} 884492e1cfeSmrg 885492e1cfeSmrg/*ARGSUSED*/ 886492e1cfeSmrgstatic Boolean 887492e1cfeSmrgSetValues(Widget current, Widget request, Widget new, 888492e1cfeSmrg ArgList args, Cardinal *num_args) 889492e1cfeSmrg{ 890492e1cfeSmrg FontGridWidget curfg = (FontGridWidget) current; 891492e1cfeSmrg FontGridWidget newfg = (FontGridWidget) new; 892492e1cfeSmrg Boolean redisplay = FALSE; 893492e1cfeSmrg 894492e1cfeSmrg if (curfg->fontgrid.text_font != newfg->fontgrid.text_font || 895492e1cfeSmrg curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) { 896492e1cfeSmrg newfg->fontgrid.cell_width = DefaultCellWidth (newfg); 897492e1cfeSmrg newfg->fontgrid.cell_height = DefaultCellHeight (newfg); 898492e1cfeSmrg redisplay = TRUE; 899492e1cfeSmrg } 900492e1cfeSmrg 901492e1cfeSmrg if (GridForeground(curfg) != GridForeground (newfg)) { 902492e1cfeSmrg XtReleaseGC (new, curfg->fontgrid.text_gc); 903492e1cfeSmrg newfg->fontgrid.text_gc = get_gc (newfg, GridForeground (newfg)); 904492e1cfeSmrg redisplay = TRUE; 905492e1cfeSmrg } 906492e1cfeSmrg 907492e1cfeSmrg if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) { 908492e1cfeSmrg XtReleaseGC (new, curfg->fontgrid.text_gc); 909492e1cfeSmrg newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel); 910492e1cfeSmrg redisplay = TRUE; 911492e1cfeSmrg } 912492e1cfeSmrg 913492e1cfeSmrg if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars || 914492e1cfeSmrg curfg->fontgrid.box_chars != newfg->fontgrid.box_chars) 915492e1cfeSmrg redisplay = TRUE; 916492e1cfeSmrg 917492e1cfeSmrg if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) { 918492e1cfeSmrg long maxn = GridLastChar (new); 919492e1cfeSmrg long page = newfg->fontgrid.cell_cols * newfg->fontgrid.cell_rows; 920492e1cfeSmrg long dir = page; 921492e1cfeSmrg long start = newfg->fontgrid.start_char; 922492e1cfeSmrg 923492e1cfeSmrg if (start < curfg->fontgrid.start_char) 924492e1cfeSmrg dir = -page; 925492e1cfeSmrg 926492e1cfeSmrg if (start < 0) 927492e1cfeSmrg start = 0; 928492e1cfeSmrg if (start > maxn) 929492e1cfeSmrg start = (maxn / page) * page; 930492e1cfeSmrg 931492e1cfeSmrg while (PageBlank (new, start, start + page - 1)) 932492e1cfeSmrg { 933492e1cfeSmrg long next = start + dir; 934492e1cfeSmrg 935492e1cfeSmrg if (next < 0 || maxn < next) 936492e1cfeSmrg break; 937492e1cfeSmrg start = next; 938492e1cfeSmrg } 939492e1cfeSmrg 940492e1cfeSmrg newfg->fontgrid.start_char = start; 941492e1cfeSmrg redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char); 942492e1cfeSmrg } 943492e1cfeSmrg 944492e1cfeSmrg return redisplay; 945492e1cfeSmrg} 946492e1cfeSmrg 947492e1cfeSmrg 948492e1cfeSmrg/* ARGSUSED */ 949492e1cfeSmrgstatic void 950492e1cfeSmrgNotify(Widget gw, XEvent *event, String *params, Cardinal *nparams) 951492e1cfeSmrg{ 952492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 953492e1cfeSmrg int x, y; /* where the event happened */ 954492e1cfeSmrg FontGridCharRec rec; /* callback data */ 955492e1cfeSmrg 956492e1cfeSmrg /* 957492e1cfeSmrg * only allow events with (x,y) 958492e1cfeSmrg */ 959492e1cfeSmrg switch (event->type) { 960492e1cfeSmrg case KeyPress: 961492e1cfeSmrg case KeyRelease: 962492e1cfeSmrg x = event->xkey.x; 963492e1cfeSmrg y = event->xkey.y; 964492e1cfeSmrg break; 965492e1cfeSmrg case ButtonPress: 966492e1cfeSmrg case ButtonRelease: 967492e1cfeSmrg x = event->xbutton.x; 968492e1cfeSmrg y = event->xbutton.y; 969492e1cfeSmrg break; 970492e1cfeSmrg case MotionNotify: 971492e1cfeSmrg x = event->xmotion.x; 972492e1cfeSmrg y = event->xmotion.y; 973492e1cfeSmrg break; 974492e1cfeSmrg default: 975492e1cfeSmrg Bell (gw, XkbBI_Ignore); 976492e1cfeSmrg return; 977492e1cfeSmrg } 978492e1cfeSmrg 979492e1cfeSmrg /* 980492e1cfeSmrg * compute the callback data 981492e1cfeSmrg */ 982492e1cfeSmrg { 983492e1cfeSmrg int cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width; 984492e1cfeSmrg int ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width; 985492e1cfeSmrg unsigned n; 986492e1cfeSmrg 987492e1cfeSmrg if (x > (fgw->fontgrid.cell_cols * cw)) { 988492e1cfeSmrg Bell (gw, XkbBI_InvalidLocation); 989492e1cfeSmrg return; 990492e1cfeSmrg } 991492e1cfeSmrg 992492e1cfeSmrg n= (fgw->fontgrid.start_char + 993492e1cfeSmrg ((y / ch) * fgw->fontgrid.cell_cols) + (x / cw)); 994492e1cfeSmrg 995492e1cfeSmrg rec.thefont = fgw->fontgrid.text_font; 996492e1cfeSmrg#ifdef XRENDER 997492e1cfeSmrg rec.theface = fgw->fontgrid.text_face; 998492e1cfeSmrg#endif 999492e1cfeSmrg rec.thechar = n; 1000492e1cfeSmrg } 1001492e1cfeSmrg 1002492e1cfeSmrg XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec); 1003492e1cfeSmrg} 1004492e1cfeSmrg 1005