1492e1cfeSmrg/* 23538fbe3Smrg * 3492e1cfeSmrgCopyright 1989, 1998 The Open Group 4492e1cfeSmrg 5492e1cfeSmrgPermission to use, copy, modify, distribute, and sell this software and its 6492e1cfeSmrgdocumentation for any purpose is hereby granted without fee, provided that 7492e1cfeSmrgthe above copyright notice appear in all copies and that both that 8492e1cfeSmrgcopyright notice and this permission notice appear in supporting 9492e1cfeSmrgdocumentation. 10492e1cfeSmrg 11492e1cfeSmrgThe above copyright notice and this permission notice shall be included in 12492e1cfeSmrgall copies or substantial portions of the Software. 13492e1cfeSmrg 14492e1cfeSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15492e1cfeSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16492e1cfeSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17492e1cfeSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18492e1cfeSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19492e1cfeSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20492e1cfeSmrg 21492e1cfeSmrgExcept as contained in this notice, the name of The Open Group shall not be 22492e1cfeSmrgused in advertising or otherwise to promote the sale, use or other dealings 23492e1cfeSmrgin this Software without prior written authorization from The Open Group. 241afad795Smrg * 25492e1cfeSmrg * Author: Jim Fulton, MIT X Consortium 26492e1cfeSmrg */ 27492e1cfeSmrg 28b78bb896Smrg#ifdef HAVE_CONFIG_H 29b78bb896Smrg# include "config.h" 30b78bb896Smrg#endif 31b78bb896Smrg 32492e1cfeSmrg#include <X11/IntrinsicP.h> 33492e1cfeSmrg#include <X11/StringDefs.h> 34492e1cfeSmrg#include <X11/Xaw/SimpleP.h> 35492e1cfeSmrg#include <X11/Xmu/Converters.h> 36492e1cfeSmrg#include <X11/Xos.h> 37492e1cfeSmrg#include "gridP.h" 38492e1cfeSmrg 39492e1cfeSmrg#ifdef XKB 40492e1cfeSmrg#include <X11/extensions/XKBbells.h> 41492e1cfeSmrg#else 42492e1cfeSmrg#define XkbBI_MinorError 2 43492e1cfeSmrg#define XkbBI_Ignore 11 44492e1cfeSmrg#endif 45492e1cfeSmrg 46492e1cfeSmrg#ifdef XKB 47492e1cfeSmrg#define Bell(w,n) XkbStdBell(XtDisplay(w), XtWindow(w), 50, n) 48492e1cfeSmrg#else 49492e1cfeSmrg#define Bell(w,n) XBell(XtDisplay(w), 0) 50492e1cfeSmrg#endif 51492e1cfeSmrg 52492e1cfeSmrgstatic GC get_gc(FontGridWidget fgw, Pixel fore); 53492e1cfeSmrgstatic void ClassInitialize(void); 543538fbe3Smrgstatic void Initialize(Widget request, Widget new, ArgList args, 55492e1cfeSmrg Cardinal *num_args); 563538fbe3Smrgstatic void Realize(Widget gw, Mask *valueMask, 57492e1cfeSmrg XSetWindowAttributes *attributes); 58492e1cfeSmrgstatic void Destroy(Widget gw); 59492e1cfeSmrgstatic void Resize(Widget gw); 60492e1cfeSmrgstatic void Redisplay(Widget gw, XEvent *event, Region region); 613538fbe3Smrgstatic void paint_grid(FontGridWidget fgw, int col, int row, 62492e1cfeSmrg int ncols, int nrows); 633538fbe3Smrgstatic Boolean SetValues(Widget current, Widget request, Widget new, 64492e1cfeSmrg ArgList args, Cardinal *num_args); 653538fbe3Smrgstatic void Notify(Widget gw, XEvent *event, String *params, 66492e1cfeSmrg Cardinal *nparams); 67492e1cfeSmrg 68492e1cfeSmrg#define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field) 69492e1cfeSmrg 70492e1cfeSmrgstatic XtResource resources[] = { 71492e1cfeSmrg { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 72492e1cfeSmrg Offset(text_font), XtRString, (XtPointer) NULL }, 73492e1cfeSmrg { XtNcellColumns, XtCCellColumns, XtRInt, sizeof(int), 74492e1cfeSmrg Offset(cell_cols), XtRImmediate, (XtPointer) 0 }, 75492e1cfeSmrg { XtNcellRows, XtCCellRows, XtRInt, sizeof(int), 76492e1cfeSmrg Offset(cell_rows), XtRImmediate, (XtPointer) 0 }, 77492e1cfeSmrg { XtNcellWidth, XtCCellWidth, XtRInt, sizeof(int), 78492e1cfeSmrg Offset(cell_width), XtRImmediate, (XtPointer) 0 }, 79492e1cfeSmrg { XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int), 80492e1cfeSmrg Offset(cell_height), XtRImmediate, (XtPointer) 0 }, 81492e1cfeSmrg { XtNstartChar, XtCStartChar, XtRLong, sizeof(long), 82492e1cfeSmrg Offset(start_char), XtRImmediate, (XtPointer) 0xffffffff }, 83492e1cfeSmrg#ifndef XRENDER 84492e1cfeSmrg { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 85492e1cfeSmrg Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground }, 86492e1cfeSmrg#endif 87492e1cfeSmrg { XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean), 88492e1cfeSmrg Offset(center_chars), XtRImmediate, (XtPointer) FALSE }, 89492e1cfeSmrg { XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean), 90492e1cfeSmrg Offset(box_chars), XtRImmediate, (XtPointer) FALSE }, 91492e1cfeSmrg { XtNboxColor, XtCForeground, XtRPixel, sizeof(Pixel), 92492e1cfeSmrg Offset(box_pixel), XtRString, (XtPointer) XtDefaultForeground }, 93492e1cfeSmrg { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), 94492e1cfeSmrg Offset(callbacks), XtRCallback, (XtPointer) NULL }, 95492e1cfeSmrg { XtNinternalPad, XtCInternalPad, XtRInt, sizeof(int), 96492e1cfeSmrg Offset(internal_pad), XtRImmediate, (XtPointer) 4 }, 97492e1cfeSmrg { XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int), 98492e1cfeSmrg Offset(grid_width), XtRImmediate, (XtPointer) 1 }, 99492e1cfeSmrg#ifdef XRENDER 100492e1cfeSmrg {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor), 101492e1cfeSmrg Offset(fg_color), XtRString, XtDefaultForeground}, 102492e1cfeSmrg {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *), 1039e0146f7Smrg Offset (text_face), XtRString, NULL}, 104492e1cfeSmrg#endif 105492e1cfeSmrg}; 106492e1cfeSmrg 107492e1cfeSmrg#undef Offset 108492e1cfeSmrg 1093538fbe3Smrgstatic char defaultTranslations[] = 110492e1cfeSmrg "<ButtonPress>: notify()"; 111492e1cfeSmrg 112492e1cfeSmrgstatic XtActionsRec actions_list[] = { 113492e1cfeSmrg { "notify", Notify }, 114492e1cfeSmrg}; 115492e1cfeSmrg 116492e1cfeSmrgFontGridClassRec fontgridClassRec = { 117492e1cfeSmrg { /* core fields */ 118492e1cfeSmrg /* superclass */ (WidgetClass) &simpleClassRec, 119492e1cfeSmrg /* class_name */ "FontGrid", 120492e1cfeSmrg /* widget_size */ sizeof(FontGridRec), 121492e1cfeSmrg /* class_initialize */ ClassInitialize, 122492e1cfeSmrg /* class_part_initialize */ NULL, 123492e1cfeSmrg /* class_inited */ FALSE, 124492e1cfeSmrg /* initialize */ Initialize, 125492e1cfeSmrg /* initialize_hook */ NULL, 126492e1cfeSmrg /* realize */ Realize, 127492e1cfeSmrg /* actions */ actions_list, 128492e1cfeSmrg /* num_actions */ XtNumber(actions_list), 129492e1cfeSmrg /* resources */ resources, 130492e1cfeSmrg /* num_resources */ XtNumber(resources), 131492e1cfeSmrg /* xrm_class */ NULLQUARK, 132492e1cfeSmrg /* compress_motion */ TRUE, 133492e1cfeSmrg /* compress_exposure */ TRUE, 134492e1cfeSmrg /* compress_enterleave */ TRUE, 135492e1cfeSmrg /* visible_interest */ FALSE, 136492e1cfeSmrg /* destroy */ Destroy, 137492e1cfeSmrg /* resize */ Resize, 138492e1cfeSmrg /* expose */ Redisplay, 139492e1cfeSmrg /* set_values */ SetValues, 140492e1cfeSmrg /* set_values_hook */ NULL, 141492e1cfeSmrg /* set_values_almost */ XtInheritSetValuesAlmost, 142492e1cfeSmrg /* get_values_hook */ NULL, 143492e1cfeSmrg /* accept_focus */ NULL, 144492e1cfeSmrg /* version */ XtVersion, 145492e1cfeSmrg /* callback_private */ NULL, 146492e1cfeSmrg /* tm_table */ defaultTranslations, 147492e1cfeSmrg /* query_geometry */ XtInheritQueryGeometry, 148492e1cfeSmrg /* display_accelerator */ XtInheritDisplayAccelerator, 149492e1cfeSmrg /* extension */ NULL 150492e1cfeSmrg }, 151492e1cfeSmrg { /* simple fields */ 15231e5d586Smrg /* change_sensitive */ XtInheritChangeSensitive, 15331e5d586Smrg /* extension */ NULL 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 173492e1cfeSmrg first = FcCharSetFirstPage (xft->charset, map, &next); 17431e5d586Smrg for (int i = 0; i < FC_CHARSET_MAP_SIZE; i++) 175492e1cfeSmrg if (map[i]) 176492e1cfeSmrg { 177492e1cfeSmrg FcChar32 bits = map[i]; 178492e1cfeSmrg first += i * 32; 179492e1cfeSmrg while (!(bits & 0x1)) 180492e1cfeSmrg { 181492e1cfeSmrg bits >>= 1; 182492e1cfeSmrg first++; 183492e1cfeSmrg } 184492e1cfeSmrg break; 185492e1cfeSmrg } 186492e1cfeSmrg return first; 187492e1cfeSmrg } 188492e1cfeSmrg else 189492e1cfeSmrg#endif 190492e1cfeSmrg if (fs) 191492e1cfeSmrg { 192492e1cfeSmrg return (fs->min_byte1 << 8) | (fs->min_char_or_byte2); 193492e1cfeSmrg } 194492e1cfeSmrg else 195492e1cfeSmrg return 0; 196492e1cfeSmrg} 197492e1cfeSmrg 198492e1cfeSmrglong 199492e1cfeSmrgGridLastChar (Widget w) 200492e1cfeSmrg{ 201492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 202492e1cfeSmrg XFontStruct *fs = fgw->fontgrid.text_font; 203492e1cfeSmrg#ifdef XRENDER 204492e1cfeSmrg XftFont *xft = fgw->fontgrid.text_face; 205492e1cfeSmrg if (xft) 206492e1cfeSmrg { 207492e1cfeSmrg FcChar32 this, last, next; 208492e1cfeSmrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 20931e5d586Smrg 210492e1cfeSmrg last = FcCharSetFirstPage (xft->charset, map, &next); 211492e1cfeSmrg while ((this = FcCharSetNextPage (xft->charset, map, &next)) != FC_CHARSET_DONE) 212492e1cfeSmrg last = this; 213492e1cfeSmrg last &= ~0xff; 21431e5d586Smrg for (int i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--) 215492e1cfeSmrg if (map[i]) 216492e1cfeSmrg { 217492e1cfeSmrg FcChar32 bits = map[i]; 218492e1cfeSmrg last += i * 32 + 31; 219492e1cfeSmrg while (!(bits & 0x80000000)) 220492e1cfeSmrg { 221492e1cfeSmrg last--; 222492e1cfeSmrg bits <<= 1; 223492e1cfeSmrg } 224492e1cfeSmrg break; 225492e1cfeSmrg } 226492e1cfeSmrg return (long) last; 227492e1cfeSmrg } 228492e1cfeSmrg else 229492e1cfeSmrg#endif 230492e1cfeSmrg if (fs) 231492e1cfeSmrg { 232492e1cfeSmrg return (fs->max_byte1 << 8) | (fs->max_char_or_byte2); 233492e1cfeSmrg } 234492e1cfeSmrg else 235492e1cfeSmrg return 0; 236492e1cfeSmrg} 237492e1cfeSmrg 238492e1cfeSmrg/* 239492e1cfeSmrg * CI_GET_CHAR_INFO_1D - return the charinfo struct for the indicated 8bit 240492e1cfeSmrg * character. If the character is in the column and exists, then return the 241492e1cfeSmrg * appropriate metrics (note that fonts with common per-character metrics will 242492e1cfeSmrg * return min_bounds). 243492e1cfeSmrg */ 244492e1cfeSmrg 245492e1cfeSmrg#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ 246492e1cfeSmrg (((cs)->rbearing|(cs)->lbearing| \ 247492e1cfeSmrg (cs)->ascent|(cs)->descent) == 0)) 248492e1cfeSmrg 249492e1cfeSmrg#define CI_GET_CHAR_INFO_1D(fs,col,cs) \ 25031e5d586Smrgdo { \ 2519e0146f7Smrg cs = NULL; \ 252492e1cfeSmrg if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 253492e1cfeSmrg if (fs->per_char == NULL) { \ 254492e1cfeSmrg cs = &fs->min_bounds; \ 255492e1cfeSmrg } else { \ 256492e1cfeSmrg cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ 257492e1cfeSmrg } \ 258492e1cfeSmrg if (CI_NONEXISTCHAR(cs)) \ 2599e0146f7Smrg cs = NULL; \ 260492e1cfeSmrg } \ 26131e5d586Smrg} while (0) 262492e1cfeSmrg 263492e1cfeSmrg/* 2643538fbe3Smrg * CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and 265492e1cfeSmrg * column. This is used for fonts that have more than row zero. 266492e1cfeSmrg */ 267492e1cfeSmrg#define CI_GET_CHAR_INFO_2D(fs,row,col,cs) \ 26831e5d586Smrgdo { \ 2699e0146f7Smrg cs = NULL; \ 270492e1cfeSmrg if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ 271492e1cfeSmrg col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 272492e1cfeSmrg if (fs->per_char == NULL) { \ 273492e1cfeSmrg cs = &fs->min_bounds; \ 274492e1cfeSmrg } else { \ 275492e1cfeSmrg cs = &fs->per_char[((row - fs->min_byte1) * \ 276492e1cfeSmrg (fs->max_char_or_byte2 - \ 277492e1cfeSmrg fs->min_char_or_byte2 + 1)) + \ 278492e1cfeSmrg (col - fs->min_char_or_byte2)]; \ 279492e1cfeSmrg } \ 280492e1cfeSmrg if (CI_NONEXISTCHAR(cs)) \ 2819e0146f7Smrg cs = NULL; \ 282492e1cfeSmrg } \ 28331e5d586Smrg} while (0) 284492e1cfeSmrg 285492e1cfeSmrgstatic Boolean 286492e1cfeSmrgGridHasChar (Widget w, long ch) 287492e1cfeSmrg{ 288492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 289492e1cfeSmrg#ifdef XRENDER 290492e1cfeSmrg XftFont *xft = fgw->fontgrid.text_face; 291492e1cfeSmrg if (xft) 292492e1cfeSmrg { 293492e1cfeSmrg return FcCharSetHasChar (xft->charset, (FcChar32) ch); 294492e1cfeSmrg } 295492e1cfeSmrg else 296492e1cfeSmrg#endif 297492e1cfeSmrg { 298492e1cfeSmrg XFontStruct *fs = fgw->fontgrid.text_font; 299492e1cfeSmrg XCharStruct *cs; 3003538fbe3Smrg 301492e1cfeSmrg if (!fs) 302492e1cfeSmrg return False; 303492e1cfeSmrg if (fs->max_byte1 == 0) 304492e1cfeSmrg { 305492e1cfeSmrg CI_GET_CHAR_INFO_1D (fs, ch, cs); 306492e1cfeSmrg } 307492e1cfeSmrg else 308492e1cfeSmrg { 309492e1cfeSmrg unsigned int r = (ch >> 8); 310492e1cfeSmrg unsigned int c = (ch & 0xff); 311492e1cfeSmrg CI_GET_CHAR_INFO_2D (fs, r, c, cs); 312492e1cfeSmrg } 3139e0146f7Smrg return cs != NULL; 314492e1cfeSmrg } 315492e1cfeSmrg} 316492e1cfeSmrg 317492e1cfeSmrg/* 318492e1cfeSmrg * public routines 319492e1cfeSmrg */ 320492e1cfeSmrg 3213538fbe3Smrgvoid 3223538fbe3SmrgGetFontGridCellDimensions(Widget w, long *startp, 323492e1cfeSmrg int *ncolsp, int *nrowsp) 324492e1cfeSmrg{ 325492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 326492e1cfeSmrg *startp = fgw->fontgrid.start_char; 327492e1cfeSmrg *ncolsp = fgw->fontgrid.cell_cols; 328492e1cfeSmrg *nrowsp = fgw->fontgrid.cell_rows; 329492e1cfeSmrg} 330492e1cfeSmrg 331492e1cfeSmrg 3323538fbe3Smrgvoid 333492e1cfeSmrgGetPrevNextStates(Widget w, Bool *prevvalidp, Bool *nextvalidp, 334492e1cfeSmrg Bool *prev16validp, Bool *next16validp) 335492e1cfeSmrg{ 336492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) w; 337492e1cfeSmrg long minn = (long) GridFirstChar (w); 338492e1cfeSmrg long maxn = (long) GridLastChar (w); 339492e1cfeSmrg 340492e1cfeSmrg *prev16validp = (fgw->fontgrid.start_char - 0xf00 > minn); 341492e1cfeSmrg *prevvalidp = (fgw->fontgrid.start_char > minn); 342492e1cfeSmrg *nextvalidp = (fgw->fontgrid.start_char + 343492e1cfeSmrg (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows) 344492e1cfeSmrg < maxn); 345492e1cfeSmrg *next16validp =((fgw->fontgrid.start_char + 0xf00 + 346492e1cfeSmrg (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows)) 347492e1cfeSmrg < maxn); 348492e1cfeSmrg} 349492e1cfeSmrg 350492e1cfeSmrg 351492e1cfeSmrg 352492e1cfeSmrg/* 353492e1cfeSmrg * private routines and methods 354492e1cfeSmrg */ 355492e1cfeSmrg 356492e1cfeSmrg 3573538fbe3Smrgstatic GC 358492e1cfeSmrgget_gc(FontGridWidget fgw, Pixel fore) 359492e1cfeSmrg{ 360492e1cfeSmrg XtGCMask mask; 361492e1cfeSmrg XGCValues gcv; 362492e1cfeSmrg 363492e1cfeSmrg mask = (GCForeground | GCBackground | GCFunction); 364492e1cfeSmrg gcv.foreground = fore; 365492e1cfeSmrg gcv.background = fgw->core.background_pixel; 366492e1cfeSmrg gcv.function = GXcopy; 367492e1cfeSmrg if (fgw->fontgrid.text_font) 368492e1cfeSmrg { 369492e1cfeSmrg mask |= GCFont; 370492e1cfeSmrg gcv.font = fgw->fontgrid.text_font->fid; 371492e1cfeSmrg } 372492e1cfeSmrg gcv.cap_style = CapProjecting; 373492e1cfeSmrg mask |= GCCapStyle; 374492e1cfeSmrg if (fgw->fontgrid.grid_width > 0) { 375492e1cfeSmrg mask |= GCLineWidth; 3763538fbe3Smrg gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 : 377492e1cfeSmrg fgw->fontgrid.grid_width); 378492e1cfeSmrg } 379492e1cfeSmrg return (XtGetGC ((Widget) fgw, mask, &gcv)); 380492e1cfeSmrg} 381492e1cfeSmrg 382492e1cfeSmrg 383492e1cfeSmrg#ifdef XRENDER 3849e0146f7Smrgstatic XtConvertArgRec xftColorConvertArgs[] = { 385492e1cfeSmrg {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 386492e1cfeSmrg sizeof(Screen *)}, 387492e1cfeSmrg {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), 388492e1cfeSmrg sizeof(Colormap)} 389492e1cfeSmrg}; 390492e1cfeSmrg 391492e1cfeSmrg#define donestr(type, value, tstr) \ 39231e5d586Smrg do { \ 393492e1cfeSmrg if (toVal->addr != NULL) { \ 394492e1cfeSmrg if (toVal->size < sizeof(type)) { \ 395492e1cfeSmrg toVal->size = sizeof(type); \ 396492e1cfeSmrg XtDisplayStringConversionWarning(dpy, \ 397492e1cfeSmrg (char*) fromVal->addr, tstr); \ 398492e1cfeSmrg return False; \ 399492e1cfeSmrg } \ 400492e1cfeSmrg *(type*)(toVal->addr) = (value); \ 401492e1cfeSmrg } \ 402492e1cfeSmrg else { \ 403492e1cfeSmrg static type static_val; \ 404492e1cfeSmrg static_val = (value); \ 405492e1cfeSmrg toVal->addr = (XPointer)&static_val; \ 406492e1cfeSmrg } \ 407492e1cfeSmrg toVal->size = sizeof(type); \ 408492e1cfeSmrg return True; \ 40931e5d586Smrg } while (0) 410492e1cfeSmrg 411492e1cfeSmrgstatic void 41231e5d586SmrgXmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, 41331e5d586Smrg XtPointer closure _X_UNUSED, 414492e1cfeSmrg XrmValuePtr args, Cardinal *num_args) 415492e1cfeSmrg{ 416492e1cfeSmrg Screen *screen; 417492e1cfeSmrg Colormap colormap; 418492e1cfeSmrg XftColor *color; 4193538fbe3Smrg 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} 4383538fbe3Smrg 439492e1cfeSmrgstatic Boolean 440492e1cfeSmrgXmuCvtStringToXftColor(Display *dpy, 441492e1cfeSmrg XrmValue *args, Cardinal *num_args, 442492e1cfeSmrg XrmValue *fromVal, XrmValue *toVal, 44331e5d586Smrg XtPointer *converter_data _X_UNUSED) 444492e1cfeSmrg{ 445492e1cfeSmrg char *spec; 446492e1cfeSmrg XRenderColor renderColor; 447492e1cfeSmrg XftColor xftColor; 448492e1cfeSmrg Screen *screen; 449492e1cfeSmrg Colormap colormap; 4503538fbe3Smrg 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; 4813538fbe3Smrg if (!XftColorAllocValue (dpy, 482492e1cfeSmrg DefaultVisual (dpy, 483492e1cfeSmrg XScreenNumberOfScreen (screen)), 484492e1cfeSmrg colormap, 485492e1cfeSmrg &renderColor, 486492e1cfeSmrg &xftColor)) 487492e1cfeSmrg return False; 4883538fbe3Smrg 489492e1cfeSmrg donestr (XftColor, xftColor, XtRXftColor); 490492e1cfeSmrg} 491492e1cfeSmrg 492492e1cfeSmrgstatic void 49331e5d586SmrgXmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure _X_UNUSED, 494492e1cfeSmrg XrmValuePtr args, Cardinal *num_args) 495492e1cfeSmrg{ 496492e1cfeSmrg Screen *screen; 497492e1cfeSmrg XftFont *font; 4983538fbe3Smrg 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, 51931e5d586Smrg XtPointer *converter_data _X_UNUSED) 520492e1cfeSmrg{ 521492e1cfeSmrg char *name; 522492e1cfeSmrg XftFont *font; 523492e1cfeSmrg Screen *screen; 5243538fbe3Smrg 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 XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont); 546492e1cfeSmrg } 547492e1cfeSmrg donestr (XftFont *, font, XtRXftFont); 548492e1cfeSmrg} 549492e1cfeSmrg 550492e1cfeSmrgstatic XtConvertArgRec xftFontConvertArgs[] = { 551492e1cfeSmrg {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 552492e1cfeSmrg sizeof(Screen *)}, 553492e1cfeSmrg}; 554492e1cfeSmrg 555492e1cfeSmrg#endif 556492e1cfeSmrg 5573538fbe3Smrgstatic void 558492e1cfeSmrgClassInitialize(void) 559492e1cfeSmrg{ 560492e1cfeSmrg XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0); 561492e1cfeSmrg#ifdef XRENDER 5623538fbe3Smrg XtSetTypeConverter (XtRString, XtRXftColor, 5633538fbe3Smrg XmuCvtStringToXftColor, 564492e1cfeSmrg xftColorConvertArgs, XtNumber(xftColorConvertArgs), 565492e1cfeSmrg XtCacheByDisplay, XmuFreeXftColor); 566492e1cfeSmrg XtSetTypeConverter (XtRString, XtRXftFont, 567492e1cfeSmrg XmuCvtStringToXftFont, 568492e1cfeSmrg xftFontConvertArgs, XtNumber(xftFontConvertArgs), 569492e1cfeSmrg XtCacheByDisplay, XmuFreeXftFont); 570492e1cfeSmrg#endif 571492e1cfeSmrg} 572492e1cfeSmrg 573492e1cfeSmrg 5743538fbe3Smrgstatic void 57531e5d586SmrgInitialize(Widget request, Widget new, 57631e5d586Smrg ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 577492e1cfeSmrg{ 578492e1cfeSmrg FontGridWidget reqfg = (FontGridWidget) request; 579492e1cfeSmrg FontGridWidget newfg = (FontGridWidget) new; 580492e1cfeSmrg XFontStruct *fs = newfg->fontgrid.text_font; 581492e1cfeSmrg#ifdef XRENDER 582492e1cfeSmrg XftFont *xft = newfg->fontgrid.text_face; 583492e1cfeSmrg#endif 584492e1cfeSmrg unsigned maxn; 585492e1cfeSmrg 586492e1cfeSmrg if (reqfg->fontgrid.cell_cols <= 0) 587492e1cfeSmrg newfg->fontgrid.cell_cols = 16; 588492e1cfeSmrg 589492e1cfeSmrg if (reqfg->fontgrid.cell_rows <= 0) { 590492e1cfeSmrg#ifdef XRENDER 591492e1cfeSmrg if (xft) 592492e1cfeSmrg newfg->fontgrid.cell_rows = 16; 593492e1cfeSmrg else 594492e1cfeSmrg#endif 595492e1cfeSmrg if (fs && fs->max_byte1 == 0) { 5963538fbe3Smrg newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 / 597492e1cfeSmrg newfg->fontgrid.cell_cols) + 1; 598492e1cfeSmrg if (newfg->fontgrid.cell_rows > 16) 599492e1cfeSmrg newfg->fontgrid.cell_rows = 16; 600492e1cfeSmrg } else 601492e1cfeSmrg newfg->fontgrid.cell_rows = 16; 602492e1cfeSmrg } 603492e1cfeSmrg 604492e1cfeSmrg if (reqfg->fontgrid.cell_width <= 0) 605492e1cfeSmrg newfg->fontgrid.cell_width = DefaultCellWidth (newfg); 606492e1cfeSmrg if (reqfg->fontgrid.cell_height <= 0) 607492e1cfeSmrg newfg->fontgrid.cell_height = DefaultCellHeight (newfg); 608492e1cfeSmrg 609492e1cfeSmrg /* give a nice size that fits one screen full */ 610492e1cfeSmrg if (newfg->core.width == 0) 611492e1cfeSmrg newfg->core.width = (newfg->fontgrid.cell_width * 612492e1cfeSmrg newfg->fontgrid.cell_cols + 613492e1cfeSmrg newfg->fontgrid.grid_width * 614492e1cfeSmrg (newfg->fontgrid.cell_cols + 1)); 615492e1cfeSmrg 6163538fbe3Smrg if (newfg->core.height == 0) 6173538fbe3Smrg newfg->core.height = (newfg->fontgrid.cell_height * 618492e1cfeSmrg newfg->fontgrid.cell_rows + 619492e1cfeSmrg newfg->fontgrid.grid_width * 620492e1cfeSmrg (newfg->fontgrid.cell_rows + 1)); 621492e1cfeSmrg 622492e1cfeSmrg /* 623492e1cfeSmrg * select the first character 624492e1cfeSmrg */ 625492e1cfeSmrg 626492e1cfeSmrg if (newfg->fontgrid.start_char == 0xffffffff) 627492e1cfeSmrg newfg->fontgrid.start_char = GridFirstChar(new) & ~0xff; 628492e1cfeSmrg maxn = GridLastChar (new); 6293538fbe3Smrg if (newfg->fontgrid.start_char > maxn) 6303538fbe3Smrg newfg->fontgrid.start_char = (maxn + 1 - 6313538fbe3Smrg (newfg->fontgrid.cell_cols * 632492e1cfeSmrg newfg->fontgrid.cell_rows)); 633492e1cfeSmrg} 634492e1cfeSmrg 6353538fbe3Smrgstatic void 636492e1cfeSmrgRealize(Widget gw, Mask *valueMask, XSetWindowAttributes *attributes) 637492e1cfeSmrg{ 638492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 639492e1cfeSmrg FontGridPart *p = &fgw->fontgrid; 640492e1cfeSmrg 641492e1cfeSmrg p->text_gc = get_gc (fgw, GridForeground (fgw)); 642492e1cfeSmrg p->box_gc = get_gc (fgw, p->box_pixel); 643492e1cfeSmrg Resize (gw); 644492e1cfeSmrg 645492e1cfeSmrg (*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes); 646492e1cfeSmrg#ifdef XRENDER 647492e1cfeSmrg p->draw = XftDrawCreate (XtDisplay (gw), XtWindow (gw), 648492e1cfeSmrg DefaultVisual (XtDisplay (gw), 649492e1cfeSmrg DefaultScreen(XtDisplay (gw))), 650492e1cfeSmrg fgw->core.colormap); 651492e1cfeSmrg#endif 652492e1cfeSmrg return; 653492e1cfeSmrg} 654492e1cfeSmrg 655492e1cfeSmrg 656492e1cfeSmrg 6573538fbe3Smrgstatic void 658492e1cfeSmrgDestroy(Widget gw) 659492e1cfeSmrg{ 660492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 661492e1cfeSmrg 662492e1cfeSmrg XtReleaseGC (gw, fgw->fontgrid.text_gc); 663492e1cfeSmrg XtReleaseGC (gw, fgw->fontgrid.box_gc); 664492e1cfeSmrg} 665492e1cfeSmrg 666492e1cfeSmrg 6673538fbe3Smrgstatic void 668492e1cfeSmrgResize(Widget gw) 669492e1cfeSmrg{ 670492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 671492e1cfeSmrg 672492e1cfeSmrg /* recompute in case we've changed size */ 673492e1cfeSmrg fgw->fontgrid.cell_width = CellWidth (fgw); 674492e1cfeSmrg if (fgw->fontgrid.cell_width <= 0) 675492e1cfeSmrg fgw->fontgrid.cell_width = 1; 676492e1cfeSmrg fgw->fontgrid.cell_height = CellHeight (fgw); 677492e1cfeSmrg if (fgw->fontgrid.cell_height <= 0) 678492e1cfeSmrg fgw->fontgrid.cell_height = 1; 679492e1cfeSmrg fgw->fontgrid.xoff = (fgw->fontgrid.cell_width - 680492e1cfeSmrg DefaultCellWidth (fgw)) / 2; 681492e1cfeSmrg fgw->fontgrid.yoff = (fgw->fontgrid.cell_height - 682492e1cfeSmrg DefaultCellHeight (fgw)) / 2; 683492e1cfeSmrg 684492e1cfeSmrg} 685492e1cfeSmrg 686492e1cfeSmrg 687492e1cfeSmrg/* ARGSUSED */ 6883538fbe3Smrgstatic void 68931e5d586SmrgRedisplay(Widget gw, XEvent *event _X_UNUSED, Region region) 690492e1cfeSmrg{ 691492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 692492e1cfeSmrg XRectangle rect; /* bounding rect for region */ 693492e1cfeSmrg int left, right, top, bottom; /* which cells were damaged */ 694492e1cfeSmrg int cw, ch; /* cell size */ 695492e1cfeSmrg 696492e1cfeSmrg#ifdef XRENDER 697492e1cfeSmrg if (!fgw->fontgrid.text_face) 698492e1cfeSmrg#endif 699492e1cfeSmrg if (!fgw->fontgrid.text_font) { 700492e1cfeSmrg Bell (gw, XkbBI_BadValue); 701492e1cfeSmrg return; 702492e1cfeSmrg } 703492e1cfeSmrg 704492e1cfeSmrg /* 705492e1cfeSmrg * compute the left, right, top, and bottom cells that were damaged 706492e1cfeSmrg */ 707492e1cfeSmrg XClipBox (region, &rect); 708492e1cfeSmrg cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width; 709492e1cfeSmrg ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width; 710492e1cfeSmrg if ((left = (((int) rect.x) / cw)) < 0) left = 0; 711492e1cfeSmrg right = (((int) (rect.x + rect.width - 1)) / cw); 712492e1cfeSmrg if ((top = (((int) rect.y) / ch)) < 0) top = 0; 713492e1cfeSmrg bottom = (((int) (rect.y + rect.height - 1)) / ch); 714492e1cfeSmrg 715492e1cfeSmrg paint_grid (fgw, left, top, right - left + 1, bottom - top + 1); 716492e1cfeSmrg} 717492e1cfeSmrg 718492e1cfeSmrg 7193538fbe3Smrgstatic void 7203538fbe3Smrgpaint_grid(FontGridWidget fgw, /* widget in which to draw */ 7213538fbe3Smrg int col, int row, /* where to start */ 7223538fbe3Smrg int ncols, int nrows) /* number of cells */ 723492e1cfeSmrg{ 724492e1cfeSmrg FontGridPart *p = &fgw->fontgrid; 725492e1cfeSmrg int i, j; 726492e1cfeSmrg Display *dpy = XtDisplay(fgw); 727492e1cfeSmrg Window wind = XtWindow(fgw); 728492e1cfeSmrg int cw = p->cell_width + p->grid_width; 729492e1cfeSmrg int ch = p->cell_height + p->grid_width; 730492e1cfeSmrg int tcols = p->cell_cols; 731492e1cfeSmrg int trows = p->cell_rows; 732492e1cfeSmrg int x1, y1, x2, y2, x, y; 733492e1cfeSmrg unsigned maxn = GridLastChar ((Widget) fgw); 734492e1cfeSmrg unsigned n, prevn; 735492e1cfeSmrg int startx; 736492e1cfeSmrg 737492e1cfeSmrg if (col + ncols >= tcols) { 738492e1cfeSmrg ncols = tcols - col; 739492e1cfeSmrg if (ncols < 1) return; 740492e1cfeSmrg } 741492e1cfeSmrg 742492e1cfeSmrg if (row + nrows >= trows) { 743492e1cfeSmrg nrows = trows - row; 744492e1cfeSmrg if (nrows < 1) return; 745492e1cfeSmrg } 746492e1cfeSmrg 747492e1cfeSmrg /* 7483538fbe3Smrg * paint the grid lines for the indicated rows 749492e1cfeSmrg */ 750492e1cfeSmrg if (p->grid_width > 0) { 751492e1cfeSmrg int half_grid_width = p->grid_width >> 1; 752492e1cfeSmrg x1 = col * cw + half_grid_width; 753492e1cfeSmrg y1 = row * ch + half_grid_width; 754492e1cfeSmrg x2 = x1 + ncols * cw; 755492e1cfeSmrg y2 = y1 + nrows * ch; 756492e1cfeSmrg for (i = 0, x = x1; i <= ncols; i++, x += cw) { 757492e1cfeSmrg XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2); 758492e1cfeSmrg } 759492e1cfeSmrg for (i = 0, y = y1; i <= nrows; i++, y += ch) { 760492e1cfeSmrg XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); 761492e1cfeSmrg } 762492e1cfeSmrg } 763492e1cfeSmrg /* 764492e1cfeSmrg * Draw a character in every box; treat all fonts as if they were 16bit 7653538fbe3Smrg * fonts. Store the high eight bits in byte1 and the low eight bits in 766492e1cfeSmrg * byte2. 767492e1cfeSmrg */ 768492e1cfeSmrg prevn = p->start_char + col + row * tcols; 769492e1cfeSmrg startx = col * cw + p->internal_pad + p->grid_width; 770492e1cfeSmrg for (j = 0, 771492e1cfeSmrg y = row * ch + p->internal_pad + p->grid_width + GridFontAscent (fgw); 772492e1cfeSmrg j < nrows; j++, y += ch) { 773492e1cfeSmrg n = prevn; 774492e1cfeSmrg for (i = 0, x = startx; i < ncols; i++, x += cw) { 775492e1cfeSmrg int xoff = p->xoff, yoff = p->yoff; 776492e1cfeSmrg if (n > maxn) goto done; /* no break out of nested */ 777492e1cfeSmrg 778492e1cfeSmrg#ifdef XRENDER 779492e1cfeSmrg if (fgw->fontgrid.text_face) 780492e1cfeSmrg { 781492e1cfeSmrg XftFont *xft = p->text_face; 782492e1cfeSmrg FcChar32 c = n; 783492e1cfeSmrg XGlyphInfo extents; 784492e1cfeSmrg XftTextExtents32 (dpy, xft, &c, 1, &extents); 785492e1cfeSmrg if (p->center_chars) 786492e1cfeSmrg { 787492e1cfeSmrg xoff = (p->cell_width - extents.width) / 2 - extents.x; 788492e1cfeSmrg yoff = (p->cell_height - extents.height) / 2 - extents.y; 789492e1cfeSmrg } 790492e1cfeSmrg if (extents.width && extents.height) 791492e1cfeSmrg { 7923538fbe3Smrg XClearArea (dpy, wind, x + xoff - extents.x, 793492e1cfeSmrg y + yoff - extents.y, 794492e1cfeSmrg extents.width, extents.height, False); 795492e1cfeSmrg if (p->box_chars) 796492e1cfeSmrg XDrawRectangle (dpy, wind, p->box_gc, 7973538fbe3Smrg x + xoff - extents.x, 798492e1cfeSmrg y + yoff - extents.y, 799492e1cfeSmrg extents.width - 1, 800492e1cfeSmrg extents.height - 1); 801492e1cfeSmrg } 802492e1cfeSmrg XftDrawString32 (p->draw, &p->fg_color, xft, 803492e1cfeSmrg x + xoff, y + yoff, &c, 1); 804492e1cfeSmrg } 805492e1cfeSmrg else 806492e1cfeSmrg#endif 807492e1cfeSmrg { 808492e1cfeSmrg XChar2b thechar; 809492e1cfeSmrg 810492e1cfeSmrg thechar.byte1 = (n >> 8); /* high eight bits */ 811492e1cfeSmrg thechar.byte2 = (n & 255); /* low eight bits */ 812492e1cfeSmrg if (p->box_chars || p->center_chars) { 813492e1cfeSmrg XCharStruct metrics; 814492e1cfeSmrg int direction, fontascent, fontdescent; 815492e1cfeSmrg 816492e1cfeSmrg XTextExtents16 (p->text_font, &thechar, 1, &direction, 817492e1cfeSmrg &fontascent, &fontdescent, &metrics); 818492e1cfeSmrg 819492e1cfeSmrg if (p->center_chars) { 820492e1cfeSmrg /* 821492e1cfeSmrg * We want to move the origin by enough to center the ink 8223538fbe3Smrg * within the cell. The left edge will then be at 823492e1cfeSmrg * (cell_width - (rbearing - lbearing)) / 2; so we subtract 824492e1cfeSmrg * the lbearing to find the origin. Ditto for vertical. 825492e1cfeSmrg */ 826492e1cfeSmrg xoff = (((p->cell_width - 827492e1cfeSmrg (metrics.rbearing - metrics.lbearing)) / 2) - 828492e1cfeSmrg p->internal_pad - metrics.lbearing); 8293538fbe3Smrg yoff = (((p->cell_height - 830492e1cfeSmrg (metrics.descent + metrics.ascent)) / 2) - 831492e1cfeSmrg p->internal_pad - 832492e1cfeSmrg p->text_font->ascent + metrics.ascent); 833492e1cfeSmrg } 834492e1cfeSmrg if (p->box_chars) { 835492e1cfeSmrg XDrawRectangle (dpy, wind, p->box_gc, 8363538fbe3Smrg x + xoff, y + yoff - p->text_font->ascent, 837492e1cfeSmrg metrics.width - 1, 838492e1cfeSmrg fontascent + fontdescent - 1); 839492e1cfeSmrg } 840492e1cfeSmrg } 841492e1cfeSmrg XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff, 842492e1cfeSmrg &thechar, 1); 843492e1cfeSmrg } 844492e1cfeSmrg n++; 845492e1cfeSmrg } 846492e1cfeSmrg prevn += tcols; 847492e1cfeSmrg } 848492e1cfeSmrg 849492e1cfeSmrg done: 850492e1cfeSmrg /* 8513538fbe3Smrg * paint the grid lines for the indicated rows 852492e1cfeSmrg */ 853492e1cfeSmrg if (p->grid_width > 0) { 854492e1cfeSmrg int half_grid_width = p->grid_width >> 1; 855492e1cfeSmrg x1 = col * cw + half_grid_width; 856492e1cfeSmrg y1 = row * ch + half_grid_width; 857492e1cfeSmrg x2 = x1 + ncols * cw; 858492e1cfeSmrg y2 = y1 + nrows * ch; 859492e1cfeSmrg for (i = 0, x = x1; i <= ncols; i++, x += cw) { 860492e1cfeSmrg XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2); 861492e1cfeSmrg } 862492e1cfeSmrg for (i = 0, y = y1; i <= nrows; i++, y += ch) { 863492e1cfeSmrg XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); 864492e1cfeSmrg } 865492e1cfeSmrg } 866492e1cfeSmrg 8673538fbe3Smrg 868492e1cfeSmrg return; 869492e1cfeSmrg} 870492e1cfeSmrg 871492e1cfeSmrgstatic Boolean 872492e1cfeSmrgPageBlank (Widget w, long first, long last) 873492e1cfeSmrg{ 874492e1cfeSmrg while (first <= last) 875492e1cfeSmrg { 876492e1cfeSmrg if (GridHasChar (w, first)) 877492e1cfeSmrg return False; 878492e1cfeSmrg first++; 879492e1cfeSmrg } 880492e1cfeSmrg return True; 881492e1cfeSmrg} 882492e1cfeSmrg 883492e1cfeSmrg/*ARGSUSED*/ 8843538fbe3Smrgstatic Boolean 88531e5d586SmrgSetValues(Widget current, Widget request _X_UNUSED, Widget new, 88631e5d586Smrg ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 887492e1cfeSmrg{ 888492e1cfeSmrg FontGridWidget curfg = (FontGridWidget) current; 889492e1cfeSmrg FontGridWidget newfg = (FontGridWidget) new; 890492e1cfeSmrg Boolean redisplay = FALSE; 891492e1cfeSmrg 892492e1cfeSmrg if (curfg->fontgrid.text_font != newfg->fontgrid.text_font || 893492e1cfeSmrg curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) { 894492e1cfeSmrg newfg->fontgrid.cell_width = DefaultCellWidth (newfg); 895492e1cfeSmrg newfg->fontgrid.cell_height = DefaultCellHeight (newfg); 896492e1cfeSmrg redisplay = TRUE; 897492e1cfeSmrg } 898492e1cfeSmrg 899492e1cfeSmrg if (GridForeground(curfg) != GridForeground (newfg)) { 900492e1cfeSmrg XtReleaseGC (new, curfg->fontgrid.text_gc); 901492e1cfeSmrg newfg->fontgrid.text_gc = get_gc (newfg, GridForeground (newfg)); 902492e1cfeSmrg redisplay = TRUE; 903492e1cfeSmrg } 904492e1cfeSmrg 905492e1cfeSmrg if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) { 906492e1cfeSmrg XtReleaseGC (new, curfg->fontgrid.text_gc); 907492e1cfeSmrg newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel); 908492e1cfeSmrg redisplay = TRUE; 909492e1cfeSmrg } 910492e1cfeSmrg 911492e1cfeSmrg if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars || 912492e1cfeSmrg curfg->fontgrid.box_chars != newfg->fontgrid.box_chars) 913492e1cfeSmrg redisplay = TRUE; 914492e1cfeSmrg 915492e1cfeSmrg if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) { 916492e1cfeSmrg long maxn = GridLastChar (new); 917492e1cfeSmrg long page = newfg->fontgrid.cell_cols * newfg->fontgrid.cell_rows; 918492e1cfeSmrg long dir = page; 919492e1cfeSmrg long start = newfg->fontgrid.start_char; 920492e1cfeSmrg 921492e1cfeSmrg if (start < curfg->fontgrid.start_char) 922492e1cfeSmrg dir = -page; 923492e1cfeSmrg 924492e1cfeSmrg if (start < 0) 925492e1cfeSmrg start = 0; 9263538fbe3Smrg if (start > maxn) 927492e1cfeSmrg start = (maxn / page) * page; 9283538fbe3Smrg 929492e1cfeSmrg while (PageBlank (new, start, start + page - 1)) 930492e1cfeSmrg { 931492e1cfeSmrg long next = start + dir; 932492e1cfeSmrg 933492e1cfeSmrg if (next < 0 || maxn < next) 934492e1cfeSmrg break; 935492e1cfeSmrg start = next; 936492e1cfeSmrg } 937492e1cfeSmrg 938492e1cfeSmrg newfg->fontgrid.start_char = start; 939492e1cfeSmrg redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char); 940492e1cfeSmrg } 941492e1cfeSmrg 942492e1cfeSmrg return redisplay; 943492e1cfeSmrg} 944492e1cfeSmrg 945492e1cfeSmrg 946492e1cfeSmrg/* ARGSUSED */ 9473538fbe3Smrgstatic void 94831e5d586SmrgNotify(Widget gw, XEvent *event, 94931e5d586Smrg String *params _X_UNUSED, Cardinal *nparams _X_UNUSED) 950492e1cfeSmrg{ 951492e1cfeSmrg FontGridWidget fgw = (FontGridWidget) gw; 952492e1cfeSmrg int x, y; /* where the event happened */ 953492e1cfeSmrg FontGridCharRec rec; /* callback data */ 954492e1cfeSmrg 955492e1cfeSmrg /* 956492e1cfeSmrg * only allow events with (x,y) 957492e1cfeSmrg */ 958492e1cfeSmrg switch (event->type) { 959492e1cfeSmrg case KeyPress: 960492e1cfeSmrg case KeyRelease: 961492e1cfeSmrg x = event->xkey.x; 962492e1cfeSmrg y = event->xkey.y; 963492e1cfeSmrg break; 964492e1cfeSmrg case ButtonPress: 965492e1cfeSmrg case ButtonRelease: 966492e1cfeSmrg x = event->xbutton.x; 967492e1cfeSmrg y = event->xbutton.y; 968492e1cfeSmrg break; 969492e1cfeSmrg case MotionNotify: 970492e1cfeSmrg x = event->xmotion.x; 971492e1cfeSmrg y = event->xmotion.y; 972492e1cfeSmrg break; 973492e1cfeSmrg default: 974492e1cfeSmrg Bell (gw, XkbBI_Ignore); 975492e1cfeSmrg return; 976492e1cfeSmrg } 977492e1cfeSmrg 978492e1cfeSmrg /* 979492e1cfeSmrg * compute the callback data 980492e1cfeSmrg */ 981492e1cfeSmrg { 982492e1cfeSmrg int cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width; 983492e1cfeSmrg int ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width; 984492e1cfeSmrg unsigned n; 985492e1cfeSmrg 986492e1cfeSmrg if (x > (fgw->fontgrid.cell_cols * cw)) { 987492e1cfeSmrg Bell (gw, XkbBI_InvalidLocation); 988492e1cfeSmrg return; 989492e1cfeSmrg } 990492e1cfeSmrg 9913538fbe3Smrg n= (fgw->fontgrid.start_char + 992492e1cfeSmrg ((y / ch) * fgw->fontgrid.cell_cols) + (x / cw)); 993492e1cfeSmrg 994492e1cfeSmrg rec.thefont = fgw->fontgrid.text_font; 995492e1cfeSmrg#ifdef XRENDER 996492e1cfeSmrg rec.theface = fgw->fontgrid.text_face; 997492e1cfeSmrg#endif 998492e1cfeSmrg rec.thechar = n; 999492e1cfeSmrg } 1000492e1cfeSmrg 1001492e1cfeSmrg XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec); 1002492e1cfeSmrg} 1003492e1cfeSmrg 1004