xlsfonts.c revision 94a251fd
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 */ 6694a251fdSmrgstatic void get_list(const 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{ 7894a251fdSmrg fprintf (stderr, "usage: %s [-options] [-fn pattern]\n%s", program_name, 7994a251fdSmrg "where options include:\n" 8094a251fdSmrg " -l[l[l]] give long info about each font\n" 8194a251fdSmrg " -m give character min and max bounds\n" 8294a251fdSmrg " -C force columns\n" 8394a251fdSmrg " -1 force single column\n" 8494a251fdSmrg " -u keep output unsorted\n" 8594a251fdSmrg " -o use OpenFont/QueryFont instead of ListFonts\n" 8694a251fdSmrg " -w width maximum width for multiple columns\n" 8794a251fdSmrg " -n columns number of columns if multi column\n" 8894a251fdSmrg " -display displayname X server to contact\n" 8994a251fdSmrg " -d displayname (alias for -display displayname)\n" 9094a251fdSmrg "\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 16894a251fdSmrgvoid get_list(const 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 20994a251fdSmrg font_list = realloc(font_list, (font_cnt + available) * sizeof(FontList)); 21094a251fdSmrg if (font_list == NULL) 21194a251fdSmrg Fatal_Error("Out of memory!"); 212e6232409Smrg for (i=0; i<available; i++) { 213e6232409Smrg font_list[font_cnt].name = fonts[i]; 214e6232409Smrg if (long_list == L_MEDIUM) 215e6232409Smrg font_list[font_cnt].info = info + i; 216e6232409Smrg else 217e6232409Smrg font_list[font_cnt].info = NULL; 218e6232409Smrg 219e6232409Smrg font_cnt++; 220e6232409Smrg } 221e6232409Smrg} 222e6232409Smrg 223e6232409Smrgstatic 224e6232409Smrgint compare(const void *arg1, const void *arg2) 225e6232409Smrg{ 226e6232409Smrg const FontList *f1 = arg1; 227e6232409Smrg const FontList *f2 = arg2; 228e6232409Smrg const char *p1 = f1->name; 229e6232409Smrg const char *p2 = f2->name; 230e6232409Smrg 231e6232409Smrg while (*p1 && *p2 && *p1 == *p2) 232e6232409Smrg p1++, p2++; 233e6232409Smrg return(*p1 - *p2); 234e6232409Smrg} 235e6232409Smrg 236e6232409Smrgstatic 237e6232409Smrgvoid show_fonts(void) 238e6232409Smrg{ 239e6232409Smrg int i; 240e6232409Smrg 241e6232409Smrg if (font_cnt == 0) 242e6232409Smrg return; 243e6232409Smrg 244e6232409Smrg /* first sort the output */ 245e6232409Smrg if (sort_output) qsort(font_list, font_cnt, sizeof(FontList), compare); 246e6232409Smrg 247e6232409Smrg if (long_list > L_MEDIUM) { 248e6232409Smrg for (i = 0; i < font_cnt; i++) { 249e6232409Smrg do_query_font (dpy, font_list[i].name); 250e6232409Smrg } 251e6232409Smrg return; 252e6232409Smrg } 253e6232409Smrg 254e6232409Smrg if (long_list == L_MEDIUM) { 255e6232409Smrg XFontStruct *pfi; 25694a251fdSmrg const char *string; 257e6232409Smrg 258e6232409Smrg printf("DIR "); 259e6232409Smrg printf("MIN "); 260e6232409Smrg printf("MAX "); 261e6232409Smrg printf("EXIST "); 262e6232409Smrg printf("DFLT "); 263e6232409Smrg printf("PROP "); 264e6232409Smrg printf("ASC "); 265e6232409Smrg printf("DESC "); 266e6232409Smrg printf("NAME"); 267e6232409Smrg printf("\n"); 268e6232409Smrg for (i=0; i<font_cnt; i++) { 269e6232409Smrg pfi = font_list[i].info; 270e6232409Smrg if (!pfi) { 271e6232409Smrg fprintf(stderr, "%s: no font information for font \"%s\".\n", 272e6232409Smrg program_name, 273e6232409Smrg font_list[i].name ? 274e6232409Smrg font_list[i].name : ""); 275e6232409Smrg continue; 276e6232409Smrg } 277e6232409Smrg switch(pfi->direction) { 278e6232409Smrg case FontLeftToRight: string = "-->"; break; 279e6232409Smrg case FontRightToLeft: string = "<--"; break; 280e6232409Smrg default: string = "???"; break; 281e6232409Smrg } 282e6232409Smrg printf("%-4s", string); 283e6232409Smrg if (pfi->min_byte1 == 0 && 284e6232409Smrg pfi->max_byte1 == 0) { 285e6232409Smrg printf(" %3d ", pfi->min_char_or_byte2); 286e6232409Smrg printf(" %3d ", pfi->max_char_or_byte2); 287e6232409Smrg } else { 288e6232409Smrg printf("*%3d ", pfi->min_byte1); 289e6232409Smrg printf("*%3d ", pfi->max_byte1); 290e6232409Smrg } 291e6232409Smrg printf("%5s ", pfi->all_chars_exist ? "all" : "some"); 292e6232409Smrg printf("%4d ", pfi->default_char); 293e6232409Smrg printf("%4d ", pfi->n_properties); 294e6232409Smrg printf("%3d ", pfi->ascent); 295e6232409Smrg printf("%4d ", pfi->descent); 296e6232409Smrg printf("%s\n", font_list[i].name); 297e6232409Smrg if (min_max) { 298e6232409Smrg char min[ BUFSIZ ], 299e6232409Smrg max[ BUFSIZ ]; 300e6232409Smrg char *pmax = max, 301e6232409Smrg *pmin = min; 302e6232409Smrg 303e6232409Smrg strcpy(pmin, " min(l,r,w,a,d) = ("); 304e6232409Smrg strcpy(pmax, " max(l,r,w,a,d) = ("); 305e6232409Smrg pmin += strlen(pmin); 306e6232409Smrg pmax += strlen(pmax); 307e6232409Smrg 308e6232409Smrg copy_number(&pmin, &pmax, 309e6232409Smrg pfi->min_bounds.lbearing, 310e6232409Smrg pfi->max_bounds.lbearing); 311e6232409Smrg *pmin++ = *pmax++ = ','; 312e6232409Smrg copy_number(&pmin, &pmax, 313e6232409Smrg pfi->min_bounds.rbearing, 314e6232409Smrg pfi->max_bounds.rbearing); 315e6232409Smrg *pmin++ = *pmax++ = ','; 316e6232409Smrg copy_number(&pmin, &pmax, 317e6232409Smrg pfi->min_bounds.width, 318e6232409Smrg pfi->max_bounds.width); 319e6232409Smrg *pmin++ = *pmax++ = ','; 320e6232409Smrg copy_number(&pmin, &pmax, 321e6232409Smrg pfi->min_bounds.ascent, 322e6232409Smrg pfi->max_bounds.ascent); 323e6232409Smrg *pmin++ = *pmax++ = ','; 324e6232409Smrg copy_number(&pmin, &pmax, 325e6232409Smrg pfi->min_bounds.descent, 326e6232409Smrg pfi->max_bounds.descent); 327e6232409Smrg *pmin++ = *pmax++ = ')'; 328e6232409Smrg *pmin = *pmax = '\0'; 329e6232409Smrg printf("%s\n", min); 330e6232409Smrg printf("%s\n", max); 331e6232409Smrg } 332e6232409Smrg } 333e6232409Smrg return; 334e6232409Smrg } 335e6232409Smrg 336e6232409Smrg if ((columns == 0 && isatty(1)) || columns > 1) { 337e6232409Smrg int width, 338e6232409Smrg max_width = 0, 339e6232409Smrg lines_per_column, 340e6232409Smrg j, 341e6232409Smrg index; 342e6232409Smrg 343e6232409Smrg for (i=0; i<font_cnt; i++) { 344e6232409Smrg width = strlen(font_list[i].name); 345e6232409Smrg if (width > max_width) 346e6232409Smrg max_width = width; 347e6232409Smrg } 348e6232409Smrg if (max_width == 0) 349e6232409Smrg Fatal_Error("all %d fontnames listed are zero length", font_cnt); 350e6232409Smrg 351e6232409Smrg if (columns == 0) { 352e6232409Smrg if ((max_width * 2) + output_line_padding > 353e6232409Smrg max_output_line_width) { 354e6232409Smrg columns = 1; 355e6232409Smrg } else { 356e6232409Smrg max_width += output_line_padding; 357e6232409Smrg columns = ((max_output_line_width + 358e6232409Smrg output_line_padding) / max_width); 359e6232409Smrg } 360e6232409Smrg } else { 361e6232409Smrg max_width += output_line_padding; 362e6232409Smrg } 363e6232409Smrg if (columns <= 1) goto single_column; 364e6232409Smrg 365e6232409Smrg if (font_cnt < columns) 366e6232409Smrg columns = font_cnt; 367e6232409Smrg lines_per_column = (font_cnt + columns - 1) / columns; 368e6232409Smrg 369e6232409Smrg for (i=0; i<lines_per_column; i++) { 370e6232409Smrg for (j=0; j<columns; j++) { 371e6232409Smrg index = j * lines_per_column + i; 372e6232409Smrg if (index >= font_cnt) 373e6232409Smrg break; 374e6232409Smrg if (j+1 == columns) 375e6232409Smrg printf("%s", font_list[ index ].name); 376e6232409Smrg else 377e6232409Smrg printf("%-*s", 378e6232409Smrg max_width, 379e6232409Smrg font_list[ index ].name); 380e6232409Smrg } 381e6232409Smrg printf("\n"); 382e6232409Smrg } 383e6232409Smrg return; 384e6232409Smrg } 385e6232409Smrg 386e6232409Smrg single_column: 387e6232409Smrg for (i=0; i<font_cnt; i++) 388e6232409Smrg printf("%s\n", font_list[i].name); 389e6232409Smrg} 390e6232409Smrg 391e6232409Smrgstatic 392e6232409Smrgvoid copy_number(char **pp1, char**pp2, int n1, int n2) 393e6232409Smrg{ 394e6232409Smrg char *p1 = *pp1; 395e6232409Smrg char *p2 = *pp2; 396e6232409Smrg int w; 397e6232409Smrg 398e6232409Smrg sprintf(p1, "%d", n1); 399e6232409Smrg sprintf(p2, "%d", n2); 400e6232409Smrg w = MAX(strlen(p1), strlen(p2)); 401e6232409Smrg sprintf(p1, "%*d", w, n1); 402e6232409Smrg sprintf(p2, "%*d", w, n2); 403e6232409Smrg p1 += strlen(p1); 404e6232409Smrg p2 += strlen(p2); 405e6232409Smrg *pp1 = p1; 406e6232409Smrg *pp2 = p2; 407e6232409Smrg} 408e6232409Smrg 409e6232409Smrg 410e6232409Smrg 411e6232409Smrg/* ARGSUSED */ 412e6232409Smrgstatic 413e6232409Smrgint IgnoreError(Display *disp, XErrorEvent *event) 414e6232409Smrg{ 415e6232409Smrg return 0; 416e6232409Smrg} 417e6232409Smrg 41894a251fdSmrgstatic const char *bounds_metrics_title = 419e6232409Smrg "width left right asc desc attr keysym\n"; 420e6232409Smrg 421e6232409Smrg#define PrintBounds(_what,_ptr) \ 422e6232409Smrg{ register XCharStruct *p = (_ptr); \ 4238fff3f40Smrg printf ("\t%3s\t\t%4d %4d %4d %4d %4d 0x%04x\n", \ 4248fff3f40Smrg (_what), p->width, p->lbearing, \ 425e6232409Smrg p->rbearing, p->ascent, p->descent, p->attributes); } 426e6232409Smrg 427e6232409Smrg 42894a251fdSmrgstatic const char* stringValued [] = { /* values are atoms */ 429e6232409Smrg /* font name components (see section 3.2 of the XLFD) */ 430e6232409Smrg "FOUNDRY", 431e6232409Smrg "FAMILY_NAME", 432e6232409Smrg "WEIGHT_NAME", 433e6232409Smrg "SLANT", 434e6232409Smrg "SETWIDTH_NAME", 435e6232409Smrg "ADD_STYLE_NAME", 436e6232409Smrg "SPACING", 437e6232409Smrg "CHARSET_REGISTRY", 438e6232409Smrg "CHARSET_ENCODING", 439e6232409Smrg 440e6232409Smrg /* other standard X font properties (see section 3.2 of the XLFD) */ 441e6232409Smrg "FONT", 442e6232409Smrg "FACE_NAME", 443e6232409Smrg "FULL_NAME", /* deprecated */ 444e6232409Smrg "COPYRIGHT", 445e6232409Smrg "NOTICE", 446e6232409Smrg "FONT_TYPE", 447e6232409Smrg "FONT_VERSION", 448e6232409Smrg "RASTERIZER_NAME", 449e6232409Smrg "RASTERIZER_VERSION", 450e6232409Smrg 451e6232409Smrg /* other registered font properties (see the X.org Registry, sec. 15) */ 452e6232409Smrg "_ADOBE_POSTSCRIPT_FONTNAME", 453e6232409Smrg 454e6232409Smrg /* unregistered font properties */ 455e6232409Smrg "CHARSET_COLLECTIONS", 456e6232409Smrg "CLASSIFICATION", 457e6232409Smrg "DEVICE_FONT_NAME", 458e6232409Smrg "FONTNAME_REGISTRY", 459e6232409Smrg "MONOSPACED", 460e6232409Smrg "QUALITY", 461e6232409Smrg "RELATIVE_SET", 462e6232409Smrg "STYLE", 463e6232409Smrg NULL 464e6232409Smrg }; 465e6232409Smrg 466e6232409Smrgstatic 467e6232409Smrgvoid PrintProperty(XFontProp *prop) 468e6232409Smrg{ 469e6232409Smrg char *atom, *value; 470e6232409Smrg char nosuch[40]; 471e6232409Smrg int i; 472e6232409Smrg XErrorHandler oldhandler = XSetErrorHandler(IgnoreError); 473e6232409Smrg 474e6232409Smrg atom = XGetAtomName(dpy, prop->name); 475e6232409Smrg if (!atom) { 476e6232409Smrg atom = nosuch; 477e6232409Smrg nosuch[0] = '\0'; 478e6232409Smrg (void)sprintf (atom, "No such atom = %ld", prop->name); 479e6232409Smrg } 480e6232409Smrg printf (" %s", atom); 481e6232409Smrg 482e6232409Smrg /* Pad out to a column width of 22, but ensure there is always at 483e6232409Smrg least one space between property name & value. */ 484e6232409Smrg for (i = strlen(atom); i < 21; i++) putchar (' '); 485e6232409Smrg putchar(' '); 486e6232409Smrg 487e6232409Smrg for (i = 0; ; i++) { 488e6232409Smrg if (stringValued[i] == NULL) { 489e6232409Smrg printf ("%ld\n", prop->card32); 490e6232409Smrg break; 491e6232409Smrg } 492e6232409Smrg if (strcmp(stringValued[i], atom) == 0) { 493e6232409Smrg value = XGetAtomName(dpy, prop->card32); 494e6232409Smrg if (value == NULL) 495e6232409Smrg printf ("%ld (expected string value)\n", prop->card32); 496e6232409Smrg else { 497e6232409Smrg printf ("%s\n", value); 498e6232409Smrg XFree (value); 499e6232409Smrg } 500e6232409Smrg break; 501e6232409Smrg } 502e6232409Smrg } 503e6232409Smrg if (atom != nosuch) XFree (atom); 504e6232409Smrg XSetErrorHandler (oldhandler); 505e6232409Smrg} 506e6232409Smrg 507e6232409Smrg 508e6232409Smrgstatic void 509e6232409SmrgComputeFontType(XFontStruct *fs) 510e6232409Smrg{ 511e6232409Smrg int i; 512e6232409Smrg Bool char_cell = True; 51394a251fdSmrg const char *reason = NULL; 514e6232409Smrg XCharStruct *cs; 515e6232409Smrg Atom awatom = XInternAtom (dpy, "AVERAGE_WIDTH", False); 516e6232409Smrg 517e6232409Smrg printf (" font type:\t\t"); 518e6232409Smrg if (fs->min_bounds.width != fs->max_bounds.width) { 519e6232409Smrg printf ("Proportional (min and max widths not equal)\n"); 520e6232409Smrg return; 521e6232409Smrg } 522e6232409Smrg 523e6232409Smrg if (awatom) { 524e6232409Smrg for (i = 0; i < fs->n_properties; i++) { 525e6232409Smrg if (fs->properties[i].name == awatom && 526e6232409Smrg (fs->max_bounds.width * 10) != fs->properties[i].card32) { 527e6232409Smrg char_cell = False; 528e6232409Smrg reason = "font width not equal to AVERAGE_WIDTH"; 529e6232409Smrg break; 530e6232409Smrg } 531e6232409Smrg } 532e6232409Smrg } 533e6232409Smrg 534e6232409Smrg if (fs->per_char) { 535e6232409Smrg for (i = fs->min_char_or_byte2, cs = fs->per_char; 536e6232409Smrg i <= fs->max_char_or_byte2; i++, cs++) { 537e6232409Smrg if (cs->width == 0) continue; 538e6232409Smrg if (cs->width != fs->max_bounds.width) { 539e6232409Smrg /* this shouldn't happen since we checked above */ 540e6232409Smrg printf ("Proportional (characters not all the same width)\n"); 541e6232409Smrg return; 542e6232409Smrg } 543e6232409Smrg if (char_cell) { 544e6232409Smrg if (cs->width < 0) { 545e6232409Smrg if (!(cs->width <= cs->lbearing && 546e6232409Smrg cs->lbearing <= cs->rbearing && 547e6232409Smrg cs->rbearing <= 0)) { 548e6232409Smrg char_cell = False; 549e6232409Smrg reason = "ink outside bounding box"; 550e6232409Smrg } 551e6232409Smrg } else { 552e6232409Smrg if (!(0 <= cs->lbearing && 553e6232409Smrg cs->lbearing <= cs->rbearing && 554e6232409Smrg cs->rbearing <= cs->width)) { 555e6232409Smrg char_cell = False; 556e6232409Smrg reason = "ink outside bounding box"; 557e6232409Smrg } 558e6232409Smrg } 559e6232409Smrg if (!(cs->ascent <= fs->ascent && 560e6232409Smrg cs->descent <= fs->descent)) { 561e6232409Smrg char_cell = False; 562e6232409Smrg reason = "characters not all same ascent or descent"; 563e6232409Smrg } 564e6232409Smrg } 565e6232409Smrg } 566e6232409Smrg } 567e6232409Smrg 568e6232409Smrg printf ("%s", char_cell ? "Character Cell" : "Monospaced"); 569e6232409Smrg if (reason) printf (" (%s)", reason); 570e6232409Smrg printf ("\n"); 571e6232409Smrg 572e6232409Smrg return; 573e6232409Smrg} 574e6232409Smrg 575e6232409Smrg 576e6232409Smrgstatic void 577e6232409Smrgprint_character_metrics(register XFontStruct *info) 578e6232409Smrg{ 579e6232409Smrg register XCharStruct *pc = info->per_char; 580e6232409Smrg register int i, j; 581e6232409Smrg unsigned n, saven; 582e6232409Smrg 583e6232409Smrg printf (" character metrics:\n"); 584e6232409Smrg saven = ((info->min_byte1 << 8) | info->min_char_or_byte2); 585e6232409Smrg for (j = info->min_byte1; j <= info->max_byte1; j++) { 586e6232409Smrg n = saven; 587e6232409Smrg for (i = info->min_char_or_byte2; i <= info->max_char_or_byte2; i++) { 588e6232409Smrg char *s = XKeysymToString ((KeySym) n); 5898fff3f40Smrg printf ("\t0x%02x%02x (%u)\t%4d %4d %4d %4d %4d 0x%04x %s\n", 5908fff3f40Smrg j, i, n, pc->width, pc->lbearing, 591e6232409Smrg pc->rbearing, pc->ascent, pc->descent, pc->attributes, 592e6232409Smrg s ? s : "."); 593e6232409Smrg pc++; 594e6232409Smrg n++; 595e6232409Smrg } 596e6232409Smrg saven += 256; 597e6232409Smrg } 598e6232409Smrg} 599e6232409Smrg 600e6232409Smrgstatic 601e6232409Smrgvoid do_query_font (Display *dpy, char *name) 602e6232409Smrg{ 603e6232409Smrg register int i; 604e6232409Smrg register XFontStruct *info = XLoadQueryFont (dpy, name); 605e6232409Smrg 606e6232409Smrg if (!info) { 607e6232409Smrg fprintf (stderr, "%s: unable to get info about font \"%s\"\n", 608e6232409Smrg program_name, name); 609e6232409Smrg return; 610e6232409Smrg } 611e6232409Smrg printf ("name: %s\n", name ? name : "(nil)"); 612e6232409Smrg printf (" direction:\t\t%s\n", ((info->direction == FontLeftToRight) 613e6232409Smrg ? "left to right" : "right to left")); 614e6232409Smrg printf (" indexing:\t\t%s\n", 615e6232409Smrg ((info->min_byte1 == 0 && info->max_byte1 == 0) ? "linear" : 616e6232409Smrg "matrix")); 617e6232409Smrg printf (" rows:\t\t\t0x%02x thru 0x%02x (%d thru %d)\n", 618e6232409Smrg info->min_byte1, info->max_byte1, 619e6232409Smrg info->min_byte1, info->max_byte1); 620e6232409Smrg printf (" columns:\t\t0x%02x thru 0x%02x (%d thru %d)\n", 621e6232409Smrg info->min_char_or_byte2, info->max_char_or_byte2, 622e6232409Smrg info->min_char_or_byte2, info->max_char_or_byte2); 623e6232409Smrg printf (" all chars exist:\t%s\n", 624e6232409Smrg (info->all_chars_exist) ? "yes" : "no"); 625e6232409Smrg printf (" default char:\t\t0x%04x (%d)\n", 626e6232409Smrg info->default_char, info->default_char); 627e6232409Smrg printf (" ascent:\t\t%d\n", info->ascent); 628e6232409Smrg printf (" descent:\t\t%d\n", info->descent); 629e6232409Smrg ComputeFontType (info); 630e6232409Smrg printf (" bounds:\t\t%s", bounds_metrics_title); 631e6232409Smrg PrintBounds ("min", &info->min_bounds); 632e6232409Smrg PrintBounds ("max", &info->max_bounds); 633e6232409Smrg if (info->per_char && long_list >= L_VERYLONG) 634e6232409Smrg print_character_metrics (info); 635e6232409Smrg printf (" properties:\t\t%d\n", info->n_properties); 636e6232409Smrg for (i = 0; i < info->n_properties; i++) 637e6232409Smrg PrintProperty (&info->properties[i]); 638e6232409Smrg printf ("\n"); 639e6232409Smrg 640e6232409Smrg XFreeFontInfo (NULL, info, 1); 641e6232409Smrg} 642e6232409Smrg 643e6232409Smrg 644