| File: | grid.c |
| Location: | line 826, column 8 |
| Description: | Access to field 'ascent' results in a dereference of a null pointer (loaded from field 'text_font') |
| 1 | /* | |||
| 2 | * | |||
| 3 | Copyright 1989, 1998 The Open Group | |||
| 4 | ||||
| 5 | Permission to use, copy, modify, distribute, and sell this software and its | |||
| 6 | documentation for any purpose is hereby granted without fee, provided that | |||
| 7 | the above copyright notice appear in all copies and that both that | |||
| 8 | copyright notice and this permission notice appear in supporting | |||
| 9 | documentation. | |||
| 10 | ||||
| 11 | The above copyright notice and this permission notice shall be included in | |||
| 12 | all copies or substantial portions of the Software. | |||
| 13 | ||||
| 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| 17 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
| 18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| 20 | ||||
| 21 | Except as contained in this notice, the name of The Open Group shall not be | |||
| 22 | used in advertising or otherwise to promote the sale, use or other dealings | |||
| 23 | in this Software without prior written authorization from The Open Group. | |||
| 24 | * | |||
| 25 | * Author: Jim Fulton, MIT X Consortium | |||
| 26 | */ | |||
| 27 | ||||
| 28 | #include <X11/IntrinsicP.h> | |||
| 29 | #include <X11/StringDefs.h> | |||
| 30 | #include <X11/Xaw/SimpleP.h> | |||
| 31 | #include <X11/Xmu/Converters.h> | |||
| 32 | #include <X11/Xos.h> | |||
| 33 | #include "gridP.h" | |||
| 34 | ||||
| 35 | #ifdef XKB | |||
| 36 | #include <X11/extensions/XKBbells.h> | |||
| 37 | #else | |||
| 38 | #define XkbBI_MinorError2 2 | |||
| 39 | #define XkbBI_Ignore11 11 | |||
| 40 | #endif | |||
| 41 | ||||
| 42 | #ifdef XKB | |||
| 43 | #define Bell(w,n)XBell((((w)->core.screen)->display), 0) XkbStdBell(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), 50, n) | |||
| 44 | #else | |||
| 45 | #define Bell(w,n)XBell((((w)->core.screen)->display), 0) XBell(XtDisplay(w)(((w)->core.screen)->display), 0) | |||
| 46 | #endif | |||
| 47 | ||||
| 48 | static GC get_gc(FontGridWidget fgw, Pixel fore); | |||
| 49 | static void ClassInitialize(void); | |||
| 50 | static void Initialize(Widget request, Widget new, ArgList args, | |||
| 51 | Cardinal *num_args); | |||
| 52 | static void Realize(Widget gw, Mask *valueMask, | |||
| 53 | XSetWindowAttributes *attributes); | |||
| 54 | static void Destroy(Widget gw); | |||
| 55 | static void Resize(Widget gw); | |||
| 56 | static void Redisplay(Widget gw, XEvent *event, Region region); | |||
| 57 | static void paint_grid(FontGridWidget fgw, int col, int row, | |||
| 58 | int ncols, int nrows); | |||
| 59 | static Boolean SetValues(Widget current, Widget request, Widget new, | |||
| 60 | ArgList args, Cardinal *num_args); | |||
| 61 | static void Notify(Widget gw, XEvent *event, String *params, | |||
| 62 | Cardinal *nparams); | |||
| 63 | ||||
| 64 | #define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field)__builtin_offsetof(FontGridRec, fontgrid.field) | |||
| 65 | ||||
| 66 | static XtResource resources[] = { | |||
| 67 | { XtNfont((char*)&XtStrings[199]), XtCFont((char*)&XtStrings[1017]), XtRFontStruct((char*)&XtStrings[1666]), sizeof(XFontStruct *), | |||
| 68 | Offset(text_font), XtRString((char*)&XtStrings[1797]), (XtPointer) NULL((void*)0) }, | |||
| 69 | { XtNcellColumns"cellColumns", XtCCellColumns"CellColumns", XtRInt((char*)&XtStrings[1718]), sizeof(int), | |||
| 70 | Offset(cell_cols), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0 }, | |||
| 71 | { XtNcellRows"cellRows", XtCCellRows"CellRows", XtRInt((char*)&XtStrings[1718]), sizeof(int), | |||
| 72 | Offset(cell_rows), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0 }, | |||
| 73 | { XtNcellWidth"cellWidth", XtCCellWidth"CellWidth", XtRInt((char*)&XtStrings[1718]), sizeof(int), | |||
| 74 | Offset(cell_width), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0 }, | |||
| 75 | { XtNcellHeight"cellHeight", XtCCellHeight"CellHeight", XtRInt((char*)&XtStrings[1718]), sizeof(int), | |||
| 76 | Offset(cell_height), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0 }, | |||
| 77 | { XtNstartChar"startChar", XtCStartChar"StartChar", XtRLong"Long", sizeof(long), | |||
| 78 | Offset(start_char), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0xffffffff }, | |||
| 79 | #ifndef XRENDER1 | |||
| 80 | { XtNforeground((char*)&XtStrings[214]), XtCForeground((char*)&XtStrings[1022]), XtRPixel((char*)&XtStrings[1754]), sizeof(Pixel), | |||
| 81 | Offset(foreground_pixel), XtRString((char*)&XtStrings[1797]), (XtPointer) XtDefaultForeground"XtDefaultForeground" }, | |||
| 82 | #endif | |||
| 83 | { XtNcenterChars"centerChars", XtCCenterChars"CenterChars", XtRBoolean((char*)&XtStrings[1561]), sizeof(Boolean), | |||
| 84 | Offset(center_chars), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) FALSE0 }, | |||
| 85 | { XtNboxChars"boxChars", XtCBoxChars"BoxChars", XtRBoolean((char*)&XtStrings[1561]), sizeof(Boolean), | |||
| 86 | Offset(box_chars), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) FALSE0 }, | |||
| 87 | { XtNboxColor"boxColor", XtCForeground((char*)&XtStrings[1022]), XtRPixel((char*)&XtStrings[1754]), sizeof(Pixel), | |||
| 88 | Offset(box_pixel), XtRString((char*)&XtStrings[1797]), (XtPointer) XtDefaultForeground"XtDefaultForeground" }, | |||
| 89 | { XtNcallback((char*)&XtStrings[136]), XtCCallback((char*)&XtStrings[952]), XtRCallback((char*)&XtStrings[1569]), sizeof(XtPointer), | |||
| 90 | Offset(callbacks), XtRCallback((char*)&XtStrings[1569]), (XtPointer) NULL((void*)0) }, | |||
| 91 | { XtNinternalPad"internalPad", XtCInternalPad"InternalPad", XtRInt((char*)&XtStrings[1718]), sizeof(int), | |||
| 92 | Offset(internal_pad), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 4 }, | |||
| 93 | { XtNgridWidth"gridWidth", XtCGridWidth"GridWidth", XtRInt((char*)&XtStrings[1718]), sizeof(int), | |||
| 94 | Offset(grid_width), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 1 }, | |||
| 95 | #ifdef XRENDER1 | |||
| 96 | {XtNforeground((char*)&XtStrings[214]), XtCForeground((char*)&XtStrings[1022]), XtRXftColor"XftColor", sizeof(XftColor), | |||
| 97 | Offset(fg_color), XtRString((char*)&XtStrings[1797]), XtDefaultForeground"XtDefaultForeground"}, | |||
| 98 | {XtNface"face", XtCFace"Face", XtRXftFont"XftFont", sizeof (XftFont *), | |||
| 99 | Offset (text_face), XtRString((char*)&XtStrings[1797]), NULL((void*)0)}, | |||
| 100 | #endif | |||
| 101 | }; | |||
| 102 | ||||
| 103 | #undef Offset | |||
| 104 | ||||
| 105 | static char defaultTranslations[] = | |||
| 106 | "<ButtonPress>: notify()"; | |||
| 107 | ||||
| 108 | static XtActionsRec actions_list[] = { | |||
| 109 | { "notify", Notify }, | |||
| 110 | }; | |||
| 111 | ||||
| 112 | FontGridClassRec fontgridClassRec = { | |||
| 113 | { /* core fields */ | |||
| 114 | /* superclass */ (WidgetClass) &simpleClassRec, | |||
| 115 | /* class_name */ "FontGrid", | |||
| 116 | /* widget_size */ sizeof(FontGridRec), | |||
| 117 | /* class_initialize */ ClassInitialize, | |||
| 118 | /* class_part_initialize */ NULL((void*)0), | |||
| 119 | /* class_inited */ FALSE0, | |||
| 120 | /* initialize */ Initialize, | |||
| 121 | /* initialize_hook */ NULL((void*)0), | |||
| 122 | /* realize */ Realize, | |||
| 123 | /* actions */ actions_list, | |||
| 124 | /* num_actions */ XtNumber(actions_list)((Cardinal) (sizeof(actions_list) / sizeof(actions_list[0]))), | |||
| 125 | /* resources */ resources, | |||
| 126 | /* num_resources */ XtNumber(resources)((Cardinal) (sizeof(resources) / sizeof(resources[0]))), | |||
| 127 | /* xrm_class */ NULLQUARK((XrmQuark) 0), | |||
| 128 | /* compress_motion */ TRUE1, | |||
| 129 | /* compress_exposure */ TRUE1, | |||
| 130 | /* compress_enterleave */ TRUE1, | |||
| 131 | /* visible_interest */ FALSE0, | |||
| 132 | /* destroy */ Destroy, | |||
| 133 | /* resize */ Resize, | |||
| 134 | /* expose */ Redisplay, | |||
| 135 | /* set_values */ SetValues, | |||
| 136 | /* set_values_hook */ NULL((void*)0), | |||
| 137 | /* set_values_almost */ XtInheritSetValuesAlmost((XtAlmostProc) _XtInherit), | |||
| 138 | /* get_values_hook */ NULL((void*)0), | |||
| 139 | /* accept_focus */ NULL((void*)0), | |||
| 140 | /* version */ XtVersion(11 * 1000 + 6), | |||
| 141 | /* callback_private */ NULL((void*)0), | |||
| 142 | /* tm_table */ defaultTranslations, | |||
| 143 | /* query_geometry */ XtInheritQueryGeometry((XtGeometryHandler) _XtInherit), | |||
| 144 | /* display_accelerator */ XtInheritDisplayAccelerator((XtStringProc) _XtInherit), | |||
| 145 | /* extension */ NULL((void*)0) | |||
| 146 | }, | |||
| 147 | { /* simple fields */ | |||
| 148 | /* change_sensitive */ XtInheritChangeSensitive((int (*)(Widget))_XtInherit) | |||
| 149 | } | |||
| 150 | }; | |||
| 151 | ||||
| 152 | WidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec; | |||
| 153 | ||||
| 154 | ||||
| 155 | long | |||
| 156 | GridFirstChar (Widget w) | |||
| 157 | { | |||
| 158 | FontGridWidget fgw = (FontGridWidget) w; | |||
| 159 | XFontStruct *fs = fgw->fontgrid.text_font; | |||
| 160 | #ifdef XRENDER1 | |||
| 161 | XftFont *xft = fgw->fontgrid.text_face; | |||
| 162 | if (xft) | |||
| 163 | { | |||
| 164 | FcChar32 map[FC_CHARSET_MAP_SIZE(256/32)]; | |||
| 165 | FcChar32 next; | |||
| 166 | FcChar32 first; | |||
| 167 | int i; | |||
| 168 | ||||
| 169 | first = FcCharSetFirstPage (xft->charset, map, &next); | |||
| 170 | for (i = 0; i < FC_CHARSET_MAP_SIZE(256/32); i++) | |||
| 171 | if (map[i]) | |||
| 172 | { | |||
| 173 | FcChar32 bits = map[i]; | |||
| 174 | first += i * 32; | |||
| 175 | while (!(bits & 0x1)) | |||
| 176 | { | |||
| 177 | bits >>= 1; | |||
| 178 | first++; | |||
| 179 | } | |||
| 180 | break; | |||
| 181 | } | |||
| 182 | return first; | |||
| 183 | } | |||
| 184 | else | |||
| 185 | #endif | |||
| 186 | if (fs) | |||
| 187 | { | |||
| 188 | return (fs->min_byte1 << 8) | (fs->min_char_or_byte2); | |||
| 189 | } | |||
| 190 | else | |||
| 191 | return 0; | |||
| 192 | } | |||
| 193 | ||||
| 194 | long | |||
| 195 | GridLastChar (Widget w) | |||
| 196 | { | |||
| 197 | FontGridWidget fgw = (FontGridWidget) w; | |||
| 198 | XFontStruct *fs = fgw->fontgrid.text_font; | |||
| 199 | #ifdef XRENDER1 | |||
| 200 | XftFont *xft = fgw->fontgrid.text_face; | |||
| 201 | if (xft) | |||
| 202 | { | |||
| 203 | FcChar32 this, last, next; | |||
| 204 | FcChar32 map[FC_CHARSET_MAP_SIZE(256/32)]; | |||
| 205 | int i; | |||
| 206 | last = FcCharSetFirstPage (xft->charset, map, &next); | |||
| 207 | while ((this = FcCharSetNextPage (xft->charset, map, &next)) != FC_CHARSET_DONE((FcChar32) -1)) | |||
| 208 | last = this; | |||
| 209 | last &= ~0xff; | |||
| 210 | for (i = FC_CHARSET_MAP_SIZE(256/32) - 1; i >= 0; i--) | |||
| 211 | if (map[i]) | |||
| 212 | { | |||
| 213 | FcChar32 bits = map[i]; | |||
| 214 | last += i * 32 + 31; | |||
| 215 | while (!(bits & 0x80000000)) | |||
| 216 | { | |||
| 217 | last--; | |||
| 218 | bits <<= 1; | |||
| 219 | } | |||
| 220 | break; | |||
| 221 | } | |||
| 222 | return (long) last; | |||
| 223 | } | |||
| 224 | else | |||
| 225 | #endif | |||
| 226 | if (fs) | |||
| 227 | { | |||
| 228 | return (fs->max_byte1 << 8) | (fs->max_char_or_byte2); | |||
| 229 | } | |||
| 230 | else | |||
| 231 | return 0; | |||
| 232 | } | |||
| 233 | ||||
| 234 | /* | |||
| 235 | * CI_GET_CHAR_INFO_1D - return the charinfo struct for the indicated 8bit | |||
| 236 | * character. If the character is in the column and exists, then return the | |||
| 237 | * appropriate metrics (note that fonts with common per-character metrics will | |||
| 238 | * return min_bounds). | |||
| 239 | */ | |||
| 240 | ||||
| 241 | #define CI_NONEXISTCHAR(cs)(((cs)->width == 0) && (((cs)->rbearing|(cs)-> lbearing| (cs)->ascent|(cs)->descent) == 0)) (((cs)->width == 0) && \ | |||
| 242 | (((cs)->rbearing|(cs)->lbearing| \ | |||
| 243 | (cs)->ascent|(cs)->descent) == 0)) | |||
| 244 | ||||
| 245 | #define CI_GET_CHAR_INFO_1D(fs,col,cs){ cs = ((void*)0); if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { if (fs->per_char == ((void*)0)) { cs = &fs->min_bounds; } else { cs = & fs->per_char[(col - fs->min_char_or_byte2)]; } if ((((cs )->width == 0) && (((cs)->rbearing|(cs)->lbearing | (cs)->ascent|(cs)->descent) == 0))) cs = ((void*)0); } } \ | |||
| 246 | { \ | |||
| 247 | cs = NULL((void*)0); \ | |||
| 248 | if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ | |||
| 249 | if (fs->per_char == NULL((void*)0)) { \ | |||
| 250 | cs = &fs->min_bounds; \ | |||
| 251 | } else { \ | |||
| 252 | cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ | |||
| 253 | } \ | |||
| 254 | if (CI_NONEXISTCHAR(cs)(((cs)->width == 0) && (((cs)->rbearing|(cs)-> lbearing| (cs)->ascent|(cs)->descent) == 0))) \ | |||
| 255 | cs = NULL((void*)0); \ | |||
| 256 | } \ | |||
| 257 | } | |||
| 258 | ||||
| 259 | /* | |||
| 260 | * CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and | |||
| 261 | * column. This is used for fonts that have more than row zero. | |||
| 262 | */ | |||
| 263 | #define CI_GET_CHAR_INFO_2D(fs,row,col,cs){ cs = ((void*)0); if (row >= fs->min_byte1 && row <= fs->max_byte1 && col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { if (fs-> per_char == ((void*)0)) { cs = &fs->min_bounds; } else { cs = &fs->per_char[((row - fs->min_byte1) * (fs-> max_char_or_byte2 - fs->min_char_or_byte2 + 1)) + (col - fs ->min_char_or_byte2)]; } if ((((cs)->width == 0) && (((cs)->rbearing|(cs)->lbearing| (cs)->ascent|(cs)-> descent) == 0))) cs = ((void*)0); } } \ | |||
| 264 | { \ | |||
| 265 | cs = NULL((void*)0); \ | |||
| 266 | if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ | |||
| 267 | col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ | |||
| 268 | if (fs->per_char == NULL((void*)0)) { \ | |||
| 269 | cs = &fs->min_bounds; \ | |||
| 270 | } else { \ | |||
| 271 | cs = &fs->per_char[((row - fs->min_byte1) * \ | |||
| 272 | (fs->max_char_or_byte2 - \ | |||
| 273 | fs->min_char_or_byte2 + 1)) + \ | |||
| 274 | (col - fs->min_char_or_byte2)]; \ | |||
| 275 | } \ | |||
| 276 | if (CI_NONEXISTCHAR(cs)(((cs)->width == 0) && (((cs)->rbearing|(cs)-> lbearing| (cs)->ascent|(cs)->descent) == 0))) \ | |||
| 277 | cs = NULL((void*)0); \ | |||
| 278 | } \ | |||
| 279 | } | |||
| 280 | ||||
| 281 | static Boolean | |||
| 282 | GridHasChar (Widget w, long ch) | |||
| 283 | { | |||
| 284 | FontGridWidget fgw = (FontGridWidget) w; | |||
| 285 | #ifdef XRENDER1 | |||
| 286 | XftFont *xft = fgw->fontgrid.text_face; | |||
| 287 | if (xft) | |||
| 288 | { | |||
| 289 | return FcCharSetHasChar (xft->charset, (FcChar32) ch); | |||
| 290 | } | |||
| 291 | else | |||
| 292 | #endif | |||
| 293 | { | |||
| 294 | XFontStruct *fs = fgw->fontgrid.text_font; | |||
| 295 | XCharStruct *cs; | |||
| 296 | ||||
| 297 | if (!fs) | |||
| 298 | return False0; | |||
| 299 | if (fs->max_byte1 == 0) | |||
| 300 | { | |||
| 301 | CI_GET_CHAR_INFO_1D (fs, ch, cs){ cs = ((void*)0); if (ch >= fs->min_char_or_byte2 && ch <= fs->max_char_or_byte2) { if (fs->per_char == ( (void*)0)) { cs = &fs->min_bounds; } else { cs = & fs->per_char[(ch - fs->min_char_or_byte2)]; } if ((((cs )->width == 0) && (((cs)->rbearing|(cs)->lbearing | (cs)->ascent|(cs)->descent) == 0))) cs = ((void*)0); } }; | |||
| 302 | } | |||
| 303 | else | |||
| 304 | { | |||
| 305 | unsigned int r = (ch >> 8); | |||
| 306 | unsigned int c = (ch & 0xff); | |||
| 307 | CI_GET_CHAR_INFO_2D (fs, r, c, cs){ cs = ((void*)0); if (r >= fs->min_byte1 && r <= fs->max_byte1 && c >= fs->min_char_or_byte2 && c <= fs->max_char_or_byte2) { if (fs->per_char == ((void*)0)) { cs = &fs->min_bounds; } else { cs = & fs->per_char[((r - fs->min_byte1) * (fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1)) + (c - fs->min_char_or_byte2 )]; } if ((((cs)->width == 0) && (((cs)->rbearing |(cs)->lbearing| (cs)->ascent|(cs)->descent) == 0))) cs = ((void*)0); } }; | |||
| 308 | } | |||
| 309 | return cs != NULL((void*)0); | |||
| 310 | } | |||
| 311 | } | |||
| 312 | ||||
| 313 | /* | |||
| 314 | * public routines | |||
| 315 | */ | |||
| 316 | ||||
| 317 | void | |||
| 318 | GetFontGridCellDimensions(Widget w, long *startp, | |||
| 319 | int *ncolsp, int *nrowsp) | |||
| 320 | { | |||
| 321 | FontGridWidget fgw = (FontGridWidget) w; | |||
| 322 | *startp = fgw->fontgrid.start_char; | |||
| 323 | *ncolsp = fgw->fontgrid.cell_cols; | |||
| 324 | *nrowsp = fgw->fontgrid.cell_rows; | |||
| 325 | } | |||
| 326 | ||||
| 327 | ||||
| 328 | void | |||
| 329 | GetPrevNextStates(Widget w, Boolint *prevvalidp, Boolint *nextvalidp, | |||
| 330 | Boolint *prev16validp, Boolint *next16validp) | |||
| 331 | { | |||
| 332 | FontGridWidget fgw = (FontGridWidget) w; | |||
| 333 | long minn = (long) GridFirstChar (w); | |||
| 334 | long maxn = (long) GridLastChar (w); | |||
| 335 | ||||
| 336 | *prev16validp = (fgw->fontgrid.start_char - 0xf00 > minn); | |||
| 337 | *prevvalidp = (fgw->fontgrid.start_char > minn); | |||
| 338 | *nextvalidp = (fgw->fontgrid.start_char + | |||
| 339 | (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows) | |||
| 340 | < maxn); | |||
| 341 | *next16validp =((fgw->fontgrid.start_char + 0xf00 + | |||
| 342 | (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows)) | |||
| 343 | < maxn); | |||
| 344 | } | |||
| 345 | ||||
| 346 | ||||
| 347 | ||||
| 348 | /* | |||
| 349 | * private routines and methods | |||
| 350 | */ | |||
| 351 | ||||
| 352 | ||||
| 353 | static GC | |||
| 354 | get_gc(FontGridWidget fgw, Pixel fore) | |||
| 355 | { | |||
| 356 | XtGCMask mask; | |||
| 357 | XGCValues gcv; | |||
| 358 | ||||
| 359 | mask = (GCForeground(1L<<2) | GCBackground(1L<<3) | GCFunction(1L<<0)); | |||
| 360 | gcv.foreground = fore; | |||
| 361 | gcv.background = fgw->core.background_pixel; | |||
| 362 | gcv.function = GXcopy0x3; | |||
| 363 | if (fgw->fontgrid.text_font) | |||
| 364 | { | |||
| 365 | mask |= GCFont(1L<<14); | |||
| 366 | gcv.font = fgw->fontgrid.text_font->fid; | |||
| 367 | } | |||
| 368 | gcv.cap_style = CapProjecting3; | |||
| 369 | mask |= GCCapStyle(1L<<6); | |||
| 370 | if (fgw->fontgrid.grid_width > 0) { | |||
| 371 | mask |= GCLineWidth(1L<<4); | |||
| 372 | gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 : | |||
| 373 | fgw->fontgrid.grid_width); | |||
| 374 | } | |||
| 375 | return (XtGetGC ((Widget) fgw, mask, &gcv)); | |||
| 376 | } | |||
| 377 | ||||
| 378 | ||||
| 379 | #ifdef XRENDER1 | |||
| 380 | static XtConvertArgRec xftColorConvertArgs[] = { | |||
| 381 | {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen)__builtin_offsetof(WidgetRec, core.screen), | |||
| 382 | sizeof(Screen *)}, | |||
| 383 | {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap)__builtin_offsetof(WidgetRec, core.colormap), | |||
| 384 | sizeof(Colormap)} | |||
| 385 | }; | |||
| 386 | ||||
| 387 | #define donestr(type, value, tstr){ if (toVal->addr != ((void*)0)) { if (toVal->size < sizeof(type)) { toVal->size = sizeof(type); XtDisplayStringConversionWarning (dpy, (char*) fromVal->addr, tstr); return 0; } *(type*)(toVal ->addr) = (value); } else { static type static_val; static_val = (value); toVal->addr = (XPointer)&static_val; } toVal ->size = sizeof(type); return 1; } \ | |||
| 388 | { \ | |||
| 389 | if (toVal->addr != NULL((void*)0)) { \ | |||
| 390 | if (toVal->size < sizeof(type)) { \ | |||
| 391 | toVal->size = sizeof(type); \ | |||
| 392 | XtDisplayStringConversionWarning(dpy, \ | |||
| 393 | (char*) fromVal->addr, tstr); \ | |||
| 394 | return False0; \ | |||
| 395 | } \ | |||
| 396 | *(type*)(toVal->addr) = (value); \ | |||
| 397 | } \ | |||
| 398 | else { \ | |||
| 399 | static type static_val; \ | |||
| 400 | static_val = (value); \ | |||
| 401 | toVal->addr = (XPointer)&static_val; \ | |||
| 402 | } \ | |||
| 403 | toVal->size = sizeof(type); \ | |||
| 404 | return True1; \ | |||
| 405 | } | |||
| 406 | ||||
| 407 | static void | |||
| 408 | XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure, | |||
| 409 | XrmValuePtr args, Cardinal *num_args) | |||
| 410 | { | |||
| 411 | Screen *screen; | |||
| 412 | Colormap colormap; | |||
| 413 | XftColor *color; | |||
| 414 | ||||
| 415 | if (*num_args != 2) | |||
| 416 | { | |||
| 417 | XtAppErrorMsg (app, | |||
| 418 | "freeXftColor", "wrongParameters", | |||
| 419 | "XtToolkitError", | |||
| 420 | "Freeing an XftColor requires screen and colormap arguments", | |||
| 421 | (String *) NULL((void*)0), (Cardinal *)NULL((void*)0)); | |||
| 422 | return; | |||
| 423 | } | |||
| 424 | ||||
| 425 | screen = *((Screen **) args[0].addr); | |||
| 426 | colormap = *((Colormap *) args[1].addr); | |||
| 427 | color = (XftColor *) toVal->addr; | |||
| 428 | XftColorFree (DisplayOfScreen (screen)((screen)->display), | |||
| 429 | DefaultVisual (DisplayOfScreen (screen),((&((_XPrivDisplay)((screen)->display))->screens[XScreenNumberOfScreen (screen)])->root_visual) | |||
| 430 | XScreenNumberOfScreen (screen))((&((_XPrivDisplay)((screen)->display))->screens[XScreenNumberOfScreen (screen)])->root_visual), | |||
| 431 | colormap, color); | |||
| 432 | } | |||
| 433 | ||||
| 434 | static Boolean | |||
| 435 | XmuCvtStringToXftColor(Display *dpy, | |||
| 436 | XrmValue *args, Cardinal *num_args, | |||
| 437 | XrmValue *fromVal, XrmValue *toVal, | |||
| 438 | XtPointer *converter_data) | |||
| 439 | { | |||
| 440 | char *spec; | |||
| 441 | XRenderColor renderColor; | |||
| 442 | XftColor xftColor; | |||
| 443 | Screen *screen; | |||
| 444 | Colormap colormap; | |||
| 445 | ||||
| 446 | if (*num_args != 2) | |||
| 447 | { | |||
| 448 | XtAppErrorMsg (XtDisplayToApplicationContext (dpy), | |||
| 449 | "cvtStringToXftColor", "wrongParameters", | |||
| 450 | "XtToolkitError", | |||
| 451 | "String to render color conversion needs screen and colormap arguments", | |||
| 452 | (String *) NULL((void*)0), (Cardinal *)NULL((void*)0)); | |||
| 453 | return False0; | |||
| 454 | } | |||
| 455 | ||||
| 456 | screen = *((Screen **) args[0].addr); | |||
| 457 | colormap = *((Colormap *) args[1].addr); | |||
| 458 | ||||
| 459 | spec = (char *) fromVal->addr; | |||
| 460 | if (strcasecmp (spec, XtDefaultForeground"XtDefaultForeground") == 0) | |||
| 461 | { | |||
| 462 | renderColor.red = 0; | |||
| 463 | renderColor.green = 0; | |||
| 464 | renderColor.blue = 0; | |||
| 465 | renderColor.alpha = 0xffff; | |||
| 466 | } | |||
| 467 | else if (strcasecmp (spec, XtDefaultBackground"XtDefaultBackground") == 0) | |||
| 468 | { | |||
| 469 | renderColor.red = 0xffff; | |||
| 470 | renderColor.green = 0xffff; | |||
| 471 | renderColor.blue = 0xffff; | |||
| 472 | renderColor.alpha = 0xffff; | |||
| 473 | } | |||
| 474 | else if (!XRenderParseColor (dpy, spec, &renderColor)) | |||
| 475 | return False0; | |||
| 476 | if (!XftColorAllocValue (dpy, | |||
| 477 | DefaultVisual (dpy,((&((_XPrivDisplay)dpy)->screens[XScreenNumberOfScreen (screen)])->root_visual) | |||
| 478 | XScreenNumberOfScreen (screen))((&((_XPrivDisplay)dpy)->screens[XScreenNumberOfScreen (screen)])->root_visual), | |||
| 479 | colormap, | |||
| 480 | &renderColor, | |||
| 481 | &xftColor)) | |||
| 482 | return False0; | |||
| 483 | ||||
| 484 | donestr (XftColor, xftColor, XtRXftColor){ if (toVal->addr != ((void*)0)) { if (toVal->size < sizeof(XftColor)) { toVal->size = sizeof(XftColor); XtDisplayStringConversionWarning (dpy, (char*) fromVal->addr, "XftColor"); return 0; } *(XftColor *)(toVal->addr) = (xftColor); } else { static XftColor static_val ; static_val = (xftColor); toVal->addr = (XPointer)&static_val ; } toVal->size = sizeof(XftColor); return 1; }; | |||
| 485 | } | |||
| 486 | ||||
| 487 | static void | |||
| 488 | XmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure, | |||
| 489 | XrmValuePtr args, Cardinal *num_args) | |||
| 490 | { | |||
| 491 | Screen *screen; | |||
| 492 | XftFont *font; | |||
| 493 | ||||
| 494 | if (*num_args != 1) | |||
| 495 | { | |||
| 496 | XtAppErrorMsg (app, | |||
| 497 | "freeXftFont", "wrongParameters", | |||
| 498 | "XtToolkitError", | |||
| 499 | "Freeing an XftFont requires screen argument", | |||
| 500 | (String *) NULL((void*)0), (Cardinal *)NULL((void*)0)); | |||
| 501 | return; | |||
| 502 | } | |||
| 503 | ||||
| 504 | screen = *((Screen **) args[0].addr); | |||
| 505 | font = *((XftFont **) toVal->addr); | |||
| 506 | if (font) | |||
| 507 | XftFontClose (DisplayOfScreen (screen)((screen)->display), font); | |||
| 508 | } | |||
| 509 | ||||
| 510 | static Boolean | |||
| 511 | XmuCvtStringToXftFont(Display *dpy, | |||
| 512 | XrmValue *args, Cardinal *num_args, | |||
| 513 | XrmValue *fromVal, XrmValue *toVal, | |||
| 514 | XtPointer *converter_data) | |||
| 515 | { | |||
| 516 | char *name; | |||
| 517 | XftFont *font; | |||
| 518 | Screen *screen; | |||
| 519 | ||||
| 520 | if (*num_args != 1) | |||
| 521 | { | |||
| 522 | XtAppErrorMsg (XtDisplayToApplicationContext (dpy), | |||
| 523 | "cvtStringToXftFont", "wrongParameters", | |||
| 524 | "XtToolkitError", | |||
| 525 | "String to XftFont conversion needs screen argument", | |||
| 526 | (String *) NULL((void*)0), (Cardinal *)NULL((void*)0)); | |||
| 527 | return False0; | |||
| 528 | } | |||
| 529 | ||||
| 530 | screen = *((Screen **) args[0].addr); | |||
| 531 | name = (char *) fromVal->addr; | |||
| 532 | ||||
| 533 | font = NULL((void*)0); | |||
| 534 | if (name) | |||
| 535 | { | |||
| 536 | font = XftFontOpenName (dpy, | |||
| 537 | XScreenNumberOfScreen (screen), | |||
| 538 | name); | |||
| 539 | if (!font) | |||
| 540 | XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont"XftFont"); | |||
| 541 | } | |||
| 542 | donestr (XftFont *, font, XtRXftFont){ if (toVal->addr != ((void*)0)) { if (toVal->size < sizeof(XftFont *)) { toVal->size = sizeof(XftFont *); XtDisplayStringConversionWarning (dpy, (char*) fromVal->addr, "XftFont"); return 0; } *(XftFont **)(toVal->addr) = (font); } else { static XftFont * static_val ; static_val = (font); toVal->addr = (XPointer)&static_val ; } toVal->size = sizeof(XftFont *); return 1; }; | |||
| 543 | } | |||
| 544 | ||||
| 545 | static XtConvertArgRec xftFontConvertArgs[] = { | |||
| 546 | {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen)__builtin_offsetof(WidgetRec, core.screen), | |||
| 547 | sizeof(Screen *)}, | |||
| 548 | }; | |||
| 549 | ||||
| 550 | #endif | |||
| 551 | ||||
| 552 | static void | |||
| 553 | ClassInitialize(void) | |||
| 554 | { | |||
| 555 | XtAddConverter (XtRString((char*)&XtStrings[1797]), XtRLong"Long", XmuCvtStringToLong, NULL((void*)0), 0); | |||
| 556 | #ifdef XRENDER1 | |||
| 557 | XtSetTypeConverter (XtRString((char*)&XtStrings[1797]), XtRXftColor"XftColor", | |||
| 558 | XmuCvtStringToXftColor, | |||
| 559 | xftColorConvertArgs, XtNumber(xftColorConvertArgs)((Cardinal) (sizeof(xftColorConvertArgs) / sizeof(xftColorConvertArgs [0]))), | |||
| 560 | XtCacheByDisplay0x003, XmuFreeXftColor); | |||
| 561 | XtSetTypeConverter (XtRString((char*)&XtStrings[1797]), XtRXftFont"XftFont", | |||
| 562 | XmuCvtStringToXftFont, | |||
| 563 | xftFontConvertArgs, XtNumber(xftFontConvertArgs)((Cardinal) (sizeof(xftFontConvertArgs) / sizeof(xftFontConvertArgs [0]))), | |||
| 564 | XtCacheByDisplay0x003, XmuFreeXftFont); | |||
| 565 | #endif | |||
| 566 | } | |||
| 567 | ||||
| 568 | ||||
| 569 | static void | |||
| 570 | Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args) | |||
| 571 | { | |||
| 572 | FontGridWidget reqfg = (FontGridWidget) request; | |||
| 573 | FontGridWidget newfg = (FontGridWidget) new; | |||
| 574 | XFontStruct *fs = newfg->fontgrid.text_font; | |||
| 575 | #ifdef XRENDER1 | |||
| 576 | XftFont *xft = newfg->fontgrid.text_face; | |||
| 577 | #endif | |||
| 578 | unsigned maxn; | |||
| 579 | ||||
| 580 | if (reqfg->fontgrid.cell_cols <= 0) | |||
| 581 | newfg->fontgrid.cell_cols = 16; | |||
| 582 | ||||
| 583 | if (reqfg->fontgrid.cell_rows <= 0) { | |||
| 584 | #ifdef XRENDER1 | |||
| 585 | if (xft) | |||
| 586 | newfg->fontgrid.cell_rows = 16; | |||
| 587 | else | |||
| 588 | #endif | |||
| 589 | if (fs && fs->max_byte1 == 0) { | |||
| 590 | newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 / | |||
| 591 | newfg->fontgrid.cell_cols) + 1; | |||
| 592 | if (newfg->fontgrid.cell_rows > 16) | |||
| 593 | newfg->fontgrid.cell_rows = 16; | |||
| 594 | } else | |||
| 595 | newfg->fontgrid.cell_rows = 16; | |||
| 596 | } | |||
| 597 | ||||
| 598 | if (reqfg->fontgrid.cell_width <= 0) | |||
| 599 | newfg->fontgrid.cell_width = DefaultCellWidth (newfg)(((newfg)->fontgrid.text_face ? (newfg)->fontgrid.text_face ->max_advance_width : (newfg)->fontgrid.text_font ? (newfg )->fontgrid.text_font->max_bounds.width : 1) + ((newfg) ->fontgrid.internal_pad * 2)); | |||
| 600 | if (reqfg->fontgrid.cell_height <= 0) | |||
| 601 | newfg->fontgrid.cell_height = DefaultCellHeight (newfg)(((newfg)->fontgrid.text_face ? (newfg)->fontgrid.text_face ->height : (newfg)->fontgrid.text_font ? (newfg)->fontgrid .text_font->ascent + (newfg)->fontgrid.text_font->descent : 1) + ((newfg)->fontgrid.internal_pad * 2)); | |||
| 602 | ||||
| 603 | /* give a nice size that fits one screen full */ | |||
| 604 | if (newfg->core.width == 0) | |||
| 605 | newfg->core.width = (newfg->fontgrid.cell_width * | |||
| 606 | newfg->fontgrid.cell_cols + | |||
| 607 | newfg->fontgrid.grid_width * | |||
| 608 | (newfg->fontgrid.cell_cols + 1)); | |||
| 609 | ||||
| 610 | if (newfg->core.height == 0) | |||
| 611 | newfg->core.height = (newfg->fontgrid.cell_height * | |||
| 612 | newfg->fontgrid.cell_rows + | |||
| 613 | newfg->fontgrid.grid_width * | |||
| 614 | (newfg->fontgrid.cell_rows + 1)); | |||
| 615 | ||||
| 616 | /* | |||
| 617 | * select the first character | |||
| 618 | */ | |||
| 619 | ||||
| 620 | if (newfg->fontgrid.start_char == 0xffffffff) | |||
| 621 | newfg->fontgrid.start_char = GridFirstChar(new) & ~0xff; | |||
| 622 | maxn = GridLastChar (new); | |||
| 623 | if (newfg->fontgrid.start_char > maxn) | |||
| 624 | newfg->fontgrid.start_char = (maxn + 1 - | |||
| 625 | (newfg->fontgrid.cell_cols * | |||
| 626 | newfg->fontgrid.cell_rows)); | |||
| 627 | } | |||
| 628 | ||||
| 629 | static void | |||
| 630 | Realize(Widget gw, Mask *valueMask, XSetWindowAttributes *attributes) | |||
| 631 | { | |||
| 632 | FontGridWidget fgw = (FontGridWidget) gw; | |||
| 633 | FontGridPart *p = &fgw->fontgrid; | |||
| 634 | ||||
| 635 | p->text_gc = get_gc (fgw, GridForeground (fgw)((fgw)->fontgrid.fg_color.pixel)); | |||
| 636 | p->box_gc = get_gc (fgw, p->box_pixel); | |||
| 637 | Resize (gw); | |||
| 638 | ||||
| 639 | (*(XtSuperclass(gw)(((gw)->core.widget_class)->core_class.superclass)->core_class.realize)) (gw, valueMask, attributes); | |||
| 640 | #ifdef XRENDER1 | |||
| 641 | p->draw = XftDrawCreate (XtDisplay (gw)(((gw)->core.screen)->display), XtWindow (gw)((gw)->core.window), | |||
| 642 | DefaultVisual (XtDisplay (gw),((&((_XPrivDisplay)(((gw)->core.screen)->display))-> screens[(((_XPrivDisplay)(((gw)->core.screen)->display) )->default_screen)])->root_visual) | |||
| 643 | DefaultScreen(XtDisplay (gw)))((&((_XPrivDisplay)(((gw)->core.screen)->display))-> screens[(((_XPrivDisplay)(((gw)->core.screen)->display) )->default_screen)])->root_visual), | |||
| 644 | fgw->core.colormap); | |||
| 645 | #endif | |||
| 646 | return; | |||
| 647 | } | |||
| 648 | ||||
| 649 | ||||
| 650 | ||||
| 651 | static void | |||
| 652 | Destroy(Widget gw) | |||
| 653 | { | |||
| 654 | FontGridWidget fgw = (FontGridWidget) gw; | |||
| 655 | ||||
| 656 | XtReleaseGC (gw, fgw->fontgrid.text_gc); | |||
| 657 | XtReleaseGC (gw, fgw->fontgrid.box_gc); | |||
| 658 | } | |||
| 659 | ||||
| 660 | ||||
| 661 | static void | |||
| 662 | Resize(Widget gw) | |||
| 663 | { | |||
| 664 | FontGridWidget fgw = (FontGridWidget) gw; | |||
| 665 | ||||
| 666 | /* recompute in case we've changed size */ | |||
| 667 | fgw->fontgrid.cell_width = CellWidth (fgw)(((int)(fgw)->core.width - (fgw)->fontgrid.grid_width) / (fgw)->fontgrid.cell_cols - (fgw)->fontgrid.grid_width ); | |||
| 668 | if (fgw->fontgrid.cell_width <= 0) | |||
| 669 | fgw->fontgrid.cell_width = 1; | |||
| 670 | fgw->fontgrid.cell_height = CellHeight (fgw)(((int)(fgw)->core.height - (fgw)->fontgrid.grid_width) / (fgw)->fontgrid.cell_rows - (fgw)->fontgrid.grid_width ); | |||
| 671 | if (fgw->fontgrid.cell_height <= 0) | |||
| 672 | fgw->fontgrid.cell_height = 1; | |||
| 673 | fgw->fontgrid.xoff = (fgw->fontgrid.cell_width - | |||
| 674 | DefaultCellWidth (fgw)(((fgw)->fontgrid.text_face ? (fgw)->fontgrid.text_face ->max_advance_width : (fgw)->fontgrid.text_font ? (fgw) ->fontgrid.text_font->max_bounds.width : 1) + ((fgw)-> fontgrid.internal_pad * 2))) / 2; | |||
| 675 | fgw->fontgrid.yoff = (fgw->fontgrid.cell_height - | |||
| 676 | DefaultCellHeight (fgw)(((fgw)->fontgrid.text_face ? (fgw)->fontgrid.text_face ->height : (fgw)->fontgrid.text_font ? (fgw)->fontgrid .text_font->ascent + (fgw)->fontgrid.text_font->descent : 1) + ((fgw)->fontgrid.internal_pad * 2))) / 2; | |||
| 677 | ||||
| 678 | } | |||
| 679 | ||||
| 680 | ||||
| 681 | /* ARGSUSED */ | |||
| 682 | static void | |||
| 683 | Redisplay(Widget gw, XEvent *event, Region region) | |||
| 684 | { | |||
| 685 | FontGridWidget fgw = (FontGridWidget) gw; | |||
| 686 | XRectangle rect; /* bounding rect for region */ | |||
| 687 | int left, right, top, bottom; /* which cells were damaged */ | |||
| 688 | int cw, ch; /* cell size */ | |||
| 689 | ||||
| 690 | #ifdef XRENDER1 | |||
| 691 | if (!fgw->fontgrid.text_face) | |||
| 692 | #endif | |||
| 693 | if (!fgw->fontgrid.text_font) { | |||
| 694 | Bell (gw, XkbBI_BadValue)XBell((((gw)->core.screen)->display), 0); | |||
| 695 | return; | |||
| 696 | } | |||
| 697 | ||||
| 698 | /* | |||
| 699 | * compute the left, right, top, and bottom cells that were damaged | |||
| 700 | */ | |||
| 701 | XClipBox (region, &rect); | |||
| 702 | cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width; | |||
| 703 | ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width; | |||
| 704 | if ((left = (((int) rect.x) / cw)) < 0) left = 0; | |||
| 705 | right = (((int) (rect.x + rect.width - 1)) / cw); | |||
| 706 | if ((top = (((int) rect.y) / ch)) < 0) top = 0; | |||
| 707 | bottom = (((int) (rect.y + rect.height - 1)) / ch); | |||
| 708 | ||||
| 709 | paint_grid (fgw, left, top, right - left + 1, bottom - top + 1); | |||
| 710 | } | |||
| 711 | ||||
| 712 | ||||
| 713 | static void | |||
| 714 | paint_grid(FontGridWidget fgw, /* widget in which to draw */ | |||
| 715 | int col, int row, /* where to start */ | |||
| 716 | int ncols, int nrows) /* number of cells */ | |||
| 717 | { | |||
| 718 | FontGridPart *p = &fgw->fontgrid; | |||
| 719 | int i, j; | |||
| 720 | Display *dpy = XtDisplay(fgw)(((fgw)->core.screen)->display); | |||
| 721 | Window wind = XtWindow(fgw)((fgw)->core.window); | |||
| 722 | int cw = p->cell_width + p->grid_width; | |||
| 723 | int ch = p->cell_height + p->grid_width; | |||
| 724 | int tcols = p->cell_cols; | |||
| 725 | int trows = p->cell_rows; | |||
| 726 | int x1, y1, x2, y2, x, y; | |||
| 727 | unsigned maxn = GridLastChar ((Widget) fgw); | |||
| ||||
| 728 | unsigned n, prevn; | |||
| 729 | int startx; | |||
| 730 | ||||
| 731 | if (col + ncols >= tcols) { | |||
| 732 | ncols = tcols - col; | |||
| 733 | if (ncols < 1) return; | |||
| 734 | } | |||
| 735 | ||||
| 736 | if (row + nrows >= trows) { | |||
| 737 | nrows = trows - row; | |||
| 738 | if (nrows < 1) return; | |||
| 739 | } | |||
| 740 | ||||
| 741 | /* | |||
| 742 | * paint the grid lines for the indicated rows | |||
| 743 | */ | |||
| 744 | if (p->grid_width > 0) { | |||
| 745 | int half_grid_width = p->grid_width >> 1; | |||
| 746 | x1 = col * cw + half_grid_width; | |||
| 747 | y1 = row * ch + half_grid_width; | |||
| 748 | x2 = x1 + ncols * cw; | |||
| 749 | y2 = y1 + nrows * ch; | |||
| 750 | for (i = 0, x = x1; i <= ncols; i++, x += cw) { | |||
| 751 | XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2); | |||
| 752 | } | |||
| 753 | for (i = 0, y = y1; i <= nrows; i++, y += ch) { | |||
| 754 | XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); | |||
| 755 | } | |||
| 756 | } | |||
| 757 | /* | |||
| 758 | * Draw a character in every box; treat all fonts as if they were 16bit | |||
| 759 | * fonts. Store the high eight bits in byte1 and the low eight bits in | |||
| 760 | * byte2. | |||
| 761 | */ | |||
| 762 | prevn = p->start_char + col + row * tcols; | |||
| 763 | startx = col * cw + p->internal_pad + p->grid_width; | |||
| 764 | for (j = 0, | |||
| 765 | y = row * ch + p->internal_pad + p->grid_width + GridFontAscent (fgw)((fgw)->fontgrid.text_face ? (fgw)->fontgrid.text_face-> ascent : (fgw)->fontgrid.text_font ? (fgw)->fontgrid.text_font ->ascent: 1); | |||
| 766 | j < nrows; j++, y += ch) { | |||
| 767 | n = prevn; | |||
| 768 | for (i = 0, x = startx; i < ncols; i++, x += cw) { | |||
| 769 | int xoff = p->xoff, yoff = p->yoff; | |||
| 770 | if (n > maxn) goto done; /* no break out of nested */ | |||
| 771 | ||||
| 772 | #ifdef XRENDER1 | |||
| 773 | if (fgw->fontgrid.text_face) | |||
| 774 | { | |||
| 775 | XftFont *xft = p->text_face; | |||
| 776 | FcChar32 c = n; | |||
| 777 | XGlyphInfo extents; | |||
| 778 | XftTextExtents32 (dpy, xft, &c, 1, &extents); | |||
| 779 | if (p->center_chars) | |||
| 780 | { | |||
| 781 | xoff = (p->cell_width - extents.width) / 2 - extents.x; | |||
| 782 | yoff = (p->cell_height - extents.height) / 2 - extents.y; | |||
| 783 | } | |||
| 784 | if (extents.width && extents.height) | |||
| 785 | { | |||
| 786 | XClearArea (dpy, wind, x + xoff - extents.x, | |||
| 787 | y + yoff - extents.y, | |||
| 788 | extents.width, extents.height, False0); | |||
| 789 | if (p->box_chars) | |||
| 790 | XDrawRectangle (dpy, wind, p->box_gc, | |||
| 791 | x + xoff - extents.x, | |||
| 792 | y + yoff - extents.y, | |||
| 793 | extents.width - 1, | |||
| 794 | extents.height - 1); | |||
| 795 | } | |||
| 796 | XftDrawString32 (p->draw, &p->fg_color, xft, | |||
| 797 | x + xoff, y + yoff, &c, 1); | |||
| 798 | } | |||
| 799 | else | |||
| 800 | #endif | |||
| 801 | { | |||
| 802 | XChar2b thechar; | |||
| 803 | ||||
| 804 | thechar.byte1 = (n >> 8); /* high eight bits */ | |||
| 805 | thechar.byte2 = (n & 255); /* low eight bits */ | |||
| 806 | if (p->box_chars || p->center_chars) { | |||
| 807 | XCharStruct metrics; | |||
| 808 | int direction, fontascent, fontdescent; | |||
| 809 | ||||
| 810 | XTextExtents16 (p->text_font, &thechar, 1, &direction, | |||
| 811 | &fontascent, &fontdescent, &metrics); | |||
| 812 | ||||
| 813 | if (p->center_chars) { | |||
| 814 | /* | |||
| 815 | * We want to move the origin by enough to center the ink | |||
| 816 | * within the cell. The left edge will then be at | |||
| 817 | * (cell_width - (rbearing - lbearing)) / 2; so we subtract | |||
| 818 | * the lbearing to find the origin. Ditto for vertical. | |||
| 819 | */ | |||
| 820 | xoff = (((p->cell_width - | |||
| 821 | (metrics.rbearing - metrics.lbearing)) / 2) - | |||
| 822 | p->internal_pad - metrics.lbearing); | |||
| 823 | yoff = (((p->cell_height - | |||
| 824 | (metrics.descent + metrics.ascent)) / 2) - | |||
| 825 | p->internal_pad - | |||
| 826 | p->text_font->ascent + metrics.ascent); | |||
| ||||
| 827 | } | |||
| 828 | if (p->box_chars) { | |||
| 829 | XDrawRectangle (dpy, wind, p->box_gc, | |||
| 830 | x + xoff, y + yoff - p->text_font->ascent, | |||
| 831 | metrics.width - 1, | |||
| 832 | fontascent + fontdescent - 1); | |||
| 833 | } | |||
| 834 | } | |||
| 835 | XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff, | |||
| 836 | &thechar, 1); | |||
| 837 | } | |||
| 838 | n++; | |||
| 839 | } | |||
| 840 | prevn += tcols; | |||
| 841 | } | |||
| 842 | ||||
| 843 | done: | |||
| 844 | /* | |||
| 845 | * paint the grid lines for the indicated rows | |||
| 846 | */ | |||
| 847 | if (p->grid_width > 0) { | |||
| 848 | int half_grid_width = p->grid_width >> 1; | |||
| 849 | x1 = col * cw + half_grid_width; | |||
| 850 | y1 = row * ch + half_grid_width; | |||
| 851 | x2 = x1 + ncols * cw; | |||
| 852 | y2 = y1 + nrows * ch; | |||
| 853 | for (i = 0, x = x1; i <= ncols; i++, x += cw) { | |||
| 854 | XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2); | |||
| 855 | } | |||
| 856 | for (i = 0, y = y1; i <= nrows; i++, y += ch) { | |||
| 857 | XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); | |||
| 858 | } | |||
| 859 | } | |||
| 860 | ||||
| 861 | ||||
| 862 | return; | |||
| 863 | } | |||
| 864 | ||||
| 865 | static Boolean | |||
| 866 | PageBlank (Widget w, long first, long last) | |||
| 867 | { | |||
| 868 | while (first <= last) | |||
| 869 | { | |||
| 870 | if (GridHasChar (w, first)) | |||
| 871 | return False0; | |||
| 872 | first++; | |||
| 873 | } | |||
| 874 | return True1; | |||
| 875 | } | |||
| 876 | ||||
| 877 | /*ARGSUSED*/ | |||
| 878 | static Boolean | |||
| 879 | SetValues(Widget current, Widget request, Widget new, | |||
| 880 | ArgList args, Cardinal *num_args) | |||
| 881 | { | |||
| 882 | FontGridWidget curfg = (FontGridWidget) current; | |||
| 883 | FontGridWidget newfg = (FontGridWidget) new; | |||
| 884 | Boolean redisplay = FALSE0; | |||
| 885 | ||||
| 886 | if (curfg->fontgrid.text_font != newfg->fontgrid.text_font || | |||
| 887 | curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) { | |||
| 888 | newfg->fontgrid.cell_width = DefaultCellWidth (newfg)(((newfg)->fontgrid.text_face ? (newfg)->fontgrid.text_face ->max_advance_width : (newfg)->fontgrid.text_font ? (newfg )->fontgrid.text_font->max_bounds.width : 1) + ((newfg) ->fontgrid.internal_pad * 2)); | |||
| 889 | newfg->fontgrid.cell_height = DefaultCellHeight (newfg)(((newfg)->fontgrid.text_face ? (newfg)->fontgrid.text_face ->height : (newfg)->fontgrid.text_font ? (newfg)->fontgrid .text_font->ascent + (newfg)->fontgrid.text_font->descent : 1) + ((newfg)->fontgrid.internal_pad * 2)); | |||
| 890 | redisplay = TRUE1; | |||
| 891 | } | |||
| 892 | ||||
| 893 | if (GridForeground(curfg)((curfg)->fontgrid.fg_color.pixel) != GridForeground (newfg)((newfg)->fontgrid.fg_color.pixel)) { | |||
| 894 | XtReleaseGC (new, curfg->fontgrid.text_gc); | |||
| 895 | newfg->fontgrid.text_gc = get_gc (newfg, GridForeground (newfg)((newfg)->fontgrid.fg_color.pixel)); | |||
| 896 | redisplay = TRUE1; | |||
| 897 | } | |||
| 898 | ||||
| 899 | if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) { | |||
| 900 | XtReleaseGC (new, curfg->fontgrid.text_gc); | |||
| 901 | newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel); | |||
| 902 | redisplay = TRUE1; | |||
| 903 | } | |||
| 904 | ||||
| 905 | if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars || | |||
| 906 | curfg->fontgrid.box_chars != newfg->fontgrid.box_chars) | |||
| 907 | redisplay = TRUE1; | |||
| 908 | ||||
| 909 | if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) { | |||
| 910 | long maxn = GridLastChar (new); | |||
| 911 | long page = newfg->fontgrid.cell_cols * newfg->fontgrid.cell_rows; | |||
| 912 | long dir = page; | |||
| 913 | long start = newfg->fontgrid.start_char; | |||
| 914 | ||||
| 915 | if (start < curfg->fontgrid.start_char) | |||
| 916 | dir = -page; | |||
| 917 | ||||
| 918 | if (start < 0) | |||
| 919 | start = 0; | |||
| 920 | if (start > maxn) | |||
| 921 | start = (maxn / page) * page; | |||
| 922 | ||||
| 923 | while (PageBlank (new, start, start + page - 1)) | |||
| 924 | { | |||
| 925 | long next = start + dir; | |||
| 926 | ||||
| 927 | if (next < 0 || maxn < next) | |||
| 928 | break; | |||
| 929 | start = next; | |||
| 930 | } | |||
| 931 | ||||
| 932 | newfg->fontgrid.start_char = start; | |||
| 933 | redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char); | |||
| 934 | } | |||
| 935 | ||||
| 936 | return redisplay; | |||
| 937 | } | |||
| 938 | ||||
| 939 | ||||
| 940 | /* ARGSUSED */ | |||
| 941 | static void | |||
| 942 | Notify(Widget gw, XEvent *event, String *params, Cardinal *nparams) | |||
| 943 | { | |||
| 944 | FontGridWidget fgw = (FontGridWidget) gw; | |||
| 945 | int x, y; /* where the event happened */ | |||
| 946 | FontGridCharRec rec; /* callback data */ | |||
| 947 | ||||
| 948 | /* | |||
| 949 | * only allow events with (x,y) | |||
| 950 | */ | |||
| 951 | switch (event->type) { | |||
| 952 | case KeyPress2: | |||
| 953 | case KeyRelease3: | |||
| 954 | x = event->xkey.x; | |||
| 955 | y = event->xkey.y; | |||
| 956 | break; | |||
| 957 | case ButtonPress4: | |||
| 958 | case ButtonRelease5: | |||
| 959 | x = event->xbutton.x; | |||
| 960 | y = event->xbutton.y; | |||
| 961 | break; | |||
| 962 | case MotionNotify6: | |||
| 963 | x = event->xmotion.x; | |||
| 964 | y = event->xmotion.y; | |||
| 965 | break; | |||
| 966 | default: | |||
| 967 | Bell (gw, XkbBI_Ignore)XBell((((gw)->core.screen)->display), 0); | |||
| 968 | return; | |||
| 969 | } | |||
| 970 | ||||
| 971 | /* | |||
| 972 | * compute the callback data | |||
| 973 | */ | |||
| 974 | { | |||
| 975 | int cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width; | |||
| 976 | int ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width; | |||
| 977 | unsigned n; | |||
| 978 | ||||
| 979 | if (x > (fgw->fontgrid.cell_cols * cw)) { | |||
| 980 | Bell (gw, XkbBI_InvalidLocation)XBell((((gw)->core.screen)->display), 0); | |||
| 981 | return; | |||
| 982 | } | |||
| 983 | ||||
| 984 | n= (fgw->fontgrid.start_char + | |||
| 985 | ((y / ch) * fgw->fontgrid.cell_cols) + (x / cw)); | |||
| 986 | ||||
| 987 | rec.thefont = fgw->fontgrid.text_font; | |||
| 988 | #ifdef XRENDER1 | |||
| 989 | rec.theface = fgw->fontgrid.text_face; | |||
| 990 | #endif | |||
| 991 | rec.thechar = n; | |||
| 992 | } | |||
| 993 | ||||
| 994 | XtCallCallbacks (gw, XtNcallback((char*)&XtStrings[136]), (XtPointer) &rec); | |||
| 995 | } | |||
| 996 |