xfd.c 16 KB

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