/* +-------------------------------------------------------------------+ */
/* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
/* | Copyright 1995, 1996 Torsten Martinsen (bullestock@dk-online.dk)  | */
/* |                                                                   | */
/* | Permission to use, copy, modify, and to distribute this software  | */
/* | and its documentation for any purpose is hereby granted without   | */
/* | fee, provided that the above copyright notice appear in all       | */
/* | copies and that both that copyright notice and this permission    | */
/* | notice appear in supporting documentation.  There is no           | */
/* | representations about the suitability of this software for        | */
/* | any purpose.  this software is provided "as is" without express   | */
/* | or implied warranty.                                              | */
/* |                                                                   | */
/* +-------------------------------------------------------------------+ */

/* $Id: main.c,v 1.6 1996/04/15 14:18:03 torsten Exp $ */

#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#ifndef NOSTDHDRS
#include <stdlib.h>
#include <unistd.h>
#endif

#include <X11/xpm.h>

#define DEFINE_GLOBAL
#include "xpaint.h"
#include "Paint.h"
#include "misc.h"
#include "operation.h"
#include "graphic.h"
#include "protocol.h"
#include "rw/rwTable.h"

#include "XPaintIcon.xpm"

extern void BrushInit(Widget toplevel);

static char *appDefaults[] =
{
#include "XPaint.ad.h"
    NULL
};

typedef struct {
    String visualType;
    String size;
    String help;
    String rcFile;
    Boolean popped;
} AppInfo;

static AppInfo appInfo;

static XtResource resources[] =
{
    {"visualType", "VisualType", XtRString, sizeof(String),
   XtOffset(AppInfo *, visualType), XtRImmediate, (XtPointer) "default"},
    {"size", "Size", XtRString, sizeof(String),
     XtOffset(AppInfo *, size), XtRImmediate, (XtPointer) "640x480"},
    {"rcFile", "RcFile", XtRString, sizeof(String),
     XtOffset(AppInfo *, rcFile), XtRImmediate, (XtPointer) NULL},
    {"help", "Help", XtRString, sizeof(String),
     XtOffset(AppInfo *, help), XtRImmediate, (XtPointer) NULL},
    {"popped", "Popped", XtRBoolean, sizeof(Boolean),
     XtOffset(AppInfo *, popped), XtRImmediate, (XtPointer) False},
};

static XrmOptionDescRec options[] =
{
    {"-24", ".visualType", XrmoptionNoArg, (XtPointer) "true24"},
    {"-12", ".visualType", XrmoptionNoArg, (XtPointer) "cmap12"},
    {"-size", ".size", XrmoptionSepArg, (XtPointer) NULL},
    {"-rcFile", ".rcFile", XrmoptionSepArg, (XtPointer) NULL},
    {"-popped", ".popped", XrmoptionNoArg, (XtPointer) "True"},
    {"-help", ".help", XrmoptionNoArg, (XtPointer) "command"},
    {"+help", ".help", XrmoptionSepArg, (XtPointer) NULL},
};


/*
**  Public query functions for application defaults
 */

void 
GetDefaultWH(int *w, int *h)
{
    int x, y;
    unsigned int width, height;

    XParseGeometry(appInfo.size, &x, &y, &width, &height);
    *w = width;
    *h = height;
}

char *
GetDefaultRC(void)
{
    return appInfo.rcFile;
}

/*
**  Create a nice icon image for XPaint...
 */
void 
SetIconImage(Widget w)
{
    static Pixmap icon = None;
    static int iconW = 1, iconH = 1;
    Window iconWindow;
    Screen *screen = XtScreen(w);
    Display *dpy = XtDisplay(w);

#if 0
    int i, count;
    XIconSize *list;

    /*
    **  Should use this information
     */

    XGetIconSizes(dpy, RootWindowOfScreen(screen), &list, &count);
    printf("got %d sizes\n", count);
    for (i = 0; i < count; i++) {
	printf("#%d:  min = %d,%d  max = %d,%d  inc = %d,%d\n", i,
	       list[i].min_width, list[i].min_height,
	       list[i].max_width, list[i].max_height,
	       list[i].width_inc, list[i].height_inc);
    }
    XFree((XPointer) list);
#endif

    /*
    **  Build the XPaint icon
     */
    iconWindow = XCreateSimpleWindow(dpy, RootWindowOfScreen(screen),
				     0, 0,	/* x, y */
				     iconW, iconH, 0,
				     BlackPixelOfScreen(screen),
				     BlackPixelOfScreen(screen));
    if (icon == None) {
	XpmCreatePixmapFromData(dpy, iconWindow,
				XPaintIcon_xpm, &icon, NULL, NULL);
	GetPixmapWHD(dpy, icon, &iconW, &iconH, NULL);
	XResizeWindow(dpy, iconWindow, iconW, iconH);
    }
    XSetWindowBackgroundPixmap(dpy, iconWindow, icon);

    XtVaSetValues(w, XtNiconWindow, iconWindow, NULL);
}


/*
**  The rest of main
 */
static void 
usage(char *prog, char *msg)
{
    if (msg)
	fprintf(stderr, "%s\n", msg);
    fprintf(stderr, "Usage: %s\n", prog);
    HelpTextOutput(stderr, appInfo.help == NULL ? "command" : appInfo.help);
    exit(1);
}

typedef struct {
    XtWorkProcId id;
    Widget toplevel;
    int nfiles;
    int pos;
    char **files;
} LocalInfo;

static void 
workProc(LocalInfo * l)
{
    char *file;
    void *v;
    static int done = 0;

    if (done || (l == NULL) || (l->id == None))
	return;
    XtRemoveWorkProc(l->id);
    l->id = None;

    file = l->files[l->pos];

    StateSetBusy(True);

    if ((v = ReadMagic(file)) != NULL)
	GraphicOpenFile(l->toplevel, file, v);
    else
	Notice(l->toplevel, "Unable to open input file \"%s\"\n	%s",
	       file, RWGetMsg());

    StateSetBusy(False);

    if (++l->pos == l->nfiles) {
	XtFree((XtPointer) l->files);
	XtFree((XtPointer) l);
	done = 1;
    } else
	l->id = XtAppAddWorkProc(XtWidgetToApplicationContext(l->toplevel),
				 (XtWorkProc) workProc, (XtPointer) l);
}


void 
main(Cardinal argc, char *argv[])
{
    Display *dpy;
    Widget toplevel;
    XtAppContext app;
    int i;
    XEvent event;
    Arg args[5];
    int nargs = 0;
    XrmDatabase rdb;
    Boolean isIcon;

    InitTypeConverters();

    XtSetLanguageProc(NULL, NULL, NULL);

    /*
    **  Create the application context
     */
    toplevel = XtAppInitialize(&Global.appContext, "XPaint",
			       options, XtNumber(options), &argc, argv,
			       appDefaults, args, nargs);

    XtGetApplicationResources(toplevel, (XtPointer) & appInfo,
			      resources, XtNumber(resources), NULL, 0);

    rdb = XtDatabase(XtDisplay(toplevel));

    if (appInfo.help != NULL)
	usage(argv[0], NULL);

    if (strcmp(appInfo.visualType, "default") != 0) {
	char *cp = appInfo.visualType;
	if (strncmp(cp, "cmap", 4) == 0) {
	    XrmPutStringResource(&rdb, "Canvas*visual", "PseudoColor");
	    cp += 4;
	} else if (strncmp(cp, "true", 4) == 0) {
	    XrmPutStringResource(&rdb, "Canvas*visual", "TrueColor");
	    cp += 4;
	} else if (strncmp(cp, "gray", 4) == 0) {
	    XrmPutStringResource(&rdb, "Canvas*visual", "StaticGray");
	    cp += 4;
	} else {
	    usage(argv[0], "bad visual type specification");
	}
	if (*cp != '\0')
	    XrmPutStringResource(&rdb, "Canvas*depth", cp);
    }
    if (argc != 1 && argv[1][0] == '-')
	usage(argv[0], "Invalid option");

    /*
    **  A little initialization
     */
    Global.region.image = NULL;
    Global.region.cmap = None;
    Global.region.width = 0;
    Global.region.height = 0;
    Global.region.pix = None;
    Global.region.mask = None;

    /*
    **
     */
    XtVaGetValues(toplevel, XtNiconic, &isIcon, NULL);
    if (isIcon)
	XrmPutStringResource(&rdb, "Canvas.iconic", "on");

    /*
    **  Now build and construct the widgets
     */
    Global.timeToDie = False;
    app = XtWidgetToApplicationContext(toplevel);
    dpy = Global.display = XtDisplay(toplevel);

    /*
    **  Call the initializers
     */

    OperationInit(toplevel);

    /*
    **  A few rogue initializers
     */
    BrushInit(toplevel);
    HelpInit(toplevel);
#ifdef USE_DRAND
    srand48((long int) time(0));
#else
    srandom((int) time(0));
#endif


    SetIconImage(toplevel);

    /*
    **  Realize it  (doesn't hurt)
     */
    XtRealizeWidget(toplevel);


    /*
    **  Now open any file on the command line
     */
    if (argc != 1) {
	LocalInfo *l = XtNew(LocalInfo);
	l->pos = 0;
	l->toplevel = toplevel;
	l->nfiles = argc - 1;
	l->files = (char **) XtCalloc(argc, sizeof(char *));
	for (i = 1; i < argc; i++)
	    l->files[i - 1] = argv[i];
	l->id = XtAppAddWorkProc(app, (XtWorkProc) workProc, (XtPointer) l);
    } else if (appInfo.popped) {
	/*
	**  If nothing is coming up, bring up a blank canvas
	 */
	GraphicCreate(toplevel, 0);
    }
    /*
    **  MainLoop
     */
    do {
	XtAppNextEvent(app, &event);
	if (event.type == ButtonPress || event.type == ButtonRelease)
	    Global.currentTime = event.xbutton.time;
	XtDispatchEvent(&event);
    }
    while (!Global.timeToDie);
}
