2 * $Xorg: xfd.c,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $
5 Copyright 1989, 1998 The Open Group
7 Permission to use, copy, modify, distribute, and sell this software and its
8 documentation for any purpose is hereby granted without fee, provided that
9 the above copyright notice appear in all copies and that both that
10 copyright notice and this permission notice appear in supporting
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of The Open Group shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from The Open Group.
27 * Author: Jim Fulton, MIT X Consortium
29 /* $XFree86: xc/programs/xfd/xfd.c,v 1.8 2003/02/20 02:56:40 dawes Exp $ */
31 #include <X11/Intrinsic.h>
32 #include <X11/StringDefs.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>
45 #include <X11/Xft/Xft.h>
46 #include <X11/extensions/Xrender.h>
51 static XrmOptionDescRec xfd_options[] = {
52 {"-fn", "*grid.font", XrmoptionSepArg, (caddr_t) NULL },
54 {"-fa", "*grid.face", XrmoptionSepArg, (caddr_t) NULL },
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 },
64 static void usage(void);
65 static void SelectChar(Widget w, XtPointer closure, XtPointer data);
66 static void do_quit(Widget w, XEvent *event, String *params,
67 Cardinal *num_params);
68 static void change_page(int page);
69 static void set_button_state(void);
70 static void do_prev(Widget w, XEvent *event, String *params,
71 Cardinal *num_params);
72 static void do_next(Widget w, XEvent *event, String *params,
73 Cardinal *num_params);
74 static void do_prev16(Widget w, XEvent *event, String *params,
75 Cardinal *num_params);
76 static void do_next16(Widget w, XEvent *event, String *params,
77 Cardinal *num_params);
78 static char *get_font_name(Display *dpy, XFontStruct *fs);
79 static void CatchFontConversionWarning(String name, String type, String class,
80 String defaultp, String *params,
83 static XtActionsRec xfd_actions[] = {
85 { "Prev16", do_prev16 },
88 { "Next16", do_next16 },
91 static Atom wm_delete_window;
93 Widget quitButton, prev16Button, prevButton, nextButton, next16Button;
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)"
102 static struct _xfd_resources {
104 char *metrics_format;
110 #define Offset(field) XtOffsetOf(struct _xfd_resources, field)
112 static 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 },
130 fprintf (stderr, "usage: %s [-options ...] -fn font\n", ProgramName);
132 fprintf (stderr, " %s [-options ...] -fa font\n", ProgramName);
134 fprintf (stderr, "where options include:\n");
136 " -display dpy X server to contact\n");
138 " -geometry geom size and location of window\n");
140 " -start num first character to show\n");
142 " -box show a box around each character\n");
144 " -center center each character inside its grid\n");
146 " -rows number number of rows in grid\n");
148 " -columns number number of columns in grid\n");
149 fprintf (stderr, "\n");
154 static Widget selectLabel, metricsLabel, rangeLabel, startLabel, fontGrid;
156 static Boolean fontConversionFailed = False;
157 static XtErrorMsgHandler oldWarningHandler;
160 main(int argc, char *argv[])
162 XtAppContext xtcontext;
163 Widget toplevel, pane, toplabel, box, form;
167 static XtCallbackRec cb[2] = { { SelectChar, NULL }, { NULL, NULL } };
175 ProgramName = argv[0];
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()"));
185 XtGetApplicationResources (toplevel, (XtPointer) &xfd_resources, Resources,
186 XtNumber (Resources), NULL, ZERO);
189 /* pane wrapping everything */
190 pane = XtCreateManagedWidget ("pane", panedWidgetClass, toplevel,
194 toplabel = XtCreateManagedWidget ("fontname", labelWidgetClass, pane,
198 box = XtCreateManagedWidget ("box", boxWidgetClass, pane, NULL, ZERO);
199 quitButton = XtCreateManagedWidget ("quit", commandWidgetClass, box,
201 prev16Button = XtCreateManagedWidget ("prev16", commandWidgetClass, box,
203 prevButton = XtCreateManagedWidget ("prev", commandWidgetClass, box,
205 nextButton = XtCreateManagedWidget ("next", commandWidgetClass, box,
207 next16Button = XtCreateManagedWidget ("next16", commandWidgetClass, box,
211 /* and labels in which to put information */
212 selectLabel = XtCreateManagedWidget ("select", labelWidgetClass,
215 metricsLabel = XtCreateManagedWidget ("metrics", labelWidgetClass,
218 rangeLabel = XtCreateManagedWidget ("range", labelWidgetClass, pane,
221 startLabel = XtCreateManagedWidget ("start", labelWidgetClass, pane,
224 /* form in which to draw */
225 form = XtCreateManagedWidget ("form", formWidgetClass, pane, NULL, ZERO);
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++;
234 oldWarningHandler = XtAppSetWarningMsgHandler(xtcontext,
235 CatchFontConversionWarning);
237 fontGrid = XtCreateManagedWidget ("grid", fontgridWidgetClass, form,
240 XtAppSetWarningMsgHandler(xtcontext, oldWarningHandler);
242 /* set the label at the top to tell us which font this is */
245 XtSetArg (av[i], XtNface, &xft); i++;
246 XtGetValues (fontGrid, av, i);
253 family = (FcChar8 *) "";
254 FcPatternGetString (xft->pattern, FC_FAMILY, 0, &family);
255 style = (FcChar8 *) "";
256 FcPatternGetString (xft->pattern, FC_STYLE, 0, &style);
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,
264 fontname = (char *) FcNameUnparse (p);
265 FcPatternDestroy (p);
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);
277 fontname = get_font_name (XtDisplay(toplevel), fs);
280 XtSetArg (av[i], XtNlabel, fontname); i++;
281 XtSetValues (toplabel, av, i);
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);
292 XtSetArg (av[i], XtNlabel, buf); i++;
293 XtSetValues (rangeLabel, av, i);
295 XtRealizeWidget (toplevel);
297 wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW",
299 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel),
300 &wm_delete_window, 1);
303 XtAppMainLoop (xtcontext);
309 SelectChar(Widget w, XtPointer closure, XtPointer data)
311 FontGridCharRec *p = (FontGridCharRec *) data;
312 XFontStruct *fs = p->thefont;
314 int direction, fontascent, fontdescent;
318 Boolean has_char = 1;
320 XtSetArg (arg, XtNlabel, buf);
326 XftFont *xft = p->theface;
327 FcChar32 c = (FcChar32) n;
328 has_char = (Boolean) FcCharSetHasChar (xft->charset, n);
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);
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))
354 char2b.byte1 = p->thechar >> 8;
355 char2b.byte2 = p->thechar & 0xff;
356 XTextExtents16 (fs, &char2b, 1, &direction, &fontascent, &fontdescent,
358 sprintf (buf, xfd_resources.metrics_format,
359 metrics.width, metrics.lbearing, metrics.rbearing,
360 metrics.ascent, metrics.descent, fontascent, fontdescent);
363 XtSetValues (metricsLabel, &arg, ONE);
367 sprintf (buf, xfd_resources.select_format,
374 sprintf (buf, xfd_resources.nochar_format,
379 XtSetValues (selectLabel, &arg, ONE);
387 do_quit (Widget w, XEvent *event, String *params, Cardinal *num_params)
393 change_page(int page)
395 long oldstart, newstart;
400 arg.name = XtNstartChar;
401 GetFontGridCellDimensions (fontGrid, &oldstart, &ncols, &nrows);
404 long start = (oldstart +
405 ((long) ncols) * ((long) nrows) * ((long) page));
407 arg.value = (XtArgVal) start;
408 XtSetValues (fontGrid, &arg, ONE);
411 /* find out what it got set to */
412 arg.value = (XtArgVal) &newstart;
413 XtGetValues (fontGrid, &arg, ONE);
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);
420 XtSetArg (arg, XtNlabel, buf);
421 sprintf (buf, xfd_resources.start_format, newstart, row, col);
422 XtSetValues (startLabel, &arg, ONE);
432 set_button_state(void)
434 Bool prevvalid, nextvalid, prev16valid, next16valid;
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);
453 do_prev16(Widget w, XEvent *event, String *params, Cardinal *num_params)
460 do_prev(Widget w, XEvent *event, String *params, Cardinal *num_params)
468 do_next(Widget w, XEvent *event, String *params, Cardinal *num_params)
475 do_next16(Widget w, XEvent *event, String *params, Cardinal *num_params)
482 get_font_name(Display *dpy, XFontStruct *fs)
484 register XFontProp *fp;
486 Atom fontatom = XInternAtom (dpy, "FONT", False);
488 for (i = 0, fp = fs->properties; i < fs->n_properties; i++, fp++) {
489 if (fp->name == fontatom) {
490 return (XGetAtomName (dpy, fp->card32));
498 CatchFontConversionWarning(String name, String type, String class,
499 String defaultp, String *params, Cardinal *np)
502 strcmp(name, "conversionError") == 0 &&
503 strcmp(type, "string") == 0 &&
504 strcmp(class, "XtToolkitError") == 0 &&
505 strcmp(params[1], "FontStruct") == 0) fontConversionFailed = True;
507 (*oldWarningHandler)(name, type, class, defaultp, params, np);