
/* Generated by Interface Builder */

/*
 * Some of this code is essentially copied from the AtYourService example
 * of Henry Krempel.
 */

#import "PlotDelegate.h"
#import "ServicesHandler.h"
#import "Plot.h"
#import "FormatHandler.h"
#import "PlotView.h"
#import "ScrollWindow.h"             // added 10-7-91 by pdhowell
#import <appkit/Application.h>
#import <appkit/Listener.h>
#import <appkit/Speaker.h>
#import <appkit/Pasteboard.h>
#import <appkit/Panel.h>
#import <strings.h>
#import <appkit/appkit.h>
#import <appkit/Form.h>
#import <defaults.h>
#import <streams/streams.h>
#import <appkit/nextstd.h>
#import <appkit/Application.h>
#import <sys/types.h>		/* only needed in the iconReleasedAt::: code */
#import <sys/stat.h>		/* ditto */

@implementation PlotDelegate

- appWillInit:sender
{
  // We used to do this in appDidInit, but ran into trouble when we got
  // the Workspace Manager to automatically run nxyplot on files with a
  // selected extension.  The problem was that the 3 windows which get
  // turned into ScrollWindows by the makeSomeScrollWindows method had not been
  // turned into ScrollWindows when a message was sent to them that only
  // a ScrollView (not an ordinary View) could understand.  The solution seems
  // to be to make them into ScrollWindows very early in the game, in the
  // appWillInit method.
  [plotParam makeSomeScrollWindows];

  NXUpdateDefaults();
  if (strncmp(NXGetDefaultValue("nxyplot", "colorOption"), "YES", 3) == 0) {
    [plotParam colorOn:YES];
    [colorOptionButton setState:1];
  }
  else {
    [plotParam colorOn:NO];
    [colorOptionButton setState:0];
  }
  if (strncmp(NXGetDefaultValue("nxyplot", "colorPrinting"), "YES", 3) == 0) {
    [printColorButton setState:1];
    [accPrintColorButton setState:1];
  }
  else {
    [printColorButton setState:0];
    [accPrintColorButton setState:0];
  }
  if (strncmp(NXGetDefaultValue("nxyplot", "cycleLineStyles"), "YES", 3) == 0) {
    [printLineStyleButton setState:1];
    [accPrintLineStyleButton setState:1];
  }
  else {
    [printLineStyleButton setState:0];
    [accPrintLineStyleButton setState:0];
  }
  if (strncmp(NXGetDefaultValue("nxyplot", "opaqueBackground"), "YES", 3) == 0) {
    [opaqueBackgroundButton setState:0];
  }
  else {
    [opaqueBackgroundButton setState:1];
  }

  return self;
}

- appDidInit:sender
{
  unsigned int windowNum;
  id           speaker;

  [[NXApp appListener] setServicesDelegate:self];
  [servicesHandler serviceSetState];

  [canvasWindow setMiniwindowIcon:"nxyplot.tiff"];
  [controlPanel setMiniwindowIcon:"nxyplot.tiff"];

  /*
   * Register our app icon window with the workspace, so we can accept
   * icons that get dropped on us.  From the Acceptor example in
   * NextDeveloper/Examples.
   */
  NXConvertWinNumToGlobal([[NXApp appIcon] windowNum], &windowNum);
  speaker = [NXApp appSpeaker];
  [speaker setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
  [speaker registerWindow:windowNum toPort:[[NXApp appListener] listenPort]];

  return self;
}

- resetDefaults:sender
{
  if ([colorOptionButton state] == 0) {
    NXWriteDefault("nxyplot", "colorOption", "NO");
    [plotParam colorOn:NO];
  }
  else {
    NXWriteDefault("nxyplot", "colorOption", "YES");
    [plotParam colorOn:YES];
  }
  if ([printColorButton state] == 0) {
    NXWriteDefault("nxyplot", "colorPrinting", "NO");
    [accPrintColorButton setState:0];
  }
  else {
    NXWriteDefault("nxyplot", "colorPrinting", "YES");
    [accPrintColorButton setState:1];
  }
  if ([printLineStyleButton state] == 0) {
    NXWriteDefault("nxyplot", "cycleLineStyles", "NO");
    [accPrintLineStyleButton setState:0];
  }
  else {
    NXWriteDefault("nxyplot", "cycleLineStyles", "YES");
    [accPrintLineStyleButton setState:1];
  }
  if ([opaqueBackgroundButton state] == 0) {
    NXWriteDefault("nxyplot", "opaqueBackground", "YES");
  }
  else {
    NXWriteDefault("nxyplot", "opaqueBackground", "NO");
  }

  return self;
}


/* This method takes data from a pasteboard and sends it to be plotted. */
- plotFromPasteboard:pb userData:(const char *)userData error:(char **)errorMessage
{
  char *data;
  int length;
  const char *const *types;
  int hasAscii, i;

  types = [pb types];
  hasAscii = 0;
  for (i = 0; !hasAscii && types[i] ; i++) 
    if (!strcmp(types[i], NXAsciiPboardType)
	|| !strcmp(types[i], NXTabularTextPboardType)) hasAscii = 1;

  if (hasAscii) {
    [pb readType:NXAsciiPboardType data:&data length:&length];

    if (data && length) {
      NXStream *dataStream = NXOpenMemory(data, length, NX_READONLY);
      if ([plotParam readData:dataStream :"pasteboard"] == 0) {
	NXRunAlertPanel("Read", "Couldn't read any data from %s", "OK",
			NULL, NULL, "pasteboard");
      }
      [plotParam plotPrepAndDraw];
    }
    else *errorMessage = "No data in your selection.";
  } 
  else *errorMessage = "No ASCII text found in your selection.";

  return self;
}

// The next 2 methods suggested by Ralph Zazula.  They are needed to get
// WorkspaceManager automatically to run nxyplot when you double-click on
// files with our registered extension(s).

- (BOOL)appAcceptsAnotherFile:sender
{
  return YES;
}

- (int)app:sender openFile:(const char *)fullPath type:(const char *)aType
{
  [plotParam openFile:(char *)fullPath :(char *)fullPath];
  return YES;
}

- getArgs
{
  int i, formatindex = 0, psindex = 0;
  NXStream *formatStream;
  BOOL quit = NO;

  [plotParam makeSomeScrollWindows]; /* must do this here! */
  NXUpdateDefaults();		/* ditto */
  if (strncmp(NXGetDefaultValue("nxyplot", "colorOption"), "YES", 3) == 0) {
    [plotParam colorOn:YES];
    [colorOptionButton setState:1];
  }
  else {
    [plotParam colorOn:NO];
    [colorOptionButton setState:0];
  }

  i = 1;
  while (i<NXArgc) {
    if (NXArgv[i][0] == '-') {
      if (NXArgv[i][1] == 'f') { /* format file */
	formatindex = ++i;
      }
      else if (NXArgv[i][1] == 'o') { /* eps file */
	psindex = ++i;
      }
      else if (NXArgv[i][1] == 'q') { /* quit after plotting */
	i++;
	quit = YES;
      }
      else if (NXArgv[i][1] == 'h') {
	NXLogError("usage: nxyplot file [file...] [-f formatfile] [-o epsfile] [-q] [-h]\n");
	exit(0);
      }
      else
	NXLogError("Unrecognized option %s\n", NXArgv[i++]);
    }
    else {
      if (NXMapFile(NXArgv[i], NX_READONLY) == NULL) {
	NXLogError("Unable to open file %s\n", NXArgv[i]);
      }
      else {
	[plotParam openFile:NXArgv[i] :NXArgv[i]];
      }
    }
    i++;
  }

  if (formatindex > 0)
    if ((formatStream = NXMapFile(NXArgv[formatindex], NX_READONLY)) == NULL)
      NXLogError("Unable to open format file %s\n", NXArgv[formatindex]);
    else
      [formatHandler readFormatData:formatStream];

  if (psindex > 0)
    [canvas savePSCode:NXArgv[psindex]];

  if (quit) {
    NXLogError("nxyplot: quit option selected\n");
    [NXApp free];
    exit(0);
  }
  else
    [plotParam drawPlot:self];

  return self;
}

/*
 * This is copied from the Listener section of the App Kit documentation.
 * All we do is save the pathname for later use.
 */
- (int)iconEntered:(int)windowNum at:(double)x :(double)y
    iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY
    iconWidth:(double)iconWidth iconHeight:(double)iconHeight
    pathList:(char *)pathList
{
  /* save the file's path for later use; there may be multiple files */
  /* If there are multiple files they are separated by tabs in pathList */

  /* allocate space for the path list and copy the string */
  iconPath = (char *)realloc((void *)iconPath, strlen(pathList)+1);
  strncpy(iconPath, pathList, strlen(pathList)+1);

  return 0;
}
   
- (int)iconExitedAt:(double)x :(double)y
{
  return 0;
}

/*
 * Try to plot the file(s) that have been dragged onto our icon.
 *
 * This note from the Draw example in NextDeveloper/Examples:
 *  Very important: an NX_DURING handler is required around all the processing
 *  of this method since an uncaught raised error will cause this method not
 *  to return and thus hang the Workspace Manager for a while.
 *
 * We also borrow some code from the ImageText MiniExample that checks
 * if a directory has been dragged in.
 */
- (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag
{
  char	 *stringPosition, *filename;
  struct stat statData;
  int    numfiles=1;

  *flag = 1;


  NX_DURING
  /*
   * If there are any tabs in the iconPath string, multiple files have
   * been dragged in and so we need to avoid the stat call (which returns
   * with an error if given multiple files).
   */
  stringPosition = iconPath;
  while (stringPosition = index(stringPosition, '\t')) {
    numfiles++;
    stringPosition++;
  }
  if (numfiles==1) {
    if (!strcmp(iconPath, "")) {
      /* an empty string means the user dragged root in; do nothing
       * except setting flag to 0 so workspace will reject this.
       */
      *flag = 0;
    }
    else {
      /* If we can't stat the file or if stat tells us the file is a
       * directory, set flag to 0.
       */
      if ( (stat(iconPath, &statData) == -1) || (statData.st_mode & S_IFDIR) ) {
	*flag = 0;
      }
    }
  }
  if (*flag == 1) {
    filename = iconPath;
    while (filename) {
      /*
       * Get the file names one by one and try plotting them.
       */
      stringPosition = strchr(filename, '\t'); /* returns first tab or NULL */
      if (stringPosition) {
	*stringPosition = '\0';
      }
      [plotParam openFile:filename :filename];
      filename = (stringPosition ? ++stringPosition : NULL);
    }
  }

  NX_HANDLER

  NX_ENDHANDLER

  return 0;
}

@end
