xlsfonts.c revision 8ae5c7d9
1e6232409Smrg/* 26a45684fSmrg 3e6232409SmrgCopyright 1989, 1998 The Open Group 4e6232409Smrg 5e6232409SmrgPermission to use, copy, modify, distribute, and sell this software and its 6e6232409Smrgdocumentation for any purpose is hereby granted without fee, provided that 7e6232409Smrgthe above copyright notice appear in all copies and that both that 8e6232409Smrgcopyright notice and this permission notice appear in supporting 9e6232409Smrgdocumentation. 10e6232409Smrg 11e6232409SmrgThe above copyright notice and this permission notice shall be included in 12e6232409Smrgall copies or substantial portions of the Software. 13e6232409Smrg 14e6232409SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15e6232409SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16e6232409SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17e6232409SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18e6232409SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19e6232409SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20e6232409Smrg 21e6232409SmrgExcept as contained in this notice, the name of The Open Group shall not be 22e6232409Smrgused in advertising or otherwise to promote the sale, use or other dealings 23e6232409Smrgin this Software without prior written authorization from The Open Group. 246a45684fSmrg 256a45684fSmrg */ 266a45684fSmrg 276a45684fSmrg#ifdef HAVE_CONFIG_H 286a45684fSmrg# include "config.h" 296a45684fSmrg#endif 30e6232409Smrg 31e6232409Smrg#include <X11/Xlib.h> 32e6232409Smrg#include <X11/Xutil.h> 33e6232409Smrg#include <X11/Xos.h> 34e6232409Smrg#include <stdio.h> 35e6232409Smrg#include <stdlib.h> 36e6232409Smrg#include <limits.h> 37e6232409Smrg#include "dsimple.h" 38e6232409Smrg 398ae5c7d9Smrg#define N_START INT_MAX /* Maximum # of fonts to start with (should 408ae5c7d9Smrg * always be be > 10000 as modern OSes like 418ae5c7d9Smrg * Solaris 8 already have more than 9000 XLFD 428ae5c7d9Smrg * fonts available) */ 43e6232409Smrg 44e6232409Smrg#define L_SHORT 0 45e6232409Smrg#define L_MEDIUM 1 46e6232409Smrg#define L_LONG 2 47e6232409Smrg#define L_VERYLONG 3 48e6232409Smrg 49e6232409Smrgstatic int max_output_line_width = 79; 50e6232409Smrgstatic int output_line_padding = 3; 51e6232409Smrgstatic int columns = 0; 52e6232409Smrg 53e6232409Smrgstatic Bool sort_output = True; 54e6232409Smrgstatic Bool open_instead_of_list = False; 55e6232409Smrgstatic int long_list = L_SHORT; 56e6232409Smrgstatic int nnames = N_START; 57e6232409Smrgstatic int font_cnt = 0; 58e6232409Smrgstatic int min_max; 59e6232409Smrg 60e6232409Smrgtypedef struct { 618ae5c7d9Smrg char *name; 628ae5c7d9Smrg XFontStruct *info; 63e6232409Smrg} FontList; 64e6232409Smrg 65e6232409Smrgstatic FontList *font_list = NULL; 66e6232409Smrg 67e6232409Smrg/* Local prototypes */ 6894a251fdSmrgstatic void get_list(const char *pattern); 69e6232409Smrgstatic int compare(const void *arg1, const void *arg2); 70e6232409Smrgstatic void show_fonts(void); 718ae5c7d9Smrgstatic void copy_number(char **pp1, char **pp2, int n1, int n2); 72e6232409Smrgstatic int IgnoreError(Display *disp, XErrorEvent *event); 73e6232409Smrgstatic void PrintProperty(XFontProp *prop); 74e6232409Smrgstatic void ComputeFontType(XFontStruct *fs); 75e6232409Smrgstatic void print_character_metrics(register XFontStruct *info); 768ae5c7d9Smrgstatic void do_query_font(Display *dpy, char *name); 77e6232409Smrg 788ae5c7d9Smrgvoid 798ae5c7d9Smrgusage(const char *errmsg) 80e6232409Smrg{ 816a45684fSmrg if (errmsg != NULL) 828ae5c7d9Smrg fprintf(stderr, "%s: %s\n\n", program_name, errmsg); 838ae5c7d9Smrg 848ae5c7d9Smrg fprintf(stderr, "usage: %s [-options] [-fn pattern]\n%s", program_name, 858ae5c7d9Smrg "where options include:\n" 868ae5c7d9Smrg " -l[l[l]] give long info about each font\n" 878ae5c7d9Smrg " -m give character min and max bounds\n" 888ae5c7d9Smrg " -C force columns\n" 898ae5c7d9Smrg " -1 force single column\n" 908ae5c7d9Smrg " -u keep output unsorted\n" 918ae5c7d9Smrg " -o use OpenFont/QueryFont instead of ListFonts\n" 928ae5c7d9Smrg " -w width maximum width for multiple columns\n" 938ae5c7d9Smrg " -n columns number of columns if multi column\n" 948ae5c7d9Smrg " -display displayname X server to contact\n" 958ae5c7d9Smrg " -d displayname (alias for -display displayname)\n" 968ae5c7d9Smrg " -v print program version\n" 978ae5c7d9Smrg "\n"); 98e6232409Smrg Close_Display(); 99e6232409Smrg exit(EXIT_FAILURE); 100e6232409Smrg} 101e6232409Smrg 1028ae5c7d9Smrgint 1038ae5c7d9Smrgmain(int argc, char **argv) 104e6232409Smrg{ 105e6232409Smrg int argcnt = 0, i; 106e6232409Smrg 107e6232409Smrg INIT_NAME; 108e6232409Smrg 109e6232409Smrg /* Handle command line arguments, open display */ 110e6232409Smrg Setup_Display_And_Screen(&argc, argv); 111e6232409Smrg 112e6232409Smrg for (argv++, argc--; argc; argv++, argc--) { 113e6232409Smrg if (argv[0][0] == '-') { 1146a45684fSmrg if (argcnt > 0) 1158ae5c7d9Smrg usage("options may not be specified after font names"); 1168ae5c7d9Smrg for (i = 1; argv[0][i]; i++) 1178ae5c7d9Smrg switch (argv[0][i]) { 118e6232409Smrg case 'l': 119e6232409Smrg long_list++; 120e6232409Smrg break; 121e6232409Smrg case 'm': 122e6232409Smrg min_max++; 123e6232409Smrg break; 124e6232409Smrg case 'C': 125e6232409Smrg columns = 0; 126e6232409Smrg break; 127e6232409Smrg case '1': 128e6232409Smrg columns = 1; 129e6232409Smrg break; 1308ae5c7d9Smrg case 'f': /* "-fn" */ 1318ae5c7d9Smrg if (argv[0][i + 1] != 'n') { 1328ae5c7d9Smrg fprintf(stderr, "%s: unrecognized argument %s\n\n", 1338ae5c7d9Smrg program_name, argv[0]); 1346a45684fSmrg usage(NULL); 1356a45684fSmrg } 1368ae5c7d9Smrg if (--argc <= 0) 1378ae5c7d9Smrg usage("-fn requires an argument"); 138e6232409Smrg argcnt++; 139e6232409Smrg argv++; 140e6232409Smrg get_list(argv[0]); 141e6232409Smrg goto next; 142e6232409Smrg case 'w': 1438ae5c7d9Smrg if (--argc <= 0) 1448ae5c7d9Smrg usage("-w requires an argument"); 145e6232409Smrg argv++; 146e6232409Smrg max_output_line_width = atoi(argv[0]); 147e6232409Smrg goto next; 148e6232409Smrg case 'n': 1498ae5c7d9Smrg if (--argc <= 0) 1508ae5c7d9Smrg usage("-n requires an argument"); 151e6232409Smrg argv++; 152e6232409Smrg columns = atoi(argv[0]); 153e6232409Smrg goto next; 154e6232409Smrg case 'o': 155e6232409Smrg open_instead_of_list = True; 156e6232409Smrg break; 157e6232409Smrg case 'u': 158e6232409Smrg sort_output = False; 159e6232409Smrg break; 1606a45684fSmrg case 'v': 1616a45684fSmrg puts(PACKAGE_STRING); 1626a45684fSmrg exit(0); 163e6232409Smrg default: 1648ae5c7d9Smrg fprintf(stderr, "%s: unrecognized argument -%c\n\n", 1658ae5c7d9Smrg program_name, argv[0][i]); 1666a45684fSmrg usage(NULL); 167e6232409Smrg break; 168e6232409Smrg } 1696a45684fSmrg if (i == 1) { 1708ae5c7d9Smrg fprintf(stderr, "%s: unrecognized argument %s\n\n", 1718ae5c7d9Smrg program_name, argv[0]); 1726a45684fSmrg usage(NULL); 1736a45684fSmrg } 1748ae5c7d9Smrg } 1758ae5c7d9Smrg else { 176e6232409Smrg argcnt++; 177e6232409Smrg get_list(argv[0]); 178e6232409Smrg } 1798ae5c7d9Smrg next: ; 180e6232409Smrg } 181e6232409Smrg 182e6232409Smrg if (argcnt == 0) 183e6232409Smrg get_list("*"); 184e6232409Smrg 185e6232409Smrg show_fonts(); 1868ae5c7d9Smrg 187e6232409Smrg Close_Display(); 188e6232409Smrg return EXIT_SUCCESS; 189e6232409Smrg} 190e6232409Smrg 1918ae5c7d9Smrgstatic void 1928ae5c7d9Smrgget_list(const char *pattern) 193e6232409Smrg{ 1948ae5c7d9Smrg int available = nnames + 1, i; 1958ae5c7d9Smrg char **fonts; 1968ae5c7d9Smrg XFontStruct *info; 197e6232409Smrg 198e6232409Smrg /* Get list of fonts matching pattern */ 199e6232409Smrg for (;;) { 200e6232409Smrg if (open_instead_of_list) { 2018ae5c7d9Smrg info = XLoadQueryFont(dpy, pattern); 202e6232409Smrg 203e6232409Smrg if (info) { 2040790806fSchristos fonts = __UNCONST(&pattern); 205e6232409Smrg available = 1; 2068ae5c7d9Smrg XUnloadFont(dpy, info->fid); 2078ae5c7d9Smrg } 2088ae5c7d9Smrg else { 209e6232409Smrg fonts = NULL; 210e6232409Smrg } 211e6232409Smrg break; 212e6232409Smrg } 2138ae5c7d9Smrg 214e6232409Smrg if (long_list == L_MEDIUM) 215e6232409Smrg fonts = XListFontsWithInfo(dpy, pattern, nnames, &available, &info); 216e6232409Smrg else 217e6232409Smrg fonts = XListFonts(dpy, pattern, nnames, &available); 218e6232409Smrg if (fonts == NULL || available < nnames) 219e6232409Smrg break; 220e6232409Smrg if (long_list == L_MEDIUM) 221e6232409Smrg XFreeFontInfo(fonts, info, available); 222e6232409Smrg else 223e6232409Smrg XFreeFontNames(fonts); 224e6232409Smrg nnames = available * 2; 225e6232409Smrg } 226e6232409Smrg 227e6232409Smrg if (fonts == NULL) { 228e6232409Smrg fprintf(stderr, "%s: pattern \"%s\" unmatched\n", 229e6232409Smrg program_name, pattern); 230e6232409Smrg return; 231e6232409Smrg } 232e6232409Smrg 23394a251fdSmrg font_list = realloc(font_list, (font_cnt + available) * sizeof(FontList)); 23494a251fdSmrg if (font_list == NULL) 23594a251fdSmrg Fatal_Error("Out of memory!"); 2368ae5c7d9Smrg for (i = 0; i < available; i++) { 237e6232409Smrg font_list[font_cnt].name = fonts[i]; 238e6232409Smrg if (long_list == L_MEDIUM) 239e6232409Smrg font_list[font_cnt].info = info + i; 240e6232409Smrg else 241e6232409Smrg font_list[font_cnt].info = NULL; 2428ae5c7d9Smrg 243e6232409Smrg font_cnt++; 244e6232409Smrg } 245e6232409Smrg} 246e6232409Smrg 2478ae5c7d9Smrgstatic int 2488ae5c7d9Smrgcompare(const void *arg1, const void *arg2) 249e6232409Smrg{ 250e6232409Smrg const FontList *f1 = arg1; 251e6232409Smrg const FontList *f2 = arg2; 252e6232409Smrg const char *p1 = f1->name; 253e6232409Smrg const char *p2 = f2->name; 254e6232409Smrg 255e6232409Smrg while (*p1 && *p2 && *p1 == *p2) 2568ae5c7d9Smrg p1++, p2++; 2578ae5c7d9Smrg return (*p1 - *p2); 258e6232409Smrg} 259e6232409Smrg 2608ae5c7d9Smrgstatic void 2618ae5c7d9Smrgshow_fonts(void) 262e6232409Smrg{ 263e6232409Smrg int i; 264e6232409Smrg 265e6232409Smrg if (font_cnt == 0) 266e6232409Smrg return; 267e6232409Smrg 268e6232409Smrg /* first sort the output */ 2698ae5c7d9Smrg if (sort_output) 2708ae5c7d9Smrg qsort(font_list, font_cnt, sizeof(FontList), compare); 271e6232409Smrg 272e6232409Smrg if (long_list > L_MEDIUM) { 273e6232409Smrg for (i = 0; i < font_cnt; i++) { 2748ae5c7d9Smrg do_query_font(dpy, font_list[i].name); 275e6232409Smrg } 276e6232409Smrg return; 277e6232409Smrg } 278e6232409Smrg 279e6232409Smrg if (long_list == L_MEDIUM) { 280e6232409Smrg XFontStruct *pfi; 2818ae5c7d9Smrg 2828ae5c7d9Smrg const char *string; 283e6232409Smrg 284e6232409Smrg printf("DIR "); 285e6232409Smrg printf("MIN "); 286e6232409Smrg printf("MAX "); 287e6232409Smrg printf("EXIST "); 288e6232409Smrg printf("DFLT "); 289e6232409Smrg printf("PROP "); 290e6232409Smrg printf("ASC "); 291e6232409Smrg printf("DESC "); 292e6232409Smrg printf("NAME"); 293e6232409Smrg printf("\n"); 2948ae5c7d9Smrg for (i = 0; i < font_cnt; i++) { 295e6232409Smrg pfi = font_list[i].info; 296e6232409Smrg if (!pfi) { 297e6232409Smrg fprintf(stderr, "%s: no font information for font \"%s\".\n", 2988ae5c7d9Smrg program_name, 2998ae5c7d9Smrg font_list[i].name ? font_list[i].name : ""); 300e6232409Smrg continue; 301e6232409Smrg } 3028ae5c7d9Smrg switch (pfi->direction) { 3038ae5c7d9Smrg case FontLeftToRight: 3048ae5c7d9Smrg string = "-->"; 3058ae5c7d9Smrg break; 3068ae5c7d9Smrg case FontRightToLeft: 3078ae5c7d9Smrg string = "<--"; 3088ae5c7d9Smrg break; 3098ae5c7d9Smrg default: 3108ae5c7d9Smrg string = "???"; 3118ae5c7d9Smrg break; 312e6232409Smrg } 313e6232409Smrg printf("%-4s", string); 3148ae5c7d9Smrg if (pfi->min_byte1 == 0 && pfi->max_byte1 == 0) { 315e6232409Smrg printf(" %3d ", pfi->min_char_or_byte2); 316e6232409Smrg printf(" %3d ", pfi->max_char_or_byte2); 3178ae5c7d9Smrg } 3188ae5c7d9Smrg else { 319e6232409Smrg printf("*%3d ", pfi->min_byte1); 320e6232409Smrg printf("*%3d ", pfi->max_byte1); 321e6232409Smrg } 322e6232409Smrg printf("%5s ", pfi->all_chars_exist ? "all" : "some"); 323e6232409Smrg printf("%4d ", pfi->default_char); 324e6232409Smrg printf("%4d ", pfi->n_properties); 325e6232409Smrg printf("%3d ", pfi->ascent); 326e6232409Smrg printf("%4d ", pfi->descent); 327e6232409Smrg printf("%s\n", font_list[i].name); 328e6232409Smrg if (min_max) { 3298ae5c7d9Smrg char min[BUFSIZ], max[BUFSIZ]; 3308ae5c7d9Smrg 3318ae5c7d9Smrg char *pmax = max, *pmin = min; 332e6232409Smrg 333e6232409Smrg strcpy(pmin, " min(l,r,w,a,d) = ("); 334e6232409Smrg strcpy(pmax, " max(l,r,w,a,d) = ("); 335e6232409Smrg pmin += strlen(pmin); 336e6232409Smrg pmax += strlen(pmax); 337e6232409Smrg 338e6232409Smrg copy_number(&pmin, &pmax, 339e6232409Smrg pfi->min_bounds.lbearing, 340e6232409Smrg pfi->max_bounds.lbearing); 341e6232409Smrg *pmin++ = *pmax++ = ','; 342e6232409Smrg copy_number(&pmin, &pmax, 343e6232409Smrg pfi->min_bounds.rbearing, 344e6232409Smrg pfi->max_bounds.rbearing); 345e6232409Smrg *pmin++ = *pmax++ = ','; 346e6232409Smrg copy_number(&pmin, &pmax, 347e6232409Smrg pfi->min_bounds.width, 348e6232409Smrg pfi->max_bounds.width); 349e6232409Smrg *pmin++ = *pmax++ = ','; 350e6232409Smrg copy_number(&pmin, &pmax, 351e6232409Smrg pfi->min_bounds.ascent, 352e6232409Smrg pfi->max_bounds.ascent); 353e6232409Smrg *pmin++ = *pmax++ = ','; 354e6232409Smrg copy_number(&pmin, &pmax, 355e6232409Smrg pfi->min_bounds.descent, 356e6232409Smrg pfi->max_bounds.descent); 357e6232409Smrg *pmin++ = *pmax++ = ')'; 358e6232409Smrg *pmin = *pmax = '\0'; 359e6232409Smrg printf("%s\n", min); 360e6232409Smrg printf("%s\n", max); 361e6232409Smrg } 362e6232409Smrg } 363e6232409Smrg return; 364e6232409Smrg } 365e6232409Smrg 366e6232409Smrg if ((columns == 0 && isatty(1)) || columns > 1) { 3678ae5c7d9Smrg int width, max_width = 0, lines_per_column, j, index; 368e6232409Smrg 3698ae5c7d9Smrg for (i = 0; i < font_cnt; i++) { 370e6232409Smrg width = strlen(font_list[i].name); 371e6232409Smrg if (width > max_width) 372e6232409Smrg max_width = width; 373e6232409Smrg } 374e6232409Smrg if (max_width == 0) 375e6232409Smrg Fatal_Error("all %d fontnames listed are zero length", font_cnt); 376e6232409Smrg 377e6232409Smrg if (columns == 0) { 378e6232409Smrg if ((max_width * 2) + output_line_padding > 379e6232409Smrg max_output_line_width) { 380e6232409Smrg columns = 1; 3818ae5c7d9Smrg } 3828ae5c7d9Smrg else { 383e6232409Smrg max_width += output_line_padding; 384e6232409Smrg columns = ((max_output_line_width + 385e6232409Smrg output_line_padding) / max_width); 386e6232409Smrg } 3878ae5c7d9Smrg } 3888ae5c7d9Smrg else { 389e6232409Smrg max_width += output_line_padding; 390e6232409Smrg } 3918ae5c7d9Smrg if (columns <= 1) 3928ae5c7d9Smrg goto single_column; 393e6232409Smrg 394e6232409Smrg if (font_cnt < columns) 395e6232409Smrg columns = font_cnt; 396e6232409Smrg lines_per_column = (font_cnt + columns - 1) / columns; 397e6232409Smrg 3988ae5c7d9Smrg for (i = 0; i < lines_per_column; i++) { 3998ae5c7d9Smrg for (j = 0; j < columns; j++) { 400e6232409Smrg index = j * lines_per_column + i; 401e6232409Smrg if (index >= font_cnt) 402e6232409Smrg break; 4038ae5c7d9Smrg if (j + 1 == columns) 4048ae5c7d9Smrg printf("%s", font_list[index].name); 405e6232409Smrg else 4068ae5c7d9Smrg printf("%-*s", max_width, font_list[index].name); 407e6232409Smrg } 408e6232409Smrg printf("\n"); 409e6232409Smrg } 410e6232409Smrg return; 411e6232409Smrg } 412e6232409Smrg 4138ae5c7d9Smrg single_column: 4148ae5c7d9Smrg for (i = 0; i < font_cnt; i++) 415e6232409Smrg printf("%s\n", font_list[i].name); 416e6232409Smrg} 417e6232409Smrg 4188ae5c7d9Smrgstatic void 4198ae5c7d9Smrgcopy_number(char **pp1, char **pp2, int n1, int n2) 420e6232409Smrg{ 421e6232409Smrg char *p1 = *pp1; 422e6232409Smrg char *p2 = *pp2; 4238ae5c7d9Smrg int w; 424e6232409Smrg 425e6232409Smrg sprintf(p1, "%d", n1); 426e6232409Smrg sprintf(p2, "%d", n2); 427e6232409Smrg w = MAX(strlen(p1), strlen(p2)); 428e6232409Smrg sprintf(p1, "%*d", w, n1); 429e6232409Smrg sprintf(p2, "%*d", w, n2); 430e6232409Smrg p1 += strlen(p1); 431e6232409Smrg p2 += strlen(p2); 432e6232409Smrg *pp1 = p1; 433e6232409Smrg *pp2 = p2; 434e6232409Smrg} 435e6232409Smrg 436e6232409Smrg/* ARGSUSED */ 4378ae5c7d9Smrgstatic int 4388ae5c7d9SmrgIgnoreError(Display * disp, XErrorEvent *event) 439e6232409Smrg{ 440e6232409Smrg return 0; 441e6232409Smrg} 442e6232409Smrg 44394a251fdSmrgstatic const char *bounds_metrics_title = 4448ae5c7d9Smrg "width left right asc desc attr keysym\n"; 445e6232409Smrg 446e6232409Smrg#define PrintBounds(_what,_ptr) \ 447e6232409Smrg{ register XCharStruct *p = (_ptr); \ 4488fff3f40Smrg printf ("\t%3s\t\t%4d %4d %4d %4d %4d 0x%04x\n", \ 4498fff3f40Smrg (_what), p->width, p->lbearing, \ 450e6232409Smrg p->rbearing, p->ascent, p->descent, p->attributes); } 451e6232409Smrg 4528ae5c7d9Smrgstatic const char *stringValued[] = { /* values are atoms */ 453e6232409Smrg /* font name components (see section 3.2 of the XLFD) */ 454e6232409Smrg "FOUNDRY", 455e6232409Smrg "FAMILY_NAME", 456e6232409Smrg "WEIGHT_NAME", 457e6232409Smrg "SLANT", 458e6232409Smrg "SETWIDTH_NAME", 459e6232409Smrg "ADD_STYLE_NAME", 460e6232409Smrg "SPACING", 461e6232409Smrg "CHARSET_REGISTRY", 462e6232409Smrg "CHARSET_ENCODING", 463e6232409Smrg 464e6232409Smrg /* other standard X font properties (see section 3.2 of the XLFD) */ 465e6232409Smrg "FONT", 466e6232409Smrg "FACE_NAME", 4678ae5c7d9Smrg "FULL_NAME", /* deprecated */ 468e6232409Smrg "COPYRIGHT", 469e6232409Smrg "NOTICE", 470e6232409Smrg "FONT_TYPE", 471e6232409Smrg "FONT_VERSION", 472e6232409Smrg "RASTERIZER_NAME", 473e6232409Smrg "RASTERIZER_VERSION", 474e6232409Smrg 475e6232409Smrg /* other registered font properties (see the X.org Registry, sec. 15) */ 476e6232409Smrg "_ADOBE_POSTSCRIPT_FONTNAME", 4778ae5c7d9Smrg 478e6232409Smrg /* unregistered font properties */ 479e6232409Smrg "CHARSET_COLLECTIONS", 480e6232409Smrg "CLASSIFICATION", 481e6232409Smrg "DEVICE_FONT_NAME", 482e6232409Smrg "FONTNAME_REGISTRY", 483e6232409Smrg "MONOSPACED", 484e6232409Smrg "QUALITY", 485e6232409Smrg "RELATIVE_SET", 486e6232409Smrg "STYLE", 4878ae5c7d9Smrg NULL 4888ae5c7d9Smrg}; 489e6232409Smrg 4908ae5c7d9Smrgstatic void 4918ae5c7d9SmrgPrintProperty(XFontProp * prop) 492e6232409Smrg{ 493e6232409Smrg char *atom, *value; 494e6232409Smrg char nosuch[40]; 495e6232409Smrg int i; 496e6232409Smrg XErrorHandler oldhandler = XSetErrorHandler(IgnoreError); 497e6232409Smrg 498e6232409Smrg atom = XGetAtomName(dpy, prop->name); 499e6232409Smrg if (!atom) { 5008ae5c7d9Smrg snprintf(nosuch, sizeof(nosuch), "No such atom = %ld", prop->name); 501e6232409Smrg atom = nosuch; 502e6232409Smrg } 5038ae5c7d9Smrg printf(" %s", atom); 504e6232409Smrg 505e6232409Smrg /* Pad out to a column width of 22, but ensure there is always at 506e6232409Smrg least one space between property name & value. */ 5078ae5c7d9Smrg for (i = strlen(atom); i < 21; i++) 5088ae5c7d9Smrg putchar(' '); 509e6232409Smrg putchar(' '); 510e6232409Smrg 5118ae5c7d9Smrg for (i = 0;; i++) { 512e6232409Smrg if (stringValued[i] == NULL) { 5138ae5c7d9Smrg printf("%ld\n", prop->card32); 514e6232409Smrg break; 515e6232409Smrg } 516e6232409Smrg if (strcmp(stringValued[i], atom) == 0) { 517e6232409Smrg value = XGetAtomName(dpy, prop->card32); 518e6232409Smrg if (value == NULL) 5198ae5c7d9Smrg printf("%ld (expected string value)\n", prop->card32); 520e6232409Smrg else { 5218ae5c7d9Smrg printf("%s\n", value); 5228ae5c7d9Smrg XFree(value); 523e6232409Smrg } 524e6232409Smrg break; 525e6232409Smrg } 5268ae5c7d9Smrg } 5278ae5c7d9Smrg if (atom != nosuch) 5288ae5c7d9Smrg XFree(atom); 5298ae5c7d9Smrg XSetErrorHandler(oldhandler); 530e6232409Smrg} 531e6232409Smrg 532e6232409Smrgstatic void 533e6232409SmrgComputeFontType(XFontStruct *fs) 534e6232409Smrg{ 535e6232409Smrg Bool char_cell = True; 53694a251fdSmrg const char *reason = NULL; 537e6232409Smrg XCharStruct *cs; 5388ae5c7d9Smrg Atom awatom = XInternAtom(dpy, "AVERAGE_WIDTH", False); 539e6232409Smrg 5408ae5c7d9Smrg printf(" font type:\t\t"); 541e6232409Smrg if (fs->min_bounds.width != fs->max_bounds.width) { 5428ae5c7d9Smrg printf("Proportional (min and max widths not equal)\n"); 543e6232409Smrg return; 544e6232409Smrg } 545e6232409Smrg 546e6232409Smrg if (awatom) { 5478ae5c7d9Smrg for (int i = 0; i < fs->n_properties; i++) { 548e6232409Smrg if (fs->properties[i].name == awatom && 549e6232409Smrg (fs->max_bounds.width * 10) != fs->properties[i].card32) { 550e6232409Smrg char_cell = False; 551e6232409Smrg reason = "font width not equal to AVERAGE_WIDTH"; 552e6232409Smrg break; 553e6232409Smrg } 554e6232409Smrg } 555e6232409Smrg } 556e6232409Smrg 557e6232409Smrg if (fs->per_char) { 5588ae5c7d9Smrg unsigned int i; 559e6232409Smrg for (i = fs->min_char_or_byte2, cs = fs->per_char; 560e6232409Smrg i <= fs->max_char_or_byte2; i++, cs++) { 5618ae5c7d9Smrg if (cs->width == 0) 5628ae5c7d9Smrg continue; 563e6232409Smrg if (cs->width != fs->max_bounds.width) { 564e6232409Smrg /* this shouldn't happen since we checked above */ 5658ae5c7d9Smrg printf("Proportional (characters not all the same width)\n"); 566e6232409Smrg return; 567e6232409Smrg } 568e6232409Smrg if (char_cell) { 569e6232409Smrg if (cs->width < 0) { 570e6232409Smrg if (!(cs->width <= cs->lbearing && 571e6232409Smrg cs->lbearing <= cs->rbearing && 572e6232409Smrg cs->rbearing <= 0)) { 573e6232409Smrg char_cell = False; 574e6232409Smrg reason = "ink outside bounding box"; 575e6232409Smrg } 5768ae5c7d9Smrg } 5778ae5c7d9Smrg else { 578e6232409Smrg if (!(0 <= cs->lbearing && 579e6232409Smrg cs->lbearing <= cs->rbearing && 580e6232409Smrg cs->rbearing <= cs->width)) { 581e6232409Smrg char_cell = False; 582e6232409Smrg reason = "ink outside bounding box"; 583e6232409Smrg } 584e6232409Smrg } 585e6232409Smrg if (!(cs->ascent <= fs->ascent && 586e6232409Smrg cs->descent <= fs->descent)) { 5878ae5c7d9Smrg char_cell = False; 588e6232409Smrg reason = "characters not all same ascent or descent"; 589e6232409Smrg } 590e6232409Smrg } 591e6232409Smrg } 592e6232409Smrg } 593e6232409Smrg 5948ae5c7d9Smrg printf("%s", char_cell ? "Character Cell" : "Monospaced"); 5958ae5c7d9Smrg if (reason) 5968ae5c7d9Smrg printf(" (%s)", reason); 5978ae5c7d9Smrg printf("\n"); 5988ae5c7d9Smrg 599e6232409Smrg return; 600e6232409Smrg} 601e6232409Smrg 602e6232409Smrgstatic void 603e6232409Smrgprint_character_metrics(register XFontStruct *info) 604e6232409Smrg{ 605e6232409Smrg register XCharStruct *pc = info->per_char; 6068ae5c7d9Smrg unsigned int i, j; 607e6232409Smrg unsigned n, saven; 608e6232409Smrg 6098ae5c7d9Smrg printf(" character metrics:\n"); 610e6232409Smrg saven = ((info->min_byte1 << 8) | info->min_char_or_byte2); 611e6232409Smrg for (j = info->min_byte1; j <= info->max_byte1; j++) { 612e6232409Smrg n = saven; 613e6232409Smrg for (i = info->min_char_or_byte2; i <= info->max_char_or_byte2; i++) { 6148ae5c7d9Smrg char *s = XKeysymToString((KeySym) n); 6158ae5c7d9Smrg 6168ae5c7d9Smrg printf("\t0x%02x%02x (%u)\t%4d %4d %4d %4d %4d 0x%04x %s\n", 6178ae5c7d9Smrg j, i, n, pc->width, pc->lbearing, 6188ae5c7d9Smrg pc->rbearing, pc->ascent, pc->descent, pc->attributes, 6198ae5c7d9Smrg s ? s : "."); 620e6232409Smrg pc++; 621e6232409Smrg n++; 622e6232409Smrg } 623e6232409Smrg saven += 256; 624e6232409Smrg } 625e6232409Smrg} 626e6232409Smrg 6278ae5c7d9Smrgstatic void 6288ae5c7d9Smrgdo_query_font(Display *display, char *name) 629e6232409Smrg{ 630e6232409Smrg register int i; 6318ae5c7d9Smrg register XFontStruct *info = XLoadQueryFont(display, name); 632e6232409Smrg 633e6232409Smrg if (!info) { 6348ae5c7d9Smrg fprintf(stderr, "%s: unable to get info about font \"%s\"\n", 6358ae5c7d9Smrg program_name, name); 636e6232409Smrg return; 637e6232409Smrg } 6388ae5c7d9Smrg printf("name: %s\n", name ? name : "(nil)"); 6398ae5c7d9Smrg printf(" direction:\t\t%s\n", ((info->direction == FontLeftToRight) 6408ae5c7d9Smrg ? "left to right" : "right to left")); 6418ae5c7d9Smrg printf(" indexing:\t\t%s\n", 6428ae5c7d9Smrg ((info->min_byte1 == 0 && info->max_byte1 == 0) 6438ae5c7d9Smrg ? "linear" : "matrix")); 6448ae5c7d9Smrg printf(" rows:\t\t\t0x%02x thru 0x%02x (%d thru %d)\n", 6458ae5c7d9Smrg info->min_byte1, info->max_byte1, 6468ae5c7d9Smrg info->min_byte1, info->max_byte1); 6478ae5c7d9Smrg printf(" columns:\t\t0x%02x thru 0x%02x (%d thru %d)\n", 6488ae5c7d9Smrg info->min_char_or_byte2, info->max_char_or_byte2, 6498ae5c7d9Smrg info->min_char_or_byte2, info->max_char_or_byte2); 6508ae5c7d9Smrg printf(" all chars exist:\t%s\n", 6518ae5c7d9Smrg (info->all_chars_exist) ? "yes" : "no"); 6528ae5c7d9Smrg printf(" default char:\t\t0x%04x (%d)\n", 6538ae5c7d9Smrg info->default_char, info->default_char); 6548ae5c7d9Smrg printf(" ascent:\t\t%d\n", info->ascent); 6558ae5c7d9Smrg printf(" descent:\t\t%d\n", info->descent); 6568ae5c7d9Smrg ComputeFontType(info); 6578ae5c7d9Smrg printf(" bounds:\t\t%s", bounds_metrics_title); 6588ae5c7d9Smrg PrintBounds("min", &info->min_bounds); 6598ae5c7d9Smrg PrintBounds("max", &info->max_bounds); 6608ae5c7d9Smrg if (info->per_char && long_list >= L_VERYLONG) 6618ae5c7d9Smrg print_character_metrics(info); 6628ae5c7d9Smrg printf(" properties:\t\t%d\n", info->n_properties); 663e6232409Smrg for (i = 0; i < info->n_properties; i++) 6648ae5c7d9Smrg PrintProperty(&info->properties[i]); 6658ae5c7d9Smrg printf("\n"); 666e6232409Smrg 6678ae5c7d9Smrg XFreeFontInfo(NULL, info, 1); 668e6232409Smrg} 669