2 * $Xorg: xlsfonts.c,v 1.4 2001/02/09 02:05:54 xorgcvs Exp $
5 Copyright 1989, 1998 The Open Group
7 Permission to use, copy, modify, distribute, and sell this software and its
8 documentation for any purpose is hereby granted without fee, provided that
9 the above copyright notice appear in all copies and that both that
10 copyright notice and this permission notice appear in supporting
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of The Open Group shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from The Open Group.
27 /* $XFree86: xc/programs/xlsfonts/xlsfonts.c,v 1.9 2003/09/08 14:25:33 eich Exp $ */
30 #include <X11/Xutil.h>
37 #define N_START INT_MAX /* Maximum # of fonts to start with (should
38 * always be be > 10000 as modern OSes like
39 * Solaris 8 already have more than 9000 XLFD
47 static int max_output_line_width = 79;
48 static int output_line_padding = 3;
49 static int columns = 0;
51 static Bool sort_output = True;
52 static Bool open_instead_of_list = False;
53 static int long_list = L_SHORT;
54 static int nnames = N_START;
55 static int font_cnt = 0;
63 static FontList *font_list = NULL;
65 /* Local prototypes */
66 static void get_list(char *pattern);
67 static int compare(const void *arg1, const void *arg2);
68 static void show_fonts(void);
69 static void copy_number(char **pp1, char**pp2, int n1, int n2);
70 static int IgnoreError(Display *disp, XErrorEvent *event);
71 static void PrintProperty(XFontProp *prop);
72 static void ComputeFontType(XFontStruct *fs);
73 static void print_character_metrics(register XFontStruct *info);
74 static void do_query_font (Display *dpy, char *name);
78 fprintf (stderr, "usage: %s [-options] [-fn pattern]\n", program_name);
79 fprintf (stderr, "where options include:\n");
80 fprintf (stderr, " -l[l[l]] give long info about each font\n");
81 fprintf (stderr, " -m give character min and max bounds\n");
82 fprintf (stderr, " -C force columns\n");
83 fprintf (stderr, " -1 force single column\n");
84 fprintf (stderr, " -u keep output unsorted\n");
85 fprintf (stderr, " -o use OpenFont/QueryFont instead of ListFonts\n");
86 fprintf (stderr, " -w width maximum width for multiple columns\n");
87 fprintf (stderr, " -n columns number of columns if multi column\n");
88 fprintf (stderr, " -display displayname X server to contact\n");
89 fprintf (stderr, " -d displayname (alias for -display displayname)\n");
90 fprintf (stderr, "\n");
95 int main(int argc, char **argv)
101 /* Handle command line arguments, open display */
102 Setup_Display_And_Screen(&argc, argv);
104 for (argv++, argc--; argc; argv++, argc--) {
105 if (argv[0][0] == '-') {
106 if (argcnt > 0) usage ();
107 for (i=1; argv[0][i]; i++)
121 case 'f': /* "-fn" */
122 if (--argc <= 0) usage ();
123 if (argv[0][i+1] != 'n') usage ();
129 if (--argc <= 0) usage ();
131 max_output_line_width = atoi(argv[0]);
134 if (--argc <= 0) usage ();
136 columns = atoi(argv[0]);
139 open_instead_of_list = True;
168 void get_list(char *pattern)
170 int available = nnames+1,
175 /* Get list of fonts matching pattern */
177 if (open_instead_of_list) {
178 info = XLoadQueryFont (dpy, pattern);
183 XUnloadFont (dpy, info->fid);
190 if (long_list == L_MEDIUM)
191 fonts = XListFontsWithInfo(dpy, pattern, nnames, &available, &info);
193 fonts = XListFonts(dpy, pattern, nnames, &available);
194 if (fonts == NULL || available < nnames)
196 if (long_list == L_MEDIUM)
197 XFreeFontInfo(fonts, info, available);
199 XFreeFontNames(fonts);
200 nnames = available * 2;
204 fprintf(stderr, "%s: pattern \"%s\" unmatched\n",
205 program_name, pattern);
209 font_list = (FontList *)Realloc((char *)font_list,
210 (font_cnt + available) * sizeof(FontList));
211 for (i=0; i<available; i++) {
212 font_list[font_cnt].name = fonts[i];
213 if (long_list == L_MEDIUM)
214 font_list[font_cnt].info = info + i;
216 font_list[font_cnt].info = NULL;
223 int compare(const void *arg1, const void *arg2)
225 const FontList *f1 = arg1;
226 const FontList *f2 = arg2;
227 const char *p1 = f1->name;
228 const char *p2 = f2->name;
230 while (*p1 && *p2 && *p1 == *p2)
236 void show_fonts(void)
243 /* first sort the output */
244 if (sort_output) qsort(font_list, font_cnt, sizeof(FontList), compare);
246 if (long_list > L_MEDIUM) {
247 for (i = 0; i < font_cnt; i++) {
248 do_query_font (dpy, font_list[i].name);
253 if (long_list == L_MEDIUM) {
267 for (i=0; i<font_cnt; i++) {
268 pfi = font_list[i].info;
270 fprintf(stderr, "%s: no font information for font \"%s\".\n",
273 font_list[i].name : "");
276 switch(pfi->direction) {
277 case FontLeftToRight: string = "-->"; break;
278 case FontRightToLeft: string = "<--"; break;
279 default: string = "???"; break;
281 printf("%-4s", string);
282 if (pfi->min_byte1 == 0 &&
283 pfi->max_byte1 == 0) {
284 printf(" %3d ", pfi->min_char_or_byte2);
285 printf(" %3d ", pfi->max_char_or_byte2);
287 printf("*%3d ", pfi->min_byte1);
288 printf("*%3d ", pfi->max_byte1);
290 printf("%5s ", pfi->all_chars_exist ? "all" : "some");
291 printf("%4d ", pfi->default_char);
292 printf("%4d ", pfi->n_properties);
293 printf("%3d ", pfi->ascent);
294 printf("%4d ", pfi->descent);
295 printf("%s\n", font_list[i].name);
302 strcpy(pmin, " min(l,r,w,a,d) = (");
303 strcpy(pmax, " max(l,r,w,a,d) = (");
304 pmin += strlen(pmin);
305 pmax += strlen(pmax);
307 copy_number(&pmin, &pmax,
308 pfi->min_bounds.lbearing,
309 pfi->max_bounds.lbearing);
310 *pmin++ = *pmax++ = ',';
311 copy_number(&pmin, &pmax,
312 pfi->min_bounds.rbearing,
313 pfi->max_bounds.rbearing);
314 *pmin++ = *pmax++ = ',';
315 copy_number(&pmin, &pmax,
316 pfi->min_bounds.width,
317 pfi->max_bounds.width);
318 *pmin++ = *pmax++ = ',';
319 copy_number(&pmin, &pmax,
320 pfi->min_bounds.ascent,
321 pfi->max_bounds.ascent);
322 *pmin++ = *pmax++ = ',';
323 copy_number(&pmin, &pmax,
324 pfi->min_bounds.descent,
325 pfi->max_bounds.descent);
326 *pmin++ = *pmax++ = ')';
327 *pmin = *pmax = '\0';
335 if ((columns == 0 && isatty(1)) || columns > 1) {
342 for (i=0; i<font_cnt; i++) {
343 width = strlen(font_list[i].name);
344 if (width > max_width)
348 Fatal_Error("all %d fontnames listed are zero length", font_cnt);
351 if ((max_width * 2) + output_line_padding >
352 max_output_line_width) {
355 max_width += output_line_padding;
356 columns = ((max_output_line_width +
357 output_line_padding) / max_width);
360 max_width += output_line_padding;
362 if (columns <= 1) goto single_column;
364 if (font_cnt < columns)
366 lines_per_column = (font_cnt + columns - 1) / columns;
368 for (i=0; i<lines_per_column; i++) {
369 for (j=0; j<columns; j++) {
370 index = j * lines_per_column + i;
371 if (index >= font_cnt)
374 printf("%s", font_list[ index ].name);
378 font_list[ index ].name);
386 for (i=0; i<font_cnt; i++)
387 printf("%s\n", font_list[i].name);
391 void copy_number(char **pp1, char**pp2, int n1, int n2)
397 sprintf(p1, "%d", n1);
398 sprintf(p2, "%d", n2);
399 w = MAX(strlen(p1), strlen(p2));
400 sprintf(p1, "%*d", w, n1);
401 sprintf(p2, "%*d", w, n2);
412 int IgnoreError(Display *disp, XErrorEvent *event)
417 static char *bounds_metrics_title =
418 "width left right asc desc attr keysym\n";
420 #define PrintBounds(_what,_ptr) \
421 { register XCharStruct *p = (_ptr); \
422 printf ("\t%3s\t\t%4d %4d %4d %4d %4d 0x%04x\n", \
423 (_what), p->width, p->lbearing, \
424 p->rbearing, p->ascent, p->descent, p->attributes); }
427 static char* stringValued [] = { /* values are atoms */
428 /* font name components (see section 3.2 of the XLFD) */
439 /* other standard X font properties (see section 3.2 of the XLFD) */
442 "FULL_NAME", /* deprecated */
448 "RASTERIZER_VERSION",
450 /* other registered font properties (see the X.org Registry, sec. 15) */
451 "_ADOBE_POSTSCRIPT_FONTNAME",
453 /* unregistered font properties */
454 "CHARSET_COLLECTIONS",
466 void PrintProperty(XFontProp *prop)
471 XErrorHandler oldhandler = XSetErrorHandler(IgnoreError);
473 atom = XGetAtomName(dpy, prop->name);
477 (void)sprintf (atom, "No such atom = %ld", prop->name);
479 printf (" %s", atom);
481 /* Pad out to a column width of 22, but ensure there is always at
482 least one space between property name & value. */
483 for (i = strlen(atom); i < 21; i++) putchar (' ');
487 if (stringValued[i] == NULL) {
488 printf ("%ld\n", prop->card32);
491 if (strcmp(stringValued[i], atom) == 0) {
492 value = XGetAtomName(dpy, prop->card32);
494 printf ("%ld (expected string value)\n", prop->card32);
496 printf ("%s\n", value);
502 if (atom != nosuch) XFree (atom);
503 XSetErrorHandler (oldhandler);
508 ComputeFontType(XFontStruct *fs)
511 Bool char_cell = True;
514 Atom awatom = XInternAtom (dpy, "AVERAGE_WIDTH", False);
516 printf (" font type:\t\t");
517 if (fs->min_bounds.width != fs->max_bounds.width) {
518 printf ("Proportional (min and max widths not equal)\n");
523 for (i = 0; i < fs->n_properties; i++) {
524 if (fs->properties[i].name == awatom &&
525 (fs->max_bounds.width * 10) != fs->properties[i].card32) {
527 reason = "font width not equal to AVERAGE_WIDTH";
534 for (i = fs->min_char_or_byte2, cs = fs->per_char;
535 i <= fs->max_char_or_byte2; i++, cs++) {
536 if (cs->width == 0) continue;
537 if (cs->width != fs->max_bounds.width) {
538 /* this shouldn't happen since we checked above */
539 printf ("Proportional (characters not all the same width)\n");
544 if (!(cs->width <= cs->lbearing &&
545 cs->lbearing <= cs->rbearing &&
546 cs->rbearing <= 0)) {
548 reason = "ink outside bounding box";
551 if (!(0 <= cs->lbearing &&
552 cs->lbearing <= cs->rbearing &&
553 cs->rbearing <= cs->width)) {
555 reason = "ink outside bounding box";
558 if (!(cs->ascent <= fs->ascent &&
559 cs->descent <= fs->descent)) {
561 reason = "characters not all same ascent or descent";
567 printf ("%s", char_cell ? "Character Cell" : "Monospaced");
568 if (reason) printf (" (%s)", reason);
576 print_character_metrics(register XFontStruct *info)
578 register XCharStruct *pc = info->per_char;
582 printf (" character metrics:\n");
583 saven = ((info->min_byte1 << 8) | info->min_char_or_byte2);
584 for (j = info->min_byte1; j <= info->max_byte1; j++) {
586 for (i = info->min_char_or_byte2; i <= info->max_char_or_byte2; i++) {
587 char *s = XKeysymToString ((KeySym) n);
588 printf ("\t0x%02x%02x (%u)\t%4d %4d %4d %4d %4d 0x%04x %s\n",
589 j, i, n, pc->width, pc->lbearing,
590 pc->rbearing, pc->ascent, pc->descent, pc->attributes,
600 void do_query_font (Display *dpy, char *name)
603 register XFontStruct *info = XLoadQueryFont (dpy, name);
606 fprintf (stderr, "%s: unable to get info about font \"%s\"\n",
610 printf ("name: %s\n", name ? name : "(nil)");
611 printf (" direction:\t\t%s\n", ((info->direction == FontLeftToRight)
612 ? "left to right" : "right to left"));
613 printf (" indexing:\t\t%s\n",
614 ((info->min_byte1 == 0 && info->max_byte1 == 0) ? "linear" :
616 printf (" rows:\t\t\t0x%02x thru 0x%02x (%d thru %d)\n",
617 info->min_byte1, info->max_byte1,
618 info->min_byte1, info->max_byte1);
619 printf (" columns:\t\t0x%02x thru 0x%02x (%d thru %d)\n",
620 info->min_char_or_byte2, info->max_char_or_byte2,
621 info->min_char_or_byte2, info->max_char_or_byte2);
622 printf (" all chars exist:\t%s\n",
623 (info->all_chars_exist) ? "yes" : "no");
624 printf (" default char:\t\t0x%04x (%d)\n",
625 info->default_char, info->default_char);
626 printf (" ascent:\t\t%d\n", info->ascent);
627 printf (" descent:\t\t%d\n", info->descent);
628 ComputeFontType (info);
629 printf (" bounds:\t\t%s", bounds_metrics_title);
630 PrintBounds ("min", &info->min_bounds);
631 PrintBounds ("max", &info->max_bounds);
632 if (info->per_char && long_list >= L_VERYLONG)
633 print_character_metrics (info);
634 printf (" properties:\t\t%d\n", info->n_properties);
635 for (i = 0; i < info->n_properties; i++)
636 PrintProperty (&info->properties[i]);
639 XFreeFontInfo (NULL, info, 1);