/******************************************************************************
* Copyright 1996-2014 United States Government as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All Rights Reserved.
******************************************************************************/

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import javax.swing.*;
import java.awt.datatransfer.*;

/** CDFcompare displays the differences in two CDFs.
 */

public class CDFCompare extends JFrame  
                         implements ActionListener, ItemListener, 
				    MouseListener, FocusListener, Runnable  {

    static final long serialVersionUID = 1L;
    static int macLib = 0;
    static String cdfbase = null;
    static String libcdfPath = null;

    JFrame parentDriver;
/** The dialog for user interface. */
    JDialog dialog;

/** The FileChooser for the file selection. */
    JFileChooser fileChooser = new JFileChooser();

    JPanel panelx = new JPanel(new BorderLayout(), true);
/** The panel for text fields and selectable buttons which goes to dialog's
    north portion. */
    JPanel panel1 = new JPanel(new GridBagLayout(), true);
/** The panel containing all checkboxes goes to dialog's center portion. */
    JPanel panel2 = new JPanel(new GridBagLayout(), true);
/** The panel containing panel31 and text area goes to dialog's south portion. */
    JPanel panel3 = new JPanel(new BorderLayout(), true);
/** The panel containing enter/help/quit buttons. */
    JPanel panel31 = new JPanel(new GridLayout(1, 3, 50, 20), true);
    JPanel tpanel1 = new JPanel(new BorderLayout(), true);
    JPanel tpanel2 = new JPanel(new BorderLayout(), true);

/** "Page Output" checkbox. */
    JCheckBox pgc = new JCheckBox("Page Output", false);
/** "Compare Attributes" checkbox. */
    JCheckBox cac = new JCheckBox("Compare Attributes",true);
/** "Compare Variables" checkbox. */
    JCheckBox cvc = new JCheckBox("Compare Variables", true);
/** "Compare Numbers" checkbox. */
    JCheckBox cnc = new JCheckBox("Compare Numbers", true);
/** "Compare Etc." checkbox. */
    JCheckBox cec = new JCheckBox("Compare Etc.", true);
/** "Report Info's" checkbox. */
    JCheckBox ric = new JCheckBox("Report Info's");
    int ricX = 0;
/** "Report Warnings" checkbox. */
    JCheckBox rwc = new JCheckBox("Report Warnings", true);
    int rwcX = 1;
/** "Report Errors" checkbox. */
    JCheckBox rec = new JCheckBox("Report Errors", true);
    int recX = 1;
/** "Log Progress" checkbox. */
    JCheckBox lpc = new JCheckBox("Log Progress");
    int lpcX = 0;
/** "-0.0 to 0.0" checkbox. */
    JCheckBox zzc = new JCheckBox("-0.0 to 0.0");
/** "Display Locations" checkbox. */
    JCheckBox dlc = new JCheckBox("Display Locations");
    int dlcX = 0;
/** "Display Statistics" checkbox. */
    JCheckBox dsc = new JCheckBox("Display Statistics");
    int dscX = 0;
/** "Display Percentages" checkbox. */
    JCheckBox dpc = new JCheckBox("Display Percentages");
    int dpcX = 0;
/** "Display Values" checkbox. */
    JCheckBox dvc = new JCheckBox("Display Values");
    int dvcX = 0;
/** "About" checkbox. */
    JCheckBox abc = new JCheckBox("About");
    int abcX = 0;
/** "Run it Batch" checkbox. */
    JCheckBox bac = new JCheckBox("Run it Batch");

/** A group radio buttons for zMode1. */
    ButtonGroup zmodex = new ButtonGroup();
/** A group radio buttons for zMode1. */
    JRadioButton zmodex0 = new JRadioButton("Off");
    JRadioButton zmodex1 = new JRadioButton("On/1");
    JRadioButton zmodex2 = new JRadioButton("On/2");
/** A radio button panel for zMode1. */
    JPanel zmode1Panel = new JPanel(true);
/** A group radio buttons for zMode2. */
    ButtonGroup zmodey = new ButtonGroup();
/** A radio button panel for zMode2. */
    JRadioButton zmodey0 = new JRadioButton("Off");
    JRadioButton zmodey1 = new JRadioButton("On/1");
    JRadioButton zmodey2 = new JRadioButton("On/2");
    JPanel zmode2Panel = new JPanel(true);

/** "Enter" button. */
    JButton entrb = new JButton(" Enter ");
/** "Help" button. */
    JButton helpb = new JButton(" Help ");
/** "Quit" button. */
    JButton quitb = new JButton(" Quit ");
/** "Select1" button for selecting the original CDF file. */
    JButton slt1 = new JButton("Select");
/** "Select2" button for selecting the comparing CDF file. */
    JButton slt2 = new JButton("Select");
/** "Select3" button for selecting the output file. */
    JButton slt3 = new JButton("Select");

/** Text area for information. */
    JTextArea info = new JTextArea(20,40);

/** Text field for entering optional cache sizes. */
    JTextField cachesizes = new JTextField("",20);
/** Text field for entering the mandatory original CDF file name. */
    JTextField cdf1 = new JTextField("", 40);
/** Text field for entering the mandatory compared CDF file name. */
    JTextField cdf2 = new JTextField("", 40);
/** Text field for entering the output file name for running it a batch. */
    JTextField outf = new JTextField("", 40);

/** A label of "CDF1:" for the original CDF text field. */
    JLabel CDF1 = new JLabel("CDF1:");
/** A label of "CDF2:" for the compared CDF text field. */
    JLabel CDF2 = new JLabel("CDF2:");
/** A label of "Output:" for the compared CDFs text field. */
    JLabel OUTF = new JLabel("Output:");
/** A label of "Cache Sizes:" for the cache sizes text field. */
    JLabel CASS = new JLabel("Cache Sizes:");
/** A label of "zMode1:" for the radio button zmode1. */
    JLabel zMode1 = new JLabel("zMode1:  ");
/** A label of "zMode2:" for the radio button zmode2. */
    JLabel zMode2 = new JLabel("zMode2:  ");

/** Scroll pane for the text area. */
    JScrollPane scroller; 

/** Hold valid extensions for the CDF files for the file chooser. */
    String[] cdfs = {"cdf", "CDF"};

/** A file filter for the file chooser. */
    SimpleFileFilter cdffilter = new SimpleFileFilter(cdfs, " CDF files (*.cdf, *.CDF)");

/** The command string. */
    String command = "cdfcompare ";
    String commandX;

/** Environment variable for the current directory. */
    String currentdir = System.getProperty("user.dir");

/** Environment variable for CDF_BASE. */
//    cdfbase = System.getProperty("CDF_BASE");

/** The file separator. */
    String separator = System.getProperty("file.separator");

    String strpo = "-nopage ";
    String strca = "-attr ";
    String strcv = "-var ";
    String strcn = "-number ";
    String strce = "-etc ";
    String strri = "";
    String strrw = "w";
    String strre = "e";
    String strlp = " ";
    String strzz = " ";
    String strdl = " ";
    String strds = " ";
    String strdp = " ";
    String strdv = " ";
    String strcs = "";
    String strz1 = "0";
    String strz2 = "0";
    String strba = "";
    String report, zmodes, caches, temp;
    String Caches = " ";
    String cdfspec1 = " ";
    String cdfspec2 = " ";
    String filespec = "";
    String cdfDelimiter1, cdfDelimiter2;
    String[] cmds = new String[3];

/** A platform-dependent Runtime object. */
    Runtime runtime = Runtime.getRuntime();
/** A separate process to run the command. */
    Process process = null;
    int hlp = 0;
    int iba = 0;

/** The text field is currently getting the focus. */
    JTextField focused = null;
/** The text field previously was focused. */
    JTextField prevfocused = null;

/** Menu bar. */
    JMenuBar menuBar = new JMenuBar();
/** A menu: File. */
    JMenu menuFile = new JMenu("File");
/** A menu: Edit. */
    JMenu menuEdit = new JMenu("Edit");
/** A menu: Help. */
    JMenu menuHelp = new JMenu("Help");
/** An Edit menu item: Copy. */
    JMenuItem menuEditCopy = new JMenuItem("Copy");
/** An Edit menu item: Cut. */
    JMenuItem menuEditCut = new JMenuItem("Cut");
/** An Edit menu item: Paste. */
    JMenuItem menuEditPaste = new JMenuItem("Paste");
/** A File menu item: Exit. */
    JMenuItem menuFileExit = new JMenuItem("Exit");
/** A Help menu item: Help. */
    JMenuItem menuHelpHelp = new JMenuItem("Help");
    int istart = -1;
    int iend = -1;

    Dimension hpad5 = new Dimension(5,1);
    Dimension hpad10 = new Dimension(10,1);
    Dimension hpad20 = new Dimension(20,1);
    Dimension hpad25 = new Dimension(25,1);
    Dimension hpad30 = new Dimension(30,1);
    Dimension hpad40 = new Dimension(40,1);
    Dimension hpad80 = new Dimension(80,1);
    Dimension vpad5 = new Dimension(1,5);
    Dimension vpad10 = new Dimension(1,10);
    Dimension vpad20 = new Dimension(1,20);
    Dimension vpad25 = new Dimension(1,25);
    Dimension vpad30 = new Dimension(1,30);
    Dimension vpad40 = new Dimension(1,40);
    Dimension vpad80 = new Dimension(1,80);

    Font  defaultFont = new Font("Dialog", Font.PLAIN, 12);
    Font  boldFont = new Font("Dialog", Font.BOLD, 12);
    Font  bigFont = new Font("Dialog", Font.PLAIN, 18);
    Font  bigboldFont = new Font("Dialog", Font.BOLD, 18);
    static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    static int INITIAL_WIDTH = 600;
    static int INITIAL_HEIGHT = 400;
/** The default dialog modal (is set to false). */
    static boolean defaultModal = false;
/** The current dialog modal. */
    boolean modal;
    int frommain = 0;

    CDFCompare() {
        this(null, null, defaultModal);
    }

    CDFCompare(JFrame parentDriver) {
        this(parentDriver, null, defaultModal);
    }

    CDFCompare(JFrame parentDriver, String basecdf) {
	this(parentDriver, basecdf, defaultModal);
    }

    CDFCompare(JFrame parentDriver, String basecdf, boolean modal) {
        if (cdfbase == null) {
          cdfbase = System.getProperty("CDF_BASE");
          if (cdfbase == null)
            cdfbase = CDFToolsUtil.getenv("CDF_BASE");
        }
        if (cdfbase != null)
          command = cdfbase + separator + "bin" + separator + "cdfcompare ";
        else
          command = "cdfcompare ";

	dialog = new JDialog(this, modal);
        this.modal = modal;
	this.parentDriver = parentDriver;
    }

/** Set up the GUI stuff for user selection.
 */

    private void buildGUI() {

        WindowListener l = new WindowAdapter() {
           public void windowClosing(WindowEvent e) {
              if (frommain == 0) {
                if (modal) dialog.dispose();
                else dialog.setVisible(false);
		if (parentDriver != null) parentDriver.setVisible(true);
              } else {
		if (macLib == 1) new File(libcdfPath).delete();
		System.exit(1);
	      }
	   }
        };
        dialog.addWindowListener(l);
        dialog.setTitle("Enter   Parameters/qualifiers  for  CDFcompare");
        dialog.setSize(INITIAL_WIDTH, INITIAL_HEIGHT);
        dialog.setLocation(screenSize.width/2 - INITIAL_WIDTH/2,
                          screenSize.height/2 - INITIAL_HEIGHT/2);
	dialog.getContentPane().setLayout(new BorderLayout());

	// set the menu bar
	dialog.setJMenuBar(menuBar);

	// add the file menu
	menuBar.add(menuFile);

	// add the menu items to file
	menuFile.add(menuFileExit);
	menuFileExit.addActionListener(this);

	// add the edit menu
	menuBar.add(menuEdit);

	// add the menu items to edit
	menuEdit.add(menuEditCopy);
	menuEdit.add(menuEditCut);
	menuEdit.add(menuEditPaste);
	menuEditCopy.addActionListener(this);
	menuEditCut.addActionListener(this);
	menuEditPaste.addActionListener(this);

	// add the help menu
	menuBar.add(menuHelp);
	
	// add the menu items to help
	menuHelp.add(menuHelpHelp);
	menuHelpHelp.addActionListener(this);

        // Panel 1

        makeJButton(panel1, Box.createRigidArea(vpad5), 0, 0, 1, 1, 1.0, 1.0);
	makeJButton(panel1, CDF1, 0, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel1, cdf1, 1, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel1, slt1, 2, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel1, CDF2, 0, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel1, cdf2, 1, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel1, slt2, 2, 2, 1, 1, 1.0, 1.0);
//      makeJButton(panel1, OUTF, 0, 3, 1, 1, 1.0, 1.0);
//      makeJButton(panel1, outf, 1, 3, 1, 1, 1.0, 1.0);
//	makeJButton(panel1, slt3, 2, 3, 1, 1, 1.0, 1.0);
        makeJButton(panel1, Box.createRigidArea(vpad20), 0, 4, 1, 1, 1.0, 1.0);
        cdf1.addActionListener(this);
	cdf1.addFocusListener(this);
	cdf1.addMouseListener(this);
        cdf1.setToolTipText("Enter the first CDF (without extension) to compare");
        cdf2.addActionListener(this);
	cdf2.addFocusListener(this);
	cdf2.addMouseListener(this);
        cdf2.setToolTipText("Enter the second CDF (without extension) to compare");
//        outf.addActionListener(this);
//      outf.addFocusListener(this);
//      outf.addMouseListener(this);

        slt1.addActionListener(this);
        slt1.setToolTipText("Use the file chooser to select the first CDF");
        slt2.addActionListener(this);
        slt2.setToolTipText("Use the file chooser to select the second CDF");
//	slt3.addActionListener(this);
        CDF1.setLabelFor(cdf1);
        CDF1.setFont(boldFont);
        cdf1.setFont(boldFont);
        CDF2.setLabelFor(cdf2);
        CDF2.setFont(boldFont);
        cdf2.setFont(boldFont);
//      OUTF.setLabelFor(cdf2);
//      OUTF.setFont(boldFont);
//      outf.setFont(boldFont);

/*        dialog.getContentPane().add(panel1,BorderLayout.NORTH); */
        panelx.add(panel1, BorderLayout.NORTH);

        // Panel 2

        // Initialize the zMode1/2 buttons.
	
        ZMode1Listener zMode1Listener = new ZMode1Listener();
        zmodex0.setActionCommand("0");
        zmodex1.setActionCommand("1");
        zmodex2.setActionCommand("2");
        zmodex0.addActionListener(zMode1Listener);
        zmodex1.addActionListener(zMode1Listener);
        zmodex2.addActionListener(zMode1Listener);
        zmodex0.setSelected(true);

        zmodex.add(zmodex0);   // Add to a ButtonGroup
        zmodex.add(zmodex1);
        zmodex.add(zmodex2);

        zmodex0.setToolTipText("Use variables as-is in the first CDF");
        zmodex1.setToolTipText("Use zMode/1 for variables in the first CDF");
        zmodex2.setToolTipText("Use zMode/2 for variables in the first CDF");
        zmode1Panel.setLayout(new FlowLayout());
        zmode1Panel.add(zmodex0);
        zmode1Panel.add(zmodex1);
        zmode1Panel.add(zmodex2);

        ZMode2Listener zMode2Listener = new ZMode2Listener();
        zmodey0.setActionCommand("0");
        zmodey1.setActionCommand("1");
        zmodey2.setActionCommand("2");
        zmodey0.addActionListener(zMode2Listener);
        zmodey1.addActionListener(zMode2Listener);
        zmodey2.addActionListener(zMode2Listener);
        zmodey0.setSelected(true);
        zmodey.add(zmodey0);
        zmodey.add(zmodey1);
        zmodey.add(zmodey2);
        zmodey0.setToolTipText("Use variables as-is in the second CDF");
        zmodey1.setToolTipText("Use zMode/1 for variables in the second CDF");
        zmodey2.setToolTipText("Use zMode/2 for variables in the second CDF");
        zmode2Panel.setLayout(new FlowLayout());
        zmode2Panel.add(zmodey0);
        zmode2Panel.add(zmodey1);
        zmode2Panel.add(zmodey2);

	makeJButton(panel2, pgc, 0, 0, 1, 1, 1.0, 1.0);    // Page Output
        makeJButton(panel2, ric, 1, 0, 1, 1, 1.0, 1.0);    // Report Info
        tpanel1.add(zMode1,BorderLayout.WEST);
        tpanel1.add(zmode1Panel, BorderLayout.CENTER);
        tpanel1.add(Box.createRigidArea(hpad5), BorderLayout.EAST);
        makeJButton(panel2, tpanel1, 2, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2, cac, 0, 1, 1, 1, 1.0, 1.0);    // Compare Attributes
        makeJButton(panel2, rwc, 1, 1, 1, 1, 1.0, 1.0);    // Report Warnings
        tpanel2.add(zMode2,BorderLayout.WEST);
        tpanel2.add(zmode2Panel, BorderLayout.CENTER);
        tpanel2.add(Box.createRigidArea(hpad5), BorderLayout.EAST);
        makeJButton(panel2, tpanel2, 2, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2, cvc, 0, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel2, rec, 1, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel2, dlc, 2, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel2, cnc, 0, 3, 1, 1, 1.0, 1.0);
        makeJButton(panel2, lpc, 1, 3, 1, 1, 1.0, 1.0);
        makeJButton(panel2, dsc, 2, 3, 1, 1, 1.0, 1.0);
        makeJButton(panel2, cec, 0, 4, 1, 1, 1.0, 1.0);
        makeJButton(panel2, zzc, 1, 4, 1, 1, 1.0, 1.0);
        makeJButton(panel2, dpc, 2, 4, 1, 1, 1.0, 1.0);
        makeJButton(panel2, dvc, 0, 5, 1, 1, 1.0, 1.0);
        makeJButton(panel2, abc, 1, 5, 1, 1, 1.0, 1.0);
//      makeJButton(panel2, bac, 2, 5, 1, 1, 1.0, 1.0);
        makeJButton(panel2, Box.createRigidArea(vpad10), 0, 6, 1, 1, 1.0, 1.0);
        makeJButton(panel2, CASS, 0, 7, 1, 1, 1.0, 1.0);
        makeJButton(panel2, cachesizes, 1, 7, 2, 1, 1.0, 1.0);
        makeJButton(panel2, Box.createRigidArea(vpad20), 0, 8, 2, 1, 1.0, 1.0);

        CASS.setLabelFor(cachesizes);
        CASS.setFont(boldFont);
        cachesizes.setFont(boldFont);

	pgc.addItemListener(this);
        pgc.setToolTipText("Select to display the output one page at a time -- not avaiable for Java");
        ric.addItemListener(this);
        ric.setToolTipText("Select to report informational messages from the CDF library calls");
        cac.addItemListener(this);
        cac.setToolTipText("Select to compare attributes between the two CDFs");
        rwc.addItemListener(this);
        rwc.setToolTipText("Select to report warning messages from the CDF library calls");
	cvc.addItemListener(this);
        cvc.setToolTipText("Select to compare variables between the two CDFs");
        rec.addItemListener(this);
        rec.setToolTipText("Select to report error messages from the CDF library calls");
        dlc.addItemListener(this);
        dlc.setToolTipText("Select to display the locations where the values differ");
        cnc.addItemListener(this);
        cnc.setToolTipText("Select to display numbering differences between attributes and variables");
        lpc.addItemListener(this);
        lpc.setToolTipText("Select to display the progress of the comparison");
        dsc.addItemListener(this);
        dsc.setToolTipText("Select to display caching statistics after comparison");
        cec.addItemListener(this);
        cec.setToolTipText("Select to compare other differences between the two CDFs, e.g., encoding, format, etc.");
        zzc.addItemListener(this);
        zzc.setToolTipText("Select to compare -0.0 with 0.0 between the two CDFs");
        dpc.addItemListener(this);
        dpc.setToolTipText("Select to display the comparison percentage of a variable");
        cachesizes.addActionListener(this);
	cachesizes.addMouseListener(this);
	cachesizes.addFocusListener(this);
        cachesizes.setToolTipText("Enter the cache sizes for dotCDF, staging and compression scratch files in 512 bytes buffer");
        dvc.addItemListener(this);
        dvc.setToolTipText("Select to display values if a difference is detected for attributes and variables");
        abc.addItemListener(this);	
        abc.setToolTipText("Display the current version");
//	bac.addItemListener(this);

/*        dialog.getContentPane().add(panel2,BorderLayout.CENTER);*/
        panelx.add(panel2, BorderLayout.CENTER);

        // Panel 3 (buttons and text area)

        panel31.add(entrb);
        panel31.add(helpb);
        panel31.add(quitb);
  	panel3.add(panel31, BorderLayout.NORTH);

        // Listen for events on buttons
        entrb.addActionListener(this);
        entrb.setToolTipText("Run CDFCompare");
        helpb.addActionListener(this);
        helpb.setToolTipText("Get the complete help information");
        quitb.addActionListener(this);
        quitb.setToolTipText("Exit CDFCompare");

	// Text Area
  	info.setEditable(false);
  	info.setVisible(true);
        scroller = new JScrollPane() {
                static final long serialVersionUID = 1L;

                public Dimension getPreferredSize() {
                   return new Dimension(80, 160);
                }
                public float getAlignmentX() {
                   return LEFT_ALIGNMENT;
                }
        };
        scroller.getViewport().add(info);
/*        panel3.add(scroller, BorderLayout.SOUTH); */
        panelx.add(panel3, BorderLayout.SOUTH);

        dialog.getContentPane().add(panelx, BorderLayout.NORTH);
        dialog.getContentPane().add(scroller, BorderLayout.CENTER);
    }

/** Implement the run method for Runabout interface.
 */

    public void run() {
	buildGUI();
        dialog.pack();
	fileChooser.setCurrentDirectory(new File(currentdir));
        dialog.setVisible(true);
	if (parentDriver != null) parentDriver.setVisible(false);
    }

/** Reenter from the main toolkit driver. Reset the dialog to visible.
 */

    public void reEnter() {
	dialog.setVisible(true);
	if (parentDriver != null) parentDriver.setVisible(false);
        info.setText("");
	cdf1.setText("");
	cdf2.setText("");
	outf.setText("");
	cachesizes.setText("");
    }


/** Action for buttons or menu items selection
 */

    public void actionPerformed(ActionEvent evt) {
	Object obj = evt.getSource();
	if (obj == quitb || obj == menuFileExit) { // for "Quit" or "Exit"
             if (frommain == 0) {
                if (modal) dialog.dispose();
                else dialog.setVisible(false);
		if (parentDriver != null) parentDriver.setVisible(true);
             } else {
		if (macLib == 1) new File(libcdfPath).delete();
		System.exit(1);
	     }
	} else if (obj == slt1 || obj == slt2 || obj == slt3) { // "Select 1|2|3" button
             if (obj == slt1) // "Select1" button for CDF1
                doFileChooser("Select/enter the first CDF", cdf1, 1, cdffilter);
             else if (obj == slt2) // "Select2" button for CDF2
                doFileChooser("Select/enter the second CDF", cdf2, 1, cdffilter);
             else // "Select3" button for Output
		doFileChooser("Select/enter the output file", outf, 1, null);
	} else if (obj == helpb || obj == menuHelpHelp) { // for "Help" 
		commandX = command + "-java";
                hlp = 1;
                String OS = System.getProperty("os.name").toLowerCase();
                if (OS.indexOf("windows") != -1) {
                    cmds[0] = commandX;
                } else if (OS.indexOf("vms") != -1) {
                    cmds[0] = commandX;
                } else {
                    cmds[0] = "/bin/sh";
                    cmds[1] = "-c";
                    cmds[2] = commandX;
                }
                runit(cmds);
                // runit(commandX);
		hlp = 0;
	} else if (obj == entrb) { // for "Enter" button
                cdfspec1 = cdf1.getText();
                cdfspec2 = cdf2.getText();

                if ((cdfspec1.equals("") || cdfspec1.trim().equals("")) ||
                    (cdfspec2.equals("") || cdfspec2.trim().equals(""))) {
                  info.setText("");
                  info.append("Please enter two source CDF files to compare...");
                  Toolkit.getDefaultToolkit().beep();
                  return;
                }

		temp = strri + strrw + strre;
		if (temp.length() == 0) report = " ";
		else if (temp.length() == 3) report = "-report \"i,w,e\" ";
		else if (temp.length() == 1) {
		   if (strri.length() == 1) report = "-report \"i\" ";
		   if (strrw.length() == 1) report = "-report \"w\" ";
		   if (strre.length() == 1) report = "-report \"e\" ";
		} else {
		   if (strri.length() == 0) report = "-report \"w,e\" ";
		   if (strrw.length() == 0) report = "-report \"i,e\" ";
		   if (strre.length() == 0) report = "-report \"i,w\" ";
		}
		zmodes = "-zmodes " + strz1 + "," + strz2 + " ";

                strcs = cachesizes.getText();
                if (strcs.equals("") || strcs.trim().equals("")) Caches = " ";
                else if (caches.startsWith("\"") || caches.startsWith("\'"))
                    	  Caches = "-cache " + caches.substring(1,caches.length()-2) + " ";
                     else Caches = "-cache " + caches + " ";

                if (cdfspec1.startsWith("'")) cdfDelimiter1 = " ";
                else if (cdfspec1.startsWith("\"")) cdfDelimiter1 = " ";
                else cdfDelimiter1 = "\"";
                if (cdfspec2.startsWith("'")) cdfDelimiter2 = " ";
                else if (cdfspec2.startsWith("\"")) cdfDelimiter2 = " ";
                else cdfDelimiter2 = "\"";

		commandX = command + strpo + strca + strcv + strcn +
                           strce   + strlp + strzz + strdl + strds +
                           strdp   + strdv + report + zmodes + 
			   // Caches  + " " + cdfspec1 + " " + cdfspec2;
			   Caches  + cdfDelimiter1 + cdfspec1 + 
			   cdfDelimiter1+ " " + cdfDelimiter2 + 
			   cdfspec2 + cdfDelimiter2;
                String OS = System.getProperty("os.name").toLowerCase();
                if (OS.indexOf("windows") != -1) {
                    cmds[0] = commandX;
                } else if (OS.indexOf("vms") != -1) {
                    commandX = commandX.replace('-', '/');
                    cmds[0] = commandX;
                } else {
                    cmds[0] = "/bin/sh";
                    cmds[1] = "-c";
                    cmds[2] = commandX;
                }
		runit(cmds);
		// runit(commandX);
	} else if (obj == cdf1) {
		cdfspec1 = cdf1.getText();
	} else if (obj == cdf2) {
                cdfspec2 = cdf2.getText();
	} else if (obj == cachesizes) {
		strcs = cachesizes.getText();
        } else if (obj == menuEditCopy) {
                if (istart == -1) {
		    info.setText("Where to copy from?");
		    Toolkit.getDefaultToolkit().beep();
                } else {
                    focused.setSelectionStart(istart);
                    focused.setSelectionEnd(iend);
                    focused.copy();
                }
        } else if (obj == menuEditCut) {
                if (istart == -1) {
		    info.setText("What to cut?");
		    Toolkit.getDefaultToolkit().beep();
                } else {
                    focused.setSelectionStart(istart);
                    focused.setSelectionEnd(iend);
                    focused.cut();
                }
        } else if (obj == menuEditPaste) {
		if (focused == null) {
		    Toolkit.getDefaultToolkit().beep();
		} else {
                  if (istart != -1) {
                    focused.setSelectionStart(istart);
                    focused.setSelectionEnd(iend);
                  }
                  String tempN;
                  try {
                    tempN = (String) Toolkit.getDefaultToolkit().
                                    getSystemClipboard().getContents(this).
                                    getTransferData(DataFlavor.stringFlavor);
                    if (tempN == null) { // no clipboard text
                        info.setText("No current selection on clipboard");
                        Toolkit.getDefaultToolkit().beep();
                    } else if (tempN.indexOf("\n") != -1) { // multiple lines
                        info.setText("Multiple lines selection on clipboard - not allowed:");
                        info.append("\n\n");
                        info.append(tempN);
                        Toolkit.getDefaultToolkit().beep();
                    } else { focused.paste();}
                  } catch (Exception e) {}
                }
	}
    }

/** Action for radio buttons for zMode
 */

    class ZMode1Listener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           strz1 = e.getActionCommand();
        }
    }

/** Action for radio buttons for zMode
 */

    class ZMode2Listener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           strz2 = e.getActionCommand();
        }
    }

/** Action for checkboxs and comboboxes selection
 */

    public void itemStateChanged(ItemEvent evt) {
	Object obj = evt.getSource();
	if (obj == pgc) { // "Page Output" checkbox
	      if (pgc.isSelected()) {
		info.setText("Page output is not allowed in Java");
		pgc.setSelected(false);
		Toolkit.getDefaultToolkit().beep();
	      }
	} else if (obj == ric) { // "Report Info's" checkbox
              if (ric.isSelected()) {
		strri = "i";
		ricX = 1; 
	      } else {
		strri = "";
		ricX = 0;
	      }
        } else if (obj == rwc) { // "Report Warnings" checkbox 
              if (rwc.isSelected()) {
                strrw = "w";
		rwcX = 1;
              } else {
                strrw = "";
		rwcX = 0;
	      }
        } else if (obj == rec) { // "Report Errors" checkbox
              if (rec.isSelected()) {
                strre = "e";
		recX = 1;
              } else {
                strre = "";
		recX = 0;
	      }
        } else if (obj == cac) { // "Compare Attributes" checkbox
              if (cac.isSelected())
                strca = "-attr ";
              else
                strca = "-noattr ";
        } else if (obj == cvc) { // "Compare Variables" checkbox
              if (cvc.isSelected())
                strcv = "-var ";
              else
                strcv = "-novar ";
        } else if (obj == cnc) { // "Compare Numbers" checkbox
              if (cnc.isSelected())
                strcn = "-number ";
              else
                strcn = "-nonumber ";
	} else if (obj == cec) { // "Compare Etc." checkbox
              if (cec.isSelected())
                strce = "-etc ";
              else
                strce = "-noetc ";
	} else if (obj == lpc) { // "Log Progress" checkbox
              if (lpc.isSelected()) {
                strlp = "-log ";
		lpcX = 1;
              } else {
                strlp = "-nolog ";
		lpcX = 0;
	      }
	} else if (obj == zzc) { // "-0.0 to 0.0" checkbox
              if (zzc.isSelected())
                strzz = "-neg2posfp0 ";
              else
                strzz = "-noneg2posfp0 ";
	} else if (obj == dlc) { // "Display Locations" checkbox
              if (dlc.isSelected()) {
                info.setText("Please note: the program may be hung if the ");
                info.append("differences are too many...");
		Toolkit.getDefaultToolkit().beep();
                strdl = "-location ";
		dlcX = 1;
              } else {
		if (dlcX == 1) info.setText("");
                strdl = "-nolocation ";
		dlcX = 0;
	      }
	} else if (obj == dsc) { // "Display Statistics" checkbox
              if (dsc.isSelected()) {
                strds = "-statistics ";
		dscX = 1;
              } else {
                strds = "-nostatistics ";
		dscX = 0;
	      }
	} else if (obj == dpc) { // "Display Percentages" checkbox
              if (dpc.isSelected()) {
                strdp = "-percent ";
		dpcX = 1;
              } else {
                strdp = "-nopercent ";
		dpcX = 0;
	      }
	} else if (obj == dvc) { // "Display Values" checkbox
              if (dvc.isSelected()) {
                info.setText("Please note: the program may be hung if the ");
                info.append("differences are too many...");
                Toolkit.getDefaultToolkit().beep();
                strdv = "-value ";
		dvcX = 1;
              } else {
		if (dvcX == 1) info.setText("");
                strdv = "-novalue ";
		dvcX = 0;
	      }
        } else if (obj == abc) { // "About" checkbox
                if (abc.isSelected()) {
		  abcX = 1;
                  commandX = command + " -about";
                  String OS = System.getProperty("os.name").toLowerCase();
                  if (OS.indexOf("windows") != -1) {
                      cmds[0] = commandX;
                  } else if (OS.indexOf("vms") != -1) {
                      cmds[0] = commandX;
                  } else {
                      cmds[0] = "/bin/sh";
                      cmds[1] = "-c";
                      cmds[2] = commandX;
                  }
                  runit(cmds);
                  // runit(commandX);
                  abc.setSelected(false);
		  abcX = 0;
                }
        } else if (obj == bac) { // "Run it Batch" checkbox
                if (bac.isSelected()) {
                  iba = 1;
                  if (outf.getText().equals("")) {
                     info.setText("");
                     info.append("Please enter an output file for a batch run...");
                     Toolkit.getDefaultToolkit().beep();
                  }
                } else
                  iba = 0;
	}
    }

    public void focusGained(FocusEvent e) {
        Object focusedObj =  e.getSource();
        if (focusedObj instanceof JTextField) {
          focused = (JTextField) focusedObj;
          if (prevfocused != null) {
            prevfocused.setText(prevfocused.getText());
            if (iend != -1)
                if (iend < focused.getText().length())
                             prevfocused.setCaretPosition(iend);
                else focused.setCaretPosition(focused.getText().length());
	  }
        }
    }

    public void focusLost(FocusEvent e) {
        if (istart != -1)     {
            focused.setSelectionStart(istart);
            focused.setSelectionEnd(iend);
            prevfocused = focused;
          }
        }
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {
        if (focused != null) {
          String selectedText = focused.getSelectedText();
          if (selectedText!=null) {
            istart = focused.getSelectionStart();
            iend = focused.getSelectionEnd();
          } else {
            istart = -1;
            iend = -1;
          }
	}
    }

/** Set up gridbaglayout
 */

    private void makeJButton(Container cont, Object arg,
            int x, int y, int w, int h, double weightx, double weighty) {
        GridBagLayout gbl = (GridBagLayout)cont.getLayout();
        GridBagConstraints c = new GridBagConstraints();
        Component comp;

        c.fill = GridBagConstraints.BOTH;
        c.gridx = x;
        c.gridy = y;
        c.gridwidth = w;
        c.gridheight = h;
        c.weightx = weightx;
        c.weighty = weighty;
        if (arg instanceof String) {
            comp = new JButton((String)arg);
        } else {
            comp = (Component)arg;
        }
        cont.add(comp);
        gbl.setConstraints(comp, c);
    }

/** Execute a command as a separate process for the user selection and returns
    the results in the text area.
 */

    private void runit(String[] command) {
    // private void runit(String command) {
        try {
           String osName = System.getProperty("os.name");
           String cwd = System.getProperty("user.dir");
           libcdfPath = cwd + "/libcdf.dylib";
           if (osName.toLowerCase().indexOf("mac") != -1) {
               File libcdf = new File(libcdfPath);
               if (libcdf.exists()) {
                   macLib = 0;
               } else {
                 if (Files.isWritable(Paths.get(cwd))) {
                   try {
                     cdfbase = System.getProperty("CDF_BASE");
                     if (cdfbase == null)
                         cdfbase = CDFToolsUtil.getenv("CDF_BASE");
                     Files.copy(Paths.get(cdfbase+"/lib/libcdf.dylib"),
                                Paths.get(libcdfPath),
                                StandardCopyOption.REPLACE_EXISTING);
                     macLib = 1;
                   } catch (Exception ex) {
                     System.out.println ("**** Error for copying... "+ex);
                   }
                 }
               }
           }

           if (command[1] != null)
                  process = runtime.exec(command);
           else
                  process = runtime.exec(command[0]);
           Dimension dialogSize = dialog.getSize();
           ((JComponent)(dialog.getContentPane())).paintImmediately(
                                                0, 0, dialogSize.width, dialogSize.height);

           InputStreamReader inReader = new InputStreamReader(process.getInputStream(), "UTF-8");
           BufferedReader inStream = new BufferedReader(inReader, 8192);
		  boolean first = true;
           String line = null;
           while ((line = inStream.readLine()) != null) {
		if (first) {
			info.setText("");
			first = false;
		}
                      info.append(line+"\n");
	   }
           process.waitFor();
	   info.setCaretPosition(0);
           if (process.exitValue() == 1) {
		    Toolkit.getDefaultToolkit().beep();
		    info.append("ERROR: error is detected... job failed\n");
	   } 
        } catch (Exception e) {
                info.setText("error executing: "+e);
                Toolkit.getDefaultToolkit().beep();
        }
    }

/** Initiate the file chooser and strip the extension for the selected file
    if necessary
 */

    private void doFileChooser (String title, JTextField textField, int theone, SimpleFileFilter filter) {
	ExampleFileView fileView = new ExampleFileView();
        fileChooser.setDialogTitle(title);
        if (filter != null) {
	  fileChooser.addChoosableFileFilter(filter);
	  fileChooser.setFileFilter(filter);
	}
	try {
	   fileView.putIcon("cdf", 
			    new ImageIcon(CDFCompare.class.getResource("CDF_Logo3.gif")));
	   fileView.putIcon("CDF", 
			    new ImageIcon(CDFCompare.class.getResource("CDF_Logo3.gif")));
	   fileChooser.setFileView(fileView);
	} catch (Exception e) {}

        int returnValue = fileChooser.showDialog(dialog, "OK");
        if (returnValue == JFileChooser.APPROVE_OPTION) {
          File selectedFile = fileChooser.getSelectedFile();
          if (selectedFile != null) {
              int ind;
              String myfile = selectedFile.getAbsolutePath();
              if (theone == 1) { // for .cdf file
                ind = myfile.lastIndexOf(".cdf");
                if (ind != -1) myfile = myfile.substring(0, ind);
                ind = myfile.lastIndexOf(".CDF");
                if (ind != -1) myfile = myfile.substring(0, ind);
              } else { // for .skt file
                ind = myfile.lastIndexOf(".skt");
                if (ind != -1) myfile = myfile.substring(0, ind);
                ind = myfile.lastIndexOf(".SKT");
                if (ind != -1) myfile = myfile.substring(0, ind);
              }
              textField.setText(myfile);
	      fileChooser.setCurrentDirectory(selectedFile);
          }
        } else {
//        JOptionPane.showMessageDialog(dialog, "No file chosen");
        }
    }

/** This class can run as an application by its own.
 */

    static public void main(String[] args) {

        String cdfbase = System.getProperty("CDF_BASE");
        if (cdfbase == null) 
          cdfbase = CDFToolsUtil.getenv("CDF_BASE");

        CDFCompare thispgm = new CDFCompare(null, cdfbase);
	thispgm.fileChooser.setCurrentDirectory(new File(thispgm.currentdir));
        thispgm.frommain = 1;
	thispgm.run();
    }
}

