/* -*- Mode: C; tab-width: 4; -*- */
/******************************************************************************
 * Copyright (c) 1996 Netscape Communications. All rights reserved.
 * Copyright (c) 1997 Lawrence T. Hoff (hoff@bnl.gov). All rights reserved.
 ******************************************************************************/
/*
 * UnixShell.c
 *
 * Netscape Client Plugin API
 * - Function that need to be implemented by plugin developers
 *
 * This file defines a "Template" plugin that plugin developers can use
 * as the basis for a real plugin.  This shell just provides empty
 * implementations of all functions that the plugin can implement
 * that will be called by Netscape (the NPP_xxx methods defined in 
 * npapi.h). 
 *
 */

#include <stdio.h>                               /* sprintf(), fprintf(), etc. */
#include <sys/types.h>                           /* pid_t */
#include <unistd.h>                              /* fork(), system(), unlink(), etc. */
#include <signal.h>                              /* SIGHUP */
#include <fcntl.h>                               /* O_RDWR */
#include <wait.h>                                /* wait() */
#include "npapi.h"
#include <sys/resource.h>                        /* maximum # of file descriptors */

/*
** Stuff for the NPP_SetWindow method:
*/
#ifdef XP_UNIX
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#endif /* XP_UNIX */

/* default library, compatible with TIMIDITY */
static const char *timdir = "/usr/local/lib/timidity";

/* resort to slow sampling rate for busy/slow processors */
static int eightKFlag = 0;

/***********************************************************************
 *                                                                     *
 *                                                                     *
 *    Read the user's environment variables for custom settings        *
 *                                                                     *
 *                                                                     *
 *                                                                     *
 *                                                                     *
 ***********************************************************************/

static void readEnv(void){

  /* see if the user has specified an alternate directory for timidity */
  if(getenv("TIMID_DIR") != NULL) timdir = getenv("TIMID_DIR");

  /* see if the user has specified an alternate directory for timidity */
  if(getenv("TIMID_8K") != NULL) eightKFlag = 1;

}

/***********************************************************************
 *                                                                     *
 *                                                                     *
 *    Stop playing music, kill the subordinate task                    *
 *                                                                     *
 *                                                                     *
 *                                                                     *
 *                                                                     *
 ***********************************************************************/

static void stopMidiPlayer(pid_t pid){
  if(pid != (pid_t) -1) kill(pid, SIGHUP);
  wait(0); /* clean up after dead child */
}

/***********************************************************************
 *                                                                     *
 *                                                                     *
 *     Function to actually play the music                             *
 *                                                                     *
 *                                                                     *
 *                                                                     *
 *                                                                     *
 ***********************************************************************/

static pid_t startMidiPlayer(const char *filename){

/* if we're the parent, return the child ID */
pid_t pid = fork(); if(pid != (pid_t)0) return pid;

/* OK, now let's get ourselves somewhat removed from our parent */
{
  int fd, sig;
  struct rlimit rlp;

  /* start by closing all file descriptors (except stderr) */
  (void) getrlimit(RLIMIT_NOFILE, &rlp);
  for(fd = 3; fd < rlp.rlim_max; fd++) (void) close(fd);

  /* now attach stdin and adtout to /dev/null */
  (void) freopen("/dev/null", "r", stdin);
  (void) freopen("/dev/null", "w", stdout);

  /* then remove an netscape-installed signal handlers */
  for(sig=0; sig < 64; sig++)signal(sig, SIG_DFL);
}

/* Now play the sound file */

{
static const char *argv[4];
argv[0] = "timidity";
argv[1] = "-Od";
argv[2] = eightKFlag ? "-s8000": "-s22050"; /* check if the user specified 8K rate */
argv[3] = filename;

/* change to the configuration directory */
chdir(timdir);

/* jump to timidity */
timiditymain(4, argv);

}

/* bye now */
_exit(0);
}

/***********************************************************************
 * Instance state information about the plugin.
 *
 * PLUGIN DEVELOPERS:
 *	Use this struct to hold per-instance information that you'll
 *	need in the various functions in this file.
 ***********************************************************************/

/* we'll read in all the file before processing. Typical MIDI files are smallish,
   so it should be OK */
static const char *filestub = "/tmp/midi";

typedef struct _PluginInstance
{
    int fd; /* file descriptor for temp file */
    const char *filename; /* name of same */
    pid_t pid; /* process ID of sound player */

	NPWindow*		fWindow;
	uint16			fMode;

/* UNIX data members */
#ifdef XP_UNIX
    Window window;
    Display *display;
    uint32 x, y;
    uint32 width, height;
#endif /* XP_UNIX */

} PluginInstance;
  

/***********************************************************************
 *
 * Empty implementations of plugin API functions
 *
 * PLUGIN DEVELOPERS:
 *	You will need to implement these functions as required by your
 *	plugin.
 *
 ***********************************************************************/

char*
NPP_GetMIMEDescription(void)
{

static char *desc = 
  "audio/midi:mid,midi:<A HREF=mailto:hoff@bnl.gov>Larry Hoff's</A> "
  "MIDIX plugin version 0.9;"
  "audio/x-midi:mid,midi:<A HREF=mailto:hoff@bnl.gov>Larry Hoff's</A> "
  "MIDIX plugin version 0.9;";

  return(desc);
}

NPError
NPP_GetValue(void *future, NPPVariable variable, void *value)
{

  NPError err = NPERR_NO_ERROR;

  static char *desc = 

		 "This plugins plays MIDI, using the timidity "
		 "toolkit, via the standard audio device.<P>"
		 "By default, timidity configuration files are in the directory "
		 "/usr/local/bin/timidity<P>"
		 "Use the TIMID_DIR environment variable to change "
		 "the configuration directory.<P>"
		 "You may set the environment variable TIMID_8K to "
		 "reduce the sampling rate (to 8000 Hz) for busy or slow "
		 "processors, or for machines which only support 8KHz.<P>";

	switch (variable) {
		case NPPVpluginNameString:
			*((char **)value) = "UNIX MIDI plugin";
			break;
		case NPPVpluginDescriptionString:
			*((char **)value) = desc;
			break;
		default:
			err = NPERR_GENERIC_ERROR;
	}
	return err;
}

NPError
NPP_Initialize(void)
{

  readEnv(); /* idon't know whether NPP_Initialize, or NPP_GetValue
				gets called first. Just to be safe, read the env in both
				places */
    return NPERR_NO_ERROR;
}

jref
NPP_GetJavaClass()
{
    return NULL;
}

void
NPP_Shutdown(void)
{
}
 

NPError 
NPP_New(NPMIMEType pluginType,
	NPP instance,
	uint16 mode,
	int16 argc,
	char* argn[],
	char* argv[],
	NPSavedData* saved)
{
        PluginInstance* This;

	if (instance == NULL)
		return NPERR_INVALID_INSTANCE_ERROR;
		
	instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
	
	This = (PluginInstance*) instance->pdata;

	if (This == NULL)
		return NPERR_OUT_OF_MEMORY_ERROR;

	{
   	  /* construct a filename unique to this instance to 
	     store the data in */
	  static char buf[256];
	  sprintf(buf, "%s%x.mid", filestub, This);
	  This->filename = buf;
	  This->pid = -1;
	}

	return NPERR_NO_ERROR;
}

NPError 
NPP_Destroy(NPP instance, NPSavedData** save)
{
	PluginInstance* This;

	if (instance == NULL)
		return NPERR_INVALID_INSTANCE_ERROR;

	This = (PluginInstance*) instance->pdata;

	/* PLUGIN DEVELOPERS:
	 *	If desired, call NP_MemAlloc to create a
	 *	NPSavedDate structure containing any state information
	 *	that you want restored if this plugin instance is later
	 *	recreated.
	 */

	if (This != NULL) {
 	        /* get rid of the temporary file */
		(void) unlink(This->filename);

		/* stop player */
		stopMidiPlayer(This->pid);

		NPN_MemFree(instance->pdata);
		instance->pdata = NULL;
	}

	return NPERR_NO_ERROR;
}

#ifdef XP_UNIX

static void displayLogo(Display *display, Window window, Widget w);

void
Redraw(Widget w, XtPointer closure, XEvent *event)
{
	PluginInstance* This = (PluginInstance*)closure;

	displayLogo(This->display, This->window, w);

}
#endif /* XP_UNIX */

NPError 
NPP_SetWindow(NPP instance, NPWindow* window)
{
	PluginInstance* This;

	if (instance == NULL)
		return NPERR_INVALID_INSTANCE_ERROR;

	if (window == NULL)
		return NPERR_NO_ERROR;

	This = (PluginInstance*) instance->pdata;

	/*
	 * PLUGIN DEVELOPERS:
	 *	Before setting window to point to the
	 *	new window, you may wish to compare the new window
	 *	info to the previous window (if any) to note window
	 *	size changes, etc.
	 */

#ifdef XP_UNIX
	{
		Widget netscape_widget;

		This->window = (Window) window->window;
		This->x = window->x;
		This->y = window->y;
		This->width = window->width;
		This->height = window->height;
		This->display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;

	    netscape_widget = XtWindowToWidget(This->display, This->window);
		XtAddEventHandler(netscape_widget, ExposureMask, FALSE, (XtEventHandler)Redraw, This);
		Redraw(netscape_widget, (XtPointer)This, NULL);
	}
#endif /* XP_UNIX */

		This->fWindow = window;

return NPERR_NO_ERROR;
}

NPError 
NPP_NewStream(NPP instance,
			  NPMIMEType type,
			  NPStream *stream, 
			  NPBool seekable,
			  uint16 *stype)
{
	NPByteRange range;
	PluginInstance* This;

	if (instance == NULL)
		return NPERR_INVALID_INSTANCE_ERROR;

	This = (PluginInstance*) instance->pdata;

	/* open the file to store data in */
	This->fd = open(This->filename, O_RDWR|O_CREAT, 0666);
	if(This->fd == -1) return NPERR_GENERIC_ERROR;

	return NPERR_NO_ERROR;
}

/* PLUGIN DEVELOPERS:
 *	These next 2 functions are directly relevant in a plug-in which
 *	handles the data in a streaming manner. If you want zero bytes
 *	because no buffer space is YET available, return 0. As long as
 *	the stream has not been written to the plugin, Navigator will
 *	continue trying to send bytes.  If the plugin doesn't want them,
 *	just return some large number from NPP_WriteReady(), and
 *	ignore them in NPP_Write().  For a NP_ASFILE stream, they are
 *	still called but can safely be ignored using this strategy.
 */

int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
				   * mode so we can take any size stream in our
				   * write call (since we ignore it) */

int32 
NPP_WriteReady(NPP instance, NPStream *stream)
{
	PluginInstance* This;
	if (instance != NULL)
		This = (PluginInstance*) instance->pdata;

	return STREAMBUFSIZE;
}

int32 
NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
{
	if (instance != NULL)
	{
		PluginInstance* This = (PluginInstance*) instance->pdata;
		len = write(This->fd, buffer, len);
		if(len <0) close(This->fd);
	}

	return len;		/* The number of bytes accepted */
}

NPError 
NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
{
	PluginInstance* This;

	if (instance == NULL)
		return NPERR_INVALID_INSTANCE_ERROR;
	This = (PluginInstance*) instance->pdata;

	close(This->fd);

	/* stop another player in progress ???*/
	stopMidiPlayer(This->pid);

	/* yahoo, now we have the data, run timidity */
	This->pid = startMidiPlayer(This->filename);

	return NPERR_NO_ERROR;
}

void 
NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
{
	PluginInstance* This;
	if (instance != NULL)
		This = (PluginInstance*) instance->pdata;
	This->pid = startMidiPlayer(This->filename);
	/* just spwan timidity */
	This->pid = startMidiPlayer(fname);
}

void 
NPP_Print(NPP instance, NPPrint* printInfo)
{
	if(printInfo == NULL)
		return;

	if (instance != NULL) {
		PluginInstance* This = (PluginInstance*) instance->pdata;
	
		if (printInfo->mode == NP_FULL) {
		    /*
		     * PLUGIN DEVELOPERS:
		     *	If your plugin would like to take over
		     *	printing completely when it is in full-screen mode,
		     *	set printInfo->pluginPrinted to TRUE and print your
		     *	plugin as you see fit.  If your plugin wants Netscape
		     *	to handle printing in this case, set
		     *	printInfo->pluginPrinted to FALSE (the default) and
		     *	do nothing.  If you do want to handle printing
		     *	yourself, printOne is true if the print button
		     *	(as opposed to the print menu) was clicked.
		     *	On the Macintosh, platformPrint is a THPrint; on
		     *	Windows, platformPrint is a structure
		     *	(defined in npapi.h) containing the printer name, port,
		     *	etc.
		     */

			void* platformPrint =
				printInfo->print.fullPrint.platformPrint;
			NPBool printOne =
				printInfo->print.fullPrint.printOne;
			
			/* Do the default*/
			printInfo->print.fullPrint.pluginPrinted = FALSE;
		}
		else {	/* If not fullscreen, we must be embedded */
		    /*
		     * PLUGIN DEVELOPERS:
		     *	If your plugin is embedded, or is full-screen
		     *	but you returned false in pluginPrinted above, NPP_Print
		     *	will be called with mode == NP_EMBED.  The NPWindow
		     *	in the printInfo gives the location and dimensions of
		     *	the embedded plugin on the printed page.  On the
		     *	Macintosh, platformPrint is the printer port; on
		     *	Windows, platformPrint is the handle to the printing
		     *	device context.
		     */

			NPWindow* printWindow =
				&(printInfo->print.embedPrint.window);
			void* platformPrint =
				printInfo->print.embedPrint.platformPrint;
		}
	}
}

#ifdef DISPLAY_COLOR_LOGO
#include "displayLogo.c"
#else

#ifdef XP_UNIX

#define umpbw_width 200
#define umpbw_height 64
static char umpbw_bits[] = {
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x90,0x24,
 0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x44,0x24,0x09,0x02,0x00,0x00,0x00,0x00,0x44,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x44,
 0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x20,0x10,0x40,
 0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x11,0x00,0x00,0xf6,0x07,0x80,0x40,0x04,0x00,0x00,0x00,0x92,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0xfe,
 0xbf,0x4e,0x02,0x04,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x2f,0x00,0x07,0x10,0x00,0x21,
 0x00,0x00,0x00,0x22,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x5e,0x00,0xc0,0x07,0x80,0x10,0x04,0x00,0x00,0x00,0x52,0x01,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0xc0,0x07,0xfc,
 0xff,0x14,0x00,0x00,0x10,0x00,0x00,0x00,0x52,0x01,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x40,0x80,0xf0,0xf8,0xff,0x3f,0x44,0x02,0x42,0x00,
 0x00,0x00,0x00,0x52,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
 0x00,0x04,0x1c,0xff,0x5f,0x19,0x04,0x20,0x08,0x42,0x00,0x00,0x00,0x51,0x02,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xbf,0x00,
 0x08,0x0c,0x00,0x00,0x08,0x00,0x00,0x00,0x49,0x02,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x01,0x80,0xfb,0x03,0x00,0x18,0xfc,0xff,0xff,0x17,
 0x00,0x00,0x00,0x49,0x02,0x00,0x00,0x00,0x00,0x06,0xf0,0x00,0x00,0x3e,0x00,
 0x00,0xc0,0x7f,0x00,0x00,0x08,0xfe,0xff,0xff,0x1f,0x00,0x00,0x00,0x29,0x02,
 0x1e,0x80,0x03,0xc7,0x1f,0xfc,0x01,0x9e,0x7f,0x00,0x00,0xe0,0x0f,0x00,0x00,
 0x18,0x6e,0xfb,0x7f,0x0f,0x60,0xff,0xff,0x39,0x7d,0xff,0xff,0xff,0xff,0xff,
 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x88,0x53,0x35,0xb0,0x47,
 0xf8,0xdb,0xee,0x38,0xff,0xdf,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 0xff,0xff,0x00,0x00,0x00,0xd0,0x24,0xe4,0xdf,0x03,0xf8,0x00,0x80,0x14,0x01,
 0x1c,0x80,0x03,0xf7,0x7f,0xff,0x07,0xee,0xff,0x01,0x00,0x78,0x00,0x00,0xf0,
 0x79,0x92,0x12,0xe0,0x10,0xf8,0x00,0x80,0x14,0x01,0x1e,0x80,0x07,0xff,0xfe,
 0xdf,0x0f,0xfe,0xf2,0x03,0x00,0x3c,0x00,0x80,0xff,0xf1,0xff,0xff,0xff,0x00,
 0xf8,0x00,0x80,0x08,0x01,0x1c,0x80,0x03,0x3f,0xf8,0x83,0x0f,0xfe,0xe0,0x03,
 0x00,0x0e,0x00,0xf8,0xff,0xf9,0xff,0xff,0x3f,0x22,0xf8,0x00,0x80,0x80,0x00,
 0x5e,0x80,0x17,0x3f,0xf2,0x23,0x17,0x7e,0xca,0x0f,0x00,0x0f,0x00,0xfe,0xff,
 0x11,0x04,0x80,0x04,0x00,0xf8,0x00,0x80,0x81,0x00,0x1c,0x80,0x07,0x9f,0xf8,
 0x01,0x0f,0x3e,0xc0,0x07,0x80,0x07,0x80,0xff,0xff,0x19,0x8c,0x10,0x80,0x10,
 0xf8,0x00,0x80,0x48,0x00,0x5e,0x80,0x13,0x1f,0xf0,0x15,0x5f,0x7e,0x85,0x27,
 0x80,0x03,0xe0,0xff,0xff,0x09,0x04,0x02,0x10,0x42,0xf8,0xff,0xff,0xf0,0xff,
 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0x01,0xf0,0xaa,0xaa,
 0x11,0x0c,0x40,0x02,0x00,0xf8,0xff,0xff,0xe1,0xfd,0x5f,0xff,0xef,0x5f,0xff,
 0xf5,0xaf,0x7f,0xfd,0xef,0xff,0x01,0xb8,0xff,0xff,0x11,0x04,0x00,0x80,0x08,
 0xf8,0x00,0x00,0x08,0x00,0x1c,0x80,0x03,0x0f,0xf0,0x00,0x0e,0x1e,0x00,0x0f,
 0xc0,0x00,0xdc,0xb5,0xb5,0x19,0x4c,0x08,0x11,0x20,0xf8,0x00,0x10,0x08,0x00,
 0x1e,0x80,0x07,0x27,0xe0,0x02,0x2f,0x9e,0x00,0x0f,0xe0,0x00,0xb6,0xde,0xde,
 0x01,0x04,0x01,0x04,0x02,0xf8,0x00,0x4c,0x08,0x00,0x5c,0x80,0x17,0x0f,0xf0,
 0x00,0x0f,0x5e,0x00,0x2f,0xe0,0x00,0x6b,0x6b,0xab,0x19,0x0c,0x20,0x40,0x08,
 0xf8,0x00,0x82,0x08,0x00,0x1e,0x80,0x03,0x27,0xf0,0x04,0x4e,0x0e,0x00,0x0f,
 0x60,0x00,0xaf,0x55,0xb5,0x11,0x04,0x80,0x00,0x40,0xf8,0x00,0x41,0x09,0x00,
 0x1c,0x80,0x07,0x0f,0xf0,0x00,0x0f,0x9e,0x00,0x4f,0x70,0x80,0xb7,0x54,0x55,
 0x11,0x4c,0x04,0x12,0x01,0xf8,0x01,0x61,0x2b,0x49,0xff,0xea,0xdf,0x6f,0xf5,
 0x56,0x7f,0xbf,0xb6,0x57,0x77,0x80,0xda,0xdb,0xb6,0x09,0x04,0x00,0x00,0x10,
 0xf8,0xff,0xf8,0xfb,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 0x7f,0x80,0xb6,0xd6,0x53,0x11,0x0c,0x21,0x48,0x04,0xf8,0x40,0x08,0xe1,0x00,
 0x1c,0x80,0x07,0x07,0xf0,0x00,0x0e,0x1e,0x00,0x0f,0x70,0xc0,0x96,0xde,0xba,
 0x11,0x04,0x84,0x00,0x40,0xf8,0xa0,0xe4,0x00,0x07,0x1e,0x80,0x07,0x0f,0xf0,
 0x00,0x0f,0x4e,0x00,0x27,0x60,0x80,0xdb,0x76,0x37,0x09,0x0c,0x00,0x42,0x02,
 0xf8,0x20,0x1a,0x00,0x18,0x5c,0x80,0x13,0x27,0xf0,0x04,0x4f,0x1e,0x00,0x0f,
 0x70,0x80,0xb2,0xd6,0xb2,0x11,0x44,0x00,0x08,0x10,0xf8,0x20,0x06,0xe4,0x10,
 0x1e,0xc0,0x07,0x0f,0xf0,0x00,0x1e,0x9e,0x80,0x4f,0x60,0x00,0x97,0xd6,0x13,
 0x11,0x0c,0x24,0x00,0x01,0xf8,0x20,0x05,0x13,0x21,0x1c,0x80,0x17,0x07,0xf0,
 0x02,0x4f,0x1e,0x00,0x07,0xe0,0x00,0xb3,0x56,0x56,0x09,0x04,0x00,0x21,0x48,
 0xf8,0xa1,0xd2,0x14,0x22,0x5e,0xc1,0x87,0x5f,0xf0,0x08,0x2f,0xbe,0x84,0x57,
 0xe1,0x00,0x96,0xd4,0x33,0x11,0x8c,0x00,0x00,0x00,0xf8,0xbf,0xf3,0xe7,0xe7,
 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x9c,0x56,0x32,
 0x11,0xb4,0xfe,0xfe,0x1b,0xf8,0xa0,0x12,0x24,0x24,0x3e,0xe4,0x27,0x8f,0xf0,
 0x12,0x8f,0x3e,0xd2,0x97,0xd4,0x01,0xb8,0xd6,0x92,0x11,0xfc,0xff,0xff,0x0f,
 0xf8,0x20,0x21,0x24,0x22,0x3c,0xc0,0x07,0x07,0xf0,0x00,0x2e,0xbe,0xc0,0x07,
 0xc0,0x01,0xf0,0xd4,0x12,0x09,0xfe,0xeb,0x5f,0x4f,0xf8,0x20,0xc0,0x23,0x25,
 0xbc,0xf0,0x13,0x2f,0xf0,0x04,0x0f,0x7e,0xc0,0x23,0x80,0x03,0xc0,0xd2,0x32,
 0x11,0x27,0x3a,0xb0,0x07,0xf8,0x20,0x00,0x20,0x21,0x7c,0xf0,0x07,0x07,0xf0,
 0x00,0x4f,0xfe,0xf0,0x13,0x00,0x07,0x00,0x57,0x12,0x89,0x51,0xf5,0xff,0x13,
 0xf8,0x40,0x20,0xa2,0x10,0xfc,0xff,0x27,0x2f,0xf0,0x02,0x1e,0xfe,0xfb,0x09,
 0x00,0x07,0x00,0x9c,0x12,0xe1,0x04,0x00,0xc5,0x01,0xf8,0xc0,0x02,0x40,0x10,
 0xf8,0xbf,0x07,0x07,0xe0,0x00,0x4f,0xee,0xff,0x21,0x00,0x0e,0x00,0xf0,0x13,
 0xf1,0xff,0xff,0xff,0x44,0xf8,0x11,0x09,0x10,0x8c,0xfc,0xbf,0xb7,0xaf,0xfa,
 0x56,0x5f,0xff,0xff,0xad,0xed,0x1e,0x00,0x00,0xfe,0xf1,0xff,0xff,0x3e,0x00,
 0xf8,0xff,0x27,0x41,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,
 0xff,0x7f,0x00,0x00,0x80,0xf0,0xfe,0xff,0x3f,0x20,0x00,0x00,0x38,0x84,0x21,
 0xe0,0x8f,0x05,0x15,0x50,0x00,0x0a,0x5e,0x7f,0x00,0x00,0xf8,0x00,0x00,0x00,
 0x08,0x04,0x00,0x00,0x09,0x00,0x00,0xc0,0x43,0x00,0x00,0x21,0x10,0x40,0x00,
 0x04,0x40,0x1e,0x0a,0x15,0x00,0xe0,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
 0x00,0x00,0x00,0x24,0x00,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x9e,0x90,0x00,
 0x01,0xc0,0x07,0x00,0x00,0x10,0x0c,0x80,0x40,0x44,0x00,0x00,0x00,0x24,0x00,
 0x00,0x60,0x00,0x00,0x04,0x05,0x20,0x1e,0x60,0x00,0x90,0x00,0x1f,0x00,0x00,
 0x08,0x44,0x08,0x0a,0x10,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,
 0x01,0x00,0x9e,0x20,0x02,0x00,0x00,0xfe,0x00,0x00,0x10,0x04,0x21,0x20,0x01,
 0x00,0x00,0x00,0x22,0x00,0x44,0x4d,0x12,0x6e,0xe4,0x05,0x00,0x4e,0xaf,0xc8,
 0x83,0x1a,0xf8,0x07,0x00,0x00,0x0e,0x00,0x00,0x20,0x00,0x00,0x00,0x26,0x00,
 0x44,0x53,0x12,0x92,0x14,0x05,0x00,0x1e,0xb1,0x28,0x82,0x26,0xc0,0xbf,0x00,
 0x10,0x07,0x82,0x84,0x04,0x00,0x00,0x00,0x12,0x00,0x44,0x51,0x0c,0x92,0x14,
 0x05,0x00,0x9e,0xb1,0x28,0xba,0x22,0x00,0xfe,0x7f,0xc9,0x23,0x10,0x10,0x20,
 0x00,0x00,0x00,0x12,0x00,0x44,0x51,0x0c,0x92,0x14,0x05,0x00,0x1e,0xb1,0x28,
 0xa2,0x22,0x00,0xe0,0xff,0xff,0x80,0x40,0x00,0x02,0x00,0x00,0x00,0x1c,0x00,
 0x64,0x51,0x12,0x92,0x14,0x05,0x00,0x9e,0xb1,0x2c,0x82,0x22,0x00,0x00,0xfa,
 0x3f,0x00,0x02,0x42,0x20,0x00,0x00,0x00,0x00,0x00,0x58,0x51,0x12,0x92,0xe4,
 0x05,0x00,0x1e,0x2f,0xcb,0x83,0x2a,0x21,0x00,0x00,0x02,0x08,0x08,0x08,0x09,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9e,0x01,0x30,
 0x02,0x00,0x00,0x12,0x00,0x00,0x20,0x80,0x00,0x20,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x01,0xc0,0x01,0x00,0x00,0x80,0x00,
 0x10,0x81,0x10,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x4a,0x84,0x00,0x88,0x00,0x08,0x00,0x42,0x00,0x00,0x02,0x08,0x45,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
 0x00,0x42,0x80,0x00,0x00,0x02,0x04,0x40,0x00,0x00};

static void displayLogo(Display *display, Window window, Widget w)
{
  GC gc;
  XGCValues gcv;

  Pixmap p;

  XtVaGetValues(w, XtNbackground, &gcv.background,
		XtNforeground, &gcv.foreground, 0);
  gc = XCreateGC(display, window, 
		 GCForeground|GCBackground, &gcv);

  /* do B&W */
  p = XCreatePixmapFromBitmapData(display, window, 
				  umpbw_bits,
				  umpbw_width, umpbw_height, 
				  WhitePixel(display, DefaultScreen(display)),
				  BlackPixel(display, DefaultScreen(display)),
				  1);
  if(p != NULL){
    XCopyPlane(display, p, window, gc, 0, 0, umpbw_width, umpbw_height,  0, 0, 1);
    XFreePixmap(display, p);
  }
}

#endif
#endif