showfont.c revision 1a28b98b
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;
1701a28b98bSmrg    unsigned int   offset = 0;
1710ed7c580Smrg    unsigned char *glyphs;
1720ed7c580Smrg    FSOffset   *offsets;
1730ed7c580Smrg    int         scanpad;
1740ed7c580Smrg    FSChar2b    chars[2];
1750ed7c580Smrg    int         num_chars;
1760ed7c580Smrg
1770ed7c580Smrg    if (show_all) {
1780ed7c580Smrg	num_chars = 0;
1790ed7c580Smrg    } else {
1800ed7c580Smrg	chars[0] = first;
1810ed7c580Smrg	chars[1] = last;
1820ed7c580Smrg	num_chars = 2;
1830ed7c580Smrg    }
1840ed7c580Smrg    FSQueryXExtents16(svr, fid, True, chars, num_chars, &extents);
1850ed7c580Smrg
1860ed7c580Smrg    if (!extents_only) {
1871a28b98bSmrg	FSBitmapFormat format = make_format();
1881a28b98bSmrg	int err = FSQueryXBitmaps16(svr, fid, format, True, chars, num_chars,
1891a28b98bSmrg				    &offsets, &glyphs);
1900ed7c580Smrg
1910ed7c580Smrg	if (err != FSSuccess) {
1920ed7c580Smrg	    fprintf(stderr, "QueryGlyphs failed\n");
1930ed7c580Smrg	    exit(1);
1940ed7c580Smrg	}
1950ed7c580Smrg    }
1960ed7c580Smrg
1970ed7c580Smrg    scanpad = scan_pad >> 3;
1980ed7c580Smrg
1991a28b98bSmrg    for (int row = (int)first.high; row <= (int)last.high; row++) {
2001a28b98bSmrg	int start = first.low + (row << 8);
2011a28b98bSmrg	for (int col = (int)first.low; col <= (int)last.low; col++) {
2020ed7c580Smrg	    int		bottom,
2030ed7c580Smrg			bpr,
2040ed7c580Smrg	        	charwidth;
2050ed7c580Smrg
2061a28b98bSmrg	    int ch = ((row - (int)first.high)
2071a28b98bSmrg                      * ((int)last.low - (int)first.low + 1))
2080ed7c580Smrg		+ (col - (int)first.low);
2091a28b98bSmrg	    int temp_ch = start + (col - (int)first.low);
2100ed7c580Smrg	    printf("char #%d", temp_ch);
2110ed7c580Smrg	    if ((temp_ch >= 0) && (temp_ch <= 127) && isprint(temp_ch))
2120ed7c580Smrg		printf(" '%c'\n", (char) (temp_ch));
2130ed7c580Smrg	    else
2140ed7c580Smrg		printf(" 0x%04x\n", temp_ch);
2150ed7c580Smrg	    show_char_info(&extents[ch]);
2160ed7c580Smrg	    if (extents_only)
2170ed7c580Smrg		continue;
2180ed7c580Smrg	    if (offset != offsets[ch].position)
2190ed7c580Smrg		fprintf(stderr, "offset mismatch: expected %d, got %d\n",
2200ed7c580Smrg			offset, offsets[ch].position);
2210ed7c580Smrg	    switch (bitmap_format) {
2220ed7c580Smrg	    case BitmapFormatImageRectMin:
2230ed7c580Smrg		bottom = extents[ch].descent + extents[ch].ascent;
2240ed7c580Smrg		charwidth = extents[ch].right - extents[ch].left;
2250ed7c580Smrg		break;
2260ed7c580Smrg	    case BitmapFormatImageRectMaxWidth:
2270ed7c580Smrg		bottom = extents[ch].descent + extents[ch].ascent;
2280ed7c580Smrg		charwidth = hdr->max_bounds.right - hdr->min_bounds.left;
2290ed7c580Smrg		break;
2300ed7c580Smrg	    case BitmapFormatImageRectMax:
2310ed7c580Smrg		bottom = hdr->max_bounds.ascent +
2320ed7c580Smrg		    hdr->max_bounds.descent;
2330ed7c580Smrg		charwidth = hdr->max_bounds.right - hdr->min_bounds.left;
2340ed7c580Smrg		break;
2350ed7c580Smrg	    default:
2360ed7c580Smrg		bottom = 0;
2370ed7c580Smrg		charwidth = 0;
2380ed7c580Smrg	    }
2390ed7c580Smrg
2400ed7c580Smrg	    if (extents[ch].left == 0 &&
2410ed7c580Smrg		extents[ch].right == 0 &&
2420ed7c580Smrg		extents[ch].width == 0 &&
2430ed7c580Smrg		extents[ch].ascent == 0 &&
2440ed7c580Smrg		extents[ch].descent == 0) {
2450ed7c580Smrg		printf ("Nonexistent character\n");
2460ed7c580Smrg		continue;
2470ed7c580Smrg	    }
2480ed7c580Smrg	    bpr = GLWIDTHBYTESPADDED(charwidth, scanpad);
2491a28b98bSmrg	    if (offsets[ch].length != (unsigned)(bottom * bpr)) {
2500ed7c580Smrg		fprintf (stderr,
2510ed7c580Smrg			 "length mismatch: expected %d (%dx%d), got %d\n",
2520ed7c580Smrg			 bottom * bpr, bpr, bottom, offsets[ch].length);
2530ed7c580Smrg	    }
2540ed7c580Smrg	    offset = offsets[ch].position;
2551a28b98bSmrg	    for (int r = 0; r < bottom; r++) {
2560ed7c580Smrg		unsigned char *rowp = glyphs + offset;
2570ed7c580Smrg
2581a28b98bSmrg		for (int b = 0; b < charwidth; b++) {
2590ed7c580Smrg		    putchar((rowp[b >> 3] &
2600ed7c580Smrg			     (1 << (7 - (b & 7)))) ? '#' : '-');
2610ed7c580Smrg		}
2620ed7c580Smrg		putchar('\n');
2630ed7c580Smrg		offset += bpr;
2640ed7c580Smrg	    }
2650ed7c580Smrg	}
2660ed7c580Smrg    }
2670ed7c580Smrg    FSFree((char *) extents);
2680ed7c580Smrg    if (!extents_only) {
2690ed7c580Smrg	FSFree((char *) offsets);
2700ed7c580Smrg	FSFree((char *) glyphs);
2710ed7c580Smrg    }
2720ed7c580Smrg}
2730ed7c580Smrg
2740ed7c580Smrgstatic void
2750ed7c580Smrgshow_props(
2760ed7c580Smrg    FSPropInfo *pi,
2770ed7c580Smrg    FSPropOffset *po,
2780ed7c580Smrg    unsigned char *pd)
2790ed7c580Smrg{
2800ed7c580Smrg    char        buf[512];
2810ed7c580Smrg    int         num_props;
2820ed7c580Smrg
2830ed7c580Smrg    num_props = pi->num_offsets;
2841a28b98bSmrg    for (int i = 0; i < num_props; i++, po++) {
2850ed7c580Smrg	strncpy(buf, (char *) (pd + po->name.position), po->name.length);
2860ed7c580Smrg	buf[po->name.length] = '\0';
2870ed7c580Smrg	printf("%s\t", buf);
2880ed7c580Smrg	switch (po->type) {
2890ed7c580Smrg	case PropTypeString:
2900ed7c580Smrg	    strncpy(buf, (char *)(pd + po->value.position), po->value.length);
2910ed7c580Smrg	    buf[po->value.length] = '\0';
2920ed7c580Smrg	    printf("%s\n", buf);
2930ed7c580Smrg	    break;
2940ed7c580Smrg	case PropTypeUnsigned:
2950ed7c580Smrg	    printf("%lu\n", (unsigned long) po->value.position);
2960ed7c580Smrg	    break;
2970ed7c580Smrg	case PropTypeSigned:
2980ed7c580Smrg	    printf("%ld\n", (long) po->value.position);
2990ed7c580Smrg	    break;
3000ed7c580Smrg	default:
3010ed7c580Smrg	    fprintf(stderr, "bogus property\n");
3020ed7c580Smrg	    break;
3030ed7c580Smrg	}
3040ed7c580Smrg    }
3050ed7c580Smrg}
3060ed7c580Smrg
3070ed7c580Smrgstatic void
3080ed7c580Smrgshow_info(
3090ed7c580Smrg    Font        fid,
3100ed7c580Smrg    FSXFontInfoHeader *hdr,
3110ed7c580Smrg    FSChar2b   *first,
3120ed7c580Smrg    FSChar2b   *last)
3130ed7c580Smrg{
3140ed7c580Smrg    FSPropInfo  pi;
3150ed7c580Smrg    FSPropOffset *po;
3160ed7c580Smrg    unsigned char *pd;
3170ed7c580Smrg
3180ed7c580Smrg    FSQueryXInfo(svr, fid, hdr, &pi, &po, &pd);
3190ed7c580Smrg    printf("Direction: %s\n", (hdr->draw_direction == LeftToRightDrawDirection)
3200ed7c580Smrg	   ? "Left to Right" : "Right to Left");
3210ed7c580Smrg    *first = hdr->char_range.min_char;
3220ed7c580Smrg    *last = hdr->char_range.max_char;
3230ed7c580Smrg    printf("Range:	%d to %d\n",
3240ed7c580Smrg	   first->low + (first->high << 8),
3250ed7c580Smrg	   last->low + (last->high << 8));
3260ed7c580Smrg    if (hdr->flags & FontInfoAllCharsExist)
3270ed7c580Smrg	printf("All chars exist\n");
3280ed7c580Smrg    printf("Default char: %d\n",
3290ed7c580Smrg	   hdr->default_char.low + (hdr->default_char.high << 8));
3300ed7c580Smrg    printf("Min bounds: \n");
3310ed7c580Smrg    show_char_info(&hdr->min_bounds);
3320ed7c580Smrg    printf("Max bounds: \n");
3330ed7c580Smrg    show_char_info(&hdr->max_bounds);
3340ed7c580Smrg    printf("Font Ascent: %d  Font Descent: %d\n",
3350ed7c580Smrg	   hdr->font_ascent, hdr->font_descent);
3360ed7c580Smrg
3370ed7c580Smrg    if (!no_props)
3380ed7c580Smrg	show_props(&pi, po, pd);
3390ed7c580Smrg    FSFree((char *) po);
3400ed7c580Smrg    FSFree((char *) pd);
3410ed7c580Smrg}
3420ed7c580Smrg
3430ed7c580Smrgstatic void
3440ed7c580Smrgusage(const char *msg)
3450ed7c580Smrg{
3460ed7c580Smrg    if (msg)
3470ed7c580Smrg	fprintf(stderr, "%s: %s\n", ProgramName, msg);
3480ed7c580Smrg    fprintf(stderr,
3490ed7c580Smrg	    "Usage: %s [-server servername] [-extents_only] [-noprops]\n"
3500ed7c580Smrg	    "       [-lsb] [-msb] [-LSB] [-MSB] [-unit #] [-pad #] [-bitmap_pad value]\n"
3510ed7c580Smrg	    "       [-start first_char] [-end last_char] -fn fontname\n"
3520ed7c580Smrg	    "   or: %s -version\n",
3530ed7c580Smrg	    ProgramName, ProgramName);
3540ed7c580Smrg    exit(1);
3550ed7c580Smrg}
3560ed7c580Smrg
3570ed7c580Smrgint
3580ed7c580Smrgmain(int argc, char **argv)
3590ed7c580Smrg{
3600ed7c580Smrg    const char *servername = "localhost:7100"; /* -server: font server name */
3610ed7c580Smrg    char *fontname = NULL; /* -fn: font name */
3620ed7c580Smrg    Font        fid,
3630ed7c580Smrg                dummy;
3640ed7c580Smrg    FSBitmapFormat format;
3650ed7c580Smrg    FSBitmapFormatMask fmask;
3660ed7c580Smrg
3670ed7c580Smrg    ProgramName = argv[0];
3680ed7c580Smrg
3691a28b98bSmrg    for (int i = 1; i < argc; i++) {
3700ed7c580Smrg	if (!strncmp(argv[i], "-se", 3)) {
3710ed7c580Smrg	    if (++i < argc)
3720ed7c580Smrg		servername = argv[i];
3730ed7c580Smrg	    else
3740ed7c580Smrg		usage("-server requires an argument");
3750ed7c580Smrg	} else if (!strncmp(argv[i], "-ext", 4)) {
3760ed7c580Smrg	    extents_only = True;
3770ed7c580Smrg	} else if (!strncmp(argv[i], "-noprops", 7)) {
3780ed7c580Smrg	    no_props = True;
3790ed7c580Smrg	} else if (!strncmp(argv[i], "-lsb", 4)) {
3800ed7c580Smrg	    bitorder = LSBFirst;
3810ed7c580Smrg	} else if (!strncmp(argv[i], "-msb", 4)) {
3820ed7c580Smrg	    bitorder = MSBFirst;
3830ed7c580Smrg	} else if (!strncmp(argv[i], "-LSB", 4)) {
3840ed7c580Smrg	    byteorder = LSBFirst;
3850ed7c580Smrg	} else if (!strncmp(argv[i], "-MSB", 4)) {
3860ed7c580Smrg	    byteorder = MSBFirst;
3870ed7c580Smrg	} else if (!strncmp(argv[i], "-p", 2)) {
3880ed7c580Smrg	    if (++i < argc)
3890ed7c580Smrg		scan_pad = atoi(argv[i]);
3900ed7c580Smrg	    else
3910ed7c580Smrg		usage("-pad requires an argument");
3920ed7c580Smrg	} else if (!strncmp(argv[i], "-u", 2)) {
3930ed7c580Smrg	    if (++i < argc)
3940ed7c580Smrg		scan_unit = atoi(argv[i]);
3950ed7c580Smrg	    else
3960ed7c580Smrg		usage("-unit requires an argument");
3970ed7c580Smrg	} else if (!strncmp(argv[i], "-b", 2)) {
3980ed7c580Smrg	    if (++i < argc)
3990ed7c580Smrg		bitmap_pad = atoi(argv[i]);
4000ed7c580Smrg	    else
4010ed7c580Smrg		usage("-bitmap_pad requires an argument");
4020ed7c580Smrg	} else if (!strncmp(argv[i], "-st", 3)) {
4030ed7c580Smrg	    if (++i < argc)
4040ed7c580Smrg		first_ch = atoi(argv[i]);
4050ed7c580Smrg	    else
4060ed7c580Smrg		usage("-start requires an argument");
4070ed7c580Smrg	} else if (!strncmp(argv[i], "-e", 2)) {
4080ed7c580Smrg	    if (++i < argc)
4090ed7c580Smrg		end_ch = atoi(argv[i]);
4100ed7c580Smrg	    else
4110ed7c580Smrg		usage("-end requires an argument");
4120ed7c580Smrg	} else if (!strncmp(argv[i], "-f", 2)) {
4130ed7c580Smrg	    if (++i < argc)
4140ed7c580Smrg		fontname = argv[i];
4150ed7c580Smrg	    else
4160ed7c580Smrg		usage("-fn requires an argument");
4170ed7c580Smrg	} else if (!strcmp(argv[i], "-version")) {
4180ed7c580Smrg	    puts(PACKAGE_STRING);
4190ed7c580Smrg	    exit(0);
4200ed7c580Smrg	} else {
4210ed7c580Smrg	    char msg[128];
4220ed7c580Smrg	    snprintf(msg, sizeof(msg), "unrecognized argument: %s", argv[i]);
4230ed7c580Smrg	    usage(msg);
4240ed7c580Smrg	}
4250ed7c580Smrg    }
4260ed7c580Smrg    if (fontname == NULL)
4270ed7c580Smrg	usage("no fontname specified");
4280ed7c580Smrg
4290ed7c580Smrg    if (first_ch != 0 && end_ch != ~0 && end_ch < first_ch) {
4300ed7c580Smrg	fprintf(stderr,
4310ed7c580Smrg		"bad character range -- end (%d) is less than start (%d)\n",
4320ed7c580Smrg		end_ch, first_ch);
4330ed7c580Smrg	exit(1);
4340ed7c580Smrg    }
4350ed7c580Smrg    if ((svr = FSOpenServer(servername)) == NULL) {
4360ed7c580Smrg	if(FSServerName(servername) != NULL)
4370ed7c580Smrg		fprintf(stderr, "can't open server \"%s\"\n", FSServerName(servername));
4380ed7c580Smrg	else
4390ed7c580Smrg		fprintf(stderr, "can't open server \"\"\n");
4400ed7c580Smrg	exit(1);
4410ed7c580Smrg    }
4420ed7c580Smrg    format = make_format();
4430ed7c580Smrg    fmask = (BitmapFormatMaskByte | BitmapFormatMaskBit |
4440ed7c580Smrg	     BitmapFormatMaskImageRectangle | BitmapFormatMaskScanLinePad |
4450ed7c580Smrg	     BitmapFormatMaskScanLineUnit);
4460ed7c580Smrg    fid = FSOpenBitmapFont(svr, format, fmask, fontname, &dummy);
4470ed7c580Smrg    if (fid) {
4481a28b98bSmrg	Bool	    show_all = True;
4491a28b98bSmrg	FSChar2b    first,
4501a28b98bSmrg		    last;
4511a28b98bSmrg	FSXFontInfoHeader hdr;
4521a28b98bSmrg
4530ed7c580Smrg	printf("opened font %s\n", fontname);
4540ed7c580Smrg	show_info(fid, &hdr, &first, &last);
4550ed7c580Smrg	if (first_ch != 0 &&
4561a28b98bSmrg            ((unsigned)first_ch >= (first.low + ((unsigned)first.high << 8)))) {
4570ed7c580Smrg	    first.low = first_ch & 0xff;
4580ed7c580Smrg	    first.high = first_ch >> 8;
4590ed7c580Smrg	    show_all = False;
4600ed7c580Smrg	}
4610ed7c580Smrg	if (end_ch != ~0 &&
4621a28b98bSmrg            ((unsigned)end_ch <= (last.low + ((unsigned)last.high << 8)))) {
4630ed7c580Smrg	    last.low = end_ch & 0xff;
4640ed7c580Smrg	    last.high = end_ch >> 8;
4650ed7c580Smrg	    show_all = False;
4660ed7c580Smrg	}
4670ed7c580Smrg	/* make sure the range is legal */
4680ed7c580Smrg	if ((first.high > last.high) || (first.high == last.high &&
4690ed7c580Smrg					 first.low > last.low)) {
4700ed7c580Smrg	    last = first;
4710ed7c580Smrg	    fprintf(stderr,
4721a28b98bSmrg		    "adjusting range -- specified first char is after end\n");
4730ed7c580Smrg	}
4740ed7c580Smrg	show_glyphs(fid, &hdr, show_all, first, last);
4750ed7c580Smrg	FSCloseFont(svr, fid);
4760ed7c580Smrg    } else {
4770ed7c580Smrg	fprintf(stderr, "couldn't get font %s\n", fontname);
4780ed7c580Smrg	FSCloseServer(svr);
4790ed7c580Smrg	exit(1);
4800ed7c580Smrg    }
4810ed7c580Smrg    FSCloseServer(svr);
4820ed7c580Smrg    exit(0);
4830ed7c580Smrg}
484