"Initial commit to Gerrit"
[profile/ivi/xorg-utils.git] / xfd / xfd.c
1 /*
2  * $Xorg: xfd.c,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $
3  *
4  * 
5 Copyright 1989, 1998  The Open Group
6
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
11 documentation.
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
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.
22
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.
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
49 char *ProgramName;
50
51 static 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
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, 
81                                        Cardinal *np);
82
83 static 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
91 static Atom wm_delete_window;
92
93 Widget 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
102 static 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
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 },
123 };
124
125 #undef Offset
126
127 static void
128 usage(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
154 static Widget selectLabel, metricsLabel, rangeLabel, startLabel, fontGrid;
155
156 static Boolean fontConversionFailed = False;
157 static XtErrorMsgHandler oldWarningHandler;
158
159 int
160 main(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*/
308 static void 
309 SelectChar(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*/
386 static void 
387 do_quit (Widget w, XEvent *event, String *params, Cardinal *num_params)
388 {
389     exit (0);
390 }
391
392 static void 
393 change_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
431 static void 
432 set_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 */
452 static void 
453 do_prev16(Widget w, XEvent *event, String *params, Cardinal *num_params)
454 {
455     change_page (-16);
456 }
457
458
459 static void 
460 do_prev(Widget w, XEvent *event, String *params, Cardinal *num_params)
461 {
462     change_page (-1);
463 }
464
465
466 /* ARGSUSED */
467 static void 
468 do_next(Widget w, XEvent *event, String *params, Cardinal *num_params)
469 {
470     change_page (1);
471 }
472
473 /* ARGSUSED */
474 static void 
475 do_next16(Widget w, XEvent *event, String *params, Cardinal *num_params)
476 {
477     change_page (16);
478 }
479
480
481 static char *
482 get_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
497 static void 
498 CatchFontConversionWarning(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 }