/******************************************************************************
* 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.*;

/** CDFDump dumps the data contents in a CDF. Optionally, the output
    can exclude the information from attributes. 
 */

public class CDFDump 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 BorderLayout(), true);
    JPanel panel2n = new JPanel(new GridBagLayout(), true);
    JPanel panel2s = 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);

/** "Use Format" checkbox. */
    JCheckBox ufc = new JCheckBox("Use Format",true);
/** "About" checkbox. */
    JCheckBox abc = new JCheckBox("About");
    int abcX = 0;
/** "Run it Batch" checkbox. */
    JCheckBox bac = new JCheckBox("Run it Batch");
/** "Header" checkbox. */
    JCheckBox qec = new JCheckBox("Header",true);
/** "Col2Row" checkbox. */
    JCheckBox crc = new JCheckBox("Column-to-Row");
/** "Detect" checkbox. */
    JCheckBox dtc = new JCheckBox("Detect");
/** A label of "Style:" for the radio button group zmode. */
    JLabel STYLE = new JLabel("Style: ");

/** A label of "Dump:" for the radio button zmode. */
    JLabel DUMP = new JLabel("Dump:  ");
/** A group radio buttons for Dump. */
    ButtonGroup dump = new ButtonGroup();
/** A group radio buttons for Dump. */
    JRadioButton dump0 = new JRadioButton("All");
    JRadioButton dump1 = new JRadioButton("Data");
    JRadioButton dump2 = new JRadioButton("MetaData");
    JRadioButton dump3 = new JRadioButton("Global");
    JRadioButton dump4 = new JRadioButton("Variable");
/** A radio button panel for Dump. */
    JPanel dumpPanel = new JPanel(true);

/** A group radio buttons for Style. */
    ButtonGroup style = new ButtonGroup();
/** A group radio buttons for style. */
    JRadioButton style0 = new JRadioButton("iso8601");
    JRadioButton style1 = new JRadioButton("iso8601/z");
/** A radio button panel for style. */
    JPanel stylePanel = new JPanel(true);

/** A label of "Precision:" for the text field Precision. */
    JLabel PRECISION = new JLabel("Significant #: ");
/** Text field for entering optional variable names. */
    JTextField precision = new JTextField("",2);

/** A label of "Vars:" for the text field vars. */
    JLabel VARS = new JLabel("Variables: ");
/** Text field for entering optional variable names. */
    JTextField vars = new JTextField("",20);

/** A label of "Rec Ranges:" for the text field vars. */
    JLabel RECS = new JLabel("Rec Ranges: ");
/** Text field for entering optional variable names. */
    JTextField recs = new JTextField("",20);

/** "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 source CDF file. */
    JButton slt1 = new JButton("Select");
/** "Select2" button for selecting the output file. */
    JButton slt2 = new JButton("Select");

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

/** iext field for entering the mandatory source CDF file name. */
    JTextField cdf = new JTextField("", 40);
/** Text field for entering the optional destination output file name. */
    JTextField outf = new JTextField("", 40);

/** A label of "CDF:" for the text field cdf (source CDF). */
    JLabel CDF = new JLabel("CDF: ");
/** A label of "Output File:" for the text field outf (output file). */
    JLabel OUTF = new JLabel("Output File: ");

/** 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 filter = new SimpleFileFilter(cdfs,
                                                " CDF files (*.cdf, *.CDF)");
/** The command string. */
    String command = "cdfdump ";
    String commandX;
    String[] cmds = new String[3];

/** Environment variable for the current directory. */
    String currentdir = System.getProperty("user.dir");
/** The file separator. */
    String separator = System.getProperty("file.separator");
    String struf = "-format ";
    String strcr = " ";
    String strqe = " ";
    String strdp = "all ";
    String strdt = " ";
    String cdfspec = " ";
    String filespec = "";
    String xxx = " ";
    String cdfDelimiter = "";
    String strvars = "";
    String strrecs = "";
    String strprec = "";
    String strsty = "0";
    String yyy;
    String zzz;

/** 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;

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

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

    CDFDump(JFrame parentDriver, String cdfbase) {
        this(parentDriver, cdfbase, defaultModal);
    }

    CDFDump(JFrame parentDriver, String cdfbase, 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 + "cdfdump ";
	else
	  command = "cdfdump ";
        dialog = new JDialog(this, modal);
	this.parentDriver = parentDriver;
        this.modal = modal;
    }

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

    private void buildGUI() {

        WindowListener l = new WindowAdapter() {
           public void windowClosing(WindowEvent e) {
	      if (macLib == 1) new File(libcdfPath).delete();
	      if (frommain == 0) {
                if (modal) dialog.dispose();
                else dialog.setVisible(false);
		if (parentDriver != null) parentDriver.setVisible(true);
	      } else {
		System.exit(1);
	      }
	   }
        };
        dialog.addWindowListener(l);
        dialog.setTitle("Enter   Parameters/qualifiers  for  CDFdump");
        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);

        // Initialize the dump radio button.
        DumpListener dumpListener = new DumpListener();
        dump0.setActionCommand("all");
        dump1.setActionCommand("data");
        dump2.setActionCommand("metadata");
        dump3.setActionCommand("global");
        dump4.setActionCommand("variable");
        dump0.addActionListener(dumpListener);
        dump1.addActionListener(dumpListener);
        dump2.addActionListener(dumpListener);
        dump3.addActionListener(dumpListener);
        dump4.addActionListener(dumpListener);
        dump0.setSelected(true);
        dump.add(dump0);
        dump.add(dump1);
        dump.add(dump2);
        dump.add(dump3);
        dump.add(dump4);
        DUMP.setToolTipText("Select how to dump the CDF");
        dump0.setToolTipText("Dump all information from the CDF");
        dump1.setToolTipText("Dump only variable data from the CDF");
        dump2.setToolTipText("Dump global and variable attributes from the CDF");
        dump3.setToolTipText("Dump global attributes from the CDF");
        dump4.setToolTipText("Dump variable attributes and entries from the CDF");
        dumpPanel.setLayout(new FlowLayout());
        dumpPanel.add(dump0);
        dumpPanel.add(dump1);
        dumpPanel.add(dump2);
        dumpPanel.add(dump3);
        dumpPanel.add(dump4);

        // Initialize the Style choice.

        StyleListener StyleListener = new StyleListener();
        style0.setActionCommand("0");
        style1.setActionCommand("1");
        style0.addActionListener(StyleListener);
        style1.addActionListener(StyleListener);
        style0.setSelected(true);
        style.add(style0);
        style.add(style1);
        style0.setToolTipText("Use ISO8601 form for date/time display");
        style1.setToolTipText("Use ISO8601 with z form for date/time display");

        stylePanel.setLayout(new FlowLayout());
        stylePanel.add(style0);
        stylePanel.add(style1);

        // Panel 1

	makeJButton(panel1, Box.createRigidArea(vpad5), 0, 0, 1, 1, 0.0, 0.0);
	makeJButton(panel1, CDF, 0, 1, 1, 1, 0.0, 0.0);
        makeJButton(panel1, cdf, 1, 1, 1, 1, 0.0, 0.0);
        makeJButton(panel1, slt1, 2, 1, 1, 1, 0.0, 0.0);
        makeJButton(panel1, OUTF, 0, 2, 1, 1, 0.0, 0.0);
        makeJButton(panel1, outf, 1, 2, 1, 1, 0.0, 0.0);
        makeJButton(panel1, slt2, 2, 2, 1, 1, 0.0, 0.0);
	makeJButton(panel1, Box.createRigidArea(vpad20), 0, 3, 1, 1, 0.0, 0.0);

        cdf.addActionListener(this);
        cdf.addFocusListener(this);
        cdf.addMouseListener(this);
        cdf.setToolTipText("Enter the source CDF (without extension) to dump");
        outf.addActionListener(this);
        outf.addFocusListener(this);
        outf.addMouseListener(this);
        outf.setToolTipText("Enter the output file (without extension) for dump");
        slt1.addActionListener(this);
        slt1.setToolTipText("Use the file chooser to select the source CDF");
        slt2.addActionListener(this);
        slt2.setToolTipText("Use the file chooser to select the output file");
        CDF.setFont(boldFont);
        cdf.setFont(boldFont);
        OUTF.setFont(boldFont);
        outf.setFont(boldFont);
	panelx.add(panel1,BorderLayout.NORTH);
	
        tpanel1.add(DUMP,BorderLayout.WEST);
        tpanel1.add(dumpPanel, BorderLayout.CENTER);
        tpanel1.add(Box.createRigidArea(hpad20), BorderLayout.EAST);

        // Panel 2

        makeJButton(panel2n, Box.createRigidArea(vpad5), 0, 0, 1, 1, 0.0, 0.0);
	makeJButton(panel2n, abc, 0, 1, 1, 1, 0.0, 0.0);
        makeJButton(panel2n, qec, 2, 1, 1, 1, 0.0, 0.0);
	makeJButton(panel2n, ufc, 4, 1, 1, 1, 0.0, 0.0);
	makeJButton(panel2n, crc, 6, 1, 1, 1, 0.0, 0.0);

        makeJButton(panel2n, dtc, 0, 2, 1, 1, 1.0, 1.0);

        makeJButton(panel2n, STYLE, 0, 3, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, stylePanel, 1, 3, 1, 1, 1.0, 1.0);

        makeJButton(panel2n, PRECISION, 0, 4, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, precision, 1, 4, 1, 1, 1.0, 1.0);
	makeJButton(panel2n, Box.createRigidArea(hpad5), 2, 4, 1, 1, 0.0, 0.0);
        makeJButton(panel2n, tpanel1, 3, 4, 1, 1, 0.0, 0.0);
        makeJButton(panel2n, Box.createRigidArea(vpad5), 4, 4, 1, 1, 0.0, 0.0);

        makeJButton(panel2s, Box.createRigidArea(vpad5), 0, 0, 1, 1, 0.0, 0.0);
        makeJButton(panel2s, VARS, 0, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2s, vars, 1, 1, 2, 1, 1.0, 1.0);
        makeJButton(panel2s, RECS, 0, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel2s, recs, 1, 2, 2, 1, 1.0, 1.0);
        makeJButton(panel2s, Box.createRigidArea(vpad20), 0, 4, 1, 1, 1.0, 1.0);

        panel2.add(panel2n, BorderLayout.NORTH);
        panel2.add(panel2s, BorderLayout.SOUTH);

        ufc.addItemListener(this);
	ufc.setToolTipText("Select to use FORMAT attribute when displaying variable data");
        crc.addItemListener(this);
	crc.setToolTipText("Select to show column-major file in row-major form. Otherwise, show the data in their order in the file.");
	abc.addItemListener(this);
        abc.setToolTipText("Display the current version");
        qec.addItemListener(this);
        qec.setToolTipText("Remove the 1-line header \"Dumping cdf from ...\" from the dump report");
        bac.addItemListener(this);
        bac.setToolTipText("Select to set up and run the dump by a batch job");
        dtc.addItemListener(this);
        dtc.setToolTipText("Select to detect and show only if the file is bad, otherwise no output");
        precision.addActionListener(this);
        precision.addMouseListener(this);
        precision.addFocusListener(this);
        PRECISION.setToolTipText("Enter the maximum significant number for showing floating-point values if FORMAT attribute entry is not available.");
        vars.addActionListener(this);
        vars.addMouseListener(this);
        vars.addFocusListener(this);
        vars.setToolTipText("Enter the comma-separated variable names in the CDF to be dumped");
        recs.addActionListener(this);
        recs.addMouseListener(this);
        recs.addFocusListener(this);
        recs.setToolTipText("Enter the comma-separated record range for all variables in the CDF to be dumped");

        VARS.setToolTipText("Enter the comma-separated variable names in the CDF to be dumped");
        VARS.setFont(boldFont);
        vars.setFont(boldFont);
        RECS.setToolTipText("Enter the comma-separated record range for all variables in the CDF to be dumped");
        RECS.setFont(boldFont);
        recs.setFont(boldFont);

        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);
	panel3.add(Box.createRigidArea(vpad30),BorderLayout.CENTER);

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

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

                public Dimension getPreferredSize() {
                   return new Dimension(80, 80);
                }
                public float getAlignmentX() {
                   return LEFT_ALIGNMENT;
                }
        };
        scroller.getViewport().add(info);
  	info.setVisible(true);

  	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("");
	cdf.setText("");
	outf.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 (macLib == 1) new File(libcdfPath).delete();
	     if (frommain == 0) {
                if (modal) dialog.dispose();
                else dialog.setVisible(false);
		if (parentDriver != null) parentDriver.setVisible(true);
	     } else {
		System.exit(1);
	     }
	}
	else if (obj == slt1 || obj == slt2) { // for "Select 1|2" button
             if (obj == slt1) { // for "Select1" button
		doFileChooser("Select/enter the CDF", cdf, 1, filter);
             } else { // for "Select2" button
		doFileChooser("Select/enter the output file", outf, 1, null);
             }
	} else if (obj == helpb || obj == menuHelpHelp) { // for "Help" 
		commandX = command + "-java";
		hlp = 1;
		iba = 0;
                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
                cdfspec = cdf.getText();
                filespec = outf.getText();
                strvars = vars.getText();
                strrecs = recs.getText();

                if (cdfspec.equals("") || cdfspec.trim().equals("")) {
                  info.setText("");
                  info.append("Please enter a CDF file for dump...");
                  Toolkit.getDefaultToolkit().beep();
                  return;
                }
                if (iba == 1) { // a batch run
                  boolean togo = true;
                  if (filespec.equals("") || filespec.trim().equals("")) {
                    togo = false;
                    info.append("Please enter an output file for a batch run...");
                    Toolkit.getDefaultToolkit().beep();
                  }
                  if (!togo) return;
                }
		xxx = " ";
		if (!filespec.equals("") && !filespec.trim().equals("")) {
                  filespec = filespec.trim();
                  String fileDelimiter;
                  if (filespec.startsWith("'")) fileDelimiter = " ";
                  else if (filespec.startsWith("\"")) fileDelimiter = " ";
                  else fileDelimiter = "\"";
                  xxx = "-output " + fileDelimiter + filespec +
                        fileDelimiter + " ";
                  iba = 1;
		}
                if (strvars.equals("") || strvars.trim().equals("")) 
                  yyy = " ";
                else
                  yyy = "-vars '" + strvars.trim() + "' ";

                if (strrecs.equals("") || strrecs.trim().equals(""))
                  zzz = " ";
                else
                  zzz = "-recordrange '" + strrecs.trim() + "' ";

		if (cdfspec.startsWith("'")) cdfDelimiter = " ";
		else if (cdfspec.startsWith("\"")) cdfDelimiter = " ";
		else cdfDelimiter = "\"";
		
		if (ufc.isSelected())
		  struf = "-format ";
		else {
		  struf = "-noformat ";
                  precision.setText("");
                }

		if (dtc.isSelected())
		  strdt = "-detect ";
		else
		  strdt = " ";

		if (crc.isSelected())
		  strcr = "-col2row ";
		else {
		  strcr = " ";
                }

		if (qec.isSelected())
		  strqe = "-header ";
		else
		  strqe = "-noheader ";

                strprec = "";
                if (struf.indexOf("noformat") == -1) {
                  String precValue = precision.getText().trim();
                  if (precValue.length() > 0) 
                    strprec = new StringBuffer("-significant ").append(precValue).toString();
                }
		commandX = command + strdt + struf + strqe + "-dump " + strdp + " " + 
                           xxx + yyy + " " + zzz + " " + 
                           (strsty.equals("1")?"-ziso8601 ":"") +
                           strprec +
                           " " + strcr + cdfDelimiter + cdfspec + cdfDelimiter;

                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 == cdf) {
		cdfspec = cdf.getText();
	} else if (obj == outf) {
                filespec = outf.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) {
		    info.setText("Where to paste to?");
                    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 Dump
 */

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

/** Action for radio buttons for Style
 */

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

/** Action for checkboxs selection
 */

    public void itemStateChanged(ItemEvent evt) {
	Object obj = evt.getSource();
	if (obj == abc) { // "About" checkbox
	   if (abc.isSelected()) {
		abcX = 1;
		iba = 0;
                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 == ufc) { // "Use Format" checkbox
           if (ufc.isSelected())
                struf = "-format ";
           else {
                struf = "-noformat ";
                precision.setText("");
           }
        } else if (obj == dtc) { // "Use Format" checkbox
           if (dtc.isSelected())
                strdt = "-detect ";
           else
                strdt = " ";
        } else if (obj == crc) { // "Column-to-Row" checkbox
           if (crc.isSelected())
                strcr = "-col2row ";
           else {
                strcr = " ";
           }
        } else if (obj == qec) { // "Header" checkbox
           if (qec.isSelected())
                strqe = "-header ";
           else
                strqe = "-noheader ";
	} 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) {
        focused = (JTextField)e.getSource();
        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]);
           info.setText("");
           Dimension dialogSize = dialog.getSize();
           ((JComponent)(dialog.getContentPane())).paintImmediately(
                                            0, 0, dialogSize.width, dialogSize.height);
           BufferedReader inStream = null;
           InputStreamReader inReader = new InputStreamReader(process.getInputStream(), "UTF-8");
           String line = null;
           inStream = new BufferedReader(inReader, 8192);
	   boolean first = true;	
           while ((line = inStream.readLine()) != null) {
		if (first) {
			info.setText("");
			first =false;
		}
                info.append(line+"\n");
	   }
           process.waitFor();
	   info.setCaretPosition(0);
           scroller.getViewport().setView(info);
           scroller.revalidate();
           scroller.repaint();

           if (iba == 1) {
                String outofpgm = info.getText().toLowerCase().trim();
                if (outofpgm.indexOf("error") != -1 || 
                    outofpgm.indexOf("fail") != -1)
                  info.append("ERROR: Dump file is not created\n"); 
                else
                  info.append("Done!\n\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(CDFDump.class.getResource("CDF_Logo3.gif")));
           fileView.putIcon("CDF",
                            new ImageIcon(CDFDump.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);
              } 
	      fileChooser.setCurrentDirectory(selectedFile);
              textField.setText(myfile);
           }
        } else {
        }
    }

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

    static public void main(String[] args) {
        cdfbase = System.getProperty("CDF_BASE");
        if (cdfbase == null)
            cdfbase = CDFToolsUtil.getenv("CDF_BASE");
	CDFDump thispgm = new CDFDump(null, cdfbase);
	thispgm.fileChooser.setCurrentDirectory(new File(thispgm.currentdir));
	thispgm.frommain = 1;
	thispgm.run();

    }

}

