xlsfonts.c revision 8fff3f40
1e6232409Smrg/* 2e6232409Smrg * $Xorg: xlsfonts.c,v 1.4 2001/02/09 02:05:54 xorgcvs Exp $ 3e6232409Smrg * 4e6232409Smrg * 5e6232409SmrgCopyright 1989, 1998 The Open Group 6e6232409Smrg 7e6232409SmrgPermission to use, copy, modify, distribute, and sell this software and its 8e6232409Smrgdocumentation for any purpose is hereby granted without fee, provided that 9e6232409Smrgthe above copyright notice appear in all copies and that both that 10e6232409Smrgcopyright notice and this permission notice appear in supporting 11e6232409Smrgdocumentation. 12e6232409Smrg 13e6232409SmrgThe above copyright notice and this permission notice shall be included in 14e6232409Smrgall copies or substantial portions of the Software. 15e6232409Smrg 16e6232409SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17e6232409SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18e6232409SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19e6232409SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20e6232409SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21e6232409SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22e6232409Smrg 23e6232409SmrgExcept as contained in this notice, the name of The Open Group shall not be 24e6232409Smrgused in advertising or otherwise to promote the sale, use or other dealings 25e6232409Smrgin this Software without prior written authorization from The Open Group. 26e6232409Smrg * */ 27e6232409Smrg/* $XFree86: xc/programs/xlsfonts/xlsfonts.c,v 1.9 2003/09/08 14:25:33 eich Exp $ */ 28e6232409Smrg 29e6232409Smrg#include <X11/Xlib.h> 30e6232409Smrg#include <X11/Xutil.h> 31e6232409Smrg#include <X11/Xos.h> 32e6232409Smrg#include <stdio.h> 33e6232409Smrg#include <stdlib.h> 34e6232409Smrg#include <limits.h> 35e6232409Smrg#include "dsimple.h" 36e6232409Smrg 37e6232409Smrg#define N_START INT_MAX /* Maximum # of fonts to start with (should 38e6232409Smrg * always be be > 10000 as modern OSes like 39e6232409Smrg * Solaris 8 already have more than 9000 XLFD 40e6232409Smrg * fonts available) */ 41e6232409Smrg 42e6232409Smrg#define L_SHORT 0 43e6232409Smrg#define L_MEDIUM 1 44e6232409Smrg#define L_LONG 2 45e6232409Smrg#define L_VERYLONG 3 46e6232409Smrg 47e6232409Smrgstatic int max_output_line_width = 79; 48e6232409Smrgstatic int output_line_padding = 3; 49e6232409Smrgstatic int columns = 0; 50e6232409Smrg 51e6232409Smrgstatic Bool sort_output = True; 52e6232409Smrgstatic Bool open_instead_of_list = False; 53e6232409Smrgstatic int long_list = L_SHORT; 54e6232409Smrgstatic int nnames = N_START; 55e6232409Smrgstatic int font_cnt = 0; 56e6232409Smrgstatic int min_max; 57e6232409Smrg 58e6232409Smrgtypedef struct { 59e6232409Smrg char *name; 60e6232409Smrg XFontStruct *info; 61e6232409Smrg} FontList; 62e6232409Smrg 63e6232409Smrgstatic FontList *font_list = NULL; 64e6232409Smrg 65e6232409Smrg/* Local prototypes */ 66e6232409Smrgstatic void get_list(char *pattern); 67e6232409Smrgstatic int compare(const void *arg1, const void *arg2); 68e6232409Smrgstatic void show_fonts(void); 69e6232409Smrgstatic void copy_number(char **pp1, char**pp2, int n1, int n2); 70e6232409Smrgstatic int IgnoreError(Display *disp, XErrorEvent *event); 71e6232409Smrgstatic void PrintProperty(XFontProp *prop); 72e6232409Smrgstatic void ComputeFontType(XFontStruct *fs); 73e6232409Smrgstatic void print_character_metrics(register XFontStruct *info); 74e6232409Smrgstatic void do_query_font (Display *dpy, char *name); 75e6232409Smrg 76e6232409Smrgvoid usage(void) 77e6232409Smrg{ 78e6232409Smrg fprintf (stderr, "usage: %s [-options] [-fn pattern]\n", program_name); 79e6232409Smrg fprintf (stderr, "where options include:\n"); 80e6232409Smrg fprintf (stderr, " -l[l[l]] give long info about each font\n"); 81e6232409Smrg fprintf (stderr, " -m give character min and max bounds\n"); 82e6232409Smrg fprintf (stderr, " -C force columns\n"); 83e6232409Smrg fprintf (stderr, " -1 force single column\n"); 84e6232409Smrg fprintf (stderr, " -u keep output unsorted\n"); 85e6232409Smrg fprintf (stderr, " -o use OpenFont/QueryFont instead of ListFonts\n"); 86e6232409Smrg fprintf (stderr, " -w width maximum width for multiple columns\n"); 87e6232409Smrg fprintf (stderr, " -n columns number of columns if multi column\n"); 88e6232409Smrg fprintf (stderr, " -display displayname X server to contact\n"); 89e6232409Smrg fprintf (stderr, " -d displayname (alias for -display displayname)\n"); 90e6232409Smrg fprintf (stderr, "\n"); 91e6232409Smrg Close_Display(); 92e6232409Smrg exit(EXIT_FAILURE); 93e6232409Smrg} 94e6232409Smrg 95e6232409Smrgint main(int argc, char **argv) 96e6232409Smrg{ 97e6232409Smrg int argcnt = 0, i; 98e6232409Smrg 99e6232409Smrg INIT_NAME; 100e6232409Smrg 101e6232409Smrg /* Handle command line arguments, open display */ 102e6232409Smrg Setup_Display_And_Screen(&argc, argv); 103e6232409Smrg 104e6232409Smrg for (argv++, argc--; argc; argv++, argc--) { 105e6232409Smrg if (argv[0][0] == '-') { 106e6232409Smrg if (argcnt > 0) usage (); 107e6232409Smrg for (i=1; argv[0][i]; i++) 108e6232409Smrg switch(argv[0][i]) { 109e6232409Smrg case 'l': 110e6232409Smrg long_list++; 111e6232409Smrg break; 112e6232409Smrg case 'm': 113e6232409Smrg min_max++; 114e6232409Smrg break; 115e6232409Smrg case 'C': 116e6232409Smrg columns = 0; 117e6232409Smrg break; 118e6232409Smrg case '1': 119e6232409Smrg columns = 1; 120e6232409Smrg break; 121e6232409Smrg case 'f': /* "-fn" */ 122e6232409Smrg if (--argc <= 0) usage (); 123e6232409Smrg if (argv[0][i+1] != 'n') usage (); 124e6232409Smrg argcnt++; 125e6232409Smrg argv++; 126e6232409Smrg get_list(argv[0]); 127e6232409Smrg goto next; 128e6232409Smrg case 'w': 129e6232409Smrg if (--argc <= 0) usage (); 130e6232409Smrg argv++; 131e6232409Smrg max_output_line_width = atoi(argv[0]); 132e6232409Smrg goto next; 133e6232409Smrg case 'n': 134e6232409Smrg if (--argc <= 0) usage (); 135e6232409Smrg argv++; 136e6232409Smrg columns = atoi(argv[0]); 137e6232409Smrg goto next; 138e6232409Smrg case 'o': 139e6232409Smrg open_instead_of_list = True; 140e6232409Smrg break; 141e6232409Smrg case 'u': 142e6232409Smrg sort_output = False; 143e6232409Smrg break; 144e6232409Smrg default: 145e6232409Smrg usage(); 146e6232409Smrg break; 147e6232409Smrg } 148e6232409Smrg if (i == 1) 149e6232409Smrg usage(); 150e6232409Smrg } else { 151e6232409Smrg argcnt++; 152e6232409Smrg get_list(argv[0]); 153e6232409Smrg } 154e6232409Smrg next: ; 155e6232409Smrg } 156e6232409Smrg 157e6232409Smrg if (argcnt == 0) 158e6232409Smrg get_list("*"); 159e6232409Smrg 160e6232409Smrg show_fonts(); 161e6232409Smrg 162e6232409Smrg Close_Display(); 163e6232409Smrg return EXIT_SUCCESS; 164e6232409Smrg} 165e6232409Smrg 166e6232409Smrg 167e6232409Smrgstatic 168e6232409Smrgvoid get_list(char *pattern) 169e6232409Smrg{ 170e6232409Smrg int available = nnames+1, 171e6232409Smrg i; 172e6232409Smrg char **fonts; 173e6232409Smrg XFontStruct *info; 174e6232409Smrg 175e6232409Smrg /* Get list of fonts matching pattern */ 176e6232409Smrg for (;;) { 177e6232409Smrg if (open_instead_of_list) { 178e6232409Smrg info = XLoadQueryFont (dpy, pattern); 179e6232409Smrg 180e6232409Smrg if (info) { 181e6232409Smrg fonts = &pattern; 182e6232409Smrg available = 1; 183e6232409Smrg XUnloadFont (dpy, info->fid); 184e6232409Smrg } else { 185e6232409Smrg fonts = NULL; 186e6232409Smrg } 187e6232409Smrg break; 188e6232409Smrg } 189e6232409Smrg 190e6232409Smrg if (long_list == L_MEDIUM) 191e6232409Smrg fonts = XListFontsWithInfo(dpy, pattern, nnames, &available, &info); 192e6232409Smrg else 193e6232409Smrg fonts = XListFonts(dpy, pattern, nnames, &available); 194e6232409Smrg if (fonts == NULL || available < nnames) 195e6232409Smrg break; 196e6232409Smrg if (long_list == L_MEDIUM) 197e6232409Smrg XFreeFontInfo(fonts, info, available); 198e6232409Smrg else 199e6232409Smrg XFreeFontNames(fonts); 200e6232409Smrg nnames = available * 2; 201e6232409Smrg } 202e6232409Smrg 203e6232409Smrg if (fonts == NULL) { 204e6232409Smrg fprintf(stderr, "%s: pattern \"%s\" unmatched\n", 205e6232409Smrg program_name, pattern); 206e6232409Smrg return; 207e6232409Smrg } 208e6232409Smrg 209e6232409Smrg font_list = (FontList *)Realloc((char *)font_list, 210e6232409Smrg (font_cnt + available) * sizeof(FontList)); 211e6232409Smrg for (i=0; i<available; i++) { 212e6232409Smrg font_list[font_cnt].name = fonts[i]; 213e6232409Smrg if (long_list == L_MEDIUM) 214e6232409Smrg font_list[font_cnt].info = info + i; 215e6232409Smrg else 216e6232409Smrg font_list[font_cnt].info = NULL; 217e6232409Smrg 218e6232409Smrg font_cnt++; 219e6232409Smrg } 220e6232409Smrg} 221e6232409Smrg 222e6232409Smrgstatic 223e6232409Smrgint compare(const void *arg1, const void *arg2) 224e6232409Smrg{ 225e6232409Smrg const FontList *f1 = arg1; 226e6232409Smrg const FontList *f2 = arg2; 227e6232409Smrg const char *p1 = f1->name; 228e6232409Smrg const char *p2 = f2->name; 229e6232409Smrg 230e6232409Smrg while (*p1 && *p2 && *p1 == *p2) 231e6232409Smrg p1++, p2++; 232e6232409Smrg return(*p1 - *p2); 233e6232409Smrg} 234e6232409Smrg 235e6232409Smrgstatic 236e6232409Smrgvoid show_fonts(void) 237e6232409Smrg{ 238e6232409Smrg int i; 239e6232409Smrg 240e6232409Smrg if (font_cnt == 0) 241e6232409Smrg return; 242e6232409Smrg 243e6232409Smrg /* first sort the output */ 244e6232409Smrg if (sort_output) qsort(font_list, font_cnt, sizeof(FontList), compare); 245e6232409Smrg 246e6232409Smrg if (long_list > L_MEDIUM) { 247e6232409Smrg for (i = 0; i < font_cnt; i++) { 248e6232409Smrg do_query_font (dpy, font_list[i].name); 249e6232409Smrg } 250e6232409Smrg return; 251e6232409Smrg } 252e6232409Smrg 253e6232409Smrg if (long_list == L_MEDIUM) { 254e6232409Smrg XFontStruct *pfi; 255e6232409Smrg char *string; 256e6232409Smrg 257e6232409Smrg printf("DIR "); 258e6232409Smrg printf("MIN "); 259e6232409Smrg printf("MAX "); 260e6232409Smrg printf("EXIST "); 261e6232409Smrg printf("DFLT "); 262e6232409Smrg printf("PROP "); 263e6232409Smrg printf("ASC "); 264e6232409Smrg printf("DESC "); 265e6232409Smrg printf("NAME"); 266e6232409Smrg printf("\n"); 267e6232409Smrg for (i=0; i<font_cnt; i++) { 268e6232409Smrg pfi = font_list[i].info; 269e6232409Smrg if (!pfi) { 270e6232409Smrg fprintf(stderr, "%s: no font information for font \"%s\".\n", 271e6232409Smrg program_name, 272e6232409Smrg font_list[i].name ? 273e6232409Smrg font_list[i].name : ""); 274e6232409Smrg continue; 275e6232409Smrg } 276e6232409Smrg switch(pfi->direction) { 277e6232409Smrg case FontLeftToRight: string = "-->"; break; 278e6232409Smrg case FontRightToLeft: string = "<--"; break; 279e6232409Smrg default: string = "???"; break; 280e6232409Smrg } 281e6232409Smrg printf("%-4s", string); 282e6232409Smrg if (pfi->min_byte1 == 0 && 283e6232409Smrg pfi->max_byte1 == 0) { 284e6232409Smrg printf(" %3d ", pfi->min_char_or_byte2); 285e6232409Smrg printf(" %3d ", pfi->max_char_or_byte2); 286e6232409Smrg } else { 287e6232409Smrg printf("*%3d ", pfi->min_byte1); 288e6232409Smrg printf("*%3d ", pfi->max_byte1); 289e6232409Smrg } 290e6232409Smrg printf("%5s ", pfi->all_chars_exist ? "all" : "some"); 291e6232409Smrg printf("%4d ", pfi->default_char); 292e6232409Smrg printf("%4d ", pfi->n_properties); 293e6232409Smrg printf("%3d ", pfi->ascent); 294e6232409Smrg printf("%4d ", pfi->descent); 295e6232409Smrg printf("%s\n", font_list[i].name); 296e6232409Smrg if (min_max) { 297e6232409Smrg char min[ BUFSIZ ], 298e6232409Smrg max[ BUFSIZ ]; 299e6232409Smrg char *pmax = max, 300e6232409Smrg *pmin = min; 301e6232409Smrg 302e6232409Smrg strcpy(pmin, " min(l,r,w,a,d) = ("); 303e6232409Smrg strcpy(pmax, " max(l,r,w,a,d) = ("); 304e6232409Smrg pmin += strlen(pmin); 305e6232409Smrg pmax += strlen(pmax); 306e6232409Smrg 307e6232409Smrg copy_number(&pmin, &pmax, 308e6232409Smrg pfi->min_bounds.lbearing, 309e6232409Smrg pfi->max_bounds.lbearing); 310e6232409Smrg *pmin++ = *pmax++ = ','; 311e6232409Smrg copy_number(&pmin, &pmax, 312e6232409Smrg pfi->min_bounds.rbearing, 313e6232409Smrg pfi->max_bounds.rbearing); 314e6232409Smrg *pmin++ = *pmax++ = ','; 315e6232409Smrg copy_number(&pmin, &pmax, 316e6232409Smrg pfi->min_bounds.width, 317e6232409Smrg pfi->max_bounds.width); 318e6232409Smrg *pmin++ = *pmax++ = ','; 319e6232409Smrg copy_number(&pmin, &pmax, 320e6232409Smrg pfi->min_bounds.ascent, 321e6232409Smrg pfi->max_bounds.ascent); 322e6232409Smrg *pmin++ = *pmax++ = ','; 323e6232409Smrg copy_number(&pmin, &pmax, 324e6232409Smrg pfi->min_bounds.descent, 325e6232409Smrg pfi->max_bounds.descent); 326e6232409Smrg *pmin++ = *pmax++ = ')'; 327e6232409Smrg *pmin = *pmax = '\0'; 328e6232409Smrg printf("%s\n", min); 329e6232409Smrg printf("%s\n", max); 330e6232409Smrg } 331e6232409Smrg } 332e6232409Smrg return; 333e6232409Smrg } 334e6232409Smrg 335e6232409Smrg if ((columns == 0 && isatty(1)) || columns > 1) { 336e6232409Smrg int width, 337e6232409Smrg max_width = 0, 338e6232409Smrg lines_per_column, 339e6232409Smrg j, 340e6232409Smrg index; 341e6232409Smrg 342e6232409Smrg for (i=0; i<font_cnt; i++) { 343e6232409Smrg width = strlen(font_list[i].name); 344e6232409Smrg if (width > max_width) 345e6232409Smrg max_width = width; 346e6232409Smrg } 347e6232409Smrg if (max_width == 0) 348e6232409Smrg Fatal_Error("all %d fontnames listed are zero length", font_cnt); 349e6232409Smrg 350e6232409Smrg if (columns == 0) { 351e6232409Smrg if ((max_width * 2) + output_line_padding > 352e6232409Smrg max_output_line_width) { 353e6232409Smrg columns = 1; 354e6232409Smrg } else { 355e6232409Smrg max_width += output_line_padding; 356e6232409Smrg columns = ((max_output_line_width + 357e6232409Smrg output_line_padding) / max_width); 358e6232409Smrg } 359e6232409Smrg } else { 360e6232409Smrg max_width += output_line_padding; 361e6232409Smrg } 362e6232409Smrg if (columns <= 1) goto single_column; 363e6232409Smrg 364e6232409Smrg if (font_cnt < columns) 365e6232409Smrg columns = font_cnt; 366e6232409Smrg lines_per_column = (font_cnt + columns - 1) / columns; 367e6232409Smrg 368e6232409Smrg for (i=0; i<lines_per_column; i++) { 369e6232409Smrg for (j=0; j<columns; j++) { 370e6232409Smrg index = j * lines_per_column + i; 371e6232409Smrg if (index >= font_cnt) 372e6232409Smrg break; 373e6232409Smrg if (j+1 == columns) 374e6232409Smrg printf("%s", font_list[ index ].name); 375e6232409Smrg else 376e6232409Smrg printf("%-*s", 377e6232409Smrg max_width, 378e6232409Smrg font_list[ index ].name); 379e6232409Smrg } 380e6232409Smrg printf("\n"); 381e6232409Smrg } 382e6232409Smrg return; 383e6232409Smrg } 384e6232409Smrg 385e6232409Smrg single_column: 386e6232409Smrg for (i=0; i<font_cnt; i++) 387e6232409Smrg printf("%s\n", font_list[i].name); 388e6232409Smrg} 389e6232409Smrg 390e6232409Smrgstatic 391e6232409Smrgvoid copy_number(char **pp1, char**pp2, int n1, int n2) 392e6232409Smrg{ 393e6232409Smrg char *p1 = *pp1; 394e6232409Smrg char *p2 = *pp2; 395e6232409Smrg int w; 396e6232409Smrg 397e6232409Smrg sprintf(p1, "%d", n1); 398e6232409Smrg sprintf(p2, "%d", n2); 399e6232409Smrg w = MAX(strlen(p1), strlen(p2)); 400e6232409Smrg sprintf(p1, "%*d", w, n1); 401e6232409Smrg sprintf(p2, "%*d", w, n2); 402e6232409Smrg p1 += strlen(p1); 403e6232409Smrg p2 += strlen(p2); 404e6232409Smrg *pp1 = p1; 405e6232409Smrg *pp2 = p2; 406e6232409Smrg} 407e6232409Smrg 408e6232409Smrg 409e6232409Smrg 410e6232409Smrg/* ARGSUSED */ 411e6232409Smrgstatic 412e6232409Smrgint IgnoreError(Display *disp, XErrorEvent *event) 413e6232409Smrg{ 414e6232409Smrg return 0; 415e6232409Smrg} 416e6232409Smrg 417e6232409Smrgstatic char *bounds_metrics_title = 418e6232409Smrg "width left right asc desc attr keysym\n"; 419e6232409Smrg 420e6232409Smrg#define PrintBounds(_what,_ptr) \ 421e6232409Smrg{ register XCharStruct *p = (_ptr); \ 4228fff3f40Smrg printf ("\t%3s\t\t%4d %4d %4d %4d %4d 0x%04x\n", \ 4238fff3f40Smrg (_what), p->width, p->lbearing, \ 424e6232409Smrg p->rbearing, p->ascent, p->descent, p->attributes); } 425e6232409Smrg 426e6232409Smrg 427e6232409Smrgstatic char* stringValued [] = { /* values are atoms */ 428e6232409Smrg /* font name components (see section 3.2 of the XLFD) */ 429e6232409Smrg "FOUNDRY", 430e6232409Smrg "FAMILY_NAME", 431e6232409Smrg "WEIGHT_NAME", 432e6232409Smrg "SLANT", 433e6232409Smrg "SETWIDTH_NAME", 434e6232409Smrg "ADD_STYLE_NAME", 435e6232409Smrg "SPACING", 436e6232409Smrg "CHARSET_REGISTRY", 437e6232409Smrg "CHARSET_ENCODING", 438e6232409Smrg 439e6232409Smrg /* other standard X font properties (see section 3.2 of the XLFD) */ 440e6232409Smrg "FONT", 441e6232409Smrg "FACE_NAME", 442e6232409Smrg "FULL_NAME", /* deprecated */ 443e6232409Smrg "COPYRIGHT", 444e6232409Smrg "NOTICE", 445e6232409Smrg "FONT_TYPE", 446e6232409Smrg "FONT_VERSION", 447e6232409Smrg "RASTERIZER_NAME", 448e6232409Smrg "RASTERIZER_VERSION", 449e6232409Smrg 450e6232409Smrg /* other registered font properties (see the X.org Registry, sec. 15) */ 451e6232409Smrg "_ADOBE_POSTSCRIPT_FONTNAME", 452e6232409Smrg 453e6232409Smrg /* unregistered font properties */ 454e6232409Smrg "CHARSET_COLLECTIONS", 455e6232409Smrg "CLASSIFICATION", 456e6232409Smrg "DEVICE_FONT_NAME", 457e6232409Smrg "FONTNAME_REGISTRY", 458e6232409Smrg "MONOSPACED", 459e6232409Smrg "QUALITY", 460e6232409Smrg "RELATIVE_SET", 461e6232409Smrg "STYLE", 462e6232409Smrg NULL 463e6232409Smrg }; 464e6232409Smrg 465e6232409Smrgstatic 466e6232409Smrgvoid PrintProperty(XFontProp *prop) 467e6232409Smrg{ 468e6232409Smrg char *atom, *value; 469e6232409Smrg char nosuch[40]; 470e6232409Smrg int i; 471e6232409Smrg XErrorHandler oldhandler = XSetErrorHandler(IgnoreError); 472e6232409Smrg 473e6232409Smrg atom = XGetAtomName(dpy, prop->name); 474e6232409Smrg if (!atom) { 475e6232409Smrg atom = nosuch; 476e6232409Smrg nosuch[0] = '\0'; 477e6232409Smrg (void)sprintf (atom, "No such atom = %ld", prop->name); 478e6232409Smrg } 479e6232409Smrg printf (" %s", atom); 480e6232409Smrg 481e6232409Smrg /* Pad out to a column width of 22, but ensure there is always at 482e6232409Smrg least one space between property name & value. */ 483e6232409Smrg for (i = strlen(atom); i < 21; i++) putchar (' '); 484e6232409Smrg putchar(' '); 485e6232409Smrg 486e6232409Smrg for (i = 0; ; i++) { 487e6232409Smrg if (stringValued[i] == NULL) { 488e6232409Smrg printf ("%ld\n", prop->card32); 489e6232409Smrg break; 490e6232409Smrg } 491e6232409Smrg if (strcmp(stringValued[i], atom) == 0) { 492e6232409Smrg value = XGetAtomName(dpy, prop->card32); 493e6232409Smrg if (value == NULL) 494e6232409Smrg printf ("%ld (expected string value)\n", prop->card32); 495e6232409Smrg else { 496e6232409Smrg printf ("%s\n", value); 497e6232409Smrg XFree (value); 498e6232409Smrg } 499e6232409Smrg break; 500e6232409Smrg } 501e6232409Smrg } 502e6232409Smrg if (atom != nosuch) XFree (atom); 503e6232409Smrg XSetErrorHandler (oldhandler); 504e6232409Smrg} 505e6232409Smrg 506e6232409Smrg 507e6232409Smrgstatic void 508e6232409SmrgComputeFontType(XFontStruct *fs) 509e6232409Smrg{ 510e6232409Smrg int i; 511e6232409Smrg Bool char_cell = True; 512e6232409Smrg char *reason = NULL; 513e6232409Smrg XCharStruct *cs; 514e6232409Smrg Atom awatom = XInternAtom (dpy, "AVERAGE_WIDTH", False); 515e6232409Smrg 516e6232409Smrg printf (" font type:\t\t"); 517e6232409Smrg if (fs->min_bounds.width != fs->max_bounds.width) { 518e6232409Smrg printf ("Proportional (min and max widths not equal)\n"); 519e6232409Smrg return; 520e6232409Smrg } 521e6232409Smrg 522e6232409Smrg if (awatom) { 523e6232409Smrg for (i = 0; i < fs->n_properties; i++) { 524e6232409Smrg if (fs->properties[i].name == awatom && 525e6232409Smrg (fs->max_bounds.width * 10) != fs->properties[i].card32) { 526e6232409Smrg char_cell = False; 527e6232409Smrg reason = "font width not equal to AVERAGE_WIDTH"; 528e6232409Smrg break; 529e6232409Smrg } 530e6232409Smrg } 531e6232409Smrg } 532e6232409Smrg 533e6232409Smrg if (fs->per_char) { 534e6232409Smrg for (i = fs->min_char_or_byte2, cs = fs->per_char; 535e6232409Smrg i <= fs->max_char_or_byte2; i++, cs++) { 536e6232409Smrg if (cs->width == 0) continue; 537e6232409Smrg if (cs->width != fs->max_bounds.width) { 538e6232409Smrg /* this shouldn't happen since we checked above */ 539e6232409Smrg printf ("Proportional (characters not all the same width)\n"); 540e6232409Smrg return; 541e6232409Smrg } 542e6232409Smrg if (char_cell) { 543e6232409Smrg if (cs->width < 0) { 544e6232409Smrg if (!(cs->width <= cs->lbearing && 545e6232409Smrg cs->lbearing <= cs->rbearing && 546e6232409Smrg cs->rbearing <= 0)) { 547e6232409Smrg char_cell = False; 548e6232409Smrg reason = "ink outside bounding box"; 549e6232409Smrg } 550e6232409Smrg } else { 551e6232409Smrg if (!(0 <= cs->lbearing && 552e6232409Smrg cs->lbearing <= cs->rbearing && 553e6232409Smrg cs->rbearing <= cs->width)) { 554e6232409Smrg char_cell = False; 555e6232409Smrg reason = "ink outside bounding box"; 556e6232409Smrg } 557e6232409Smrg } 558e6232409Smrg if (!(cs->ascent <= fs->ascent && 559e6232409Smrg cs->descent <= fs->descent)) { 560e6232409Smrg char_cell = False; 561e6232409Smrg reason = "characters not all same ascent or descent"; 562e6232409Smrg } 563e6232409Smrg } 564e6232409Smrg } 565e6232409Smrg } 566e6232409Smrg 567e6232409Smrg printf ("%s", char_cell ? "Character Cell" : "Monospaced"); 568e6232409Smrg if (reason) printf (" (%s)", reason); 569e6232409Smrg printf ("\n"); 570e6232409Smrg 571e6232409Smrg return; 572e6232409Smrg} 573e6232409Smrg 574e6232409Smrg 575e6232409Smrgstatic void 576e6232409Smrgprint_character_metrics(register XFontStruct *info) 577e6232409Smrg{ 578e6232409Smrg register XCharStruct *pc = info->per_char; 579e6232409Smrg register int i, j; 580e6232409Smrg unsigned n, saven; 581e6232409Smrg 582e6232409Smrg printf (" character metrics:\n"); 583e6232409Smrg saven = ((info->min_byte1 << 8) | info->min_char_or_byte2); 584e6232409Smrg for (j = info->min_byte1; j <= info->max_byte1; j++) { 585e6232409Smrg n = saven; 586e6232409Smrg for (i = info->min_char_or_byte2; i <= info->max_char_or_byte2; i++) { 587e6232409Smrg char *s = XKeysymToString ((KeySym) n); 5888fff3f40Smrg printf ("\t0x%02x%02x (%u)\t%4d %4d %4d %4d %4d 0x%04x %s\n", 5898fff3f40Smrg j, i, n, pc->width, pc->lbearing, 590e6232409Smrg pc->rbearing, pc->ascent, pc->descent, pc->attributes, 591e6232409Smrg s ? s : "."); 592e6232409Smrg pc++; 593e6232409Smrg n++; 594e6232409Smrg } 595e6232409Smrg saven += 256; 596e6232409Smrg } 597e6232409Smrg} 598e6232409Smrg 599e6232409Smrgstatic 600e6232409Smrgvoid do_query_font (Display *dpy, char *name) 601e6232409Smrg{ 602e6232409Smrg register int i; 603e6232409Smrg register XFontStruct *info = XLoadQueryFont (dpy, name); 604e6232409Smrg 605e6232409Smrg if (!info) { 606e6232409Smrg fprintf (stderr, "%s: unable to get info about font \"%s\"\n", 607e6232409Smrg program_name, name); 608e6232409Smrg return; 609e6232409Smrg } 610e6232409Smrg printf ("name: %s\n", name ? name : "(nil)"); 611e6232409Smrg printf (" direction:\t\t%s\n", ((info->direction == FontLeftToRight) 612e6232409Smrg ? "left to right" : "right to left")); 613e6232409Smrg printf (" indexing:\t\t%s\n", 614e6232409Smrg ((info->min_byte1 == 0 && info->max_byte1 == 0) ? "linear" : 615e6232409Smrg "matrix")); 616e6232409Smrg printf (" rows:\t\t\t0x%02x thru 0x%02x (%d thru %d)\n", 617e6232409Smrg info->min_byte1, info->max_byte1, 618e6232409Smrg info->min_byte1, info->max_byte1); 619e6232409Smrg printf (" columns:\t\t0x%02x thru 0x%02x (%d thru %d)\n", 620e6232409Smrg info->min_char_or_byte2, info->max_char_or_byte2, 621e6232409Smrg info->min_char_or_byte2, info->max_char_or_byte2); 622e6232409Smrg printf (" all chars exist:\t%s\n", 623e6232409Smrg (info->all_chars_exist) ? "yes" : "no"); 624e6232409Smrg printf (" default char:\t\t0x%04x (%d)\n", 625e6232409Smrg info->default_char, info->default_char); 626e6232409Smrg printf (" ascent:\t\t%d\n", info->ascent); 627e6232409Smrg printf (" descent:\t\t%d\n", info->descent); 628e6232409Smrg ComputeFontType (info); 629e6232409Smrg printf (" bounds:\t\t%s", bounds_metrics_title); 630e6232409Smrg PrintBounds ("min", &info->min_bounds); 631e6232409Smrg PrintBounds ("max", &info->max_bounds); 632e6232409Smrg if (info->per_char && long_list >= L_VERYLONG) 633e6232409Smrg print_character_metrics (info); 634e6232409Smrg printf (" properties:\t\t%d\n", info->n_properties); 635e6232409Smrg for (i = 0; i < info->n_properties; i++) 636e6232409Smrg PrintProperty (&info->properties[i]); 637e6232409Smrg printf ("\n"); 638e6232409Smrg 639e6232409Smrg XFreeFontInfo (NULL, info, 1); 640e6232409Smrg} 641e6232409Smrg 642e6232409Smrg 643