/*
 * file:     fileMenu.c
 * author:   Wes Barris
 * date:     4/22/92
 * purpose:  creates File menu
 *
 * copyright info:
 *
 *    @Copyright 1992
 *    Research Equipment Inc. dba Minnesota Supercomputer Center
 *
 * RESTRICTED RIGHTS LEGEND
 *
 * Use, duplication, or disclosure of this software and its documentation
 * by the Government is subject to restrictions as set forth in subdivision
 * { (b) (3) (ii) } of the Rights in Technical Data and Computer Software
 * clause at 52.227-7013.
 */

#include "icop.h"
#include "proto.h"
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <gl.h>
#include <gl/image.h>
#include <X11/StringDefs.h>
#include <Xm/Xm.h>
#include <Xm/CascadeB.h>
#include <Xm/FileSB.h>
#include <Xm/Frame.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/Separator.h>
#include <Xm/ToggleB.h>


extern ICOP	icop;
extern int	haveplot;

static Widget	ssb = NULL,
		osb = NULL,
		closeBox = NULL,
		img,
		map,
		warea;

char		*tmpname = "/usr/tmp/icop.sgi";
int		havefile = 0;

int	sizeofimage(char*, int*, int*);
int	longstoimage(unsigned long*, int, int, int, char*);
unsigned long* longimagedata(char*);

static void
CheckOpenCB(Widget w, XtPointer client_data, char *call_data)
{
   char	*filename;
   char *periodP, cmd[80];
   long	nbytes;

   XmStringGetLtoR(((XmSelectionBoxCallbackStruct *)call_data)->value,
                   XmSTRING_DEFAULT_CHARSET, &filename);
   if ((int)filename[strlen(filename)-1] == '/')
      fprintf(stderr, "Aborting open...\n");
   else {
      haveplot = 0;
      if (XmToggleButtonGetState(img)) {
         periodP = strrchr(filename, (int)'.');
         if (periodP) {
            if (!strcmp(periodP, ".sgi") || !strcmp(periodP, ".rgb"))
               sprintf(cmd, "cp %s %s", filename, tmpname);
            else if (!strcmp(periodP, ".jpg"))
               sprintf(cmd, "fromjpeg %s %s", filename, tmpname);
            else if (!strcmp(periodP, ".rle"))
               sprintf(cmd, "fromutah %s %s", filename, tmpname);
            else if (!strcmp(periodP, ".gif"))
               sprintf(cmd, "fromgif %s %s", filename, tmpname);
            else if (!strcmp(periodP, ".tiff"))
               sprintf(cmd, "fromtiff %s %s", filename, tmpname);
            else if (!strcmp(periodP, ".rla"))
               sprintf(cmd, "fromrla %s %s", filename, tmpname);
            }
         system(cmd);
         }
/*
 * If we already had an image buf it must be freed and remalloced.
 */
      if (icop.image.legalbuf) {
         free(icop.image.origbuf);
         free(icop.image.legalbuf);
         free(icop.image.illegalbuf);
         free(icop.image.correctedbuf);
         }
      if (XmToggleButtonGetState(img)) {
         icop.image.origbuf = longimagedata(tmpname);
         sizeofimage(tmpname, &icop.image.width, &icop.image.height);
         havefile = IMAGE_FILE;
         }
/*
 * Handle color map here.
 */
      else {
         FILE	*fptr;
         char	inbuf[10];
         int	size, lines;
         char	rgb[3];
         int	r, g, b;
         int	x, y;
/*
 * Is it a binary or ascii file?
 */
         sprintf(cmd, "ls -l %s | awk '{print $5}'", filename);
         if ((fptr = popen(cmd, "r")) == NULL)
            fprintf(stderr, "Cannot open pipe to test file.\n");
         fread(inbuf, 10, 1, fptr);
         pclose(fptr);
         size = atoi(inbuf);
         sprintf(cmd, "wc -l %s | awk '{print $1}'", filename);
         if ((fptr = popen(cmd, "r")) == NULL)
            fprintf(stderr, "Cannot open pipe to test file.\n");
         fread(inbuf, 80, 1, fptr);
         pclose(fptr);
         lines = atoi(inbuf);
         if (size == 768)
            havefile = BINARY_MAP;
         else if (lines == 256)
            havefile = ASCII_MAP;
         else {
            fprintf(stderr, "Unknown map type.\n");
            havefile = 0;
            return;
            }
/*
 * Make a dummy image and fill it with the color map values.
 */
         icop.image.width = 100;
         icop.image.height = 256;
         icop.image.origbuf = (unsigned long *)malloc(icop.image.width*icop.image.height*sizeof(long));
         fptr = fopen(filename, "r");
         for (y=255; y>=0; y--) {
            if (havefile == BINARY_MAP)
               fread(rgb, 1, 3, fptr);
            else {
               fscanf(fptr, "%d %d %d", &r, &g, &b);
               rgb[0] = r;
               rgb[1] = g;
               rgb[2] = b;
               }
            for (x=0; x<=99; x++)
               icop.image.origbuf[x+y*icop.image.width] =
                            (int)rgb[0] | (int)rgb[1] << 8 | (int)rgb[2] << 16;
            }
         fclose(fptr);
         }
      ResizeImage(icop.image.width, icop.image.height);
      nbytes = icop.image.width*icop.image.height*sizeof(long);
      icop.image.legalbuf	= (unsigned long*)malloc(nbytes);
      icop.image.illegalbuf	= (unsigned long*)malloc(nbytes);
      icop.image.correctedbuf	= (unsigned long*)malloc(nbytes);
      DrawPlotCB(icop.plot.w, (XtPointer)NULL, (char *)NULL);
      FillImageBuffs();
      ShowImageCB(icop.image.w, (XtPointer)NULL, (char *)NULL);
      }
}


static void
ImgorMapCB(Widget w, XtPointer client_data, char *call_data)
{
   Arg args;

   if (!((XmToggleButtonCallbackStruct *)call_data)->set)
      return;
   if (!strcmp(client_data, "img"))
      XtSetArg(args, XmNpattern, XmStringCreateSimple("*.[gjrst][gilp][abefgi]*"));
   else
      XtSetArg(args, XmNpattern, XmStringCreateSimple("*"));
   XtSetValues(osb, &args, 1);
}



static void
MakeOpenBox(void)
{
   Arg		args[10];
   int		n;
   Widget	work,
		frame,
		rc;
/*
 * Let the user pick a icop file name.
 */
   n = 0;
   osb = XmCreateFileSelectionDialog(icop.toplevel, "osb", args, n);
   XtUnmanageChild(XmFileSelectionBoxGetChild(osb, XmDIALOG_HELP_BUTTON));
   XtAddCallback(osb, XmNokCallback, unmanageCB, NULL);
   XtAddCallback(osb, XmNokCallback, CheckOpenCB, NULL);
   XtAddCallback(osb, XmNcancelCallback, unmanageCB, NULL);
/*
 * Add a rowcolumn thing to this selection box.
 */
   n = 0;
   work = XmCreateWorkArea(osb, "warea", args, n);
   XtManageChild(work);
/*
 * Inside the work area put some unique things for images.
 */
   frame = XtCreateManagedWidget("frame",xmFrameWidgetClass,     work,args,0);
   rc    = XtCreateManagedWidget("rc",   xmRowColumnWidgetClass,frame,args,0);
   img   = XtCreateManagedWidget("img",  xmToggleButtonWidgetClass,rc,args,0);
   map   = XtCreateManagedWidget("map",  xmToggleButtonWidgetClass,rc,args,0);

   XtAddCallback(img, XmNvalueChangedCallback, ImgorMapCB, "img");
   XtAddCallback(map, XmNvalueChangedCallback, ImgorMapCB, "map");
}


void
DumpWindowToSGI(char *filename, unsigned long *buffer)
{
   IMAGE	*oimage;
   long		xorg, yorg, width, height;
   int		y;
   unsigned long *scrbuf, *ss;

/* write the data to the image file */

   if ((longstoimage(buffer, icop.image.width, icop.image.height, 3, filename)) != 1)
      printf("ERROR: fileMenu problems writing to sgi image file.\n");
   free(scrbuf);
}


static void
CheckSaveCB(w, client_data, call_data)
Widget                          w;
XtPointer                       client_data;
XmSelectionBoxCallbackStruct    *call_data;
{
   char *filename;
   unsigned long *tmpbuf;
   int	i, y;
   char rgb[3];
   FILE *fptr;

   XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &filename);
   if ((int)filename[strlen(filename)-1] == '/' || strlen(filename) == 0)
      fprintf(stderr, "Aborting save...\n");
   else if (havefile == IMAGE_FILE) {
      if (XmToggleButtonGetState(XtNameToWidget(ssb, "warea.frame.radio.csave"))) {
         tmpbuf = (unsigned long *)malloc(icop.image.width*icop.image.height*sizeof(long));
         for (i=0; i<icop.image.width*icop.image.height; i++)
            tmpbuf[i] = icop.image.legalbuf[i] | icop.image.correctedbuf[i];
         DumpWindowToSGI(filename, tmpbuf);
         free(tmpbuf);
         }
      else if (XmToggleButtonGetState(XtNameToWidget(ssb, "warea.frame.radio.lsave")))
         DumpWindowToSGI(filename, icop.image.legalbuf);
      else if (XmToggleButtonGetState(XtNameToWidget(ssb, "warea.frame.radio.isave")))
         DumpWindowToSGI(filename, icop.image.illegalbuf);
      }
   else if (havefile == ASCII_MAP || havefile == BINARY_MAP) {
      fptr = fopen(filename, "w");
      for (y=255; y>=0; y--) {
         rgb[0] = (icop.image.legalbuf[y*icop.image.width] |
                   icop.image.correctedbuf[y*icop.image.width]) & 0xff;
         rgb[1] = (icop.image.legalbuf[y*icop.image.width] |
                   icop.image.correctedbuf[y*icop.image.width]) >> 8 & 0xff;
         rgb[2] = (icop.image.legalbuf[y*icop.image.width] |
                   icop.image.correctedbuf[y*icop.image.width]) >> 16 & 0xff;
         if (havefile == ASCII_MAP)
            fprintf(fptr, "%d %d %d\n", rgb[0], rgb[1], rgb[2]);
         else
            fwrite(rgb, 3, 1, fptr);
         }
      fclose(fptr);
      }
   XtFree(filename);
}



static struct {
   char		*name;		/* name of menu item widget */
   } savelist[] = {
      { "csave" },
      { "lsave" },
      { "isave" },
      };
/*      { "bsave" },*/

static void
MakeSaveBox(void)
{
   Arg		args[10];
   Widget	frame, radio, w;
   int		i, n;
/*
 * Let the user pick a script file name.
 */
   n = 0;
   ssb = XmCreateFileSelectionDialog(icop.toplevel, "ssb", args, n);
   XtUnmanageChild(XmFileSelectionBoxGetChild(ssb, XmDIALOG_HELP_BUTTON));
   XtAddCallback(ssb, XmNokCallback, unmanageCB, NULL);
   /*XtAddCallback(ssb, XmNokCallback, BusyCursorCB, NULL);*/
   XtAddCallback(ssb, XmNokCallback, CheckSaveCB, NULL);
   /*XtAddCallback(ssb, XmNokCallback, UnBusyCursorCB, NULL);*/
   XtAddCallback(ssb, XmNcancelCallback, unmanageCB, NULL);
/*
 * Add a rowcolumn thing to this file selection box.
 */
   n = 0;
   warea = XmCreateWorkArea(ssb, "warea", args, n);
   XtManageChild(warea);
/*
 * Inside the rowcolumn put a frame.
 */
   n = 0;
   frame = XmCreateFrame(warea, "frame", args, n);
   XtManageChild(frame);
/*
 * Inside the frame put a radio box.
 */
   n = 0;
   XtSetArg(args[n], XmNradioBehavior, True); n++;
   radio = XmCreateWorkArea(frame, "radio", args, n);
   XtManageChild(radio);
   n = 0;
   for (i=0; i<XtNumber(savelist); i++) {
      w = XtCreateWidget(savelist[i].name, xmToggleButtonWidgetClass, radio,
                            args, n);
      /*XtAddCallback(w, XmNarmCallback, RadioCB, savelist[i].name);*/
      XtManageChild(w);
      }
}

static void
OpenCB(Widget w, XtPointer client_data, char *call_data)
{
   if (osb == NULL)
      MakeOpenBox();
   XtManageChild(osb);
}

void
SaveAsCB(Widget w, XtPointer client_data, char *call_data)
{
   Arg args;

   if (!havefile)
      return;
   if (ssb == NULL)
      MakeSaveBox();
   if (havefile == IMAGE_FILE) {
      XtManageChild(warea);
      XtSetArg(args, XmNpattern, XmStringCreateSimple("*.[rs]g[bi]"));
      }
   else {	/* Must be a colormap */
      XtUnmanageChild(warea);
      XtSetArg(args, XmNpattern, XmStringCreateSimple("*"));
      }
   XtSetValues(ssb, &args, 1);
   XtManageChild(ssb);
}

static void
QuitCB(Widget w, XtPointer client_data, char *call_data)
{
   char cmd[80];

   sprintf(cmd, "rm -f %s", tmpname);
   system(cmd);
   exit(0);
}


static struct {
   char   *name;         /* name of menu item widget */
   void   (*func)(Widget, XtPointer, char*);      /* callback function */
   } list[] = {
      { "open",		OpenCB},
      { "saveas",	SaveAsCB},
      { NULL,		NULL},
      { "quit",		QuitCB}
      };

void
FileMenuInit(Widget parent)
{
   int		i, n;
   Arg		arg[10];
   Widget	fileMenu, w;
/*
 * Create pulldown menu.
 */
   n = 0;
   fileMenu = XmCreatePulldownMenu(parent, "fileMenu", arg, n);
/*
 * Create the entries for the file menu.
 */
   for (i = 0; i < XtNumber(list); i++) {
      if (list[i].name != NULL) {
         w = XmCreatePushButton(fileMenu, list[i].name, arg, 0);
         XtAddCallback(w, XmNactivateCallback, list[i].func, list[i].name);
         }
      else 
         w = XmCreateSeparator(fileMenu, "sep", arg, 0);
      XtManageChild(w);
      }
   n = 0;
   XtSetArg(arg[n], XmNsubMenuId, fileMenu); n++;
   w = XmCreateCascadeButton(parent, "file", arg, n);
   XtManageChild(w);
} /* FileMenuInit */
