showfont.c revision 0ed7c580
10ed7c580Smrg/*
20ed7c580Smrg * Copyright 1990 Network Computing Devices;
30ed7c580Smrg * Portions Copyright 1987 by Digital Equipment Corporation
40ed7c580Smrg *
50ed7c580Smrg * Permission to use, copy, modify, distribute, and sell this software and
60ed7c580Smrg * its documentation for any purpose is hereby granted without fee, provided
70ed7c580Smrg * that the above copyright notice appear in all copies and that both that
80ed7c580Smrg * copyright notice and this permission notice appear in supporting
90ed7c580Smrg * documentation, and that the names of Network Computing Devices or Digital
100ed7c580Smrg * not be used in advertising or publicity pertaining to distribution
110ed7c580Smrg * of the software without specific, written prior permission.
120ed7c580Smrg *
130ed7c580Smrg * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
140ed7c580Smrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
150ed7c580Smrg * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL NETWORK COMPUTING DEVICES
160ed7c580Smrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
170ed7c580Smrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
180ed7c580Smrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
190ed7c580Smrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
200ed7c580Smrg * THIS SOFTWARE.
210ed7c580Smrg */
220ed7c580Smrg/*
230ed7c580Smrg
240ed7c580SmrgCopyright (c) 1987  X Consortium
250ed7c580Smrg
260ed7c580SmrgPermission is hereby granted, free of charge, to any person obtaining
270ed7c580Smrga copy of this software and associated documentation files (the
280ed7c580Smrg"Software"), to deal in the Software without restriction, including
290ed7c580Smrgwithout limitation the rights to use, copy, modify, merge, publish,
300ed7c580Smrgdistribute, sublicense, and/or sell copies of the Software, and to
310ed7c580Smrgpermit persons to whom the Software is furnished to do so, subject to
320ed7c580Smrgthe following conditions:
330ed7c580Smrg
340ed7c580SmrgThe above copyright notice and this permission notice shall be included
350ed7c580Smrgin all copies or substantial portions of the Software.
360ed7c580Smrg
370ed7c580SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
380ed7c580SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
390ed7c580SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
400ed7c580SmrgIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
410ed7c580SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
420ed7c580SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
430ed7c580SmrgOTHER DEALINGS IN THE SOFTWARE.
440ed7c580Smrg
450ed7c580SmrgExcept as contained in this notice, the name of the X Consortium shall
460ed7c580Smrgnot be used in advertising or otherwise to promote the sale, use or
470ed7c580Smrgother dealings in this Software without prior written authorization
480ed7c580Smrgfrom the X Consortium.
490ed7c580Smrg
500ed7c580Smrg*/
510ed7c580Smrg
520ed7c580Smrg#ifdef HAVE_CONFIG_H
530ed7c580Smrg# include "config.h"
540ed7c580Smrg#endif
550ed7c580Smrg
560ed7c580Smrg#include	<stdio.h>
570ed7c580Smrg#include	<stdlib.h>
580ed7c580Smrg#include	<string.h>
590ed7c580Smrg#include	<ctype.h>
600ed7c580Smrg#include	<X11/fonts/FSlib.h>
610ed7c580Smrg
620ed7c580Smrg/*
630ed7c580Smrg * the equivalent of showsnf
640ed7c580Smrg */
650ed7c580Smrg
660ed7c580Smrg#define	GLWIDTHBYTESPADDED(bits,nbytes) \
670ed7c580Smrg	((nbytes) == 1 ? (((bits)+7)>>3)        /* pad to 1 byte */ \
680ed7c580Smrg	:(nbytes) == 2 ? ((((bits)+15)>>3)&~1)  /* pad to 2 bytes */ \
690ed7c580Smrg	:(nbytes) == 4 ? ((((bits)+31)>>3)&~3)  /* pad to 4 bytes */ \
700ed7c580Smrg	:(nbytes) == 8 ? ((((bits)+63)>>3)&~7)  /* pad to 8 bytes */ \
710ed7c580Smrg	: 0)
720ed7c580Smrg
730ed7c580Smrgstatic int	   byteorder = MSBFirst; /* -LSB or -MSB */
740ed7c580Smrgstatic int	   bitorder = MSBFirst; /* -lsb or -msb */
750ed7c580Smrgstatic int	   bitmap_pad = 0;	/* -bitmap_pad: ImageRect bitmap format */
760ed7c580Smrgstatic int	   scan_pad = 8;	/* -pad: ScanlinePad */
770ed7c580Smrgstatic int	   scan_unit = 8;	/* -unit: ScanlineUnit */
780ed7c580Smrgstatic int	   first_ch = 0;	/* -start: first character*/
790ed7c580Smrgstatic int	   end_ch = ~0;	/* -end: end character */
800ed7c580Smrgstatic const char *ProgramName;
810ed7c580Smrgstatic Bool	   no_props = False;	/* -noprops: don't show font properties */
820ed7c580Smrgstatic Bool	   extents_only = False; /* -extents_only */
830ed7c580Smrg
840ed7c580Smrgstatic FSServer	  *svr;
850ed7c580Smrg
860ed7c580Smrg/* set from bitmap_pad to ImageRectMin, ImageMaxWidth, or ImageMax */
870ed7c580Smrgstatic int	   bitmap_format;
880ed7c580Smrg
890ed7c580Smrgstatic FSBitmapFormat
900ed7c580Smrgmake_format(void)
910ed7c580Smrg{
920ed7c580Smrg    FSBitmapFormat format;
930ed7c580Smrg
940ed7c580Smrg    format = 0;
950ed7c580Smrg    /* set up format */
960ed7c580Smrg    switch (scan_pad) {
970ed7c580Smrg    case 8:
980ed7c580Smrg	format |= BitmapFormatScanlinePad8;
990ed7c580Smrg	break;
1000ed7c580Smrg    case 16:
1010ed7c580Smrg	format |= BitmapFormatScanlinePad16;
1020ed7c580Smrg	break;
1030ed7c580Smrg    case 32:
1040ed7c580Smrg	format |= BitmapFormatScanlinePad32;
1050ed7c580Smrg	break;
1060ed7c580Smrg    case 64:
1070ed7c580Smrg	format |= BitmapFormatScanlinePad64;
1080ed7c580Smrg	break;
1090ed7c580Smrg    default:
1100ed7c580Smrg	fprintf(stderr, "bogus scanline pad value: %d\n", scan_pad);
1110ed7c580Smrg	break;
1120ed7c580Smrg    }
1130ed7c580Smrg    switch (scan_unit) {
1140ed7c580Smrg    case 8:
1150ed7c580Smrg	format |= BitmapFormatScanlineUnit8;
1160ed7c580Smrg	break;
1170ed7c580Smrg    case 16:
1180ed7c580Smrg	format |= BitmapFormatScanlineUnit16;
1190ed7c580Smrg	break;
1200ed7c580Smrg    case 32:
1210ed7c580Smrg	format |= BitmapFormatScanlineUnit32;
1220ed7c580Smrg	break;
1230ed7c580Smrg    case 64:
1240ed7c580Smrg	format |= BitmapFormatScanlineUnit64;
1250ed7c580Smrg	break;
1260ed7c580Smrg    default:
1270ed7c580Smrg	fprintf(stderr, "bogus scanline unit value: %d\n", scan_unit);
1280ed7c580Smrg	break;
1290ed7c580Smrg    }
1300ed7c580Smrg    switch (bitmap_pad) {
1310ed7c580Smrg    case 0:
1320ed7c580Smrg	bitmap_format = BitmapFormatImageRectMin;
1330ed7c580Smrg	break;
1340ed7c580Smrg    case 1:
1350ed7c580Smrg	bitmap_format = BitmapFormatImageRectMaxWidth;
1360ed7c580Smrg	break;
1370ed7c580Smrg    case 2:
1380ed7c580Smrg	bitmap_format = BitmapFormatImageRectMax;
1390ed7c580Smrg	break;
1400ed7c580Smrg    default:
1410ed7c580Smrg	fprintf(stderr, "bogus bitmap pad value: %d\n", bitmap_pad);
1420ed7c580Smrg	break;
1430ed7c580Smrg    }
1440ed7c580Smrg    format |= bitmap_format;
1450ed7c580Smrg
1460ed7c580Smrg    format |= (bitorder == MSBFirst) ? BitmapFormatBitOrderMSB :
1470ed7c580Smrg	BitmapFormatBitOrderLSB;
1480ed7c580Smrg    format |= (byteorder == MSBFirst) ? BitmapFormatByteOrderMSB :
1490ed7c580Smrg	BitmapFormatByteOrderLSB;
1500ed7c580Smrg
1510ed7c580Smrg    return format;
1520ed7c580Smrg}
1530ed7c580Smrg
1540ed7c580Smrgstatic void
1550ed7c580Smrgshow_char_info(FSXCharInfo *ci)
1560ed7c580Smrg{
1570ed7c580Smrg    printf("Left: %-3d    Right: %-3d    Ascent: %-3d    Descent: %-3d    Width: %d\n",
1580ed7c580Smrg	   ci->left, ci->right, ci->ascent, ci->descent, ci->width);
1590ed7c580Smrg}
1600ed7c580Smrg
1610ed7c580Smrgstatic void
1620ed7c580Smrgshow_glyphs(
1630ed7c580Smrg    Font        fid,
1640ed7c580Smrg    FSXFontInfoHeader *hdr,
1650ed7c580Smrg    Bool        show_all,
1660ed7c580Smrg    FSChar2b    first,
1670ed7c580Smrg    FSChar2b    last)
1680ed7c580Smrg{
1690ed7c580Smrg    FSXCharInfo *extents;
1700ed7c580Smrg    int         err,
1710ed7c580Smrg                ch,
1720ed7c580Smrg		start;
1730ed7c580Smrg    int         offset = 0;
1740ed7c580Smrg    unsigned char *glyphs;
1750ed7c580Smrg    FSOffset   *offsets;
1760ed7c580Smrg    int         scanpad;
1770ed7c580Smrg    int         r,
1780ed7c580Smrg                b;
1790ed7c580Smrg    FSBitmapFormat format;
1800ed7c580Smrg    FSChar2b    chars[2];
1810ed7c580Smrg    int         num_chars;
1820ed7c580Smrg    int		row,
1830ed7c580Smrg		col,
1840ed7c580Smrg		temp_ch;
1850ed7c580Smrg
1860ed7c580Smrg    if (show_all) {
1870ed7c580Smrg	num_chars = 0;
1880ed7c580Smrg    } else {
1890ed7c580Smrg	chars[0] = first;
1900ed7c580Smrg	chars[1] = last;
1910ed7c580Smrg	num_chars = 2;
1920ed7c580Smrg    }
1930ed7c580Smrg    FSQueryXExtents16(svr, fid, True, chars, num_chars, &extents);
1940ed7c580Smrg
1950ed7c580Smrg    if (!extents_only) {
1960ed7c580Smrg	format = make_format();
1970ed7c580Smrg	err = FSQueryXBitmaps16(svr, fid, format, True, chars, num_chars,
1980ed7c580Smrg				&offsets, &glyphs);
1990ed7c580Smrg
2000ed7c580Smrg	if (err != FSSuccess) {
2010ed7c580Smrg	    fprintf(stderr, "QueryGlyphs failed\n");
2020ed7c580Smrg	    exit(1);
2030ed7c580Smrg	}
2040ed7c580Smrg    }
2050ed7c580Smrg
2060ed7c580Smrg    scanpad = scan_pad >> 3;
2070ed7c580Smrg
2080ed7c580Smrg    for (row = (int)first.high; row <= (int)last.high; row++) {
2090ed7c580Smrg	start = first.low + (row << 8);
2100ed7c580Smrg	for (col = (int)first.low; col <= (int)last.low; col++) {
2110ed7c580Smrg	    int		bottom,
2120ed7c580Smrg			bpr,
2130ed7c580Smrg	        	charwidth;
2140ed7c580Smrg
2150ed7c580Smrg	    ch = ((row - (int)first.high)
2160ed7c580Smrg		  * ((int)last.low - (int)first.low + 1))
2170ed7c580Smrg		+ (col - (int)first.low);
2180ed7c580Smrg	    temp_ch = start + (col - (int)first.low);
2190ed7c580Smrg	    printf("char #%d", temp_ch);
2200ed7c580Smrg	    if ((temp_ch >= 0) && (temp_ch <= 127) && isprint(temp_ch))
2210ed7c580Smrg		printf(" '%c'\n", (char) (temp_ch));
2220ed7c580Smrg	    else
2230ed7c580Smrg		printf(" 0x%04x\n", temp_ch);
2240ed7c580Smrg	    show_char_info(&extents[ch]);
2250ed7c580Smrg	    if (extents_only)
2260ed7c580Smrg		continue;
2270ed7c580Smrg	    if (offset != offsets[ch].position)
2280ed7c580Smrg		fprintf(stderr, "offset mismatch: expected %d, got %d\n",
2290ed7c580Smrg			offset, offsets[ch].position);
2300ed7c580Smrg	    switch (bitmap_format) {
2310ed7c580Smrg	    case BitmapFormatImageRectMin:
2320ed7c580Smrg		bottom = extents[ch].descent + extents[ch].ascent;
2330ed7c580Smrg		charwidth = extents[ch].right - extents[ch].left;
2340ed7c580Smrg		break;
2350ed7c580Smrg	    case BitmapFormatImageRectMaxWidth:
2360ed7c580Smrg		bottom = extents[ch].descent + extents[ch].ascent;
2370ed7c580Smrg		charwidth = hdr->max_bounds.right - hdr->min_bounds.left;
2380ed7c580Smrg		break;
2390ed7c580Smrg	    case BitmapFormatImageRectMax:
2400ed7c580Smrg		bottom = hdr->max_bounds.ascent +
2410ed7c580Smrg		    hdr->max_bounds.descent;
2420ed7c580Smrg		charwidth = hdr->max_bounds.right - hdr->min_bounds.left;
2430ed7c580Smrg		break;
2440ed7c580Smrg	    default:
2450ed7c580Smrg		bottom = 0;
2460ed7c580Smrg		charwidth = 0;
2470ed7c580Smrg	    }
2480ed7c580Smrg
2490ed7c580Smrg	    if (extents[ch].left == 0 &&
2500ed7c580Smrg		extents[ch].right == 0 &&
2510ed7c580Smrg		extents[ch].width == 0 &&
2520ed7c580Smrg		extents[ch].ascent == 0 &&
2530ed7c580Smrg		extents[ch].descent == 0) {
2540ed7c580Smrg		printf ("Nonexistent character\n");
2550ed7c580Smrg		continue;
2560ed7c580Smrg	    }
2570ed7c580Smrg	    bpr = GLWIDTHBYTESPADDED(charwidth, scanpad);
2580ed7c580Smrg	    if (offsets[ch].length != bottom * bpr) {
2590ed7c580Smrg		fprintf (stderr,
2600ed7c580Smrg			 "length mismatch: expected %d (%dx%d), got %d\n",
2610ed7c580Smrg			 bottom * bpr, bpr, bottom, offsets[ch].length);
2620ed7c580Smrg	    }
2630ed7c580Smrg	    offset = offsets[ch].position;
2640ed7c580Smrg	    for (r = 0; r < bottom; r++) {
2650ed7c580Smrg		unsigned char *rowp = glyphs + offset;
2660ed7c580Smrg
2670ed7c580Smrg		for (b = 0; b < charwidth; b++) {
2680ed7c580Smrg		    putchar((rowp[b >> 3] &
2690ed7c580Smrg			     (1 << (7 - (b & 7)))) ? '#' : '-');
2700ed7c580Smrg		}
2710ed7c580Smrg		putchar('\n');
2720ed7c580Smrg		offset += bpr;
2730ed7c580Smrg	    }
2740ed7c580Smrg	}
2750ed7c580Smrg    }
2760ed7c580Smrg    FSFree((char *) extents);
2770ed7c580Smrg    if (!extents_only) {
2780ed7c580Smrg	FSFree((char *) offsets);
2790ed7c580Smrg	FSFree((char *) glyphs);
2800ed7c580Smrg    }
2810ed7c580Smrg}
2820ed7c580Smrg
2830ed7c580Smrgstatic void
2840ed7c580Smrgshow_props(
2850ed7c580Smrg    FSPropInfo *pi,
2860ed7c580Smrg    FSPropOffset *po,
2870ed7c580Smrg    unsigned char *pd)
2880ed7c580Smrg{
2890ed7c580Smrg    int         i;
2900ed7c580Smrg    char        buf[512];
2910ed7c580Smrg    int         num_props;
2920ed7c580Smrg
2930ed7c580Smrg    num_props = pi->num_offsets;
2940ed7c580Smrg    for (i = 0; i < num_props; i++, po++) {
2950ed7c580Smrg	strncpy(buf, (char *) (pd + po->name.position), po->name.length);
2960ed7c580Smrg	buf[po->name.length] = '\0';
2970ed7c580Smrg	printf("%s\t", buf);
2980ed7c580Smrg	switch (po->type) {
2990ed7c580Smrg	case PropTypeString:
3000ed7c580Smrg	    strncpy(buf, (char *)(pd + po->value.position), po->value.length);
3010ed7c580Smrg	    buf[po->value.length] = '\0';
3020ed7c580Smrg	    printf("%s\n", buf);
3030ed7c580Smrg	    break;
3040ed7c580Smrg	case PropTypeUnsigned:
3050ed7c580Smrg	    printf("%lu\n", (unsigned long) po->value.position);
3060ed7c580Smrg	    break;
3070ed7c580Smrg	case PropTypeSigned:
3080ed7c580Smrg	    printf("%ld\n", (long) po->value.position);
3090ed7c580Smrg	    break;
3100ed7c580Smrg	default:
3110ed7c580Smrg	    fprintf(stderr, "bogus property\n");
3120ed7c580Smrg	    break;
3130ed7c580Smrg	}
3140ed7c580Smrg    }
3150ed7c580Smrg}
3160ed7c580Smrg
3170ed7c580Smrgstatic void
3180ed7c580Smrgshow_info(
3190ed7c580Smrg    Font        fid,
3200ed7c580Smrg    FSXFontInfoHeader *hdr,
3210ed7c580Smrg    FSChar2b   *first,
3220ed7c580Smrg    FSChar2b   *last)
3230ed7c580Smrg{
3240ed7c580Smrg    FSPropInfo  pi;
3250ed7c580Smrg    FSPropOffset *po;
3260ed7c580Smrg    unsigned char *pd;
3270ed7c580Smrg
3280ed7c580Smrg    FSQueryXInfo(svr, fid, hdr, &pi, &po, &pd);
3290ed7c580Smrg    printf("Direction: %s\n", (hdr->draw_direction == LeftToRightDrawDirection)
3300ed7c580Smrg	   ? "Left to Right" : "Right to Left");
3310ed7c580Smrg    *first = hdr->char_range.min_char;
3320ed7c580Smrg    *last = hdr->char_range.max_char;
3330ed7c580Smrg    printf("Range:	%d to %d\n",
3340ed7c580Smrg	   first->low + (first->high << 8),
3350ed7c580Smrg	   last->low + (last->high << 8));
3360ed7c580Smrg    if (hdr->flags & FontInfoAllCharsExist)
3370ed7c580Smrg	printf("All chars exist\n");
3380ed7c580Smrg    printf("Default char: %d\n",
3390ed7c580Smrg	   hdr->default_char.low + (hdr->default_char.high << 8));
3400ed7c580Smrg    printf("Min bounds: \n");
3410ed7c580Smrg    show_char_info(&hdr->min_bounds);
3420ed7c580Smrg    printf("Max bounds: \n");
3430ed7c580Smrg    show_char_info(&hdr->max_bounds);
3440ed7c580Smrg    printf("Font Ascent: %d  Font Descent: %d\n",
3450ed7c580Smrg	   hdr->font_ascent, hdr->font_descent);
3460ed7c580Smrg
3470ed7c580Smrg    if (!no_props)
3480ed7c580Smrg	show_props(&pi, po, pd);
3490ed7c580Smrg    FSFree((char *) po);
3500ed7c580Smrg    FSFree((char *) pd);
3510ed7c580Smrg}
3520ed7c580Smrg
3530ed7c580Smrgstatic void
3540ed7c580Smrgusage(const char *msg)
3550ed7c580Smrg{
3560ed7c580Smrg    if (msg)
3570ed7c580Smrg	fprintf(stderr, "%s: %s\n", ProgramName, msg);
3580ed7c580Smrg    fprintf(stderr,
3590ed7c580Smrg	    "Usage: %s [-server servername] [-extents_only] [-noprops]\n"
3600ed7c580Smrg	    "       [-lsb] [-msb] [-LSB] [-MSB] [-unit #] [-pad #] [-bitmap_pad value]\n"
3610ed7c580Smrg	    "       [-start first_char] [-end last_char] -fn fontname\n"
3620ed7c580Smrg	    "   or: %s -version\n",
3630ed7c580Smrg	    ProgramName, ProgramName);
3640ed7c580Smrg    exit(1);
3650ed7c580Smrg}
3660ed7c580Smrg
3670ed7c580Smrgint
3680ed7c580Smrgmain(int argc, char **argv)
3690ed7c580Smrg{
3700ed7c580Smrg    const char *servername = "localhost:7100"; /* -server: font server name */
3710ed7c580Smrg    char *fontname = NULL; /* -fn: font name */
3720ed7c580Smrg    int         i;
3730ed7c580Smrg    Font        fid,
3740ed7c580Smrg                dummy;
3750ed7c580Smrg    FSBitmapFormat format;
3760ed7c580Smrg    FSBitmapFormatMask fmask;
3770ed7c580Smrg    FSChar2b    first,
3780ed7c580Smrg                last;
3790ed7c580Smrg    FSXFontInfoHeader hdr;
3800ed7c580Smrg    Bool        show_all = True;
3810ed7c580Smrg
3820ed7c580Smrg    ProgramName = argv[0];
3830ed7c580Smrg
3840ed7c580Smrg    for (i = 1; i < argc; i++) {
3850ed7c580Smrg	if (!strncmp(argv[i], "-se", 3)) {
3860ed7c580Smrg	    if (++i < argc)
3870ed7c580Smrg		servername = argv[i];
3880ed7c580Smrg	    else
3890ed7c580Smrg		usage("-server requires an argument");
3900ed7c580Smrg	} else if (!strncmp(argv[i], "-ext", 4)) {
3910ed7c580Smrg	    extents_only = True;
3920ed7c580Smrg	} else if (!strncmp(argv[i], "-noprops", 7)) {
3930ed7c580Smrg	    no_props = True;
3940ed7c580Smrg	} else if (!strncmp(argv[i], "-lsb", 4)) {
3950ed7c580Smrg	    bitorder = LSBFirst;
3960ed7c580Smrg	} else if (!strncmp(argv[i], "-msb", 4)) {
3970ed7c580Smrg	    bitorder = MSBFirst;
3980ed7c580Smrg	} else if (!strncmp(argv[i], "-LSB", 4)) {
3990ed7c580Smrg	    byteorder = LSBFirst;
4000ed7c580Smrg	} else if (!strncmp(argv[i], "-MSB", 4)) {
4010ed7c580Smrg	    byteorder = MSBFirst;
4020ed7c580Smrg	} else if (!strncmp(argv[i], "-p", 2)) {
4030ed7c580Smrg	    if (++i < argc)
4040ed7c580Smrg		scan_pad = atoi(argv[i]);
4050ed7c580Smrg	    else
4060ed7c580Smrg		usage("-pad requires an argument");
4070ed7c580Smrg	} else if (!strncmp(argv[i], "-u", 2)) {
4080ed7c580Smrg	    if (++i < argc)
4090ed7c580Smrg		scan_unit = atoi(argv[i]);
4100ed7c580Smrg	    else
4110ed7c580Smrg		usage("-unit requires an argument");
4120ed7c580Smrg	} else if (!strncmp(argv[i], "-b", 2)) {
4130ed7c580Smrg	    if (++i < argc)
4140ed7c580Smrg		bitmap_pad = atoi(argv[i]);
4150ed7c580Smrg	    else
4160ed7c580Smrg		usage("-bitmap_pad requires an argument");
4170ed7c580Smrg	} else if (!strncmp(argv[i], "-st", 3)) {
4180ed7c580Smrg	    if (++i < argc)
4190ed7c580Smrg		first_ch = atoi(argv[i]);
4200ed7c580Smrg	    else
4210ed7c580Smrg		usage("-start requires an argument");
4220ed7c580Smrg	} else if (!strncmp(argv[i], "-e", 2)) {
4230ed7c580Smrg	    if (++i < argc)
4240ed7c580Smrg		end_ch = atoi(argv[i]);
4250ed7c580Smrg	    else
4260ed7c580Smrg		usage("-end requires an argument");
4270ed7c580Smrg	} else if (!strncmp(argv[i], "-f", 2)) {
4280ed7c580Smrg	    if (++i < argc)
4290ed7c580Smrg		fontname = argv[i];
4300ed7c580Smrg	    else
4310ed7c580Smrg		usage("-fn requires an argument");
4320ed7c580Smrg	} else if (!strcmp(argv[i], "-version")) {
4330ed7c580Smrg	    puts(PACKAGE_STRING);
4340ed7c580Smrg	    exit(0);
4350ed7c580Smrg	} else {
4360ed7c580Smrg	    char msg[128];
4370ed7c580Smrg	    snprintf(msg, sizeof(msg), "unrecognized argument: %s", argv[i]);
4380ed7c580Smrg	    usage(msg);
4390ed7c580Smrg	}
4400ed7c580Smrg    }
4410ed7c580Smrg    if (fontname == NULL)
4420ed7c580Smrg	usage("no fontname specified");
4430ed7c580Smrg
4440ed7c580Smrg    if (first_ch != 0 && end_ch != ~0 && end_ch < first_ch) {
4450ed7c580Smrg	fprintf(stderr,
4460ed7c580Smrg		"bad character range -- end (%d) is less than start (%d)\n",
4470ed7c580Smrg		end_ch, first_ch);
4480ed7c580Smrg	exit(1);
4490ed7c580Smrg    }
4500ed7c580Smrg    if ((svr = FSOpenServer(servername)) == NULL) {
4510ed7c580Smrg	if(FSServerName(servername) != NULL)
4520ed7c580Smrg		fprintf(stderr, "can't open server \"%s\"\n", FSServerName(servername));
4530ed7c580Smrg	else
4540ed7c580Smrg		fprintf(stderr, "can't open server \"\"\n");
4550ed7c580Smrg	exit(1);
4560ed7c580Smrg    }
4570ed7c580Smrg    format = make_format();
4580ed7c580Smrg    fmask = (BitmapFormatMaskByte | BitmapFormatMaskBit |
4590ed7c580Smrg	     BitmapFormatMaskImageRectangle | BitmapFormatMaskScanLinePad |
4600ed7c580Smrg	     BitmapFormatMaskScanLineUnit);
4610ed7c580Smrg    fid = FSOpenBitmapFont(svr, format, fmask, fontname, &dummy);
4620ed7c580Smrg    if (fid) {
4630ed7c580Smrg	printf("opened font %s\n", fontname);
4640ed7c580Smrg	show_info(fid, &hdr, &first, &last);
4650ed7c580Smrg	if (first_ch != 0 &&
4660ed7c580Smrg		((unsigned)first_ch >= (first.low + (first.high << 8)))) {
4670ed7c580Smrg	    first.low = first_ch & 0xff;
4680ed7c580Smrg	    first.high = first_ch >> 8;
4690ed7c580Smrg	    show_all = False;
4700ed7c580Smrg	}
4710ed7c580Smrg	if (end_ch != ~0 &&
4720ed7c580Smrg		((unsigned)end_ch <= (last.low + (last.high << 8)))) {
4730ed7c580Smrg	    last.low = end_ch & 0xff;
4740ed7c580Smrg	    last.high = end_ch >> 8;
4750ed7c580Smrg	    show_all = False;
4760ed7c580Smrg	}
4770ed7c580Smrg	/* make sure the range is legal */
4780ed7c580Smrg	if ((first.high > last.high) || (first.high == last.high &&
4790ed7c580Smrg					 first.low > last.low)) {
4800ed7c580Smrg	    last = first;
4810ed7c580Smrg	    fprintf(stderr,
4820ed7c580Smrg		    "adjusting range -- specifed first char is after end\n");
4830ed7c580Smrg	}
4840ed7c580Smrg	show_glyphs(fid, &hdr, show_all, first, last);
4850ed7c580Smrg	FSCloseFont(svr, fid);
4860ed7c580Smrg    } else {
4870ed7c580Smrg	fprintf(stderr, "couldn't get font %s\n", fontname);
4880ed7c580Smrg	FSCloseServer(svr);
4890ed7c580Smrg	exit(1);
4900ed7c580Smrg    }
4910ed7c580Smrg    FSCloseServer(svr);
4920ed7c580Smrg    exit(0);
4930ed7c580Smrg}
494