xfd.c revision 492e1cfe
1/* 2 * $Xorg: xfd.c,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $ 3 * 4 * 5Copyright 1989, 1998 The Open Group 6 7Permission to use, copy, modify, distribute, and sell this software and its 8documentation for any purpose is hereby granted without fee, provided that 9the above copyright notice appear in all copies and that both that 10copyright notice and this permission notice appear in supporting 11documentation. 12 13The above copyright notice and this permission notice shall be included in 14all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of The Open Group shall not be 24used in advertising or otherwise to promote the sale, use or other dealings 25in this Software without prior written authorization from The Open Group. 26 * * 27 * Author: Jim Fulton, MIT X Consortium 28 */ 29/* $XFree86: xc/programs/xfd/xfd.c,v 1.8 2003/02/20 02:56:40 dawes Exp $ */ 30 31#include <X11/Intrinsic.h> 32#include <X11/StringDefs.h> 33#include <X11/Xos.h> 34#include <X11/Xatom.h> 35#include <X11/Shell.h> 36#include <X11/Xaw/Cardinals.h> 37#include <X11/Xaw/Paned.h> 38#include <X11/Xaw/Box.h> 39#include <X11/Xaw/Form.h> 40#include <X11/Xaw/Command.h> 41#include <stdio.h> 42#include <stdlib.h> 43#include "grid.h" 44#ifdef XRENDER 45#include <X11/Xft/Xft.h> 46#include <X11/extensions/Xrender.h> 47#endif 48 49char *ProgramName; 50 51static XrmOptionDescRec xfd_options[] = { 52{"-fn", "*grid.font", XrmoptionSepArg, (caddr_t) NULL }, 53#ifdef XRENDER 54{"-fa", "*grid.face", XrmoptionSepArg, (caddr_t) NULL }, 55#endif 56{"-start", "*startChar", XrmoptionSepArg, (caddr_t) NULL }, 57{"-box", "*grid.boxChars", XrmoptionNoArg, (caddr_t) "on" }, 58{"-bc", "*grid.boxColor", XrmoptionSepArg, (caddr_t) NULL }, 59{"-center", "*grid.centerChars", XrmoptionNoArg, (caddr_t) "on" }, 60{"-rows", "*grid.cellRows", XrmoptionSepArg, (caddr_t) NULL }, 61{"-columns", "*grid.cellColumns", XrmoptionSepArg, (caddr_t) NULL }, 62}; 63 64static void usage(void); 65static void SelectChar(Widget w, XtPointer closure, XtPointer data); 66static void do_quit(Widget w, XEvent *event, String *params, 67 Cardinal *num_params); 68static void change_page(int page); 69static void set_button_state(void); 70static void do_prev(Widget w, XEvent *event, String *params, 71 Cardinal *num_params); 72static void do_next(Widget w, XEvent *event, String *params, 73 Cardinal *num_params); 74static void do_prev16(Widget w, XEvent *event, String *params, 75 Cardinal *num_params); 76static void do_next16(Widget w, XEvent *event, String *params, 77 Cardinal *num_params); 78static char *get_font_name(Display *dpy, XFontStruct *fs); 79static void CatchFontConversionWarning(String name, String type, String class, 80 String defaultp, String *params, 81 Cardinal *np); 82 83static XtActionsRec xfd_actions[] = { 84 { "Quit", do_quit }, 85 { "Prev16", do_prev16 }, 86 { "Prev", do_prev }, 87 { "Next", do_next }, 88 { "Next16", do_next16 }, 89}; 90 91static Atom wm_delete_window; 92 93Widget quitButton, prev16Button, prevButton, nextButton, next16Button; 94 95 96#define DEF_SELECT_FORMAT "character 0x%04x%02x (%u,%u) (%#o,%#o)" 97#define DEF_METRICS_FORMAT "width %d; left %d, right %d; ascent %d, descent %d (font %d, %d)" 98#define DEF_RANGE_FORMAT "range: 0x%04x%02x (%u,%u) thru 0x%04x%02x (%u,%u)" 99#define DEF_START_FORMAT "upper left: 0x%06x (%d,%d)" 100#define DEF_NOCHAR_FORMAT "no such character 0x%04x%02x (%u,%u) (%#o,%#o)" 101 102static struct _xfd_resources { 103 char *select_format; 104 char *metrics_format; 105 char *range_format; 106 char *start_format; 107 char *nochar_format; 108} xfd_resources; 109 110#define Offset(field) XtOffsetOf(struct _xfd_resources, field) 111 112static XtResource Resources[] = { 113 { "selectFormat", "SelectFormat", XtRString, sizeof(char *), 114 Offset(select_format), XtRString, DEF_SELECT_FORMAT }, 115 { "metricsFormat", "MetricsFormat", XtRString, sizeof(char *), 116 Offset(metrics_format), XtRString, DEF_METRICS_FORMAT }, 117 { "rangeFormat", "RangeFormat", XtRString, sizeof(char *), 118 Offset(range_format), XtRString, DEF_RANGE_FORMAT }, 119 { "startFormat", "StartFormat", XtRString, sizeof(char *), 120 Offset(start_format), XtRString, DEF_START_FORMAT }, 121 { "nocharFormat", "NocharFormat", XtRString, sizeof(char *), 122 Offset(nochar_format), XtRString, DEF_NOCHAR_FORMAT }, 123}; 124 125#undef Offset 126 127static void 128usage(void) 129{ 130 fprintf (stderr, "usage: %s [-options ...] -fn font\n", ProgramName); 131#ifdef XRENDER 132 fprintf (stderr, " %s [-options ...] -fa font\n", ProgramName); 133#endif 134 fprintf (stderr, "where options include:\n"); 135 fprintf (stderr, 136 " -display dpy X server to contact\n"); 137 fprintf (stderr, 138 " -geometry geom size and location of window\n"); 139 fprintf (stderr, 140 " -start num first character to show\n"); 141 fprintf (stderr, 142 " -box show a box around each character\n"); 143 fprintf (stderr, 144 " -center center each character inside its grid\n"); 145 fprintf (stderr, 146 " -rows number number of rows in grid\n"); 147 fprintf (stderr, 148 " -columns number number of columns in grid\n"); 149 fprintf (stderr, "\n"); 150 exit (1); 151} 152 153 154static Widget selectLabel, metricsLabel, rangeLabel, startLabel, fontGrid; 155 156static Boolean fontConversionFailed = False; 157static XtErrorMsgHandler oldWarningHandler; 158 159int 160main(int argc, char *argv[]) 161{ 162 XtAppContext xtcontext; 163 Widget toplevel, pane, toplabel, box, form; 164 char buf[256]; 165 Arg av[10]; 166 Cardinal i; 167 static XtCallbackRec cb[2] = { { SelectChar, NULL }, { NULL, NULL } }; 168 XFontStruct *fs; 169#ifdef XRENDER 170 XftFont *xft; 171#endif 172 char *fontname; 173 long minn, maxn; 174 175 ProgramName = argv[0]; 176 177 toplevel = XtAppInitialize (&xtcontext, "Xfd", 178 xfd_options, XtNumber(xfd_options), 179 &argc, argv, NULL, NULL, 0); 180 if (argc != 1) usage (); 181 XtAppAddActions (xtcontext, xfd_actions, XtNumber (xfd_actions)); 182 XtOverrideTranslations 183 (toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); 184 185 XtGetApplicationResources (toplevel, (XtPointer) &xfd_resources, Resources, 186 XtNumber (Resources), NULL, ZERO); 187 188 189 /* pane wrapping everything */ 190 pane = XtCreateManagedWidget ("pane", panedWidgetClass, toplevel, 191 NULL, ZERO); 192 193 /* font name */ 194 toplabel = XtCreateManagedWidget ("fontname", labelWidgetClass, pane, 195 NULL, ZERO); 196 197 /* button box */ 198 box = XtCreateManagedWidget ("box", boxWidgetClass, pane, NULL, ZERO); 199 quitButton = XtCreateManagedWidget ("quit", commandWidgetClass, box, 200 NULL, ZERO); 201 prev16Button = XtCreateManagedWidget ("prev16", commandWidgetClass, box, 202 NULL, ZERO); 203 prevButton = XtCreateManagedWidget ("prev", commandWidgetClass, box, 204 NULL, ZERO); 205 nextButton = XtCreateManagedWidget ("next", commandWidgetClass, box, 206 NULL, ZERO); 207 next16Button = XtCreateManagedWidget ("next16", commandWidgetClass, box, 208 NULL, ZERO); 209 210 211 /* and labels in which to put information */ 212 selectLabel = XtCreateManagedWidget ("select", labelWidgetClass, 213 pane, NULL, ZERO); 214 215 metricsLabel = XtCreateManagedWidget ("metrics", labelWidgetClass, 216 pane, NULL, ZERO); 217 218 rangeLabel = XtCreateManagedWidget ("range", labelWidgetClass, pane, 219 NULL, ZERO); 220 221 startLabel = XtCreateManagedWidget ("start", labelWidgetClass, pane, 222 NULL, ZERO); 223 224 /* form in which to draw */ 225 form = XtCreateManagedWidget ("form", formWidgetClass, pane, NULL, ZERO); 226 227 i = 0; 228 XtSetArg (av[i], XtNtop, XtChainTop); i++; 229 XtSetArg (av[i], XtNbottom, XtChainBottom); i++; 230 XtSetArg (av[i], XtNleft, XtChainLeft); i++; 231 XtSetArg (av[i], XtNright, XtChainRight); i++; 232 XtSetArg (av[i], XtNcallback, cb); i++; 233 234 oldWarningHandler = XtAppSetWarningMsgHandler(xtcontext, 235 CatchFontConversionWarning); 236 237 fontGrid = XtCreateManagedWidget ("grid", fontgridWidgetClass, form, 238 av, i); 239 240 XtAppSetWarningMsgHandler(xtcontext, oldWarningHandler); 241 242 /* set the label at the top to tell us which font this is */ 243#ifdef XRENDER 244 i = 0; 245 XtSetArg (av[i], XtNface, &xft); i++; 246 XtGetValues (fontGrid, av, i); 247 if (xft) 248 { 249 FcChar8 *family; 250 FcChar8 *style; 251 FcPattern *p; 252 double size; 253 family = (FcChar8 *) ""; 254 FcPatternGetString (xft->pattern, FC_FAMILY, 0, &family); 255 style = (FcChar8 *) ""; 256 FcPatternGetString (xft->pattern, FC_STYLE, 0, &style); 257 size = 0; 258 FcPatternGetDouble (xft->pattern, FC_SIZE, 0, &size); 259 p = FcPatternBuild (0, 260 FC_FAMILY, FcTypeString, family, 261 FC_STYLE, FcTypeString, style, 262 FC_SIZE, FcTypeDouble, size, 263 NULL); 264 fontname = (char *) FcNameUnparse (p); 265 FcPatternDestroy (p); 266 } 267 else 268#endif 269 { 270 i = 0; 271 XtSetArg (av[i], XtNfont, &fs); i++; 272 XtGetValues (fontGrid, av, i); 273 if (!fs || fontConversionFailed) { 274 fprintf (stderr, "%s: no font to display\n", ProgramName); 275 exit (1); 276 } 277 fontname = get_font_name (XtDisplay(toplevel), fs); 278 } 279 i = 0; 280 XtSetArg (av[i], XtNlabel, fontname); i++; 281 XtSetValues (toplabel, av, i); 282 283 minn = GridFirstChar (fontGrid); 284 maxn = GridLastChar (fontGrid); 285 sprintf (buf, xfd_resources.range_format, 286 minn >> 8, minn & 0xff, 287 minn >> 8, minn & 0xff, 288 maxn >> 8, maxn & 0xff, 289 maxn >> 8, maxn & 0xff); 290 291 i = 0; 292 XtSetArg (av[i], XtNlabel, buf); i++; 293 XtSetValues (rangeLabel, av, i); 294 295 XtRealizeWidget (toplevel); 296 297 wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", 298 False); 299 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), 300 &wm_delete_window, 1); 301 302 change_page (0); 303 XtAppMainLoop (xtcontext); 304 exit(0); 305} 306 307/*ARGSUSED*/ 308static void 309SelectChar(Widget w, XtPointer closure, XtPointer data) 310{ 311 FontGridCharRec *p = (FontGridCharRec *) data; 312 XFontStruct *fs = p->thefont; 313 long n = p->thechar; 314 int direction, fontascent, fontdescent; 315 XCharStruct metrics; 316 char buf[256]; 317 Arg arg; 318 Boolean has_char = 1; 319 320 XtSetArg (arg, XtNlabel, buf); 321 322 buf[0] = '\0'; 323#ifdef XRENDER 324 if (p->theface) 325 { 326 XftFont *xft = p->theface; 327 FcChar32 c = (FcChar32) n; 328 has_char = (Boolean) FcCharSetHasChar (xft->charset, n); 329 if (has_char) 330 { 331 XGlyphInfo extents; 332 XftTextExtents32 (XtDisplay (w), xft, &c, 1, &extents); 333 sprintf (buf, xfd_resources.metrics_format, 334 extents.xOff, - extents.x, 335 extents.xOff - extents.width + extents.x, 336 extents.y, extents.height - extents.y, 337 xft->ascent, xft->descent); 338 } 339 } 340 else 341#endif 342 { 343 if ((!fs->min_byte1 && !fs->max_byte1) ? 344 (n < fs->min_char_or_byte2 || n > fs->max_char_or_byte2) : 345 (n >> 8 < fs->min_byte1 || n >> 8 > fs->max_byte1 || 346 (n & 0xff) < fs->min_char_or_byte2 || 347 (n & 0xff) > fs->max_char_or_byte2)) 348 { 349 has_char = 0; 350 } 351 else 352 { 353 XChar2b char2b; 354 char2b.byte1 = p->thechar >> 8; 355 char2b.byte2 = p->thechar & 0xff; 356 XTextExtents16 (fs, &char2b, 1, &direction, &fontascent, &fontdescent, 357 &metrics); 358 sprintf (buf, xfd_resources.metrics_format, 359 metrics.width, metrics.lbearing, metrics.rbearing, 360 metrics.ascent, metrics.descent, fontascent, fontdescent); 361 } 362 } 363 XtSetValues (metricsLabel, &arg, ONE); 364 365 if (has_char) 366 { 367 sprintf (buf, xfd_resources.select_format, 368 n >> 8, n & 0xff, 369 n >> 8, n & 0xff, 370 n >> 8, n & 0xff); 371 } 372 else 373 { 374 sprintf (buf, xfd_resources.nochar_format, 375 n >> 8, n & 0xff, 376 n >> 8, n & 0xff, 377 n >> 8, n & 0xff); 378 } 379 XtSetValues (selectLabel, &arg, ONE); 380 381 return; 382} 383 384 385/*ARGSUSED*/ 386static void 387do_quit (Widget w, XEvent *event, String *params, Cardinal *num_params) 388{ 389 exit (0); 390} 391 392static void 393change_page(int page) 394{ 395 long oldstart, newstart; 396 int ncols, nrows; 397 char buf[256]; 398 Arg arg; 399 400 arg.name = XtNstartChar; 401 GetFontGridCellDimensions (fontGrid, &oldstart, &ncols, &nrows); 402 403 if (page) { 404 long start = (oldstart + 405 ((long) ncols) * ((long) nrows) * ((long) page)); 406 407 arg.value = (XtArgVal) start; 408 XtSetValues (fontGrid, &arg, ONE); 409 } 410 411 /* find out what it got set to */ 412 arg.value = (XtArgVal) &newstart; 413 XtGetValues (fontGrid, &arg, ONE); 414 415 /* if not paging, then initialize it, else only do it actually changed */ 416 if (!page || newstart != oldstart) { 417 unsigned int row = (unsigned int) ((newstart >> 8)); 418 unsigned int col = (unsigned int) (newstart & 0xff); 419 420 XtSetArg (arg, XtNlabel, buf); 421 sprintf (buf, xfd_resources.start_format, newstart, row, col); 422 XtSetValues (startLabel, &arg, ONE); 423 } 424 425 set_button_state (); 426 427 return; 428} 429 430 431static void 432set_button_state(void) 433{ 434 Bool prevvalid, nextvalid, prev16valid, next16valid; 435 Arg arg; 436 437 GetPrevNextStates (fontGrid, &prevvalid, &nextvalid, &prev16valid, &next16valid); 438 arg.name = XtNsensitive; 439 arg.value = (XtArgVal) (prevvalid ? TRUE : FALSE); 440 XtSetValues (prevButton, &arg, ONE); 441 arg.value = (XtArgVal) (nextvalid ? TRUE : FALSE); 442 XtSetValues (nextButton, &arg, ONE); 443 arg.name = XtNsensitive; 444 arg.value = (XtArgVal) (prev16valid ? TRUE : FALSE); 445 XtSetValues (prev16Button, &arg, ONE); 446 arg.value = (XtArgVal) (next16valid ? TRUE : FALSE); 447 XtSetValues (next16Button, &arg, ONE); 448} 449 450 451/* ARGSUSED */ 452static void 453do_prev16(Widget w, XEvent *event, String *params, Cardinal *num_params) 454{ 455 change_page (-16); 456} 457 458 459static void 460do_prev(Widget w, XEvent *event, String *params, Cardinal *num_params) 461{ 462 change_page (-1); 463} 464 465 466/* ARGSUSED */ 467static void 468do_next(Widget w, XEvent *event, String *params, Cardinal *num_params) 469{ 470 change_page (1); 471} 472 473/* ARGSUSED */ 474static void 475do_next16(Widget w, XEvent *event, String *params, Cardinal *num_params) 476{ 477 change_page (16); 478} 479 480 481static char * 482get_font_name(Display *dpy, XFontStruct *fs) 483{ 484 register XFontProp *fp; 485 register int i; 486 Atom fontatom = XInternAtom (dpy, "FONT", False); 487 488 for (i = 0, fp = fs->properties; i < fs->n_properties; i++, fp++) { 489 if (fp->name == fontatom) { 490 return (XGetAtomName (dpy, fp->card32)); 491 } 492 } 493 return NULL; 494} 495 496 497static void 498CatchFontConversionWarning(String name, String type, String class, 499 String defaultp, String *params, Cardinal *np) 500{ 501 if (np && *np > 1 && 502 strcmp(name, "conversionError") == 0 && 503 strcmp(type, "string") == 0 && 504 strcmp(class, "XtToolkitError") == 0 && 505 strcmp(params[1], "FontStruct") == 0) fontConversionFailed = True; 506 507 (*oldWarningHandler)(name, type, class, defaultp, params, np); 508} 509