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