xlsfonts.c revision 6a45684f
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 39e6232409Smrg#define N_START INT_MAX /* Maximum # of fonts to start with (should 40e6232409Smrg * always be be > 10000 as modern OSes like 41e6232409Smrg * Solaris 8 already have more than 9000 XLFD 42e6232409Smrg * 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 { 61e6232409Smrg char *name; 62e6232409Smrg 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); 71e6232409Smrgstatic 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); 76e6232409Smrgstatic void do_query_font (Display *dpy, char *name); 77e6232409Smrg 786a45684fSmrgvoid usage(const char *errmsg) 79e6232409Smrg{ 806a45684fSmrg if (errmsg != NULL) 816a45684fSmrg fprintf (stderr, "%s: %s\n\n", program_name, errmsg); 826a45684fSmrg 8394a251fdSmrg fprintf (stderr, "usage: %s [-options] [-fn pattern]\n%s", program_name, 8494a251fdSmrg "where options include:\n" 8594a251fdSmrg " -l[l[l]] give long info about each font\n" 8694a251fdSmrg " -m give character min and max bounds\n" 8794a251fdSmrg " -C force columns\n" 8894a251fdSmrg " -1 force single column\n" 8994a251fdSmrg " -u keep output unsorted\n" 9094a251fdSmrg " -o use OpenFont/QueryFont instead of ListFonts\n" 9194a251fdSmrg " -w width maximum width for multiple columns\n" 9294a251fdSmrg " -n columns number of columns if multi column\n" 9394a251fdSmrg " -display displayname X server to contact\n" 9494a251fdSmrg " -d displayname (alias for -display displayname)\n" 956a45684fSmrg " -v print program version\n" 9694a251fdSmrg "\n"); 97e6232409Smrg Close_Display(); 98e6232409Smrg exit(EXIT_FAILURE); 99e6232409Smrg} 100e6232409Smrg 101e6232409Smrgint main(int argc, char **argv) 102e6232409Smrg{ 103e6232409Smrg int argcnt = 0, i; 104e6232409Smrg 105e6232409Smrg INIT_NAME; 106e6232409Smrg 107e6232409Smrg /* Handle command line arguments, open display */ 108e6232409Smrg Setup_Display_And_Screen(&argc, argv); 109e6232409Smrg 110e6232409Smrg for (argv++, argc--; argc; argv++, argc--) { 111e6232409Smrg if (argv[0][0] == '-') { 1126a45684fSmrg if (argcnt > 0) 1136a45684fSmrg usage ("options may not be specified after font names"); 114e6232409Smrg for (i=1; argv[0][i]; i++) 115e6232409Smrg switch(argv[0][i]) { 116e6232409Smrg case 'l': 117e6232409Smrg long_list++; 118e6232409Smrg break; 119e6232409Smrg case 'm': 120e6232409Smrg min_max++; 121e6232409Smrg break; 122e6232409Smrg case 'C': 123e6232409Smrg columns = 0; 124e6232409Smrg break; 125e6232409Smrg case '1': 126e6232409Smrg columns = 1; 127e6232409Smrg break; 128e6232409Smrg case 'f': /* "-fn" */ 1296a45684fSmrg if (argv[0][i+1] != 'n') { 1306a45684fSmrg fprintf (stderr, "%s: unrecognized argument %s\n\n", 1316a45684fSmrg program_name, argv[0]); 1326a45684fSmrg usage(NULL); 1336a45684fSmrg } 1346a45684fSmrg if (--argc <= 0) usage ("-fn requires an argument"); 135e6232409Smrg argcnt++; 136e6232409Smrg argv++; 137e6232409Smrg get_list(argv[0]); 138e6232409Smrg goto next; 139e6232409Smrg case 'w': 1406a45684fSmrg if (--argc <= 0) usage ("-w requires an argument"); 141e6232409Smrg argv++; 142e6232409Smrg max_output_line_width = atoi(argv[0]); 143e6232409Smrg goto next; 144e6232409Smrg case 'n': 1456a45684fSmrg if (--argc <= 0) usage ("-n requires an argument"); 146e6232409Smrg argv++; 147e6232409Smrg columns = atoi(argv[0]); 148e6232409Smrg goto next; 149e6232409Smrg case 'o': 150e6232409Smrg open_instead_of_list = True; 151e6232409Smrg break; 152e6232409Smrg case 'u': 153e6232409Smrg sort_output = False; 154e6232409Smrg break; 1556a45684fSmrg case 'v': 1566a45684fSmrg puts(PACKAGE_STRING); 1576a45684fSmrg exit(0); 158e6232409Smrg default: 1596a45684fSmrg fprintf (stderr, "%s: unrecognized argument -%c\n\n", 1606a45684fSmrg program_name, argv[0][i]); 1616a45684fSmrg usage(NULL); 162e6232409Smrg break; 163e6232409Smrg } 1646a45684fSmrg if (i == 1) { 1656a45684fSmrg fprintf (stderr, "%s: unrecognized argument %s\n\n", 1666a45684fSmrg program_name, argv[0]); 1676a45684fSmrg usage(NULL); 1686a45684fSmrg } 169e6232409Smrg } else { 170e6232409Smrg argcnt++; 171e6232409Smrg get_list(argv[0]); 172e6232409Smrg } 173e6232409Smrg next: ; 174e6232409Smrg } 175e6232409Smrg 176e6232409Smrg if (argcnt == 0) 177e6232409Smrg get_list("*"); 178e6232409Smrg 179e6232409Smrg show_fonts(); 180e6232409Smrg 181e6232409Smrg Close_Display(); 182e6232409Smrg return EXIT_SUCCESS; 183e6232409Smrg} 184e6232409Smrg 185e6232409Smrg 186e6232409Smrgstatic 18794a251fdSmrgvoid get_list(const char *pattern) 188e6232409Smrg{ 189e6232409Smrg int available = nnames+1, 190e6232409Smrg i; 191e6232409Smrg char **fonts; 192e6232409Smrg XFontStruct *info; 193e6232409Smrg 194e6232409Smrg /* Get list of fonts matching pattern */ 195e6232409Smrg for (;;) { 196e6232409Smrg if (open_instead_of_list) { 197e6232409Smrg info = XLoadQueryFont (dpy, pattern); 198e6232409Smrg 199e6232409Smrg if (info) { 200e6232409Smrg fonts = &pattern; 201e6232409Smrg available = 1; 202e6232409Smrg XUnloadFont (dpy, info->fid); 203e6232409Smrg } else { 204e6232409Smrg fonts = NULL; 205e6232409Smrg } 206e6232409Smrg break; 207e6232409Smrg } 208e6232409Smrg 209e6232409Smrg if (long_list == L_MEDIUM) 210e6232409Smrg fonts = XListFontsWithInfo(dpy, pattern, nnames, &available, &info); 211e6232409Smrg else 212e6232409Smrg fonts = XListFonts(dpy, pattern, nnames, &available); 213e6232409Smrg if (fonts == NULL || available < nnames) 214e6232409Smrg break; 215e6232409Smrg if (long_list == L_MEDIUM) 216e6232409Smrg XFreeFontInfo(fonts, info, available); 217e6232409Smrg else 218e6232409Smrg XFreeFontNames(fonts); 219e6232409Smrg nnames = available * 2; 220e6232409Smrg } 221e6232409Smrg 222e6232409Smrg if (fonts == NULL) { 223e6232409Smrg fprintf(stderr, "%s: pattern \"%s\" unmatched\n", 224e6232409Smrg program_name, pattern); 225e6232409Smrg return; 226e6232409Smrg } 227e6232409Smrg 22894a251fdSmrg font_list = realloc(font_list, (font_cnt + available) * sizeof(FontList)); 22994a251fdSmrg if (font_list == NULL) 23094a251fdSmrg Fatal_Error("Out of memory!"); 231e6232409Smrg for (i=0; i<available; i++) { 232e6232409Smrg font_list[font_cnt].name = fonts[i]; 233e6232409Smrg if (long_list == L_MEDIUM) 234e6232409Smrg font_list[font_cnt].info = info + i; 235e6232409Smrg else 236e6232409Smrg font_list[font_cnt].info = NULL; 237e6232409Smrg 238e6232409Smrg font_cnt++; 239e6232409Smrg } 240e6232409Smrg} 241e6232409Smrg 242e6232409Smrgstatic 243e6232409Smrgint compare(const void *arg1, const void *arg2) 244e6232409Smrg{ 245e6232409Smrg const FontList *f1 = arg1; 246e6232409Smrg const FontList *f2 = arg2; 247e6232409Smrg const char *p1 = f1->name; 248e6232409Smrg const char *p2 = f2->name; 249e6232409Smrg 250e6232409Smrg while (*p1 && *p2 && *p1 == *p2) 251e6232409Smrg p1++, p2++; 252e6232409Smrg return(*p1 - *p2); 253e6232409Smrg} 254e6232409Smrg 255e6232409Smrgstatic 256e6232409Smrgvoid show_fonts(void) 257e6232409Smrg{ 258e6232409Smrg int i; 259e6232409Smrg 260e6232409Smrg if (font_cnt == 0) 261e6232409Smrg return; 262e6232409Smrg 263e6232409Smrg /* first sort the output */ 264e6232409Smrg if (sort_output) qsort(font_list, font_cnt, sizeof(FontList), compare); 265e6232409Smrg 266e6232409Smrg if (long_list > L_MEDIUM) { 267e6232409Smrg for (i = 0; i < font_cnt; i++) { 268e6232409Smrg do_query_font (dpy, font_list[i].name); 269e6232409Smrg } 270e6232409Smrg return; 271e6232409Smrg } 272e6232409Smrg 273e6232409Smrg if (long_list == L_MEDIUM) { 274e6232409Smrg XFontStruct *pfi; 27594a251fdSmrg const char *string; 276e6232409Smrg 277e6232409Smrg printf("DIR "); 278e6232409Smrg printf("MIN "); 279e6232409Smrg printf("MAX "); 280e6232409Smrg printf("EXIST "); 281e6232409Smrg printf("DFLT "); 282e6232409Smrg printf("PROP "); 283e6232409Smrg printf("ASC "); 284e6232409Smrg printf("DESC "); 285e6232409Smrg printf("NAME"); 286e6232409Smrg printf("\n"); 287e6232409Smrg for (i=0; i<font_cnt; i++) { 288e6232409Smrg pfi = font_list[i].info; 289e6232409Smrg if (!pfi) { 290e6232409Smrg fprintf(stderr, "%s: no font information for font \"%s\".\n", 291e6232409Smrg program_name, 292e6232409Smrg font_list[i].name ? 293e6232409Smrg font_list[i].name : ""); 294e6232409Smrg continue; 295e6232409Smrg } 296e6232409Smrg switch(pfi->direction) { 297e6232409Smrg case FontLeftToRight: string = "-->"; break; 298e6232409Smrg case FontRightToLeft: string = "<--"; break; 299e6232409Smrg default: string = "???"; break; 300e6232409Smrg } 301e6232409Smrg printf("%-4s", string); 302e6232409Smrg if (pfi->min_byte1 == 0 && 303e6232409Smrg pfi->max_byte1 == 0) { 304e6232409Smrg printf(" %3d ", pfi->min_char_or_byte2); 305e6232409Smrg printf(" %3d ", pfi->max_char_or_byte2); 306e6232409Smrg } else { 307e6232409Smrg printf("*%3d ", pfi->min_byte1); 308e6232409Smrg printf("*%3d ", pfi->max_byte1); 309e6232409Smrg } 310e6232409Smrg printf("%5s ", pfi->all_chars_exist ? "all" : "some"); 311e6232409Smrg printf("%4d ", pfi->default_char); 312e6232409Smrg printf("%4d ", pfi->n_properties); 313e6232409Smrg printf("%3d ", pfi->ascent); 314e6232409Smrg printf("%4d ", pfi->descent); 315e6232409Smrg printf("%s\n", font_list[i].name); 316e6232409Smrg if (min_max) { 317e6232409Smrg char min[ BUFSIZ ], 318e6232409Smrg max[ BUFSIZ ]; 319e6232409Smrg char *pmax = max, 320e6232409Smrg *pmin = min; 321e6232409Smrg 322e6232409Smrg strcpy(pmin, " min(l,r,w,a,d) = ("); 323e6232409Smrg strcpy(pmax, " max(l,r,w,a,d) = ("); 324e6232409Smrg pmin += strlen(pmin); 325e6232409Smrg pmax += strlen(pmax); 326e6232409Smrg 327e6232409Smrg copy_number(&pmin, &pmax, 328e6232409Smrg pfi->min_bounds.lbearing, 329e6232409Smrg pfi->max_bounds.lbearing); 330e6232409Smrg *pmin++ = *pmax++ = ','; 331e6232409Smrg copy_number(&pmin, &pmax, 332e6232409Smrg pfi->min_bounds.rbearing, 333e6232409Smrg pfi->max_bounds.rbearing); 334e6232409Smrg *pmin++ = *pmax++ = ','; 335e6232409Smrg copy_number(&pmin, &pmax, 336e6232409Smrg pfi->min_bounds.width, 337e6232409Smrg pfi->max_bounds.width); 338e6232409Smrg *pmin++ = *pmax++ = ','; 339e6232409Smrg copy_number(&pmin, &pmax, 340e6232409Smrg pfi->min_bounds.ascent, 341e6232409Smrg pfi->max_bounds.ascent); 342e6232409Smrg *pmin++ = *pmax++ = ','; 343e6232409Smrg copy_number(&pmin, &pmax, 344e6232409Smrg pfi->min_bounds.descent, 345e6232409Smrg pfi->max_bounds.descent); 346e6232409Smrg *pmin++ = *pmax++ = ')'; 347e6232409Smrg *pmin = *pmax = '\0'; 348e6232409Smrg printf("%s\n", min); 349e6232409Smrg printf("%s\n", max); 350e6232409Smrg } 351e6232409Smrg } 352e6232409Smrg return; 353e6232409Smrg } 354e6232409Smrg 355e6232409Smrg if ((columns == 0 && isatty(1)) || columns > 1) { 356e6232409Smrg int width, 357e6232409Smrg max_width = 0, 358e6232409Smrg lines_per_column, 359e6232409Smrg j, 360e6232409Smrg index; 361e6232409Smrg 362e6232409Smrg for (i=0; i<font_cnt; i++) { 363e6232409Smrg width = strlen(font_list[i].name); 364e6232409Smrg if (width > max_width) 365e6232409Smrg max_width = width; 366e6232409Smrg } 367e6232409Smrg if (max_width == 0) 368e6232409Smrg Fatal_Error("all %d fontnames listed are zero length", font_cnt); 369e6232409Smrg 370e6232409Smrg if (columns == 0) { 371e6232409Smrg if ((max_width * 2) + output_line_padding > 372e6232409Smrg max_output_line_width) { 373e6232409Smrg columns = 1; 374e6232409Smrg } else { 375e6232409Smrg max_width += output_line_padding; 376e6232409Smrg columns = ((max_output_line_width + 377e6232409Smrg output_line_padding) / max_width); 378e6232409Smrg } 379e6232409Smrg } else { 380e6232409Smrg max_width += output_line_padding; 381e6232409Smrg } 382e6232409Smrg if (columns <= 1) goto single_column; 383e6232409Smrg 384e6232409Smrg if (font_cnt < columns) 385e6232409Smrg columns = font_cnt; 386e6232409Smrg lines_per_column = (font_cnt + columns - 1) / columns; 387e6232409Smrg 388e6232409Smrg for (i=0; i<lines_per_column; i++) { 389e6232409Smrg for (j=0; j<columns; j++) { 390e6232409Smrg index = j * lines_per_column + i; 391e6232409Smrg if (index >= font_cnt) 392e6232409Smrg break; 393e6232409Smrg if (j+1 == columns) 394e6232409Smrg printf("%s", font_list[ index ].name); 395e6232409Smrg else 396e6232409Smrg printf("%-*s", 397e6232409Smrg max_width, 398e6232409Smrg font_list[ index ].name); 399e6232409Smrg } 400e6232409Smrg printf("\n"); 401e6232409Smrg } 402e6232409Smrg return; 403e6232409Smrg } 404e6232409Smrg 405e6232409Smrg single_column: 406e6232409Smrg for (i=0; i<font_cnt; i++) 407e6232409Smrg printf("%s\n", font_list[i].name); 408e6232409Smrg} 409e6232409Smrg 410e6232409Smrgstatic 411e6232409Smrgvoid copy_number(char **pp1, char**pp2, int n1, int n2) 412e6232409Smrg{ 413e6232409Smrg char *p1 = *pp1; 414e6232409Smrg char *p2 = *pp2; 415e6232409Smrg int w; 416e6232409Smrg 417e6232409Smrg sprintf(p1, "%d", n1); 418e6232409Smrg sprintf(p2, "%d", n2); 419e6232409Smrg w = MAX(strlen(p1), strlen(p2)); 420e6232409Smrg sprintf(p1, "%*d", w, n1); 421e6232409Smrg sprintf(p2, "%*d", w, n2); 422e6232409Smrg p1 += strlen(p1); 423e6232409Smrg p2 += strlen(p2); 424e6232409Smrg *pp1 = p1; 425e6232409Smrg *pp2 = p2; 426e6232409Smrg} 427e6232409Smrg 428e6232409Smrg 429e6232409Smrg 430e6232409Smrg/* ARGSUSED */ 431e6232409Smrgstatic 432e6232409Smrgint IgnoreError(Display *disp, XErrorEvent *event) 433e6232409Smrg{ 434e6232409Smrg return 0; 435e6232409Smrg} 436e6232409Smrg 43794a251fdSmrgstatic const char *bounds_metrics_title = 438e6232409Smrg "width left right asc desc attr keysym\n"; 439e6232409Smrg 440e6232409Smrg#define PrintBounds(_what,_ptr) \ 441e6232409Smrg{ register XCharStruct *p = (_ptr); \ 4428fff3f40Smrg printf ("\t%3s\t\t%4d %4d %4d %4d %4d 0x%04x\n", \ 4438fff3f40Smrg (_what), p->width, p->lbearing, \ 444e6232409Smrg p->rbearing, p->ascent, p->descent, p->attributes); } 445e6232409Smrg 446e6232409Smrg 44794a251fdSmrgstatic const char* stringValued [] = { /* values are atoms */ 448e6232409Smrg /* font name components (see section 3.2 of the XLFD) */ 449e6232409Smrg "FOUNDRY", 450e6232409Smrg "FAMILY_NAME", 451e6232409Smrg "WEIGHT_NAME", 452e6232409Smrg "SLANT", 453e6232409Smrg "SETWIDTH_NAME", 454e6232409Smrg "ADD_STYLE_NAME", 455e6232409Smrg "SPACING", 456e6232409Smrg "CHARSET_REGISTRY", 457e6232409Smrg "CHARSET_ENCODING", 458e6232409Smrg 459e6232409Smrg /* other standard X font properties (see section 3.2 of the XLFD) */ 460e6232409Smrg "FONT", 461e6232409Smrg "FACE_NAME", 462e6232409Smrg "FULL_NAME", /* deprecated */ 463e6232409Smrg "COPYRIGHT", 464e6232409Smrg "NOTICE", 465e6232409Smrg "FONT_TYPE", 466e6232409Smrg "FONT_VERSION", 467e6232409Smrg "RASTERIZER_NAME", 468e6232409Smrg "RASTERIZER_VERSION", 469e6232409Smrg 470e6232409Smrg /* other registered font properties (see the X.org Registry, sec. 15) */ 471e6232409Smrg "_ADOBE_POSTSCRIPT_FONTNAME", 472e6232409Smrg 473e6232409Smrg /* unregistered font properties */ 474e6232409Smrg "CHARSET_COLLECTIONS", 475e6232409Smrg "CLASSIFICATION", 476e6232409Smrg "DEVICE_FONT_NAME", 477e6232409Smrg "FONTNAME_REGISTRY", 478e6232409Smrg "MONOSPACED", 479e6232409Smrg "QUALITY", 480e6232409Smrg "RELATIVE_SET", 481e6232409Smrg "STYLE", 482e6232409Smrg NULL 483e6232409Smrg }; 484e6232409Smrg 485e6232409Smrgstatic 486e6232409Smrgvoid PrintProperty(XFontProp *prop) 487e6232409Smrg{ 488e6232409Smrg char *atom, *value; 489e6232409Smrg char nosuch[40]; 490e6232409Smrg int i; 491e6232409Smrg XErrorHandler oldhandler = XSetErrorHandler(IgnoreError); 492e6232409Smrg 493e6232409Smrg atom = XGetAtomName(dpy, prop->name); 494e6232409Smrg if (!atom) { 495e6232409Smrg atom = nosuch; 496e6232409Smrg nosuch[0] = '\0'; 497e6232409Smrg (void)sprintf (atom, "No such atom = %ld", prop->name); 498e6232409Smrg } 499e6232409Smrg printf (" %s", atom); 500e6232409Smrg 501e6232409Smrg /* Pad out to a column width of 22, but ensure there is always at 502e6232409Smrg least one space between property name & value. */ 503e6232409Smrg for (i = strlen(atom); i < 21; i++) putchar (' '); 504e6232409Smrg putchar(' '); 505e6232409Smrg 506e6232409Smrg for (i = 0; ; i++) { 507e6232409Smrg if (stringValued[i] == NULL) { 508e6232409Smrg printf ("%ld\n", prop->card32); 509e6232409Smrg break; 510e6232409Smrg } 511e6232409Smrg if (strcmp(stringValued[i], atom) == 0) { 512e6232409Smrg value = XGetAtomName(dpy, prop->card32); 513e6232409Smrg if (value == NULL) 514e6232409Smrg printf ("%ld (expected string value)\n", prop->card32); 515e6232409Smrg else { 516e6232409Smrg printf ("%s\n", value); 517e6232409Smrg XFree (value); 518e6232409Smrg } 519e6232409Smrg break; 520e6232409Smrg } 521e6232409Smrg } 522e6232409Smrg if (atom != nosuch) XFree (atom); 523e6232409Smrg XSetErrorHandler (oldhandler); 524e6232409Smrg} 525e6232409Smrg 526e6232409Smrg 527e6232409Smrgstatic void 528e6232409SmrgComputeFontType(XFontStruct *fs) 529e6232409Smrg{ 530e6232409Smrg int i; 531e6232409Smrg Bool char_cell = True; 53294a251fdSmrg const char *reason = NULL; 533e6232409Smrg XCharStruct *cs; 534e6232409Smrg Atom awatom = XInternAtom (dpy, "AVERAGE_WIDTH", False); 535e6232409Smrg 536e6232409Smrg printf (" font type:\t\t"); 537e6232409Smrg if (fs->min_bounds.width != fs->max_bounds.width) { 538e6232409Smrg printf ("Proportional (min and max widths not equal)\n"); 539e6232409Smrg return; 540e6232409Smrg } 541e6232409Smrg 542e6232409Smrg if (awatom) { 543e6232409Smrg for (i = 0; i < fs->n_properties; i++) { 544e6232409Smrg if (fs->properties[i].name == awatom && 545e6232409Smrg (fs->max_bounds.width * 10) != fs->properties[i].card32) { 546e6232409Smrg char_cell = False; 547e6232409Smrg reason = "font width not equal to AVERAGE_WIDTH"; 548e6232409Smrg break; 549e6232409Smrg } 550e6232409Smrg } 551e6232409Smrg } 552e6232409Smrg 553e6232409Smrg if (fs->per_char) { 554e6232409Smrg for (i = fs->min_char_or_byte2, cs = fs->per_char; 555e6232409Smrg i <= fs->max_char_or_byte2; i++, cs++) { 556e6232409Smrg if (cs->width == 0) continue; 557e6232409Smrg if (cs->width != fs->max_bounds.width) { 558e6232409Smrg /* this shouldn't happen since we checked above */ 559e6232409Smrg printf ("Proportional (characters not all the same width)\n"); 560e6232409Smrg return; 561e6232409Smrg } 562e6232409Smrg if (char_cell) { 563e6232409Smrg if (cs->width < 0) { 564e6232409Smrg if (!(cs->width <= cs->lbearing && 565e6232409Smrg cs->lbearing <= cs->rbearing && 566e6232409Smrg cs->rbearing <= 0)) { 567e6232409Smrg char_cell = False; 568e6232409Smrg reason = "ink outside bounding box"; 569e6232409Smrg } 570e6232409Smrg } else { 571e6232409Smrg if (!(0 <= cs->lbearing && 572e6232409Smrg cs->lbearing <= cs->rbearing && 573e6232409Smrg cs->rbearing <= cs->width)) { 574e6232409Smrg char_cell = False; 575e6232409Smrg reason = "ink outside bounding box"; 576e6232409Smrg } 577e6232409Smrg } 578e6232409Smrg if (!(cs->ascent <= fs->ascent && 579e6232409Smrg cs->descent <= fs->descent)) { 580e6232409Smrg char_cell = False; 581e6232409Smrg reason = "characters not all same ascent or descent"; 582e6232409Smrg } 583e6232409Smrg } 584e6232409Smrg } 585e6232409Smrg } 586e6232409Smrg 587e6232409Smrg printf ("%s", char_cell ? "Character Cell" : "Monospaced"); 588e6232409Smrg if (reason) printf (" (%s)", reason); 589e6232409Smrg printf ("\n"); 590e6232409Smrg 591e6232409Smrg return; 592e6232409Smrg} 593e6232409Smrg 594e6232409Smrg 595e6232409Smrgstatic void 596e6232409Smrgprint_character_metrics(register XFontStruct *info) 597e6232409Smrg{ 598e6232409Smrg register XCharStruct *pc = info->per_char; 599e6232409Smrg register int i, j; 600e6232409Smrg unsigned n, saven; 601e6232409Smrg 602e6232409Smrg printf (" character metrics:\n"); 603e6232409Smrg saven = ((info->min_byte1 << 8) | info->min_char_or_byte2); 604e6232409Smrg for (j = info->min_byte1; j <= info->max_byte1; j++) { 605e6232409Smrg n = saven; 606e6232409Smrg for (i = info->min_char_or_byte2; i <= info->max_char_or_byte2; i++) { 607e6232409Smrg char *s = XKeysymToString ((KeySym) n); 6088fff3f40Smrg printf ("\t0x%02x%02x (%u)\t%4d %4d %4d %4d %4d 0x%04x %s\n", 6098fff3f40Smrg j, i, n, pc->width, pc->lbearing, 610e6232409Smrg pc->rbearing, pc->ascent, pc->descent, pc->attributes, 611e6232409Smrg s ? s : "."); 612e6232409Smrg pc++; 613e6232409Smrg n++; 614e6232409Smrg } 615e6232409Smrg saven += 256; 616e6232409Smrg } 617e6232409Smrg} 618e6232409Smrg 619e6232409Smrgstatic 620e6232409Smrgvoid do_query_font (Display *dpy, char *name) 621e6232409Smrg{ 622e6232409Smrg register int i; 623e6232409Smrg register XFontStruct *info = XLoadQueryFont (dpy, name); 624e6232409Smrg 625e6232409Smrg if (!info) { 626e6232409Smrg fprintf (stderr, "%s: unable to get info about font \"%s\"\n", 627e6232409Smrg program_name, name); 628e6232409Smrg return; 629e6232409Smrg } 630e6232409Smrg printf ("name: %s\n", name ? name : "(nil)"); 631e6232409Smrg printf (" direction:\t\t%s\n", ((info->direction == FontLeftToRight) 632e6232409Smrg ? "left to right" : "right to left")); 633e6232409Smrg printf (" indexing:\t\t%s\n", 634e6232409Smrg ((info->min_byte1 == 0 && info->max_byte1 == 0) ? "linear" : 635e6232409Smrg "matrix")); 636e6232409Smrg printf (" rows:\t\t\t0x%02x thru 0x%02x (%d thru %d)\n", 637e6232409Smrg info->min_byte1, info->max_byte1, 638e6232409Smrg info->min_byte1, info->max_byte1); 639e6232409Smrg printf (" columns:\t\t0x%02x thru 0x%02x (%d thru %d)\n", 640e6232409Smrg info->min_char_or_byte2, info->max_char_or_byte2, 641e6232409Smrg info->min_char_or_byte2, info->max_char_or_byte2); 642e6232409Smrg printf (" all chars exist:\t%s\n", 643e6232409Smrg (info->all_chars_exist) ? "yes" : "no"); 644e6232409Smrg printf (" default char:\t\t0x%04x (%d)\n", 645e6232409Smrg info->default_char, info->default_char); 646e6232409Smrg printf (" ascent:\t\t%d\n", info->ascent); 647e6232409Smrg printf (" descent:\t\t%d\n", info->descent); 648e6232409Smrg ComputeFontType (info); 649e6232409Smrg printf (" bounds:\t\t%s", bounds_metrics_title); 650e6232409Smrg PrintBounds ("min", &info->min_bounds); 651e6232409Smrg PrintBounds ("max", &info->max_bounds); 652e6232409Smrg if (info->per_char && long_list >= L_VERYLONG) 653e6232409Smrg print_character_metrics (info); 654e6232409Smrg printf (" properties:\t\t%d\n", info->n_properties); 655e6232409Smrg for (i = 0; i < info->n_properties; i++) 656e6232409Smrg PrintProperty (&info->properties[i]); 657e6232409Smrg printf ("\n"); 658e6232409Smrg 659e6232409Smrg XFreeFontInfo (NULL, info, 1); 660e6232409Smrg} 661e6232409Smrg 662e6232409Smrg 663