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