[comp.sources.x] v03i068: xface -- displays USENIX FaceSaver pictures

argv@island.uu.net (Dan Heller) (04/07/89)

Submitted-by: Jeff Michaud <michaud@decvax.dec.com>
Posting-number: Volume 3, Issue 68
Archive-name: xface/part01

[ I had to modify xface.c to compile on my sun3/60.  strchr() was used
  rather than index().  X11/Xos.h defines strchr for index(), but not
  the other way around.  I didn't find anymore sys-v-isms, so BSD machines
  shouldn't have too much trouble.  I couldn't really test this because
  I don't have any facesaver images.  --argv ]

#!/bin/sh
# This is a shell archive file. Remove everything above this line
# to unbundle. chmod +x "thisfile", then run it: e.g. % thisfile
# SHAR archive format.  Archive created Thu Apr 6 16:03:12 PDT 1989
# file contains: 
#	AUTHOR
#	Imakefile
#	Makefile
#	README
#	patchlevel.h
#	xface.c
#	xface.h
#	xface.man
#	xfaceload.c
echo x - AUTHOR
sed 's/^X//' > AUTHOR <<'+END+OF+AUTHOR'
XAuthor: Jeff Michaud (michaud@decvax.dec.com), DEC
X
XAdapted from xgif by,
X    John Bradley (bradley@cis.upenn.edu), University of Pennsylvania.
+END+OF+AUTHOR
echo '-rw-rw-r--  1 argv          144 Apr  6 15:45 AUTHOR    (as sent)'
chmod u=rw,g=rw,o=r AUTHOR
ls -l AUTHOR
echo x - Imakefile
sed 's/^X//' > Imakefile <<'+END+OF+Imakefile'
XLOCAL_LIBRARIES = $(XLIB)
X
XOBJS = \
X	xface.o \
X	xfaceload.o
X
XSRCS = \
X	xface.c \
X	xfaceload.c
X
XComplexProgramTarget(xface)
X
+END+OF+Imakefile
echo '-rw-rw-r--  1 argv          124 Apr  6 15:45 Imakefile    (as sent)'
chmod u=rw,g=rw,o=r Imakefile
ls -l Imakefile
echo x - Makefile
sed 's/^X//' > Makefile <<'+END+OF+Makefile'
X# Makefile generated by imake - do not edit!
X# $XConsortium: imake.c,v 1.37 88/10/08 20:08:30 jim Exp $
X#
X# The cpp used on this machine replaces all newlines and multiple tabs and
X# spaces in a macro expansion with a single space.  Imake tries to compensate
X# for this, but is not always successful.
X#
X
X###########################################################################
X# X Window System Makefile generated from template file Imake.tmpl
X# $XConsortium: Imake.tmpl,v 1.91 88/10/23 22:37:10 jim Exp $
X#
X# Do not change the body of the imake template file.  Server-specific
X# parameters may be set in the appropriate .macros file; site-specific
X# parameters (but shared by all servers) may be set in site.def.  If you
X# make any changes, you'll need to rebuild the makefiles using
X# "make World" (at best) or "make Makefile; make Makefiles" (at least) in
X# the top level directory.
X#
X# If your C preprocessor doesn't define any unique symbols, you'll need
X# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
X# "make Makefile", "make Makefiles", or "make World").
X#
X# If you absolutely can't get imake to work, you'll need to set the
X# variables at the top of each Makefile as well as the dependencies at the
X# bottom (makedepend will do this automatically).
X#
X
X###########################################################################
X# platform-specific configuration parameters - edit Sun.macros to change
X
X# platform:  $XConsortium: Sun.macros,v 1.52 88/10/23 11:00:55 jim Exp $
X# operating system:   SunOS 3.4
X
XBOOTSTRAPCFLAGS =
X             AS = as
X             CC = cc
X            CPP = /lib/cpp
X             LD = ld
X           LINT = lint
X        INSTALL = install
X           TAGS = ctags
X             RM = rm -f
X             MV = mv
X             LN = ln -s
X         RANLIB = ranlib
XRANLIBINSTFLAGS = -t
X             AR = ar clq
X             LS = ls
X       LINTOPTS = -xz
X    LINTLIBFLAG = -C
X           MAKE = make
XSTD_CPP_DEFINES =
X    STD_DEFINES =
X
X###########################################################################
X# site-specific configuration parameters - edit site.def to change
X
X# site:  $XConsortium: site.def,v 1.16 88/10/12 10:30:24 jim Exp $
X
X###########################################################################
X# definitions common to all Makefiles - do not edit
X
X          SHELL =  /bin/sh
X
X        DESTDIR = /usr
X      USRLIBDIR = $(DESTDIR)/lib
X         BINDIR = $(DESTDIR)/bin/X11
X         INCDIR = $(DESTDIR)/include
X         ADMDIR = $(DESTDIR)/usr/adm
X         LIBDIR = $(USRLIBDIR)/X11
X     LINTLIBDIR = $(USRLIBDIR)/lint
X        FONTDIR = $(LIBDIR)/fonts
X       XINITDIR = $(LIBDIR)/xinit
X         XDMDIR = $(LIBDIR)/xdm
X         UWMDIR = $(LIBDIR)/uwm
X         AWMDIR = $(LIBDIR)/awm
X         TWMDIR = $(LIBDIR)/twm
X          DTDIR = $(LIBDIR)/dt
X        MANPATH = /usr/man
X  MANSOURCEPATH = $(MANPATH)/man
X         MANDIR = $(MANSOURCEPATH)n
X      LIBMANDIR = $(MANSOURCEPATH)n3
X    XAPPLOADDIR = $(LIBDIR)/app-defaults
X
X   INSTBINFLAGS = -m 0755
X   INSTUIDFLAGS = -m 4755
X   INSTLIBFLAGS = -m 0664
X   INSTINCFLAGS = -m 0444
X   INSTMANFLAGS = -m 0444
X   INSTAPPFLAGS = -m 0444
X  INSTKMEMFLAGS = -m 4755
X        FCFLAGS = -t
X    CDEBUGFLAGS = -O
X
X        PATHSEP = /
X         DEPEND = $(BINDIR)/makedepend
X          IMAKE = $(BINDIR)/imake
X            RGB = $(LIBDIR)/rgb
X             FC = $(BINDIR)/bdftosnf
X      MKFONTDIR = $(BINDIR)/mkfontdir
X      MKDIRHIER = $(BINDIR)/mkdirhier.sh
X
X         CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES)
X      LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT
X        LDFLAGS = $(CDEBUGFLAGS) -L$(USRLIBDIR) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES)
X
X       IRULESRC = $(LIBDIR)/imake.includes
X
X   EXTENSIONLIB = $(USRLIBDIR)/libext.a
X           XLIB = $(USRLIBDIR)/libX11.a
X         XMULIB = $(USRLIBDIR)/libXmu.a
X        OLDXLIB = $(USRLIBDIR)/liboldX.a
X       XTOOLLIB = $(USRLIBDIR)/libXt.a
X         XAWLIB = $(USRLIBDIR)/libXaw.a
X       LINTXLIB = $(USRLIBDIR)/lint/llib-lX11.ln
X        LINTXMU = $(USRLIBDIR)/lint/llib-lXmu.ln
X      LINTXTOOL = $(USRLIBDIR)/lint/llib-lXt.ln
X        LINTXAW = $(USRLIBDIR)/lint/llib-lXaw.ln
X       INCLUDES = -I$(INCDIR)
X      MACROFILE = Sun.macros
X   ICONFIGFILES = $(IRULESRC)/Imake.tmpl \
X			$(IRULESRC)/$(MACROFILE) $(IRULESRC)/site.def
X  IMAKE_DEFINES =
X      IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl -I$(NEWTOP)$(IRULESRC) \
X			-s Makefile $(IMAKE_DEFINES)
X         RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \
X			.emacs_* tags TAGS make.log MakeOut
X
X###########################################################################
X# rules:  $XConsortium: Imake.rules,v 1.71 88/10/23 22:46:34 jim Exp $
X
X###########################################################################
X# start of Imakefile
X
XLOCAL_LIBRARIES = $(XLIB)
X
XOBJS = \
X	xface.o \
X	xfaceload.o
X
XSRCS = \
X	xface.c \
X	xfaceload.c
X
X PROGRAM = xface
X
Xall:: xface
X
Xxface: $(OBJS) $(LOCAL_LIBRARIES)
X	$(RM) $@
X	$(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES)
X
Xrelink::
X	$(RM) $(PROGRAM)
X	$(MAKE) $(MFLAGS) $(PROGRAM)
X
Xinstall:: xface
X	$(INSTALL) -c $(INSTALLFLAGS) xface $(BINDIR)
X
Xinstall.man:: xface.man
X	$(INSTALL) -c $(INSTMANFLAGS) xface.man $(MANDIR)/xface.n
X
Xdepend:: $(DEPEND)
X
Xdepend::
X	$(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS)
X
X$(DEPEND):
X	@echo "making $@"; \
X	cd $(DEPENDSRC); $(MAKE)
X
Xclean::
X	$(RM) $(PROGRAM)
X
X###########################################################################
X# Imake.tmpl common rules for all Makefiles - do not edit
X
Xemptyrule::
X
Xclean::
X	$(RM_CMD) \#*
X
XMakefile:: $(IMAKE)
X
XMakefile:: Imakefile \
X	$(IRULESRC)/Imake.tmpl \
X	$(IRULESRC)/Imake.rules \
X	$(IRULESRC)/site.def \
X	$(IRULESRC)/$(MACROFILE)
X	-@if [ -f Makefile ]; then \
X	echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
X	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
X	else exit 0; fi
X	$(IMAKE_CMD) -DTOPDIR=$(TOP)
X
X$(IMAKE):
X	@echo "making $@"; \
X	cd $(IMAKESRC); $(MAKE) BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS)
X
Xtags::
X	$(TAGS) -w *.[ch]
X	$(TAGS) -xw *.[ch] > TAGS
X
X###########################################################################
X# empty rules for directories that do not have SUBDIRS - do not edit
X
Xinstall::
X	@echo "install done"
X
Xinstall.man::
X	@echo "install.man done"
X
XMakefiles::
X
X###########################################################################
X# dependencies generated by makedepend
X
X# DO NOT DELETE
X
X#xface.o: xface.h /usr/include/stdio.h /usr/include/math.h /usr/include/ctype.h
X#xface.o: /global/include/X11/Xos.h /usr/include/sys/types.h
X#xface.o: /usr/include/sys/sysmacros.h /usr/include/strings.h
X#xface.o: /usr/include/sys/file.h /usr/include/sys/fcntl.h
X#xface.o: /usr/include/sys/time.h /usr/include/sys/time.h
X#xface.o: /global/include/X11/Xlib.h /global/include/X11/X.h
X#xface.o: /global/include/X11/Xutil.h
X#xfaceload.o: xface.h /usr/include/stdio.h /usr/include/math.h
X#xfaceload.o: /usr/include/ctype.h /global/include/X11/Xos.h
X#xfaceload.o: /usr/include/sys/types.h /usr/include/sys/sysmacros.h
X#xfaceload.o: /usr/include/strings.h /usr/include/sys/file.h
X#xfaceload.o: /usr/include/sys/fcntl.h /usr/include/sys/time.h
X#xfaceload.o: /usr/include/sys/time.h /global/include/X11/Xlib.h
X#xfaceload.o: /global/include/X11/X.h /global/include/X11/Xutil.h
+END+OF+Makefile
echo '-rw-rw-r--  1 argv         7314 Apr  6 15:47 Makefile    (as sent)'
chmod u=rw,g=rw,o=r Makefile
ls -l Makefile
echo x - README
sed 's/^X//' > README <<'+END+OF+README'
Xxface displays the USENIX FaceSaver Project pictures on an X11 display
X(requires at least an 8-plane server, but note that it hasn't been
Xtested at on anything greater than 8 planes either).
X
XThe complete archive of 1,616 faces taken by the FaceSaver project lives
Xon uunet.uu.net in the directory faces.
X
XAuthor: Jeff Michuad - michaud@decvax.dec.com
XAdapted from xgif, by John Bradley  -  bradley@cis.upenn.edu
+END+OF+README
echo '-rw-rw-r--  1 argv          413 Apr  6 15:45 README    (as sent)'
chmod u=rw,g=rw,o=r README
ls -l README
echo x - patchlevel.h
sed 's/^X//' > patchlevel.h <<'+END+OF+patchlevel.h'
X#define PATCHLEVEL 3
+END+OF+patchlevel.h
echo '-rw-rw-r--  1 argv           21 Apr  6 15:45 patchlevel.h    (as sent)'
chmod u=rw,g=rw,o=r patchlevel.h
ls -l patchlevel.h
echo x - xface.c
sed 's/^X//' > xface.c <<'+END+OF+xface.c'
X/*
X * xface.c - displays FaceSaver UUNET pictures on an X11 display
X *
X *  Author:    Jeff Michaud, Digital Equipment Corporation
X *		  (michaud@decvax.dec.com)
X *
X *  Adapted from xgif by:
X *  	     John Bradley, University of Pennsylvania
X *                (bradley@cis.upenn.edu)
X */
X
X#define MAIN
X#include "xface.h"
X
X/*******************************************/
Xmain(argc, argv)
X    int   argc;
X    char *argv[];
X/*******************************************/
X{
X    int        i;
X    char      *display, *geom, *fname;
X    XEvent     event;
X
X    cmd = argv[0];
X    display = geom = fname = NULL;
X    expImage = NULL;
X
X    expand = 1;  strip = 0;  nostrip = 0;
X
X    /*********************Options*********************/
X
X    for (i = 1; i < argc; i++) {
X        char *strind;
X
X        if (!strncmp(argv[i],"-g",2)) {		/* geometry */
X            i++;
X            geom = argv[i];
X            continue;
X            }
X
X        if (argv[i][0] == '=') {		/* old-style geometry */
X            geom = argv[i];
X            continue;
X            }
X
X        if (!strncmp(argv[i],"-d",2)) {		/* display */
X            i++;
X            display = argv[i];
X            continue;
X            }
X
X        strind = index(argv[i], ':');		/* old-style display */
X        if(strind != NULL) {
X            display = argv[i];
X            continue;
X            }
X
X        if (!strcmp(argv[i],"-e")) {		/* expand */
X            i++;
X            expand=atoi(argv[i]);
X            continue;
X            }
X
X         if (!strcmp(argv[i],"-s")) {          /* strip */
X             i++;
X             strip=atoi(argv[i]);
X             continue;
X             }
X
X        if (!strcmp(argv[i],"-ns")) {		/* nostrip */
X            nostrip++;
X            continue;
X            }
X
X        if (argv[i][0] != '-') {		/* the file name */
X            fname = argv[i];
X            continue;
X            }
X
X        Syntax(cmd);
X    }
X
X    if (fname==NULL) fname="-";
X    if (expand<1 || expand>MAXEXPAND) Syntax(cmd);
X    if (strip<0 || strip>7) Syntax(cmd);
X
X    /*****************************************************/
X
X    /* Open up the display. */
X
X    if ( (theDisp=XOpenDisplay(display)) == NULL) {
X        fprintf(stderr, "%s: Can't open display\n",argv[0]);
X        exit(1);
X        }
X
X    theScreen = DefaultScreen(theDisp);
X    theCmap   = DefaultColormap(theDisp, theScreen);
X    rootW     = RootWindow(theDisp,theScreen);
X    theGC     = DefaultGC(theDisp,theScreen);
X    fcol      = WhitePixel(theDisp,theScreen);
X    bcol      = BlackPixel(theDisp,theScreen);
X    theVisual = DefaultVisual(theDisp,theScreen);
X
X    dispcells = DisplayCells(theDisp, theScreen);
X    if (dispcells<=2) 
X        FatalError("This program requires a color display, pref. 8 bits.");
X
X
X    /****************** Open/Read the File  *****************/
X    LoadFACE(fname);
X    iWIDE = theImage->width;  iHIGH = theImage->height;
X
X    eWIDE = iWIDE * expand;  eHIGH = iHIGH * expand;
X    if (eWIDE > DisplayWidth(theDisp,theScreen)) 
X        eWIDE = DisplayWidth(theDisp,theScreen);
X    if (eHIGH > DisplayHeight(theDisp,theScreen)) 
X        eHIGH = DisplayHeight(theDisp,theScreen);
X
X    /**************** Create/Open X Resources ***************/
X    if ((mfinfo = XLoadQueryFont(theDisp,"variable"))==NULL)
X       FatalError("couldn't open 'variable' font\n");
X    mfont=mfinfo->fid;
X    XSetFont(theDisp,theGC,mfont);
X    XSetForeground(theDisp,theGC,fcol);
X    XSetBackground(theDisp,theGC,bcol);
X
X    CreateMainWindow(cmd,geom,argc,argv);
X    Resize(eWIDE,eHIGH);
X
X    XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
X                               | StructureNotifyMask);
X    XMapWindow(theDisp,mainW);
X
X    /**************** Main loop *****************/
X    while (1) {
X        XNextEvent(theDisp, &event);
X        HandleEvent(&event);
X        }
X}
X
X
X
X/****************/
XHandleEvent(event)
X    XEvent *event;
X/****************/
X{
X    switch (event->type) {
X        case Expose: {
X            XExposeEvent *exp_event = (XExposeEvent *) event;
X
X            if (exp_event->window==mainW) 
X                DrawWindow(exp_event->x,exp_event->y,
X                           exp_event->width, exp_event->height);
X            }
X            break;
X
X        case KeyPress: {
X            XKeyEvent *key_event = (XKeyEvent *) event;
X            char buf[128];
X            KeySym ks;
X            XComposeStatus status;
X
X            XLookupString(key_event,buf,128,&ks,&status);
X            if (buf[0]=='q' || buf[0]=='Q') Quit();
X            }
X            break;
X
X        case ConfigureNotify: {
X            XConfigureEvent *conf_event = (XConfigureEvent *) event;
X
X            if (conf_event->window == mainW && 
X                 (conf_event->width != eWIDE || conf_event->height != eHIGH))
X                Resize(conf_event->width, conf_event->height);
X            }
X            break;
X
X
X        case CirculateNotify:
X        case MapNotify:
X        case DestroyNotify:
X        case GravityNotify:
X        case ReparentNotify:
X        case UnmapNotify:       break;
X
X        default:		/* ignore unexpected events */
X	  break;
X        }  /* end of switch */
X}
X
X
X/***********************************/
XSyntax()
X{
X    printf("Usage: %s filename [[-geometry] geom] [[-display] display]\n",cmd);
X    printf("       [-e 1..%d] [-s 0-7] [-ns]\n",MAXEXPAND);
X    exit(1);
X}
X
X
X/***********************************/
XFatalError (identifier)
X       char *identifier;
X{
X    fprintf(stderr, "%s: %s\n",cmd, identifier);
X    exit(-1);
X}
X
X
X/***********************************/
XQuit()
X{
X    exit(0);
X}
X
X
X/***********************************/
XDrawWindow(x,y,w,h)
X{
X    XPutImage(theDisp,mainW,theGC,expImage,x,y,x,y,w,h);
X}
X
X
X/***********************************/
XResize(w,h)
Xint w,h;
X{
X    int  ix,iy,ex,ey;
X    byte *ximag,*ilptr,*ipptr,*elptr,*epptr;
X    static char *rstr = "Resizing Image.  Please wait...";
X
X    /* warning:  this code'll only run machines where int=32-bits */
X
X    if (w==iWIDE && h==iHIGH) {		/* very special case */
X        if (expImage != theImage) {
X            if (expImage) XDestroyImage(expImage);
X            expImage = theImage;
X            eWIDE = iWIDE;  eHIGH = iHIGH;
X            }
X        }
X
X    else {				/* have to do some work */
X        /* if it's a big image, this'll take a while.  mention it */
X        if (w*h>(500*500)) {
X            XDrawImageString(theDisp,mainW,theGC,CENTERX(mfinfo,w/2,rstr),
X                  CENTERY(mfinfo,h/2),rstr, strlen(rstr));
X            XFlush(theDisp);
X            }
X
X	/* first, kill the old expImage, if one exists */
X	if (expImage && expImage != theImage) {
X            free(expImage->data);  expImage->data = NULL;
X            XDestroyImage(expImage);
X            }
X
X        /* create expImage of the appropriate size */
X        
X        eWIDE = w;  eHIGH = h;
X        ximag = (byte *) malloc(w*h);
X        expImage = XCreateImage(theDisp,theVisual,8,ZPixmap,0,ximag,
X                        eWIDE,eHIGH,8,eWIDE);
X
X        if (!ximag || !expImage) {
X            fprintf(stderr,"ERROR: unable to create a %dx%d image\n",w,h);
X            exit(0);
X            }
X
X        elptr = epptr = (byte *) expImage->data;
X
X        for (ey=0;  ey<eHIGH;  ey++, elptr+=eWIDE) {
X            iy = (iHIGH * ey) / eHIGH;
X            epptr = elptr;
X            ilptr = (byte *) theImage->data + (iy * iWIDE);
X            for (ex=0;  ex<eWIDE;  ex++,epptr++) {
X                ix = (iWIDE * ex) / eWIDE;
X                ipptr = ilptr + ix;
X                *epptr = *ipptr;
X                }
X            }
X        }
X}
X                
X
X/***********************************/
XCreateMainWindow(name,geom,argc,argv)
X    char *name,*geom,**argv;
X    int   argc;
X{
X    XSetWindowAttributes xswa;
X    unsigned int xswamask;
X    XSizeHints hints;
X    int i,x,y,w,h;
X
X    x=y=w=h=1;
X    i=XParseGeometry(geom,&x,&y,&w,&h);
X    if (i&WidthValue)  eWIDE = w;
X    if (i&HeightValue) eHIGH = h;
X
X    if (i&XValue || i&YValue) hints.flags = USPosition;  
X                         else hints.flags = PPosition;
X
X    hints.flags |= USSize;
X
X    if (i&XValue && i&XNegative) 
X        x = XDisplayWidth(theDisp,theScreen)-eWIDE-abs(x);
X    if (i&YValue && i&YNegative) 
X        y = XDisplayHeight(theDisp,theScreen)-eHIGH-abs(y);
X
X    hints.x=x;             hints.y=y;
X    hints.width  = eWIDE;  hints.height = eHIGH;
X    hints.max_width = DisplayWidth(theDisp,theScreen);
X    hints.max_height = DisplayHeight(theDisp,theScreen);
X    hints.flags |= PMaxSize;
X
X    xswa.background_pixel = bcol;
X    xswa.border_pixel     = fcol;
X    xswamask = CWBackPixel | CWBorderPixel;
X
X    mainW = XCreateWindow(theDisp,rootW,x,y,eWIDE,eHIGH,2,0,CopyFromParent,
X                          CopyFromParent, xswamask, &xswa);
X
X    XSetStandardProperties(theDisp,mainW,"xface","xface",None,
X                            argv,argc,&hints);
X
X    if (!mainW) FatalError("Can't open main window");
X
X}
X
X
+END+OF+xface.c
echo '-rw-rw-r--  1 argv         8848 Apr  6 15:53 xface.c    (as sent)'
chmod u=rw,g=rw,o=r xface.c
ls -l xface.c
echo x - xface.h
sed 's/^X//' > xface.h <<'+END+OF+xface.h'
X/*
X *  xface.h  -  header file for xface, but you probably already knew as much
X */
X
X
X#define REVDATE   "Rev: 2/13/89"
X#define MAXEXPAND 16
X
X/* include files */
X#include <stdio.h>
X#include <math.h>
X#include <ctype.h>
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X
X
X#ifdef vms
X#ifndef MAIN
X#define WHERE globaldef
X#else
X#define WHERE globalref
X#endif
X#else !vms
X#ifndef MAIN
X#define WHERE extern
X#else
X#define WHERE
X#endif
X#endif
X
Xtypedef unsigned char byte;
X
X#define CENTERX(f,x,str) ((x)-XTextWidth(f,str,strlen(str))/2)
X#define CENTERY(f,y) ((y)-((f->ascent+f->descent)/2)+f->ascent)
X
X
X/* X stuff */
XWHERE Display       *theDisp;
XWHERE int           theScreen, dispcells;
XWHERE Colormap      theCmap;
XWHERE Window        rootW, mainW;
XWHERE GC            theGC;
XWHERE unsigned long fcol,bcol;
XWHERE Font          mfont;
XWHERE XFontStruct   *mfinfo;
XWHERE Visual        *theVisual;
XWHERE XImage        *theImage, *expImage;
X
X/* global vars */
XWHERE int            iWIDE,iHIGH,eWIDE,eHIGH,expand,numcols,strip,nostrip;
XWHERE unsigned long  cols[256];
XWHERE XColor         defs[256];
XWHERE char          *cmd;
+END+OF+xface.h
echo '-rw-rw-r--  1 argv         1130 Apr  6 15:45 xface.h    (as sent)'
chmod u=rw,g=rw,o=r xface.h
ls -l xface.h
echo x - xface.man
sed 's/^X//' > xface.man <<'+END+OF+xface.man'
X.TH xface 1X
X.SH NAME
Xxface \- displays FaceSaver pictures on X11 displays
X.SH SYNTAX
X\fBxface\fP [\fIdisplay\fP] [ [-g] \fIgeometry\fP] [-e \fIexpansion\fP]
X[-s 0-7] [-ns] [\fIfilename\fP]
X.SH DESCRIPTION
X\fBxface\fP is an X11 program that displays FaceSaver pictures on an 8-plane 
Xdisplay.  
X.SH OPTIONS
XThe '-e' option allows you to expand the picture by an integer amount.  For
Xexample, viewing a 320x200 picture with an expansion factor of '2' will 
Xresult in a 640x400 picture, each pixel of which is a 2x2 block.
X.PP
XYou may also specify an expansion of the picture by specifying the size of
Xthe window in the \fIgeometry\fP option.  This also allows you specify 
Xnon-integer expansion factors, and different aspect ratios.  Example:  if
Xyou view a 320x200 picture, but specify a window size of 640x300, the picture
Xwill be expanded by a factor of two along the X-axis, but only by a factor of
X1.5 along the Y-axis.
X.PP
XIf you specify both the '-e' option and a window size (via \fIgeometry\fP), 
Xthe '-e' will be ignored.
X.PP
XThe '-s' option allows you specify the number of bits to strip off of the
Xresolution.  The theory runs like this:  if you have
X256 unique gray levels in your
Xface file, you will almost certainly be unable to allocate all of them on an
X8-plane display, as a couple colors will already be allocated for the
Xwindow manager, and such. Setting this option allows you to strip off the
Xlow \fIstrip\fP bits of the R,G,B entries in the colormap.  This will
Xhave the desired effect of making some of the (previously different) gray levels
Xthe SAME, and you will be able to allocate all the colors you need now.
X.PP
XYou shouldn't ever HAVE to set this option, because if the program is unable
Xto allocate the required colors, it will try again after incrementing
X\fIstrip\fP.  You can, however save some time, or alternately get neat
Xvisual effects by setting this option.
X.PP
XThe '-ns' option turns off the 'auto-strip' feature described above.  You
Xuse this to FORCE the program to use as many gray levels as possible.
XThe theory
Xworks like this:  if you have 256 unique gray levels in your face file, you will
Xprobably be able to allocate all but a few of them.  Rather than stripping off
Xbits, decreasing the resolution for the whole picture uniformly, the
X'nostrip' option makes the program set the few unallocatable colors equal to
Xthe 'closest' colors that were allocated.  This may cause nasty 'blotches'
Xon the picture.  Then again, it might not.  Only way to tell is to try both
Xwith and without the 'auto-strip' 'feature'.
X.PP
XAlso, it should be noted that if the optional \fIfilename\fP is not supplied,
Xthe program will read the picture from stdin.
X.SH LIMITATIONS
XYou'll require (at least) an 8-plane X11 display.
X.PP
XNote:  This program points out a bug in the X11R2 server for the IBM RT
XMegapel display.  This bug will occasionally cause the colors in a picture
Xto be wrong, but no 'unable to allocate' message will be printed by the
Xprogram.  (Essentially, the problem is a discrepancy between what the 
Xserver THINKS the colormap is, and what the colormap in the hardware 
XACTUALLY is.)
X.PP
X.SH AUTHOR
XJeff Michaud - michaud@decvax.dec.com
X.PP
XAdapted from xgif, by John Bradley  -  bradley@cis.upenn.edu, which was
Xbased (heavily) on gif2ras.c, by Patrick J. Naughton (naughton@wind.sun.com),
Xa program that converts GIF pictures to Sun Rasterfiles.
+END+OF+xface.man
echo '-rw-rw-r--  1 argv         3395 Apr  6 15:45 xface.man    (as sent)'
chmod u=rw,g=rw,o=r xface.man
ls -l xface.man
echo x - xfaceload.c
sed 's/^X//' > xfaceload.c <<'+END+OF+xfaceload.c'
X/*
X */
X
X#include "xface.h"
X
Xtypedef int boolean;
X
XFILE *fp;
X
Xint XC = 0, YC = 0,		/* Output X and Y coords of current pixel */
X    Width, Height,		/* image dimensions */
X    BytesPerScanline;		/* bytes per scanline in output raster */
X
Xboolean HasColormap = True;
Xboolean Verbose = False;
X
Xbyte *Image;			/* The result array */
X
Xbyte Red[256], Green[256], Blue[256], used[256];
Xint  numused = 0;
X
X
X/*****************************/
XLoadFACE(fname)
X  char *fname;
X/*****************************/
X{
X    int i;
X
X    if (strcmp(fname,"-")==0) { fp = stdin;  fname = "<stdin>"; }
X                         else fp = fopen(fname,"r");
X
X    if (!fp) FatalError("file not found");
X
X    init();
X
X    numcols = 256;
X
X    for( i = 0 ; i < 256 ; ++i )
X	used[i] = 0, Red[i] = Green[i] = Blue[i] = cols[i] = i;
X
X/* Allocate the X Image */
X    Image = (byte *) malloc(Width*Height);
X    if (!Image) FatalError("not enough memory for XImage");
X
X    theImage = XCreateImage(theDisp,theVisual,8,ZPixmap,0,Image,
X                         Width,Height,8,Width);
X    if (!theImage) FatalError("unable to create XImage");
X
X    BytesPerScanline = Width;
X
X    YC = Height - 1;
X
X    fillitup();
X
X    ColorDicking(fname);
X}
X
XAddToPixel(Index)
Xbyte Index;
X{
X
X    if (!used[Index]) { used[Index]=1;  numused++; }
X
X    if (YC>=0)
X        *(Image + YC * BytesPerScanline + XC) = Index;
X
X/* Update the X-coordinate, and if it overflows, update the Y-coordinate */
X
X    if (++XC == Width) {
X	XC = 0;
X	YC--;
X    }
X}
X
X
X
X/*************************/
XColorDicking(fname)
Xchar *fname;
X{
X    /* we've got the picture loaded, we know what colors are needed. get 'em */
X
X    register int   i,j;
X    static byte    lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
X    byte           lmask, *ptr;
X
X
X    if (!HasColormap) return;
X
X    /* Allocate the X colors for this picture */
X
X    if (nostrip)  {   /* nostrip was set.  try REAL hard to do it */
X        for (i=j=0; i<numcols; i++) {
X            if (used[i]) {
X                defs[i].red   = Red[i]<<8;
X                defs[i].green = Green[i]<<8;
X                defs[i].blue  = Blue[i]<<8;
X                defs[i].flags = DoRed | DoGreen | DoBlue;
X                if (!XAllocColor(theDisp,theCmap,&defs[i])) { 
X                    j++;  defs[i].pixel = 0xffff;
X                    }
X                cols[i] = defs[i].pixel;
X                }
X            }
X
X        if (j) {		/* failed to pull it off */
X            XColor ctab[256];
X            int    dc;
X
X            dc = (dispcells<256) ? dispcells : 256;
X
X            fprintf(stderr,"failed to allocate %d out of %d colors.  Trying extra hard.\n",j,numused);
X
X            /* read in the color table */
X            for (i=0; i<dc; i++) ctab[i].pixel = i;
X            XQueryColors(theDisp,theCmap,ctab,dc);
X                
X            /* run through the used colors.  any used color that has a pixel
X               value of 0xffff wasn't allocated.  for such colors, run through
X               the entire X colormap and pick the closest color */
X
X            for (i=0; i<numcols; i++)
X                if (used[i] && cols[i]==0xffff) {  /* an unallocated pixel */
X                    int d, mdist, close;
X                    unsigned long r,g,b;
X
X                    mdist = 100000;   close = -1;
X                    r =  Red[i];
X                    g =  Green[i];
X                    b =  Blue[i];
X                    for (j=0; j<dc; j++) {
X                        d = abs(r - (ctab[j].red>>8)) +
X                            abs(g - (ctab[j].green>>8)) +
X                            abs(b - (ctab[j].blue>>8));
X                        if (d<mdist) { mdist=d; close=j; }
X                        }
X                    if (close<0) FatalError("simply can't do it.  Sorry.");
X                    /*bcopy(&defs[close],&defs[i],sizeof(XColor));*/
X                    memcpy(&defs[close],&defs[i],sizeof(XColor));
X                    cols[i] = ctab[close].pixel;
X                    }
X            }	/* end 'failed to pull it off' */
X        }
X
X    else {          /* strip wasn't set, do the best auto-strip */
X        j = 0;
X        while (strip<8) {
X            lmask = lmasks[strip];
X            for (i=0; i<numcols; i++)
X                if (used[i]) {
X                    defs[i].red   = (Red[i]  &lmask)<<8;
X                    defs[i].green = (Green[i]&lmask)<<8;
X                    defs[i].blue  = (Blue[i] &lmask)<<8;
X                    defs[i].flags = DoRed | DoGreen | DoBlue;
X                    if (!XAllocColor(theDisp,theCmap,&defs[i])) break;
X                    cols[i] = defs[i].pixel;
X                    }
X
X            if (i<numcols) {		/* failed */
X                strip++;  j++;
X                for (i--; i>=0; i--)
X                    if (used[i]) XFreeColors(theDisp,theCmap,cols+i,1,0L);
X                }
X            else break;
X            }
X
X        if (j && strip<8)
X            fprintf(stderr,"%s:  %s stripped %d bits\n",cmd,fname,strip);
X
X        if (strip==8) {
X            fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n");
X            for (i=0; i<numcols; i++) cols[i]=i;
X            }
X        }
X
X    ptr = Image;
X    for (i=0; i<Height; i++)
X        for (j=0; j<Width; j++,ptr++) 
X            *ptr = (byte) cols[*ptr];
X}
X
X
X#define BUFSIZE	1024
X#define PIXSIZE	2
X#define MAXBPL	15	/* Max bytes per output line in resultant XBM */
X
Xchar line[BUFSIZE];
X
Xchar firstname[BUFSIZE];
Xchar lastname [BUFSIZE];
Xchar email    [BUFSIZE];
X
Xint depth;
Xint iwidth, iheight, idepth;
X
Xint totalpixels;
X
X/* Scan line Enum junk */
X    char *enum_ptr; /* local to enum routines */
Xvoid
Xinit_enum(buf)
X    char *buf;
X{
X    enum_ptr = buf;
X}
X
X/* Dithering junk */
Xchar **dithtab;
X
Xint
Xnext_enum(out)
X    char *out;
X{
X    if( enum_ptr[0] == '\n'  ||  enum_ptr[0] == '\0' )
X	return False;
X
X    strncpy(out, enum_ptr, PIXSIZE);
X    out[PIXSIZE] = '\0';
X    enum_ptr += PIXSIZE;
X
X    return True;
X}
X
Xinit()
X{
X    int nlcounter = 1;
X
X    fgets(line, BUFSIZE, fp);
X    sscanf(line, "%*s %s", firstname);
X
X    fgets(line, BUFSIZE, fp);
X    sscanf(line, "%*s %s", lastname);
X
X    fgets(line, BUFSIZE, fp);
X    sscanf(line, "%*s %s", email);
X
X    fgets(line, BUFSIZE, fp);
X    sscanf(line, "%*s %d %d %d", &Width, &Height, &depth);
X
X    fgets(line, BUFSIZE, fp);
X    sscanf(line, "%*s %d %d %d", &iwidth, &iheight, &idepth);
X
X    fgets(line, BUFSIZE, fp);
X
X    totalpixels = Width * Height;
X}
X
Xfillitup()
X{
X    while( fgets(line, BUFSIZE, fp) != NULL ) {
X	char pixel[PIXSIZE+1];
X
X	init_enum(line);
X
X	while( next_enum(pixel)  ) {
X	    unsigned int value;
X
X	    sscanf(pixel, "%x", &value);
X	    AddToPixel((byte)value);
X	}
X    }
X}
+END+OF+xfaceload.c
echo '-rw-rw-r--  1 argv         6622 Apr  6 15:45 xfaceload.c    (as sent)'
chmod u=rw,g=rw,o=r xfaceload.c
ls -l xfaceload.c
exit 0