#ident "@(#)xgrasp.c	1.8 91/04/01 XGRASP"
/*-
 * xgrasp.c - main routines for grasp viewer.
 *
 * Copyright (c) 1991 by Patrick J. Naughton
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This file is provided AS IS with no warranties of any kind.  The author
 * shall have no liability with respect to the infringement of copyrights,
 * trade secrets or any patents by this file or any part thereof.  In no
 * event will the author be liable for any lost revenue or profits or
 * other special, indirect and consequential damages.
 *
 * Comments and additions should be sent to the author:
 *
 *                     Patrick J. Naughton
 *                     Sun Microsystems
 *                     2550 Garcia Ave, MS 10-20
 *                     Mountain View, CA 94043
 *                     (415) 336-1080
 *
 */

#include "grasp.h"
#include <X11/Xatom.h>

char       *pname;
int         imageloop = 0;
int         showdirectory = 0;
int         showtext = 0;
int         printthecodes = 0;
int         verbose = 0;
int         imverbose = 0;
Display    *dsp;
Window      win;
Visual     *vis;
XVisualInfo vinfo;
int         screen;
int         planes;
GC          gc;
GC          gc1;
long        white;
long        black;
Atom        protocol_atom;
Atom        kill_atom;


void
error(s1, s2)
    char       *s1, *s2;
{
    fprintf(stderr, s1, pname, s2);
    exit(1);
}

void
outi(s, i)
    char       *s;
    int         i;
{
    fprintf(stderr, "%s: %d\n", s, i);
}

void
outs(s1, s2)
    char       *s1, *s2;
{
    fprintf(stderr, "%s: %s\n", s1, s2);
}


u_int
GetByte(fp)
    FILE       *fp;
{
    return (u_int) getc(fp);
}

u_int
GetWord(fp)
    FILE       *fp;
{
    u_char      b1 = (u_char) getc(fp);
    u_char      b2 = (u_char) getc(fp);

    return (u_int) (b1 + b2 * 256);
}

u_int
GetLong(fp)
    FILE       *fp;
{
    u_char      b1 = (u_char) getc(fp);
    u_char      b2 = (u_char) getc(fp);
    u_char      b3 = (u_char) getc(fp);
    u_char      b4 = (u_char) getc(fp);
    return (u_int) (b1 + b2 * 256 + b3 * 256 * 256 + b4 * 256 * 256 * 256);
}


FilenameStruct *
readdirectory(fp, count)
    FILE       *fp;
    int        *count;
{
    FilenameStruct *fn;
    int         i;
    int         len = GetWord(fp);

    *count = (len / 17) - 1;
    fn = (FilenameStruct *) malloc(*count * sizeof(FilenameStruct));
    for (i = 0; i < *count; i++) {
	fn[i].offset = GetLong(fp);
	fread(fn[i].fname, 13, 1, fp);
	fn[i].fname[13] = 0;
	lowerstr(fn[i].fname);
	if (showdirectory)
	    fprintf(stderr, "%13s   %6d\n", fn[i].fname, fn[i].offset);
    }
    return (fn);
}

usage()
{
    error("usage: %s [-display dsp] [-verbose] graspfile\n", NULL);
}

main(argc, argv)
    int         argc;
    char       *argv[];
{
    char       *displayName = 0;
    XSetWindowAttributes xswa;
    XFontStruct *xfont;
    XGCValues   gcv;
    XWMHints    xwmh;
    Pixmap      pix;
    char       *filename = 0;
    FILE       *fp;
    FilenameStruct *dir;
    int         count;
    int         i;

    pname = argv[0];
    for (i = 1; i < argc; i++) {
	char       *s = argv[i];
	int         n = strlen(s);

	if (!strncmp("-display", s, n))
	    displayName = argv[++i];
	else if (!strncmp("-dir", s, n))
	    showdirectory = 1;
	else if (!strncmp("-textout", s, n))
	    showtext = 1;
	else if (!strncmp("-images", s, n))
	    imageloop = 1;
	else if (!strncmp("-verbose", s, n))
	    verbose = 1;
	else if (!strncmp("-imverbose", s, n))
	    imverbose = 1;
	else if (!strncmp("-printcodes", s, n))
	    printthecodes = 1;
	else if (filename || s[0] == '-')
	    usage();
	else
	    filename = s;
    }
    if (!filename)
	usage();

    if (!(dsp = XOpenDisplay(displayName)))
	error("%s: unable to open display \"%s\".\n",
	      XDisplayName(displayName));

    protocol_atom = XInternAtom(dsp, "WM_PROTOCOLS", False);
    kill_atom = XInternAtom(dsp, "WM_DELETE_WINDOW", False);

    screen = DefaultScreen(dsp);
    gc = DefaultGC(dsp, screen);
    white = WhitePixel(dsp, screen);
    black = BlackPixel(dsp, screen);
    planes = DisplayPlanes(dsp, screen);
    xfont = XLoadQueryFont(dsp, "8x13");
    XSetFont(dsp, gc, xfont->fid);
    pix = XCreatePixmap(dsp, RootWindow(dsp, screen), 1, 1, 1);
    gcv.foreground = black;
    gcv.background = white;
    if (!(gc1 = XCreateGC(dsp, pix, GCForeground | GCBackground, &gcv)))
	error("%s: couldn't create mono gc.\n");
    XFreePixmap(dsp, pix);

    if (!XMatchVisualInfo(dsp, screen, planes, PseudoColor, &vinfo))
	if (!XMatchVisualInfo(dsp, screen, planes, GrayScale, &vinfo))
	    if (!XMatchVisualInfo(dsp, screen, planes, DirectColor, &vinfo))
		error("%s: only works on color displays\n");
    vis = vinfo.visual;

    xswa.event_mask = ExposureMask | KeyPressMask |
	ButtonPress | StructureNotifyMask;
    xswa.backing_store = Always;
    win = XCreateWindow(dsp,
			RootWindow(dsp, screen),
			0, 0, 1, 1, 0,
			DefaultDepth(dsp, screen),
			InputOutput,
			vis,
			CWEventMask | CWBackingStore,
			&xswa);
    XStoreName(dsp, win, filename);
    XSetWMProtocols(dsp, win, &kill_atom, 1);
    xwmh.flags = InputHint;
    xwmh.input = True;
    XChangeProperty(dsp, win, XA_WM_HINTS, XA_WM_HINTS, 32,
	       PropModeReplace, (u_char *) &xwmh, sizeof(xwmh) / sizeof(int));

    fp = fopen(filename, "r");
    if (!fp)
	error("%s: %s not found.\n", filename);
    dir = readdirectory(fp, &count);
    readfiles(fp, dir, count);
    fclose(fp);
    execfile(exec[0], 0);
    exit(0);
}
