/*
 * DirFilePane.java
 *
 * Java based graphical user interface for the LTOOLS toolkit.
 * Requires Java 1.2 or newer. Does run as a standalone application, not as an applet.
 * Copyright (C) 1999-2006 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
 */
import java.awt. *;
import java.awt.dnd. *;
import java.awt.datatransfer. *;
//import java.awt.event. *;
import javax.swing. *;
import javax.swing.tree. *;
//import javax.swing.event. *;
import javax.swing.table. *;
import java.io. *;
import java.util. *;
import java.awt.Cursor;

/** The DirFilePane-class creates a Component with a JTree(which shows the
 * directory-structure), a JTable (which shows the content of the selected
 * directory in the tree) and a JLabel (which shows the selected directory as a String)
 * @author Werner Zimmermann
 * @author Joerg Holzapfel
 */
public class DirFilePane extends JComponent implements DropTargetListener, DragGestureListener, DragSourceListener
{   // ################################################################################################################ 
    // FIELDS 
    // ################################################################################################################ 
    static boolean DEBUG = false;				// true in DEBUG-mode 
    private boolean isLinux = false;				// true if linux-files are shown 
    static final int BUFSIZE = 32768;				// BUFSIZE for the socket connection 
    static final int startColumnLinuxFileName = 56;		// start column of LINUX filename in dirListing's lines 
    private static String currentDirectory;			// current selected directory in the tree 
    private static final String rootNodeText = "Computer";	// the text of the root-Node in the JTree 
    public static final ImageIcon ICON_COMPUTER =		// Icon for the Computer-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/computer.gif"));
    public static final ImageIcon ICON_DRIVE_FIXED =		// Icon for a fixedDrive-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/FIXED16x16.gif"));
    public static final ImageIcon ICON_DRIVE_CDROM =		// Icon for a CDROMDrive-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/CDROM16x16.gif"));
    public static final ImageIcon ICON_DRIVE_NOROOTDIR =	// Icon for a NoRootDirDrive-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/NOROOTDIR16x16.gif"));
    public static final ImageIcon ICON_DRIVE_RAMDISK =		// Icon for a RamDiskDrive-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/RAMDISK16x16.gif"));
    public static final ImageIcon ICON_DRIVE_REMOTE =		// Icon for a RemoteDrive-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/REMOTE16x16.gif"));
    public static final ImageIcon ICON_DRIVE_REMOVEABLE =	// Icon for a REMOVEABLEDrive-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/REMOVEABLE16x16.gif"));
    public static final ImageIcon ICON_DRIVE_UNKNOWN =		// Icon for a UnknownDrive-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/UNKNOWN16x16.gif"));
    public static final ImageIcon ICON_FOLDER =			// Icon for a Folder-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/FOLDER16x16.gif"));
    public static final ImageIcon ICON_EXPANDEDFOLDER =		// Icon for a ExpandedFolder-node in the JTree 
    new ImageIcon(LTOOLSgui.class.getResource("images/FOLDEROPENED16x16.gif"));

    private DefaultMutableTreeNode root;			// the root-node of the JTree 
    private JScrollPane jScrollPaneTree;			// the JScrollPane of the JTree 
    private JTree jTree;					// the JTree on the left side 
    private DefaultTreeModel treeModel;				// the DefaultTreeModel of the JTree 

    private JScrollPane jScrollPaneTable;			// the JScrollPane of the JTable 
    private JTable jTable;					// the JTable on the right side 
    private LToolGuiTableModel tableModel;			// the LToolGuiTableModel of the JTable 
    private JTableHeader jTableHeader;				// the JTableHeader of the JTable 
    private boolean sortOrder = true;				// sortOrder in the JTable (true asc, false desc) 
    private BorderLayout borderLayoutCenter;			//
    private JPanel jPanelDirectory ;                            //
    private BorderLayout borderLayoutPaneDir;			//
    // ###### context-menus
    private ContextMenuTable contextMenuTable;			// Contextmenu in the JTable if a file/directory is 
    // selected 
    private ContextMenuTree contextMenuTree;			// Contextmenu in the JTree 

    DragSource dragSource;					// variables for the Drag n Drop events 
    DropTarget dropTargetTree;
    DropTarget dropTargetTable;
    Vector dosDrives;						// the DOS-drives on the (local/remote) machine 

    // ################################################################################################################ 
    // CONSTRUCTORS 
    // ################################################################################################################ 
//* The Constructor creates an instance of the DirFilePane and builds up the GUI 
    public DirFilePane()
    {   //{{INIT_CONTROLS 
	setLayout(new BorderLayout(0, 0));
	Insets ins = getInsets();
	 setSize(430, 270);
	 JPanelDirectory.setLayout(new GridLayout(1, 1, 0, 0));
	 add(BorderLayout.NORTH, JPanelDirectory);
	 JPanelDirectory.setBounds(0, 0, 430, 15);
	 jLabelDirectory.setText("Directory:");
	 JPanelDirectory.add(jLabelDirectory);
	 jLabelDirectory.setBounds(0, 0, 430, 15);
	 jSplitPaneExplorer.setContinuousLayout(true);
	 jSplitPaneExplorer.setLastDividerLocation(100);
	 add(BorderLayout.CENTER, jSplitPaneExplorer);
	 jSplitPaneExplorer.setBounds(0, 15, 430, 255);
	//}} 

	//{{REGISTER_LISTENERS 
	//}} 
    }
    /** The Constructor creates an instance of the DirFilePane and builds up the GUI
     * @param isLinuxPanel sets the flag if it's a Linux-DirFilePane or a DOS-DirFilePane
     */
    public DirFilePane(boolean isLinuxPanel)
    {   this();
	// ########################################################################################## 
	//
	this.isLinux = isLinuxPanel ;

	jScrollPaneTree = new JScrollPane();
	jTree = new JTree();
	jScrollPaneTable = new JScrollPane();
	jTable = new JTable();

	jScrollPaneTree.setBounds(0,0,0,0);
	jScrollPaneTree.getViewport().add(jTree);
	jScrollPaneTable.setBounds(0,0,0,0);
	jScrollPaneTable.getViewport().add(jTable);
	jSplitPaneExplorer.add(jScrollPaneTree, JSplitPane.LEFT) ;
	jSplitPaneExplorer.add(jScrollPaneTable, JSplitPane.RIGHT) ;

	debugOutput("DirFilePane - NEW Version isLinuxPanel: " + isLinuxPanel) ;

	// JTree
	root = new DefaultMutableTreeNode();
	jScrollPaneTree = new JScrollPane();
	treeModel = new DefaultTreeModel(root);
	jTree = new JTree(treeModel);
	contextMenuTree = new ContextMenuTree(this);
	jTree.setScrollsOnExpand(true);
	jTree.addTreeSelectionListener(new LToolGuiTreeSelectionListener(this));
	jTree.addTreeWillExpandListener(new LToolGuiTreeWillExpandListener(this));
	jTree.addMouseListener(new LToolGuiTreeMouseListener(this));
	jTree.setRootVisible(false);				// Set the root-node "Computer" visible or not 

	// JTable 
	contextMenuTable = new ContextMenuTable(this);
	jScrollPaneTable = new JScrollPane();
	tableModel = new LToolGuiTableModel(isLinux);
	jTable = new JTable();					// tableModel 
	jTable.setShowGrid(false);				// don't show the grid 
	jTable.setAutoCreateColumnsFromModel(false);
	jTable.setModel(tableModel);
	for (int k = 0; k < LToolGuiTableModel.columns.length; k++)
        {   DefaultTableCellRenderer renderer = new LToolGuiTableCellRenderer();
	    LToolGuiTableColumnData col = (LToolGuiTableColumnData) LToolGuiTableModel.columns[k];
	     renderer.setHorizontalAlignment(col.getAlignment());
	    TableColumn column = new TableColumn(k, col.getWidth(), renderer, null);
	     jTable.addColumn(column);
	}
	jTable.addMouseListener(new LToolGuiTableMouseListener(this));
	 jTable.addKeyListener(new LToolGuiTableKeyListener(this));
	// jTable.addMouseMotionListener(new LToolGuiTableMouseMotionListener(this)) ; 
	// jTable.setDragEnabled(true) ; // since SunJava1.4 

	 dragSource = DragSource.getDefaultDragSource();
	 dragSource.createDefaultDragGestureRecognizer(jTable, DnDConstants.ACTION_COPY_OR_MOVE, this);
	 dropTargetTree = new DropTarget(jTree, this);
	 dropTargetTree = new DropTarget(jTable, this);

	 jTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);	// (ListSelectionModel.SINGLE_SELECTION) ; 
	 jTableHeader = jTable.getTableHeader();
	 jTableHeader.addMouseListener(new LToolGuiTableHeaderMouseListener(this));

	// ######################################################### 
	 borderLayoutCenter = new BorderLayout();
	 jPanelDirectory = new JPanel();
	 jLabelDirectory = new JLabel();
	 borderLayoutPaneDir = new BorderLayout();
	 this.setLayout(borderLayoutCenter);
	 jSplitPaneExplorer.setMaximumSize(new Dimension(200, 100));
	 jSplitPaneExplorer.setMinimumSize(new Dimension(200, 100));
	 jSplitPaneExplorer.setPreferredSize(new Dimension(200, 100));
	 jSplitPaneExplorer.setTopComponent(null);
	 jLabelDirectory.setHorizontalAlignment(SwingConstants.LEFT);
	 jLabelDirectory.setHorizontalTextPosition(SwingConstants.LEFT);
	 jLabelDirectory.setText("Directory:");
	 jPanelDirectory.setLayout(borderLayoutPaneDir);
	 this.add(jSplitPaneExplorer, BorderLayout.CENTER);
	 jSplitPaneExplorer.add(jScrollPaneTree, JSplitPane.LEFT);
	 jScrollPaneTree.getViewport().add(jTree, null);
	 jSplitPaneExplorer.add(jScrollPaneTable, JSplitPane.RIGHT);
	 jScrollPaneTable.getViewport().add(jTable, null);
	 this.add(jPanelDirectory, BorderLayout.NORTH);
	 jPanelDirectory.add(jLabelDirectory, BorderLayout.CENTER);
	 jSplitPaneExplorer.setDividerLocation(200);

	 try
        {   DirFilePane.DEBUG = LTOOLSgui.getDebug();

	    if (isLinux)
            {   fillLinuxDirectoryTree();
	    } else
            {   fillDosDirectoryTree();
	    }
	}
	catch(Exception e)
        {   e.printStackTrace();
	}
    }

    //{{DECLARE_CONTROLS 
    javax.swing.JPanel JPanelDirectory = new javax.swing.JPanel();
    javax.swing.JLabel jLabelDirectory = new javax.swing.JLabel();
    javax.swing.JSplitPane jSplitPaneExplorer = new javax.swing.JSplitPane();
    //}} 

    /** the getTreeNode()-method returns the DefaultMutableTreeNode with the given
     * TreePath
     * @param path the TreePath of the node
     * @return DefaultMutableTreeNode of the given TreePath
     */
    public DefaultMutableTreeNode getTreeNode(TreePath path)
    {   return (DefaultMutableTreeNode) (path.getLastPathComponent());
    }
    /** Deletes a Dos file or empty directory, Called by the Del button or menu item
     * @param item the file to delete represented by the ListItem in the JTable
     */
    public void deleteDosFile(ListItemFile item)		// public void deleteDosFile(TreePath path) 
    {   String caption = "LTOOLS";
	String currentFileFullPath = item.getFullFilePath();
	 debugOutput("deleteDosFile - " + currentFileFullPath);

	if (LTOOLSgui.myProg.confirmDelete)
        {   String msg = "Do you really want to delete \"" + item.getFullFilePath() + "\" ?";
	    if (JOptionPane.showConfirmDialog(LTOOLSgui.myProg, msg, caption,
					      JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)
		== JOptionPane.NO_OPTION)
            {   return;
	    }
	}
	File file = new File(currentFileFullPath);
	if (file.delete() == false)
        {   LTOOLSgui.beepSound();
	    String msg = "Could not delete file or directory \"" + item.getFullFilePath() + "\".";
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, caption, JOptionPane.ERROR_MESSAGE);
	    return;
	}
    }

    /** Delete a Linux file or empty directory, Called by the Del button or menu item
     * @param item the file to delete represented by the ListItem in the JTable
     */
    public void deleteLinuxFile(ListItemFile item)		// public void deleteLinuxFile(TreePath path) 
    {   String caption = "LTOOLS";
	String currentDrive = getLinuxDrive(item.getFullFilePath());
	String currentFileFullPath = getLinuxPath(item.getFullFilePath());
	 debugOutput("deleteLinuxFile \"" + currentDrive + " " + currentFileFullPath + "\"");

	if (item.isLink())
        {   currentFileFullPath = getLinuxPath(getLinkName(item.getFullFilePath()));
	}
	if (LTOOLSgui.isLinuxReadOnly == true)
        {   LTOOLSgui.beepSound();
	    String msg = "Your Linux filesystem is set to read only - change in menu 'File - Linux read only' first.";
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, caption, JOptionPane.ERROR_MESSAGE);
	    return;
	}
	if (LTOOLSgui.myProg.confirmDelete)
        {   String msg = "Do you really want to delete file \"" + item.getFullFilePath() + "\" ?";
	    if (JOptionPane.showConfirmDialog(LTOOLSgui.myProg, msg, caption,
					      JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)
		== JOptionPane.NO_OPTION)
            {   return;
	    }
	}
	String command = "ldir -WRITE -x -del -s" + currentDrive + " \"" + currentFileFullPath + "\"";
	command = execOperatingSystemCommand(command, false);
	if (command.length() > 0)
        {   LTOOLSgui.beepSound();
	    // if LTOOLS's command line tool issues an error message, show first line of response in message box 
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, command.trim(), caption, JOptionPane.ERROR_MESSAGE);
	    return;
	}
    }
    /** Modify the name or attributes of a Dos file or directory in a dialog
     * @param item the DOS-file to modify represented  by this ListItemFile in the JTable
     */
    public void modifyDosFile(ListItemFile item)
    {   debugOutput("modifyDosFile ");
	File file = new File(item.getFullFilePath());
	String fileDate = (new Date(file.lastModified())).toString();
	String fileLength = new Long(file.length()).toString();

	ModifyDosDialog dialog = new ModifyDosDialog(LTOOLSgui.myProg, false,
				      item.getFileName(), fileDate, fileLength, file.isDirectory(), !file.canWrite());
	 dialog.setVisible(true);

	if (dialog.getStatus() != ModifyDosDialog.OK)
        {   return;
	}
	if (!dialog.getFileName().equals(item.getFileName()))
        {   file.renameTo(new File(file.getParent() + file.separator + dialog.getFileName()));
	    if (item.isDirectory())
            {   refreshTreeNode();
	    }
	}
    }
    /** Modify the name or attributes of a Linux file or directory
     * @param item the Linux-file to modify represented  by this ListItemFile in the JTable
     */
    public void modifyLinuxFile(ListItemFile item)
    {   debugOutput("modifyLinuxFile");

	String fileName;
	if (item.isLink())
        {   fileName = getLinkName(item.getFileName());
	} else
        {   fileName = item.getFileName();
	}
	ModifyLinuxDialog dialog = new ModifyLinuxDialog(LTOOLSgui.myProg, false,
							 fileName, item.getFileLastModified(), item.getFileSize(),
							 item.getUserID(), item.getGroupID(), item.getAccess());
	dialog.setVisible(true);

	if (dialog.getStatus() != ModifyLinuxDialog.OK)
        {   return;
	}
	if (LTOOLSgui.isLinuxReadOnly == true)
        {   LTOOLSgui.beepSound();
	    String msg = "Your Linux filesystem is set to read only - change in menu 'File - Linux read only' first";
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, "LTOOLS", JOptionPane.ERROR_MESSAGE);
	    return;
	}
	String command = "ldir -WRITE ";
	if (!dialog.getFileName().equals(item.getFileName()))
        {   command = command + "-ren ";
	}
	command = command + "-x -s" + getLinuxDrive(item.getFullFilePath()) + " -f" + dialog.getAccess() + " ";
	if (!dialog.getGid().trim().equals(item.getGroupID().trim()))
        {   command = command + "-g" + dialog.getGid().trim() + " ";
	}
	if (!dialog.getUid().trim().equals(item.getUserID().trim()))
        {   command = command + "-u" + dialog.getUid().trim() + " ";
	}
	command = command + "\"" + getLinuxPath(item.getFullFilePath()) + "\" ";
	if (!dialog.getFileName().equals(item.getFileName()))
        {   command = command + "\"" + dialog.getFileName() + "\"";
	}
	command = execOperatingSystemCommand(command, false);
	if (command.length() > 0)
        {   LTOOLSgui.beepSound();
	    // if LTOOLS's command line tool issues an error message, show first line of response in message box 
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, command.trim(), "LTOOLS", JOptionPane.ERROR_MESSAGE);
	    return;
	}
	if (item.isDirectory())
        {   refreshTreeNode();
	}
    }

    /** Paste a Dos or Linux file into a DOS directory
     * @param issueMessages true if errormessages should be shown
     */
    public void pasteToDos(boolean issueMessages)
    {   debugOutput("pasteToDos()");
	String caption = "LTOOLS";
	boolean fileCopied = false;
	TreePath destinationTreePath;
	if (LTOOLSgui.getCopyToDirectory() == null)
        {   // LTOOLSgui.getCopyToDirectory() returns not null if by dragOver() was a TreePath set to copyToDirectory 
	    destinationTreePath = jTree.getSelectionPath();
	} else
        {   destinationTreePath = LTOOLSgui.getCopyToDirectory();
	}

	for (int k = 0; k < LTOOLSgui.copyListItemFiles.size(); k++)
        {   ListItemFile item = (ListItemFile) LTOOLSgui.copyListItemFiles.elementAt(k);
	    String sourcePath = item.getFullFilePath();
	    String targetPath = getName(destinationTreePath, false);
	    /*
	       debugOutput("*******************************************************************************************") ;
	       debugOutput("targetPath                  : " + targetPath) ;
	       debugOutput("LTOOLSgui.getCopyToDirectory: " + LTOOLSgui.getCopyToDirectory()) ;
	       debugOutput("jTree.getSelectionPath()    : " + jTree.getSelectionPath()) ;
	       debugOutput("destinationTreePath         : " + destinationTreePath)  ;
	       debugOutput("*******************************************************************************************") ;
	     */
	    if (!targetPath.endsWith(File.separator))
            {   targetPath = targetPath + File.separator;
	    }
	    debugOutput("pasteToDos: " + sourcePath + " --> " + targetPath + " as " + item.getFileName());
	    String targetFileFullPathname = targetPath + item.getFileName();

	    if (LTOOLSgui.copyFileIsLinux)			// Linux to Dos copy ---------------- 
            {   File test = new File(targetFileFullPathname);
		if (test.exists())
                {   debugOutput("File exists: sourcePath: " + sourcePath +
				" --- targetFileFullPathname: " + targetFileFullPathname);
		    String msg = "Overwrite existing file \"" + targetFileFullPathname + "\"" +
		    "\nwith \"" + sourcePath + "\"";
		    int response = JOptionPane.showConfirmDialog(LTOOLSgui.myProg, msg, "LTOOLS",
							     JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
		    if (response == JOptionPane.NO_OPTION)
                    {   continue;
		    }
		}
		String command;
		if (LTOOLSgui.isConnected() == false)
                {   // command = "ldir -READ -x -s" + LTOOLSgui.copyFileDrive + " \"" + sourcePath + "\" \"" + targetFileFullPathname+"\""; 
		    command = "ldir -READ -x -s" + getLinuxDrive(sourcePath) +
			" \"" + getLinuxPath(sourcePath) + "\" \"" + targetFileFullPathname + "\"";
		} else
                {   // command = "ldir -READ -x -s" + LTOOLSgui.copyFileDrive + " \"" + sourcePath + "\" " + "zzz.xxx"; 
		    command = "ldir -READ -x -s" + getLinuxDrive(sourcePath) +
			" \"" + getLinuxPath(sourcePath) + "\" " + "zzz.xxx";
		}
		command = execOperatingSystemCommand(command, false);
		if (command.length() > 0)
		{						// if LTOOLS's command line tool issues an error message, show first line of response in message box 
		    if (issueMessages)
                    {   LTOOLSgui.beepSound();
			JOptionPane.showMessageDialog(this, command.trim(),
						      "LTOOLS", JOptionPane.ERROR_MESSAGE);
		    }
		    break;
		}
		if (LTOOLSgui.isConnected())
                {   getFileFromHost(targetFileFullPathname);
		}
		fileCopied = true;
		debugOutput("File \"" + targetFileFullPathname + "\" copied.");
	    } else
		// Dos to Dos copy ------------------ 
            {   try
                {   File test = new File(targetFileFullPathname);
		    if (test.exists())
                    {   debugOutput("File exists: sourcePath: " + sourcePath + " --- targetFileFullPathname: " + targetFileFullPathname);
			String msg = "Overwrite existing file \"" + targetFileFullPathname + "\"" +
			"\nwith \"" + sourcePath + "\"";
			int response = JOptionPane.showConfirmDialog(LTOOLSgui.myProg, msg, "LTOOLS",
							     JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
			if (response == JOptionPane.NO_OPTION)
                        {   continue;
			}
		    }
		    FileInputStream fdIn = new FileInputStream(sourcePath);	// Open the files 
		    FileOutputStream fdOut = new FileOutputStream(targetFileFullPathname);
		    int i;
		    byte[]buffer = new byte[BUFSIZE];
		    do						// Read the source and write to target 
                    {   i = fdIn.read(buffer, 0, BUFSIZE);
			if (i < 0)
                        {   break;
			}
			fdOut.write(buffer, 0, i);
		    }
		    while (i > 0);
		    fdIn.close();
		    fdOut.close();
		    fileCopied = true;
		    debugOutput("File \"" + targetFileFullPathname + "\" copied.");
		}
		catch(java.io.FileNotFoundException e)
                {   if (issueMessages)
                    {   LTOOLSgui.beepSound();
			String msg = "Sorry, could not open file \"" + sourcePath + "\"";
			JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, caption, JOptionPane.ERROR_MESSAGE);
		    }
		    break;
		}
		catch(java.io.IOException e)
                {   if (issueMessages)
                    {   LTOOLSgui.beepSound();
			String msg = "Sorry, could not write to \"" + targetFileFullPathname + "\"";
			JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, caption, JOptionPane.ERROR_MESSAGE);
		    }
		    break;
		}
	    }
	}
	if (fileCopied)
        {   updateDOSJTable(getTreeNode(destinationTreePath));
	}
    }
    /** Paste a Dos or Linux file into a Linux directory
     * @param issueMessages true if errormessages should be shown
     */
    public void pasteToLinux(boolean issueMessages)		// public boolean pasteToLinux(TreePath path, boolean issueMessages) 
    {   debugOutput("pasteToLinux()");
	String caption = "LTOOLS";
	boolean fileCopied = false;

	if (LTOOLSgui.isLinuxReadOnly == true)
        {   LTOOLSgui.beepSound();
	    String msg = "Your Linux filesystem is set to read only - change in menu 'File - Linux read only' first.";
	     JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, caption, JOptionPane.ERROR_MESSAGE);
	     return;
	}
	TreePath destinationTreePath;
	if (LTOOLSgui.getCopyToDirectory() == null)
        {   // LTOOLSgui.getCopyToDirectory() returns not null if by dragOver() was a TreePath set to copyToDirectory 
	    destinationTreePath = jTree.getSelectionPath();
	} else
        {   destinationTreePath = LTOOLSgui.getCopyToDirectory();
	}

	for (int i = 0; i < LTOOLSgui.copyListItemFiles.size(); i++)
        {   ListItemFile item = (ListItemFile) LTOOLSgui.copyListItemFiles.elementAt(i);
	    String sourcePath;
	    if (LTOOLSgui.copyFileIsLinux)
            {   sourcePath = getLinuxPath(item.getFullFilePath());
	    } else
            {   sourcePath = item.getFullFilePath();
	    }

	    // DirectoryMutableTreeNode node = (DirectoryMutableTreeNode)getTreeNode(destinationTreePath) ; 
	    String currentDrive = getLinuxDrive(getLdirPath(destinationTreePath));
	    String targetPath = getLinuxPath(getLdirPath(destinationTreePath));
	    if (!targetPath.endsWith("/"))
            {   targetPath = targetPath + "/";
	    }
	    /*
	       debugOutput("*******************************************************************************************") ;
	       debugOutput("targetPath                  : " + targetPath) ;
	       debugOutput("LTOOLSgui.getCopyToDirectory: " + LTOOLSgui.getCopyToDirectory()) ;
	       debugOutput("jTree.getSelectionPath()    : " + jTree.getSelectionPath())  ;
	       debugOutput("destinationTreePath         : " + destinationTreePath)  ;
	       debugOutput("*******************************************************************************************") ;
	     */
	    String targetFile = item.getFileName();		// aktuelles LinuxVerzeichnis + item.getFileName() ; 

	    debugOutput("pasteToLinux " + sourcePath + " --> " + targetPath + " as " + targetFile);

	    if (LTOOLSgui.copyFileIsLinux)			// Linux to Linux copy---------------- 
            {   String command;
		//Copy the file from Linux to Dos 
		// command = "ldir -READ -x -s" + LTOOLSgui.copyFileDrive + " \"" + sourcePath + "\" " + "zzz.tmp"; 
		command = "ldir -READ -x -s" + getLinuxDrive(item.getFullFilePath());
		command = command + " \"" + getLinuxPath(item.getFullFilePath()) + "\" " + "zzz.tmp";
		command = execOperatingSystemCommand(command, false);

		if (command.length() > 0)
                {   // if LTOOLS's command line tool issues an error message, show first line of response in message box 
		    if (issueMessages)
                    {   LTOOLSgui.beepSound();
			JOptionPane.showMessageDialog(LTOOLSgui.myProg, command.trim(),
						      caption, JOptionPane.ERROR_MESSAGE);
		    }
		    break;
		}
		command = "ldir -WRITE -x -s" + currentDrive + " -copy " + "zzz.tmp" + " \"" + targetPath + targetFile + "\"";
		command = execOperatingSystemCommand(command, false);
		if (command.length() > 0)
                {   // if LTOOLS's command line tool issues an error message, show first line of response in messagebox 
		    if (issueMessages)
                    {   LTOOLSgui.beepSound();
			JOptionPane.showMessageDialog(LTOOLSgui.myProg, command.trim(), caption, JOptionPane.ERROR_MESSAGE);
		    }
		    break;
		}
		fileCopied = true;
		debugOutput("File \"" + targetPath + targetFile + "\" copied.");
	    } else
		// Dos to Linux copy 
            {   String command;
		if (LTOOLSgui.isConnected() == false)
                {   command = "ldir -WRITE -x -s" + currentDrive + " -copy \"" + sourcePath + "\" \"" + targetPath + targetFile + "\"";
		} else
                {   putFileToHost(sourcePath);
		    command = "ldir -WRITE -x -s" + currentDrive + " -copy " + "zzz.xxx" + " \"" + targetPath + targetFile + "\"";
		}
		command = execOperatingSystemCommand(command, false);
		if (command.length() > 0)
                {   // if LTOOLS's command line tool issues an error message, show first line of response in message box 
		    if (issueMessages)
                    {   LTOOLSgui.beepSound();
			JOptionPane.showMessageDialog(LTOOLSgui.myProg, command.trim(),
						      caption, JOptionPane.ERROR_MESSAGE);
		    }
		    break;
		}
		fileCopied = true;
		debugOutput("File \"" + targetPath + targetFile + "\" copied.");
	    }
	}
	// LTOOLSgui.copyFileIsValied = false ; 
	if (fileCopied)
        {   updateLinuxJTable(getTreeNode(destinationTreePath));
	}
    }
    /** Show all Linux partitions on all disks
     * @return returns a readable String of all partitions on the local (or remote machine if
     * connected to a remote server)
     */
    public String showPartitions()
    {   debugOutput("showPartitions()");
	String rawInfo = execOperatingSystemCommand("ldir -x -part", !LTOOLSgui.isConnected());		// true); 
	String partInfo = "*** Partition table info from LTOOLS: ***\n";
	String temp, temp1;
	String disk = "";

	int i = 0, j = 0, k = 0;
	while (true)
        {   i = rawInfo.indexOf("#", i);			//Find line starting with '#' 
	    if (i < 0)						//Bail out, if all lines have been scanned 
            {   break;
	    }
	    j = rawInfo.indexOf("\n", i);			//Find end of this line 

	    if ((k = rawInfo.substring(i, j).indexOf("Disk ")) > 0)	//Line containing disk info 
            {
//              temp = rawInfo.substring(i,j).substring(k+5,k+8); 
		disk = rawInfo.substring(i, j).substring(k + 11, k + 19);	//Get disk name 

		partInfo = partInfo + "------------------------------------------------\n";
	    } else if ((k = rawInfo.substring(i, j).indexOf("Type:")) > 0)	//Line containing partition info 
            {   temp1 = rawInfo.substring(i, j).substring(1, 4);	// Partition number 
		temp = rawInfo.substring(i, j).substring(k + 5, k + 25);	// Partition type 
		partInfo = partInfo + " " + disk + temp1 + " :   " + temp + "\n";
	    } else if ((k = rawInfo.substring(i, j).indexOf("RFSTOOL infos")) > 0)	//Line containing RFSTOOL header 
            {   partInfo = partInfo + "\n*** Partition table info from RFSTOOL: ***\n";
	    }
	    i = j;						//goto next line 
	}
	return partInfo;
    }

    /** Get a file "zzz.xxx" from a remote host
     * file will be stored as 'fileName'
     * @param fileName fileName - file from host will be stored as 'fileName'
     */
    void getFileFromHost(String fileName)
    {   debugOutput("getFileFromHost(\"" + fileName + "\")");
	String temp = "";
	int bytesRead = 0, bytesToRead, i, j;
	 byte[] buffer = new byte[BUFSIZE];

	 try
        {   temp = "SENDFILE" + "\n";
	    LTOOLSgui.qSend.write(temp, 0, temp.length());	//Send command to server 
	    LTOOLSgui.qSend.flush();

	    i = LTOOLSgui.bReceive.read(buffer, 0, BUFSIZE);	//Receive response 
	    temp = new String(buffer, 0, 32);			//Find out file length 
	    bytesToRead = Integer.parseInt(temp.substring(0, temp.indexOf('\n')));

	    for (j = 0; j < i; j++)				//Find the start of data in buffer 
            {   if (buffer[j] == 0x0D)				//DOS and UNIX files 
                {   if (buffer[j] == 0x0A)
                    {   j = j + 2;
			break;
		    } else
                    {   j = j + 1;
			break;
		    }
		}
		if (buffer[j] == 0x0A)
                {   if (buffer[j] == 0x0D)
                    {   j = j + 2;
			break;
		    } else
                    {   j = j + 1;
			break;
		    }
		}
	    }
	    FileOutputStream fd = new FileOutputStream(fileName);
	    bytesRead = i - j;
	    fd.write(buffer, j, bytesRead);

	    while (bytesRead < bytesToRead)
            {   i = LTOOLSgui.bReceive.read(buffer, 0, BUFSIZE);
		bytesRead = bytesRead + i;
		fd.write(buffer, 0, i);
	    }
	    fd.close();

	}
	catch(IOException excpt)
        {   System.err.println("Failed I/O " + excpt);
	    return;
	}
    }
    /** Extract a field from ldir's output
     * 0=mode 1=uid 2=gid 3=length ... 9=file/directory name
     * @param command it's a String representing the infos of a file from the output of ldir.exe
     * @param fieldNr the fieldNr of the command-String
     * @return returns the the String in fieldNr position of the command-string
     */
    public static String getLdirField(String command, int fieldNr)
    {   //debugOutput("****getLdirField"); 
	StringTokenizer token = new StringTokenizer(command, " ");
	String cmd;

	int i = 0;
	while (token.hasMoreTokens())
        {   cmd = token.nextToken();
	    if (i == 9)						//Special treatment for (long) filenames 
            {   cmd = command.substring(command.indexOf(cmd));
	    }
	    //debugOutput("i="+i+":  ---"+cmd+"---"); 
	    if (i == fieldNr)
            {   return cmd;
	    }
	    i++;
	}
	return "";
    }
    /** Converts a Dos or Linux path to a string representing the full pathname
     * @param path current TreePath in the Tree
     * @param isLinux true if it's a linux-path
     * @return String - a linux or a dos-path or "" if TreeNode "Computer" is selected
     */
    String getName(TreePath path, boolean isLinux)
    {   String currentFileFullPath, delimiter;

	if (isLinux)						// Linux-Path 
        {   delimiter = "/";
	    String drive = getLinuxDrive(path.getPathComponent(1).toString()) + " ";
	    if (path.getPathCount() >= 3)
            {   currentFileFullPath = drive + delimiter + path.getPathComponent(2).toString();	// Build the full pathname 
	    } else if (path.getPathCount() > 1)
            {   currentFileFullPath = drive + delimiter;
	    } else
            {   return "";
	    }
	    for (int i = 3; i < path.getPathCount(); i++)
            {   currentFileFullPath = currentFileFullPath + delimiter + path.getPathComponent(i);
	    }
	} else
	    // DOS-Path 
        {   delimiter = File.separator;
	    if (path.getPathCount() >= 3)			// Build the full pathname 
            {   currentFileFullPath = path.getPathComponent(1).toString() + path.getPathComponent(2).toString();
	    } else if (path.getPathCount() > 1)
            {   currentFileFullPath = path.getPathComponent(1).toString();
	    } else
            {   return "";
	    }
	    for (int i = 3; i < path.getPathCount(); i++)
            {   currentFileFullPath = currentFileFullPath + delimiter + path.getPathComponent(i);
	    }
	}
	return currentFileFullPath;
    }
    /** Make a new Dos directory
     * @param path The TreePath where a new DOS-directory should be added
     */
    void newDosDirectory(TreePath path)
    {   String directoryFullPathName = getName(path, false);
	if (directoryFullPathName.equals(""))
        {   return;
	} else if (!directoryFullPathName.endsWith(File.separator))
        {   directoryFullPathName = directoryFullPathName + File.separator;
	}
	debugOutput("newDosDirectory in directory: " + directoryFullPathName);

	ModifyDosDialog dialog = new ModifyDosDialog(LTOOLSgui.myProg, true, "", "", "", true, false);
	dialog.setVisible(true);

	if (dialog.getStatus() != ModifyDosDialog.OK)
        {   return;
	}
	if (!dialog.getFileName().equals(""))
        {   String newDir = directoryFullPathName + dialog.getFileName();
	    File directory = new File(newDir);
	    if (!directory.mkdir())
            {   LTOOLSgui.beepSound();
		String msg = "Could not create directory \"" + newDir + "\".";
		JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, "LTOOLS", JOptionPane.ERROR_MESSAGE);
	    }
	    updateTreeNode(path);
	}
    }
    /** Make a new Linux directory
     * @param path the TreePath to add a new directory to
     */
    void newLinuxDirectory(TreePath path)
    {   debugOutput("newLinuxDirectory");
	String msg = "Your Linux filesystem is set to read only - change in menu 'File - Linux read only' first";
	String caption = "LTOOLS";
	String driveDirectoryFullPathName = getName(path, true);	// returns "", if the TreeNode "Computer" is selected

	if (driveDirectoryFullPathName.equals(""))
        {   return;
	}
	String directoryFullPathName = getLinuxPath(driveDirectoryFullPathName);	// driveDirectoryFullPathName.substring(driveDirectoryFullPathName.indexOf(" ") + 1) ; 

	if (LTOOLSgui.isLinuxReadOnly == true)
        {   LTOOLSgui.beepSound();
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, caption, JOptionPane.ERROR_MESSAGE);
	    return;
	}
	ModifyLinuxDialog dialog = new ModifyLinuxDialog(LTOOLSgui.myProg, true, "", "", "", "0", "0", "-rwxr-xr-x");
	dialog.setVisible(true);

	if (dialog.getStatus() != ModifyLinuxDialog.OK)
        {   return;
	}
	if (LTOOLSgui.isConnected())
        {   putFileToHost("ldirtmpl");
	}
	String command = "ldir -WRITE ";
	if (dialog.isLink())
        {   command = command + "-link ";
	} else
        {   command = command + "-mkdir ";
	}
	command = command + "-x -s" + getLinuxDrive(driveDirectoryFullPathName) + " -f" + dialog.getAccess();
	command = command + " -g" + dialog.getGid().trim() + " -u" + dialog.getUid().trim() + " ";
	if (dialog.isLink())
        {   command = command + dialog.getTargetName() + " ";
	} else
        {   if (LTOOLSgui.isConnected())
            {   command = command + "zzz.xxx  ";
	    } else
            {   command = command + "ldirtmpl ";
	    }
	}
	if (directoryFullPathName.equals("/"))
        {   command = command + "\"" + directoryFullPathName + dialog.getFileName() + "\"";
	} else
        {   command = command + "\"" + directoryFullPathName + "/" + dialog.getFileName() + "\"";
	}
	if (dialog.getFileName().equals("") ||
	    (dialog.getFileName().indexOf("/") >= 0))
        {   LTOOLSgui.beepSound();
	    String message = "Invalid filename.";
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, message, caption, JOptionPane.ERROR_MESSAGE);
	} else
        {   command = execOperatingSystemCommand(command, false);
	    if (command.length() > 0)
            {   LTOOLSgui.beepSound();
		//if LTOOLS's command line tool0 issues an error message, show first line of response in message box 
		JOptionPane.showMessageDialog(LTOOLSgui.myProg, command.trim(), caption, JOptionPane.ERROR_MESSAGE);
		return;
	    }
	    updateTreeNode(path);
	}
    }
    /** the updateTreeNode-method collapses the node of this TreePath, removes all children, adds the directories
     * to this node, expands this node and updates the table.
     * @param path the path to update in the tree
     */
    void updateTreeNode(TreePath path)
    {   debugOutput("updateTreeNode(TreePath path): " + path.toString());
	jTree.collapsePath(path);
	DefaultMutableTreeNode node = getTreeNode(path);
	 node.removeAllChildren();
	if (isLinux)
        {   addLinuxDirectories((DirectoryMutableTreeNode) node, getLdirPath(path), true);
	    addLinuxSubDirectories((DirectoryMutableTreeNode) node, getLdirPath(path));
	    treeModel.reload(node);
	    jTree.expandPath(path);
	    updateLinuxJTable(node);
	} else
        {   setCurrentDirectory(jTree.getSelectionPath());
	    addDOSDirectories((DirectoryMutableTreeNode) node, currentDirectory);
	    addDOSSubDirectories((DirectoryMutableTreeNode) node, currentDirectory);
	    treeModel.reload(node);
	    // node.add(new DefaultMutableTreeNode(new Boolean(true))); 
	    jTree.expandPath(path);
	    updateDOSJTable(node);
	}
    }
    /** Put file "fileName" to remote host
     * file will be stored as "zzz.xxx"
     * @param fileName the file 'filename' will be stored on remote host as "zzz.xxx"
     */
    void putFileToHost(String fileName)
    {   //send command RECEIVEFILE\n filelength\n  file 
	String temp = "";
	int bytesRead = 0, bytesToRead, i, j;
	 byte[] buffer = new byte[BUFSIZE];

	 try
        {   File DOSfile = new File(fileName);
	    FileInputStream fd = new FileInputStream(fileName);

	     temp = "RECEIVEFILE\n" + DOSfile.length() + "\n";
	     LTOOLSgui.qSend.write(temp, 0, temp.length());	//Send command to remote server 
	     LTOOLSgui.qSend.flush();

	    do
            {   i = fd.read(buffer, 0, BUFSIZE);
		if (i < 0)
                {   break;
		}
		LTOOLSgui.bSend.write(buffer, 0, i);
		bytesRead = bytesRead + i;
	    }
	    while (i > 0);
	    LTOOLSgui.bSend.flush();
	    fd.close();
	}
	catch(IOException excpt)
        {   System.err.println("Failed I/O " + excpt);
	    return;
	}
    }
    /** Execute an operating system command on local computer and return commands response
     * @param command the command to execute (ldir-command)
     * @param runLocal true if it should run on the local machine (not connecte to a remote host)
     * @return the response of the ldir-command
     */
    String execOperatingSystemCommand(String command, boolean runLocal)
    {   String response = "";
	Runtime r = Runtime.getRuntime();
        Cursor oldCursor=Cursor.getDefaultCursor();
        Cursor newCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
	Process myProcess;
	
	if (!File.separator.equals("\\"))
        {   command = "./" + command;
	}
	int i = 0;
	byte[]buffer = new byte[BUFSIZE];

	if (LTOOLSgui.isConnected() && !runLocal)
        {   return remoteOperatingSystemCommand(command);
	}
	
	if (LTOOLSgui.myProg != null)
	{   oldCursor = LTOOLSgui.myProg.getCursor();
	    LTOOLSgui.myProg.setCursor(newCursor);
	}

	debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
	debugOutput("Executing operating system command:\n   --" + command + "--");
	if (File.separatorChar == '/')				// replace under linux the "-Char 
        {   command = command.replace('"', ' ');
	}
	// debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ; 
	try
        {   // debugOutput("execOperatingSystemCommand: " + LTOOLSgui.lreadguiDirectory + command) ; 
	    // myProcess = r.exec(LTOOLSgui.lreadguiDirectory + command);       //Execute operating system command as external process 
	    myProcess = r.exec(command);			// Execute operating system command as external process 
	    //Output goes to file 'zzz.zwz' 
	    try
            {   myProcess.waitFor();				// Wait until process has finished 
	    }
	    catch(InterruptedException excpt)
            {   System.err.println("Failed Process waitFor " + excpt);
	    }

	    FileInputStream fd = new FileInputStream("zzz.zwz");	// Read in command's response 

	    do
            {   i = fd.read(buffer, 0, BUFSIZE);
		if (i < 0)
                {   break;
		}
		response = response + new String(buffer, 0, i);
	    }
	    while (i > 0);

	}
	catch(IOException excpt)
        {   System.err.println("Failed I/O " + excpt);
	    LTOOLSgui.beepSound();
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, excpt.getMessage(),
					  "LTOOLS", JOptionPane.ERROR_MESSAGE);
	    if (LTOOLSgui.myProg != null)
	    {   LTOOLSgui.myProg.setCursor(oldCursor);
	    }
	    return "Executing operating system command failed:\n   " + command;
	}
	
	if (LTOOLSgui.myProg != null)
	{   LTOOLSgui.myProg.setCursor(oldCursor);
	}
	return response;
    }
    /** Execute an operating system command on a remote computer and return commands response
     * @param command the ldir-command to execute on the remote host
     * @return the response of the ldir-command
     */
    String remoteOperatingSystemCommand(String command)
    {   debugOutput("Executing command on remote server: \n   " + command);
	String response = "";
	String temp;
	int bytesRead, i, j;
	char[] buffer = new char[BUFSIZE];
        Cursor oldCursor=Cursor.getDefaultCursor();
        Cursor newCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);

	if (LTOOLSgui.myProg != null)
	{   oldCursor = LTOOLSgui.myProg.getCursor();
	    LTOOLSgui.myProg.setCursor(newCursor);
	}

        try
        {   temp = "EXECUTE\n" + command + "\n";
	    LTOOLSgui.qSend.write(temp, 0, temp.length());	//Send command to remote server 
	    LTOOLSgui.qSend.flush();

	    temp = LTOOLSgui.qReceive.readLine();
	    i = Integer.parseInt(temp);

	    // debugOutput("Bytes To Read i: " + i + " --- BUFSIZE: " + BUFSIZE) ; 

	    bytesRead = 0;
	    while (bytesRead < i)
            {   // j = LTOOLSgui.qReceive.read(buffer, 0, i); 
		j = LTOOLSgui.qReceive.read(buffer, 0, BUFSIZE);
		temp = new String(buffer, 0, j);
		bytesRead = bytesRead + j;
		response = response + temp;
	    }
	}
	catch(IOException excpt)
        {   System.err.println("Failed I/O to " + excpt);
	    LTOOLSgui.beepSound();
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, excpt.getMessage(),
					  "LTOOLS", JOptionPane.ERROR_MESSAGE);
	}

	if (LTOOLSgui.myProg != null)
	{   LTOOLSgui.myProg.setCursor(oldCursor);
	}
	return response;
    }
    /** Starts a file or its application when double clicked
     * @param item ListItemFile contains all necessary infos to start a Dos-application
     */
    void startDosApplication(ListItemFile item, boolean start)
    {   debugOutput("startDosApplication");
	String command;
	
	if (start && (File.separator.equals("\\") == false))
        {   LTOOLSgui.beepSound();
	    JOptionPane.showMessageDialog(this, "Sorry, starting applications only supported under Dos", "LTOOLS", JOptionPane.ERROR_MESSAGE);
	    return;
	}
	// String currentFileFullPath = getName(path, false); 
	// String command = "runit.bat \"" + currentFileFullPath + "\"" ; 
	if (start)		//start application
	{   command = "runit.bat \"" + item.getFullFilePath() + "\"";
	} else			//view file
	{   command = "edit.bat \"" + item.getFullFilePath() + "\"";
	}
	command = execOperatingSystemCommand(command, true);
    }
    /**
     * necessary for LToolGuiTableMouseListener(doubleClick) and LToolGuiTableKeyListener(Enter pressed)
     */
    public void doubleClickDOSTable()
    {   int rowIndex = jTable.getSelectedRow();
	ListItemFile item = tableModel.getListItemFile(rowIndex);
	if (item.isError())
        {   return;
	}
	if (item.isDirectory())
        {   debugOutput("jTree.getSelectionPath(): " + jTree.getSelectionPath().toString());
	    // createNewDOSPath(item.getFileName()) ; 
	    // debugOutput("DirFilePane.newDOSPath: " + DirFilePane.newDOSPath.toString()) ; 

	    if (item.getFileName().equals(".."))		// change in parent-directory 
            {   jTree.setSelectionPath(jTree.getSelectionPath().getParentPath());
		return;
	    }
	    TreePath path = jTree.getSelectionPath();

	    if (!jTree.isExpanded(path))			// if the selected path in the tree isn't expanded 
            {   jTree.expandPath(path);
	    }
	    TreePath newPath = jTree.getSelectionPath().pathByAddingChild(item.getFileName());
	    try
            {   DefaultMutableTreeNode node = getTreeNode(path);
		int selectedRow = jTree.getSelectionRows()[0];
		int offset = 0;
		for (int k = 0; k < node.getChildCount(); k++)
                {   int collapseRow = selectedRow + k + 1;
		    if (jTree.isExpanded(collapseRow))		// collapse all children 
                    {   jTree.collapseRow(collapseRow);
		    }
		    if (node.getChildAt(k).toString().equals((String) newPath.getLastPathComponent()))
                    {   offset = k + 1;
		    }
		}
		jTree.setSelectionRow(selectedRow + offset);
	    }
	    catch(Exception ex)
            {   System.out.println(ex.getMessage());
	    }
	} else
        {   startDosApplication(item, true);
	}
    }
    /** Starts a file or its application when double clicked
     * @param path path -
     * @param item item - all necessary infos to start a Linux-application
     */
    void startLinuxApplication(ListItemFile item, boolean start)
    {   debugOutput("startLinuxApplication");
	// ######################################################################### 
	// item.printItem() ; 
	// ######################################################################### 
	if (start && (File.separator.equals("\\") == false))
        {   LTOOLSgui.beepSound();
	    String msg = "Sorry, starting applications only supported under Dos";
	     JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, "LTOOLS", JOptionPane.ERROR_MESSAGE);
	     return;
	}
	// String currentFileFullPath = getName(path, true); 
	String currentFileFullPath = item.getFullFilePath();
	//String fileName = path.getLastPathComponent().toString(); 
	String fileName = item.getFileName();

	String command;
	String drive, fullPath;
	if (item.isLink())					// it's a LINK 
	{							// Handle symbolic links 

	    // debugOutput("fileName()LINK: \"" + fileName + "\"") ; 
	    drive = getLinuxDrive(currentDirectory);
	    fileName = getFileNameFromLink(item.getFullFilePath());
	    fullPath = getFilePathFromLink(item.getFullFilePath());
	    // debugOutput("fileName: " + fileName) ; 
	    // debugOutput("fullPath: " + fullPath) ; 
	} else
	    // no LINK 
        {   drive = getLinuxDrive(currentDirectory);
	    fullPath = getLinuxPath(currentFileFullPath);
	}

	if (LTOOLSgui.isConnected())
        {   command = "ldir -READ -x -s" + drive + " \"" + fullPath + "\" " + "zzz.xxx";
	} else
        {   // command = "ldir -READ -x -s" + drive + " \"" + fullPath + "\" \"" + fileName + "\""; 
	    command = "ldir -READ -x -s" + drive + " \"" + fullPath + "\" \"" + LTOOLSgui.tempPathLinuxFiles + fileName + "\"";
	}

	command = execOperatingSystemCommand(command, false);	// Copy the application from Linux to Dos 
	if (command.length() > 0)				// if LTOOLS's command line tool issues an error message, show it 
        {   LTOOLSgui.beepSound();
	    JOptionPane.showMessageDialog(this, command.trim(), "LTOOLS", JOptionPane.ERROR_MESSAGE);
	    return;
	}
	if (LTOOLSgui.isConnected())				// Remote files must be copied to the local machine, 
	{							// before we can start them 
	    getFileFromHost(LTOOLSgui.tempPathLinuxFiles + fileName);
	}
	// command = "runit.bat /wait \"" + tempPathLinuxFiles + fileName + "\"";       // Start it in Dos (wait, until application is closed again) 
	if (start)
	    command = "runit.bat \"" + LTOOLSgui.tempPathLinuxFiles + fileName + "\"";	// Start it in Dos (wait, until application is closed again) 
	else
	    command = "edit.bat \"" + LTOOLSgui.tempPathLinuxFiles + fileName + "\"";	// Edit
	execOperatingSystemCommand(command, true);

	/*
	   File file = new File(fileName) ;                         // Delete the Dos file again 
	if (file != null)
	    file.delete();
	*/
    }
    /**
     * necessary for LToolGuiTableMouseListener(doubleClick) and LToolGuiTableKeyListener(Enter pressed)
     */
    public void doubleClickLinuxTable()
    {   int rowIndex = jTable.getSelectedRow();
	ListItemFile item = tableModel.getListItemFile(rowIndex);

	TreePath path = jTree.getSelectionPath();

	debugOutput("doubleClickLinuxTable(): \"" + item.getFullFilePath() + "\" --- path: " + path.toString());
	if (item.isError())
        {   return;
	} else if (item.isDirectory())
        {   if (item.getFileName().equals(".."))		// change in parent-directory 
            {   jTree.setSelectionPath(jTree.getSelectionPath().getParentPath());
		return;
	    }
	    if (!jTree.isExpanded(path))			// if the selected path in the tree isn't expanded 
            {   jTree.expandPath(path);
	    }
	    TreePath newPath = jTree.getSelectionPath().pathByAddingChild(item.getFileName());
	    try
            {   DefaultMutableTreeNode node = getTreeNode(path);
		int selectedRow = jTree.getSelectionRows()[0];
		int offset = 0;
		for (int k = 0; k < node.getChildCount(); k++)
                {   int collapseRow = selectedRow + k + 1;
		    if (jTree.isExpanded(collapseRow))		// collapse all children 
                    {   jTree.collapseRow(collapseRow);
		    }
		    if (node.getChildAt(k).toString().equals((String) newPath.getLastPathComponent()))
                    {   offset = k + 1;
		    }
		}
		jTree.setSelectionRow(selectedRow + offset);
	    }
	    catch(Exception ex)
            {   System.out.println(ex.getMessage());
	    }
	} else
        {   startLinuxApplication(item, true);
	}
    }
    /** returns the filename of a link
     * e.g. "/dev/hda6 /home/test/testlink -> /home/test/test.txt":
     * returns "test.txt"
     * @param fullPath the full path of the symbolic link with drive and "->"-symbol
     * @return the filename of the link without the drive and path
     */
    private String getFileNameFromLink(String fullPath)
    {   int index = fullPath.indexOf("->", 0) + 3;
	String fileName = fullPath.substring(index);

	String name;
	if (fileName.startsWith("/"))
        {   // it's full path to a file, e.g. "link -> /home/test/test.txt" 
	    name = fileName.substring(fileName.lastIndexOf("/") + 1);
	} else
        {   // it's a file in the current directory, e.g. "link -> test.txt" 
	    name = fileName;
	}
	return name;
    }
    /** returns the full filepath from a link
     * e.g. "/dev/hda6 /home/test/testlink -> /home/test/test.txt":
     * returns "/home/test/test.txt" or
     * e.g. "/dev/hda6 /home/test/testlink -> test.txt":
     * returns "/home/test/test.txt"
     * @param fullPath - a full linux path with device, path and linkpath
     * @return String - returns the full filepath of a link
     */
    public String getFilePathFromLink(String fullPath)
    {   // /dev/hda6 /joe/test verzeichnis/joe/testLink -> Test.java ---- testLink -> Test.java 
	// /dev/hda6 /joe/test verzeichnis/joe/testlink2 -> /joe/test verzeichnis/fhte.java ---- testlink2 -> /joe/test verzeichnis/fhte.java 
	int index = fullPath.indexOf("->", 0) + 3;
	String fileName = fullPath.substring(index);
	String path;
	if (fileName.startsWith("/"))
        {   // it's full path to a file, e.g. "link -> /home/test/test.txt" 
	    path = fileName;
	} else
        {   // it's a file in the current directory, e.g. "link -> test.txt" 
	    // last index of LinuxDirectorySeparatorChar + fileName 
	    String linuxPath = getLinuxPath(fullPath);
	    path = linuxPath.substring(0, linuxPath.lastIndexOf("/") + 1) + fileName;
	}
	return path;
    }
    /**
     * returns the filename of the symbolic link without the "-> filepath"
     * e.g. "/dev/hda6 /home/test/testlink -> /home/test/test.txt":
     * returns "/dev/hda6 /home/test/testlink"
     * @param link - a full linux path with device, path and linkpath
     * @return String - the filename of the link
     */
    private String getLinkName(String link)
    {   int index = link.indexOf("->", 0) - 1;
	String linkName = link.substring(0, index);
	 return linkName;
    }

//* fills the JTree with the DOS drives on the system 
    public void fillDosDirectoryTree()
    {   debugOutput("fillDosDirectoryTree");
    	dosDrives = new Vector();
	getDOSDriveTypes();

	DefaultMutableTreeNode top =
	new DefaultMutableTreeNode(new LToolGuiTreeIconData(ICON_COMPUTER, null, rootNodeText));
	 this.root = top;

	for (int i = 0; i < dosDrives.size(); i++)
        {   DriveType drive = (DriveType) dosDrives.elementAt(i);
	    // debugOutput("dosDrives[i]: " + drive.toString()) ; 

	    DirectoryMutableTreeNode node = new DirectoryMutableTreeNode(this,
		       new LToolGuiTreeIconData(getDriveIcon(drive), null, drive.getDrive()), "\\", drive.getDrive());
	    if (drive.getType() == DriveType.DriveRemoveable ||
		drive.getType() == DriveType.DriveCDRom)
            {   node.setIsRemovableDrive(true);
	    }
	    top.add(node);
	    currentDirectory = drive.getDrive();
	    if (!node.isRemovableDrive())
            {   addDOSDirectories(node, currentDirectory);
	    }
	}
	treeModel = new DefaultTreeModel(top);
	jTree.setModel(treeModel);
	jTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
	jTree.putClientProperty("JTree.lineStyle", "Angled");
	TreeCellRenderer renderer = new LToolGuiTreeIconCellRenderer();
	jTree.setCellRenderer(renderer);
	jTree.setShowsRootHandles(true);
	jTree.setEditable(false);
	if (File.separator.equals("\\"))			// Windows 
        {   selectDriveC();
	} else
        {   selectDriveFirst();
	}
    }
    /**
     * selects the Drive C:\ in the DOS-Tree or the first Drive in the Tree if C:\ doesn't exist
     */
    public void selectDriveC()
    {   // select "C:\" 
	boolean driveCExists = false;
	for (int j = 0; j < root.getChildCount(); j++)
        {   if (root.getChildAt(j).toString().equals("C:\\"))
            {   driveCExists = true;
		int offset = 0;
		if (jTree.isRootVisible())
                {   offset = 1;
		}
		jTree.setSelectionRow(j + offset);
		break;
	    }
	}
	if (!driveCExists)					// if there is no "C:\" select first drive 
        {   jTree.setSelectionRow(1);
	}
    }
    /** the addDOSDirectories adds the directories to a given Node
     * @param node node - the node to add the directories
     * @param pathDir path - a full DOS-path with a drive in front e.g. "C:\"
     */
    public void addDOSDirectories(DirectoryMutableTreeNode node, String pathDir)
    {   debugOutput("addDOSDirectories-path: " + pathDir);
	try
        {   File path = new File(pathDir);

	    Vector directories = new Vector();
	     File[] files = path.listFiles();
	    for (int i = 0; i < files.length; i++)
            {   if (files[i].isDirectory())
                {   DirectoryMutableTreeNode dn = new DirectoryMutableTreeNode(this,
									       new LToolGuiTreeIconData(ICON_FOLDER, ICON_EXPANDEDFOLDER, files[i].getName()), files[i].getName(), node.getDrive());
		     directories.add(dn);
		}
	    }
	    Collections.sort(directories);
	    for (int i = 0; i < directories.size(); i++)	// add the sorted nodes to the tree 
            {   node.add((DirectoryMutableTreeNode) directories.get(i));
	    }
	}
	catch(Exception e)
        {   e.printStackTrace();
	}
    }
    /** For a given node, add the sub-directories for node's children in the directoryTree.
     * @param node The node to add the DOS-sub-directories
     * @param pathParent the TreePath of the parentNode where the subdirectories should be added
     */
    public void addDOSSubDirectories(DirectoryMutableTreeNode node, String pathParent)
    {   debugOutput("addDOSSubDirectories");
    	try
        {   for (int i = 0; i < node.getChildCount(); i++)
            {   DirectoryMutableTreeNode childNode = (DirectoryMutableTreeNode) node.getChildAt(i);
		String pathLdir;

		if (!pathParent.endsWith(File.separator))
                {   pathParent = pathParent + File.separator;
		}
		pathLdir = pathParent + childNode.toString();
		if (!pathLdir.endsWith(File.separator))
                {   pathLdir = pathLdir + File.separator;
		}
		addDOSDirectories(childNode, pathLdir);
	    }
	    node.setSubDirectoriesAdded(true);
	}
	catch(Exception e)
        {   e.printStackTrace();
	}
    }
    /** the updateDOSJTable()-method shows the contents of the selected directory in the
     * JTree in the JTable on the right side
     * @param node the node which contents should be shown in the JTable
     */
    public void updateDOSJTable(DefaultMutableTreeNode node)
    {   Vector directories = new Vector();			// collection with all directories in currentDirectory 
	Vector filesVector = new Vector();			// collection with all files in currentDirectory 
	debugOutput("updateDOSJTable");
	 try
        {   // debugOutput("ACTIVE DIRFILEPANE: " + (LTOOLSgui.getActiveDirFilePane() == this)) ; 
	    if (node.toString().equals(rootNodeText))
            {   // show all drives in the jTable 
		showDrives();
		return;
	    }
	    tableModel.removeAllRows();

	    if (jTree.getSelectionPath() != null)
            {   setCurrentDirectory(jTree.getSelectionPath());
	    }
	    debugOutput("updateDOSJTable() - DOS: \"" + currentDirectory + "\"");

	    jLabelDirectory.setText("Directory: " + currentDirectory);	// set the Text of the directory-label 

	    String path = getCurrentDirectory();
	    File DOSdir = new File(path);
	    String[]files = DOSdir.list(new DOSFileFilter(LTOOLSgui.getDosFilePattern()));

	    if (node.getLevel() > 1)				// add a ".." in the JTable 
            {   ListItemFile li = new ListItemFile("..", true, "", "",
						   "", "", "", ListItemFile.ICON_FOLDERUP);
		tableModel.addListItemFile(li);
	    }
	    for (int i = 0; i < files.length; i++)
            {   File file = new File(path + File.separator + files[i]);
		if (file.isDirectory())
                {   String length = new Long(file.length()).toString();
		    String last = (new Date(file.lastModified())).toString();
		    ListItemFile li = new ListItemFile(file.getName(), file.isDirectory(), file.getPath(), file.getPath(),
						       length, last, "", ListItemFile.ICON_FOLDER);
		    directories.add(li);
		}
	    }
	    for (int i = 0; i < files.length; i++)
            {   File file = new File(path + File.separator + files[i]);
		if (!file.isDirectory())
                {   String length = new Long(file.length()).toString();
		    String last = (new Date(file.lastModified())).toString();

		    ListItemFile li = new ListItemFile(file.getName(), file.isDirectory(), file.getPath(), file.getPath(),
						       length, last, "", ListItemFile.ICON_FILE);
		    filesVector.add(li);
		}
	    }
	    insertListItemFilesInJTable(directories, filesVector);
	}
	catch(NullPointerException e)
        {   e.printStackTrace();

	    directories.removeAllElements();
	    filesVector.removeAllElements();
	    String error = "";
	    if (e.getMessage() != null)
            {   error = e.getMessage();
	    } else
            {   error = "Drive not ready";
	    }
	    ListItemFile li = new ListItemFile(error);

	    directories.add(li);

	    insertListItemFilesInJTable(directories, filesVector);
	}
    }

//* the fillLinuxDirectoryTree fills the linux JTree with all linux-drives 
    public void fillLinuxDirectoryTree()
    {   debugOutput("fillLinuxDirectoryTree");
    	if (tableModel.getRowCount() > 0)
        {   tableModel.removeAllRows();
	    tableModel.fireTableDataChanged();
	}
	// fill the linux JTree 
	DefaultMutableTreeNode top =
	new DefaultMutableTreeNode(new LToolGuiTreeIconData(ICON_COMPUTER, null, rootNodeText));
	this.root = top;

	// get all Drives in the System 
	Vector drives = getLinuxDrives();
	for (int i = 0; i < drives.size(); i++)
        {   // debugOutput("drives[" + i + "]: " + (String)drives.elementAt(i)) ; 
	    String driveDirectory = (String) drives.elementAt(i);
	    String drive = driveDirectory.substring(0, driveDirectory.indexOf(" "));
	    String dir = driveDirectory.substring(driveDirectory.indexOf(" ") + 1);
	    DirectoryMutableTreeNode node = new DirectoryMutableTreeNode(this,
				   new LToolGuiTreeIconData(ICON_DRIVE_FIXED, null, drives.elementAt(i)), dir, drive);
	    // ################################################## 
	    // debugOutput(node.showAttributes()) ; 
	    // ################################################## 
	    // node.setSubDirectoriesAdded(true) ; 
	    top.add(node);
	    currentDirectory = (String) drives.elementAt(i);
	    if (addLinuxDirectories(node, currentDirectory, false) == false)
		top.remove(node);
	}
	treeModel = new DefaultTreeModel(top);
	jTree.setModel(treeModel);
	jTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
	jTree.putClientProperty("JTree.lineStyle", "Angled");
	TreeCellRenderer renderer = new LToolGuiTreeIconCellRenderer();
	jTree.setCellRenderer(renderer);
	jTree.setShowsRootHandles(true);
	jTree.setEditable(false);
	selectDriveFirst();
    }
//* selects the first drive in the Linux-Tree 
    public void selectDriveFirst()
    {   if (root.getChildCount() >= 1)
        {   int offset = 0;
	    if (jTree.isRootVisible())
            {   offset = 1;
	    }
	    jTree.setSelectionRow(0 + offset);			// select the first drive in the tree 
	}
    }
    /** the addLinuxDirectories adds the directories to a given Node
     * @param node node - the node to add the directories
     * @param pathLdir pathLdir - a full linux-path with a drive in front e.g. "/dev/hda6 /home/test"
     */
    public boolean addLinuxDirectories(DirectoryMutableTreeNode node, String pathLdir, boolean showError)
    {   debugOutput("addLinuxDirectories-path: " + pathLdir);
	try
        {   // Aufbau des ldir-Aufrufs !! ldir -s/dev/hda6 /joerg/testverzeichnis/ 
	    // wichtig ist hinten der Slash, sonst wird nur Info zum Verzeichnis ausgegeben !!! 
	    String path = getLinuxPath(pathLdir);
	    String command = "ldir -x -s" + node.getDrive() + " \"" + path + "\"";
	    String response = execOperatingSystemCommand(command, !LTOOLSgui.isConnected());

	    if (!(response.startsWith("d") && ("" + response.charAt(startColumnLinuxFileName)).equals(".")))
            {   if (showError)
		    JOptionPane.showMessageDialog(LTOOLSgui.myProg, "ERROR: " + response, "LTOOLSgui", JOptionPane.ERROR_MESSAGE);
		return false;
	    }
	    Vector directories = new Vector();
	    StringTokenizer st = new StringTokenizer(response, "\n\r");

	    while (st.hasMoreTokens())
            {   String token = st.nextToken();

		if (token.length() > startColumnLinuxFileName)
                {   String access = getLdirField(token, 0);
		    if (access.charAt(0) == 'd')
                    {   String name = getLdirField(token, 9);
			if (!name.equals(".") && !name.equals(".."))
                        {   DirectoryMutableTreeNode dn = new DirectoryMutableTreeNode(this,
			     new LToolGuiTreeIconData(ICON_FOLDER, ICON_EXPANDEDFOLDER, name), name, node.getDrive());
			    directories.add(dn);
			}
		    }
		}
	    }

	    Collections.sort(directories);
	    for (int i = 0; i < directories.size(); i++)	// add the sorted nodes to the tree 
            {   node.add((DirectoryMutableTreeNode) directories.get(i));
	    }
	}
	catch(Exception e)
        {   e.printStackTrace();
	}
	return true;
    }
    /** For a given node, add the sub-directories for node's children in the directoryTree.
     * @param node The node to add the Linux-sub-directories
     * @param pathParent the path of the parent-node where the subdirectories should be added
     */
    public void addLinuxSubDirectories(DirectoryMutableTreeNode node, String pathParent)
    {   debugOutput("addLinuxSubDirectories()");
    	try
        {   for (int i = 0; i < node.getChildCount(); i++)
            {   DirectoryMutableTreeNode childNode = (DirectoryMutableTreeNode) node.getChildAt(i);
		String pathLdir;

		if (!pathParent.endsWith("/"))
                {   pathParent = pathParent + "/";
		}
		pathLdir = pathParent + childNode.toString();
		if (!pathLdir.endsWith("/"))
                {   pathLdir = pathLdir + "/";
		}
		addLinuxDirectories(childNode, pathLdir, true);
	    }
	    node.setSubDirectoriesAdded(true);
	}
	catch(Exception e)
        {   e.printStackTrace();
	}
    }
    /** the getLinuxDrive()-method returns just the drive of a full linux-path
     * @param path the full path of the symbolic link with drive and directory-path
     * @return the drive(/dev/hda6) of a String like "/dev/hda6 /home/test/test.txt"
     */
    private String getLinuxDrive(String path)
    {   String drive = path.substring(0, path.indexOf(" "));
	// debugOutput("getLinuxDrive(" + path + ") returns --" + drive + "--") ; 
	 return drive;
    }
    /** the getLinuxPath()-method returns just the path of a linux-file without the
     * drive
     * @param path the full linux-path with drive
     * @return the path of the file(/home/test/test.txt) of a String like "/dev/hda6
     * /home/test/test.txt"
     */
    private String getLinuxPath(String path)
    {   String filePath = path.substring(path.indexOf(" ") + 1);
	// debugOutput("getLinuxDrive(" + path + ") returns --" + filePath + "--") ; 
	 return filePath;
    }
    /** the updateDOSJTable()-method shows the contents of the selected directory in the
     * JTree in the JTable on the right side
     * @param node the node which contents should be shown in the JTable
     */
    public void updateLinuxJTable(DefaultMutableTreeNode node)
    {   debugOutput("updateLinuxJTable");
    	try
        {   // debugOutput("ACTIVE DIRFILEPANE: " + (LTOOLSgui.getActiveDirFilePane() == this)) ; 
	    if (node.toString().equals(rootNodeText))
            {   // show all drives in the jTable, later 
		showDrives();
		return;
	    }
	}
	catch(Exception e)
        {   LTOOLSgui.beepSound();
	    JOptionPane.showMessageDialog(LTOOLSgui.myProg, "error: " + e.getMessage());
	}

	try
        {   Vector directories = new Vector();			// collection with all directories in currentDirectory 
	    Vector files = new Vector();			// collection with all files in currentDirectory 
	    tableModel.removeAllRows();

	    if (jTree.getSelectionPath() != null)
            {   setCurrentDirectory(jTree.getSelectionPath());
	    }
	    debugOutput("updateLinuxJTable() - LINUX: \"" + currentDirectory + "\"");
	    jLabelDirectory.setText("Directory: " + currentDirectory);	// set the Text of the directory-label 
	    if (node.getLevel() > 1)				// add a ".." in the JTable 
            {   // debugOutput("node.getLevel(): " + node.getLevel()); 
		ListItemFile li = new ListItemFile("..", true, "", "",
						   "", "", "", ListItemFile.ICON_FOLDERUP);
		tableModel.addListItemFile(li);
	    }
	    String ldirPath = currentDirectory;			// the path of the directory in treeView 
	    String arguments = "-x -s" + getLinuxDrive(currentDirectory) + " \"" + getLinuxPath(currentDirectory) + "\"";
	    String command = "ldir " + arguments;

	    String response = execOperatingSystemCommand(command, !LTOOLSgui.isConnected());
	    if (!(response.startsWith("d") && ("" + response.charAt(startColumnLinuxFileName)).equals(".")))
            {   JOptionPane.showMessageDialog(LTOOLSgui.myProg, "ERROR: " + response, "LTOOLSgui", JOptionPane.ERROR_MESSAGE);
		return;
	    }
	    StringTokenizer st = new StringTokenizer(response, "\n\r");
	    while (st.hasMoreTokens())
            {   String token = st.nextToken();
		/*
		   debugOutput("token:\t" + token) ;
		   debugOutput("\tfield0:\t" + getLdirField(token, 0)) ;
		   debugOutput("\tfield1:\t" + getLdirField(token, 1)) ;
		   debugOutput("\tfield2:\t" + getLdirField(token, 2)) ;
		   debugOutput("\tfield3:\t" + getLdirField(token, 3)) ;
		   debugOutput("\tfield4:\t" + getLdirField(token, 4)) ;
		   debugOutput("\tfield5:\t" + getLdirField(token, 5)) ;
		   debugOutput("\tfield6:\t" + getLdirField(token, 6)) ;
		   debugOutput("\tfield7:\t" + getLdirField(token, 7)) ;
		   debugOutput("\tfield8:\t" + getLdirField(token, 8)) ;
		   debugOutput("\tfield9:\t" + getLdirField(token, 9)) ;
		 */
		if (token.length() < startColumnLinuxFileName)	// something is wrong, it's not a Linux-drive 
                {   // ############################################ 
		    directories.removeAllElements();
		    files.removeAllElements();

		    String error = token;
		    ListItemFile li = new ListItemFile(error);
		    directories.add(li);
		    while (st.hasMoreTokens())			// show the complete error-message 
                    {   error = st.nextToken();
			li = new ListItemFile(error);
			directories.add(li);
		    }
		    // show error in JTable 
		    insertListItemFilesInJTable(directories, files);
		    return;
		    // ############################################ 
		} else
                {   String name = getLdirField(token, 9);
		    String field1 = getLdirField(token, 0);
		    char type = field1.charAt(0);
		    if (type == 'd')				// it's a directory 
                    {   if (!name.equals(".") && !name.equals(".."))
                        {   String size = getLdirField(token, 3);
			    String last = getLdirField(token, 4) + " " + getLdirField(token, 5) + " " +
			    getLdirField(token, 6) + " " + getLdirField(token, 7) + " " +
			    getLdirField(token, 8);
			    String fullPath;
			    if (currentDirectory.endsWith("/"))
                            {   fullPath = currentDirectory + name;
			    } else
                            {   fullPath = currentDirectory + "/" + name;
			    }
			    ListItemFile dir = new ListItemFile(name, true, currentDirectory, fullPath,
								size, last, token, ListItemFile.ICON_FOLDER);
			    directories.addElement(dir);
			}
		    } else if (LTOOLSgui.getLinuxFilePattern().equals("*"))	// it's a file 
                    {   String size = getLdirField(token, 3);
			String last = getLdirField(token, 4) + " " + getLdirField(token, 5) + " " +
			getLdirField(token, 6) + " " + getLdirField(token, 7) + " " +
			getLdirField(token, 8);
			String fullPath;
			if (currentDirectory.endsWith("/"))
                        {   fullPath = currentDirectory + name;
			} else
                        {   fullPath = currentDirectory + "/" + name;
			}

			ListItemFile file = new ListItemFile(name, false, currentDirectory, fullPath,
							     size, last, token, ListItemFile.ICON_FILE);
			files.addElement(file);
		    }
		}
	    }
	    if (!LTOOLSgui.getLinuxFilePattern().equals("*"))	// get files with pattern ############################# 
            {   String patternCommand = "ldir -x -s" + getLinuxDrive(currentDirectory) +
		" \"" + getLinuxPath(currentDirectory) + LTOOLSgui.getLinuxFilePattern() + "\"";
		response = execOperatingSystemCommand(patternCommand, !LTOOLSgui.isConnected());
		if (!(response.startsWith("d") && ("" + response.charAt(startColumnLinuxFileName)).equals(".")))
                {   JOptionPane.showMessageDialog(LTOOLSgui.myProg, "ERROR: " + response, "LTOOLSgui", JOptionPane.ERROR_MESSAGE);
		    return;
		}
		StringTokenizer stFilePattern = new StringTokenizer(response, "\n\r");
		String cantFind = "Can't find '" + LTOOLSgui.getLinuxFilePattern() + "'.Linux Path Invalid";
		while (stFilePattern.hasMoreTokens())
                {   String token = stFilePattern.nextToken();
		    if (token.length() < startColumnLinuxFileName)	// something is wrong, it's not a Linux-drive 
                    {   String nextToken = "";
			Vector errorMsg = new Vector();
			String error = token;
			errorMsg.add(token);
			while (stFilePattern.hasMoreTokens())	// show the complete error-message 
                        {   String nextErrorToken = stFilePattern.nextToken();
			    errorMsg.add(nextErrorToken);
			    error = error + nextErrorToken;
			}
			if (!error.equals(cantFind))
                        {   // ######################################## 
			    directories.removeAllElements();
			    files.removeAllElements();
			    for (int j = 0; j < errorMsg.size(); j++)
                            {   ListItemFile li = new ListItemFile((String) errorMsg.elementAt(j));
				directories.add(li);
			    }
			    // show error in JTable 
			    insertListItemFilesInJTable(directories, files);
			    // ######################################## 
			    return;
			}
		    } else
                    {   String name = getLdirField(token, 9);
			String field1 = getLdirField(token, 0);
			char type = field1.charAt(0);
			if (type != 'd')			// it's a file included in pattern 
                        {   String size = getLdirField(token, 3);
			    String last = getLdirField(token, 4) + " " + getLdirField(token, 5) + " " +
			    getLdirField(token, 6) + " " + getLdirField(token, 7) + " " +
			    getLdirField(token, 8);
			    String fullPath;
			    if (currentDirectory.endsWith("/"))
                            {   fullPath = currentDirectory + name;
			    } else
                            {   fullPath = currentDirectory + "/" + name;
			    }

			    ListItemFile file = new ListItemFile(name, false, currentDirectory, fullPath,
								 size, last, token, ListItemFile.ICON_FILE);
			    files.addElement(file);
			}
		    }
		}
	    }							// END: if (!LTOOLSgui.getLinuxFilePattern().equals("*")) 
	    insertListItemFilesInJTable(directories, files);
	}
	catch(Exception e)
        {   debugOutput("updateLinuxJTable(): " + e.getMessage());
	    e.printStackTrace();
	}
    }

    /** the insertListItemFilesInJTable()-method inserts the directories and files to
     * the TableModel of the JTable.
     * @param directories the directories to add to the JTable
     * @param files the files to add to the JTable
     */
    private void insertListItemFilesInJTable(Vector directories, Vector files)
    {   Collections.sort(directories);
	Collections.sort(files);

	for (int i = 0; i < directories.size(); i++)
        {   tableModel.addListItemFile((ListItemFile) directories.elementAt(i));
	}
	for (int i = 0; i < files.size(); i++)
        {   tableModel.addListItemFile((ListItemFile) files.elementAt(i));
	}
	tableModel.fireTableDataChanged();
	if (sortOrder == false)
        {   changeSortOrderInJTable();
	}
    }
    /** the changeSortOrderInJTable()-method changes the sortorder of the Files in the JTable by name
     * (descending or ascending sortorder)
     */
    public void changeSortOrderInJTable()
    {   Vector items = new Vector();
	for (int i = 0; i < tableModel.getRowCount(); i++)
        {   items.add(tableModel.getListItemFile(i));
	}
	tableModel.removeAllRows();
	for (int i = items.size() - 1; i >= 0; i--)
        {   tableModel.addListItemFile((ListItemFile) items.elementAt(i));
	}
	tableModel.fireTableDataChanged();
    }
//* Changes the sortorder-field 
    public void changeSortOrder()
    {   sortOrder = !sortOrder;
    }
    /**
     * the GetLinuxDrives() gets all ext2/3 (no swap-partitions) partitions on the local or remote machine.
     * @return Vector - with all available LinuxDrives on the local or remote machine
     */
    private Vector getLinuxDrives()
    {   debugOutput("getLinuxDrives()");
	Vector drives = new Vector();
	 try
        {   String partitions = showPartitions();

	    StringTokenizer lines = new StringTokenizer(partitions, "\n\r");
	    // lines looks like: 
	    // lines[0]: Partition table info: 
	    // lines[1]: ------------------------------------------------ 
	    // lines[2]: /dev/hda 1 :   NTFS / HPFS   19077M 
	    // lines[3]: /dev/hda 2 :   Win ExPar     19077M 
	    // lines[4]: /dev/hda 5 :   Win9x FAT32   18983M 
	    // lines[5]: /dev/hda 6 :   Linux EXT2      47MB 
	    // lines[6]: /dev/hda 7 :   Linux EXT2      47MB 
	    // fieldno.  0        1 2   3     4         5 
	    while (lines.hasMoreTokens())
            {   String token = lines.nextToken();
		if (getLdirField(token, 3).toLowerCase().equals("linux") &&
		    !getLdirField(token, 4).toLowerCase().equals("swap"))
                {   String drive = getLdirField(token, 0) + getLdirField(token, 1) + " " + "/";
		     drives.add(drive);
		}
	    }
	}
	catch(Exception e)
        {   e.printStackTrace();
	    drives.removeAllElements();
	}

	for (int i = 0; i < drives.size(); i++)			//Remove duplicate partitions 
        {   String drive1 = ("" + drives.elementAt(i)).substring(6, 10);
	    for (int j = i + 1; j < drives.size(); j++)
            {   String drive2 = ("" + drives.elementAt(j)).substring(6, 10);

		if (drive1.equals(drive2))
                {   debugOutput("i=" + i + "---" + drive1 + "---   " + "j=" + j + "---" + drive2 + "---   ");
		    drives.removeElementAt(i);
		    break;
		}
	    }
	}

	return drives;
    }
    /** the setCurrentDirectory sets the currentDirectory-field (getting infos from the TreePath)
     * @param path the TreePath to set the currentDirectory
     */
    public void setCurrentDirectory(TreePath path)
    {   currentDirectory = getDOSLinuxPath(path);
    }
    /** the setCurrentDirectory sets the currentDirectory-field
     * @param path the new current DOS-Directory
     */
    public void setCurrentDirectory(String path)
    {   currentDirectory = path;
    }
    /** The getCurrentDirectory()-method returns the value of the currentDirecory-field
     * @return the currentDirectory-field
     */
    public String getCurrentDirectory()
    {   return currentDirectory;
    }
    /** the getDOSLinuxPath gets a path-String of a directory from a TreePath
     * @param path the TreePath to get the DOS- or Linux-Path from
     * @return the Path represented by the TreePath
     */
    public String getDOSLinuxPath(TreePath path)
    {   String currentFilePath = "";
	if (isLinux())
        {   for (int i = 1; i < path.getPathCount(); i++)	// forget the path-element "Computer" 
            {   // System.out.println(path.getPathComponent(i)) ; 
		currentFilePath += path.getPathComponent(i);
		if (!currentFilePath.endsWith("/"))
                {   currentFilePath += "/";
		}
	    }
	    if (!currentFilePath.endsWith("/"))
            {   currentFilePath += "/";
	    }
	} else
        {   for (int i = 1; i < path.getPathCount(); i++)	// forget the path-element "Computer" 
            {   currentFilePath += path.getPathComponent(i);
		if (!currentFilePath.endsWith(File.separator))
                {   currentFilePath += File.separator;
		}
	    }
	    if (!currentFilePath.endsWith(File.separator))
            {   currentFilePath += File.separator;
	    }
	}
	return currentFilePath;
    }
    /** the getLdirPath gets a path-String of a directory from a TreePath
     * @param path path - is a TreePath
     * @return the full path of the selected Directory with the drive
     */
    public String getLdirPath(TreePath path)
    {   String currentFilePath = "";
	for (int i = 1; i < path.getPathCount(); i++)		// forget the path-element "Computer" 
        {   // System.out.println(path.getPathComponent(i)) ; 
	    currentFilePath += path.getPathComponent(i);
	    if (!currentFilePath.endsWith("/"))
            {   currentFilePath += "/";
	    }
	}
	if (!currentFilePath.endsWith("/"))
        {   currentFilePath += "/";
	}
	return currentFilePath;
    }
    /** the getTreeSelectionPath()-method gets the TreePath of the selected node in the
     * JTree. (to get this value from another class)
     * @return TreePath of the selected Node in the JTree
     */
    public TreePath getTreeSelectionPath()
    {   return jTree.getSelectionPath();
    }
    /** the getSelectedListItemFile returns a Vector with all selected "files" in the table
     * @return all selected ListItemFile in the JTable in a Vector
     */
    public Vector getSelectedListItemFile()
    {   Vector items = new Vector();

	int[] selectedRows = jTable.getSelectedRows();
	for (int i = 0; i < jTable.getSelectedRowCount(); i++)
        {   ListItemFile item = tableModel.getListItemFile(selectedRows[i]);
	     items.add(item);
	}
	return items;
    }
    /** the getTableSelectionCount() gets the number of selected items in the JTable
     * @return the number of selected rows in the JTable
     */
    public int getTableSelectionCount()
    {   return jTable.getSelectedRowCount();
    }
    /**
     * the showDrives()-method should show all drives in the JTable in the future
     * now the method just removes all rows of the JTable
     */
    private void showDrives()
    {   System.out.println("showDrives()");
	tableModel.removeAllRows();
	tableModel.fireTableDataChanged();
    }
    /**
     * the refreshTreeNode()-method collapses the selected node, removes all children and updates the node again.
     */
    public void refreshTreeNode()
    {   debugOutput("refreshTreeNode(): " + jTree.getSelectionPath().toString());
	if (jTree.getSelectionCount() == 1)
        {   int row = jTree.getSelectionRows()[0];
	    if (jTree.isExpanded(row))
            {   jTree.collapseRow(row);
	    }
	    // remove childs and add new Directories to node 
	    if (isLinux())
            {   DirectoryMutableTreeNode node =
		(DirectoryMutableTreeNode) getTreeNode(jTree.getSelectionPath());
		node.removeAllChildren();
		addLinuxDirectories(node, getLdirPath(jTree.getSelectionPath()), true);
		addLinuxSubDirectories(node, getLdirPath(jTree.getSelectionPath()));
		treeModel.reload(node);
		jTree.expandRow(row);
	    } else
            {   // DefaultMutableTreeNode node = getTreeNode(jTree.getSelectionPath()) ; 
		// node.removeAllChildren() ; 
		// node.add(new DefaultMutableTreeNode(new Boolean(true))); 
		DirectoryMutableTreeNode node =
		(DirectoryMutableTreeNode) getTreeNode(jTree.getSelectionPath());
		node.removeAllChildren();
		setCurrentDirectory(jTree.getSelectionPath());
		addDOSDirectories(node, currentDirectory);
		addDOSSubDirectories(node, currentDirectory);
		treeModel.reload(node);
		jTree.expandRow(row);
	    }
	}
    }
    /**
     * the removeDrive()-method removes the drive of the selected Node in the tree.
     */
    public void removeDrive()
    {   if (jTree.getSelectionCount() == 1)
        {   if (jTree.getSelectionPath().getPathCount() >= 2)
            {   int row = jTree.getSelectionRows()[0];
		TreePath path = jTree.getSelectionPath();

		while (path.getPathCount() > 2)
                {   path = path.getParentPath();
		}
		debugOutput("remove: " + path.toString());
		DefaultMutableTreeNode root = getTreeRoot();
		debugOutput("getTreeNode(path): " + getTreeNode(path));
		debugOutput("root: " + root.toString());
		root.remove(getTreeNode(path));
		treeModel.reload();
		if (isLinux())
                {   selectDriveFirst();
		} else
                {   selectDriveC();
		}
	    } else
		// the node "Computer" cannot be removed 
            {   debugOutput("cannot remove " + jTree.getSelectionPath().toString());
		return;
	    }
	}
    }
    /**
     * the addDrive()-method shows a dialog where you can specify a drive and a directory, which will be added to the
     * tree if confirm with OK
     */
    public void addDrive()
    {   AddDriveDialog dialog = new AddDriveDialog(LTOOLSgui.myProg, true, isLinux());
	 dialog.show();
	if (dialog.getStatus())
        {   // add a drive 
	    debugOutput("add a drive --- device: \"" + dialog.getDevice() + "\" " +
			"directory: \"" + dialog.getDirectory() + "\"");

	    DefaultMutableTreeNode top = getTreeRoot();
	    if (isLinux())
            {   debugOutput("top.toString(): " + top.toString());
		String dir = dialog.getDirectory();
		if (!dir.endsWith("/"))
                {   dir = dir + "/";
		}
		String drive = dialog.getDevice();
		String driveDir = drive + " " + dir;
		DirectoryMutableTreeNode node = new DirectoryMutableTreeNode(this,
					      new LToolGuiTreeIconData(ICON_DRIVE_FIXED, null, driveDir), dir, drive);
		top.add(node);
		addLinuxDirectories(node, driveDir, true);
		getTreeModel().reload();
		selectDriveFirst();
	    } else
            {   debugOutput("top.toString(): " + top.toString());
		String driveDir = dialog.getDevice() + dialog.getDirectory();
		if (!driveDir.endsWith(File.separator))
                {   driveDir = driveDir + File.separator;
		}
		/*
		   DefaultMutableTreeNode node =
		   new DefaultMutableTreeNode(new LToolGuiTreeIconData(ICON_DRIVE_FIXED, null, new FileTreeNode(new File(driveDir))));
		 */

		// setCurrentDirectory(jTree.getSelectionPath()) ; 
		setCurrentDirectory(driveDir);
		DirectoryMutableTreeNode node = new DirectoryMutableTreeNode(this,
					  new LToolGuiTreeIconData(ICON_DRIVE_FIXED, null, driveDir), "\\", driveDir);
		addDOSDirectories(node, currentDirectory);

		top.add(node);
		// node.add(new DefaultMutableTreeNode(new Boolean(true))); 
		getTreeModel().reload();
		selectDriveC();
	    }
	}
    }
    /** returns the reference to the JTable for another classes
     * @return JTable - returns the jTable for working in the Event-Listeners
     */
    public JTable getJTable()
    {   return jTable;
    }
    /** returns the reference to the tableModel for another classes
     * @return LToolGuiTableModel - returns the tableModel for working in the Event-Listeners
     */
    public LToolGuiTableModel getTableModel()
    {   return tableModel;
    }
    /** returns the reference to the JTableHeader for another classes
     * @return returns the JTableHeader of the JTable
     */
    public JTableHeader getJTableHeader()
    {   return jTableHeader;
    }
    /** returns the contextmenu ContextMenuTable
     * @return ContextMenuTable
     */
    public ContextMenuTable getContextMenuTable()
    {   return contextMenuTable;
    }
    /** returns the contextmenu contextMenuTree
     * @return ContextMenuTree
     */
    public ContextMenuTree getContextMenuTree()
    {   return contextMenuTree;
    }
    /** returns the reference to the JTree for another classes
     * @return JTree - returns the jTree for working in the Event-Listeners
     */
    public JTree getJTree()
    {   return jTree;
    }
    /** returns the reference to the treeModel for another classes
     * @return DefaultTreeModel - returns the treeModel for working in the Event-Listeners
     */
    public DefaultTreeModel getTreeModel()
    {   return treeModel;
    }
    /** returns the value of the isLinux-field
     * @return the value of the isLinux-field
     */
    public boolean isLinux()
    {   return isLinux;
    }
    /** returns the text of the root-node of the JTree
     * @return String - returns the Text of the root-node in the JTree ("Computer")
     */
    public String getRootNodeText()
    {   return rootNodeText;
    }
    /** returns the root-node of the JTree
     * @return the root-node of the JTree
     */
    public DefaultMutableTreeNode getTreeRoot()
    {   return this.root;
    }

    /**
     *
     */
    /*
       public void createNewDOSPath(String child)
       {
       Vector pathComponents = new Vector() ;
       TreePath selectedPath = jTree.getSelectionPath() ;
       for (int i=0; i < selectedPath.getPathCount(); i++)
       {
       pathComponents.add (selectedPath.getPathComponent(i)) ;
       }
       pathComponents.add(child) ;
       Object[] pathArray = pathComponents.toArray() ;
       TreePath treePath = new TreePath(pathArray) ;

       newDOSPath = treePath ;
       }
     */
    /** the getDOSDriveTypes()-method gets all DOS-drives on the local machine and sets
     * the Vector dosDrives with this drives and their type (CDROM, fixed drive,
     * removable drive, ...)
     * this method gets its information from an extern C-application
     */
    public void getDOSDriveTypes()
    {   debugOutput("getDOSDriveTypes");
    	try
        {   dosDrives.removeAllElements();
	    dosDrives = DriveType.getDOSDriveTypesOnMachine();
	    /*
	       for (int i=0; i < dosDrives.size(); i++)
               {
               debugOutput(((DriveType)dosDrives.elementAt(i)).toString()) ;
	       }
	     */
	}
	catch(Exception e)
        {   e.printStackTrace();
	}
    }
    /** the getDriveIcon()-method returns the Image of the given drive-type
     * @param drive the type of the drive
     * @return the Icon of the type of the drive
     */
    public static ImageIcon getDriveIcon(DriveType drive)
    {   switch (drive.getType())
        {   case 0:
		return ICON_DRIVE_UNKNOWN;
		case 1:
		return ICON_DRIVE_NOROOTDIR;
		case 2:
		return ICON_DRIVE_REMOVEABLE;
		case 3:
		return ICON_DRIVE_FIXED;
		case 4:
		return ICON_DRIVE_REMOTE;
		case 5:
		return ICON_DRIVE_CDROM;
		case 6:
		return ICON_DRIVE_RAMDISK;
	}
	return ICON_DRIVE_FIXED;
    }
    /** setBackgroundTreeTable()-method sets the background of the JTable and the JTree
     * if Linux-DirFilePane isConnected another Color !!!
     * @param c the new background-color of the JTree and the JTable
     */
    public void setBackgroundTreeTable(Color c)
    {   jTree.setBackground(c);
	jTable.setBackground(c);
    }
    /** the debugOutput()-method shows debugging-information on the stdout
     * @param text the text to be shown on the stdout
     */
    static void debugOutput(String text)			// Debug output to console 
    {   if (DEBUG == true)
        {   System.out.println(text);
	}
    }
    // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
    // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
    // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
    // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
    // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 

    /** This method is invoked to signify that the Drag and Drop
     * operation is complete. The getDropSuccess() method of
     * the <code>DragSourceDropEvent</code> can be used to
     * determine the termination state. The getDropAction() method
     * returns the operation that the drop site selected
     * to apply to the Drop operation. Once this method is complete, the
     * current <code>DragSourceContext</code> and
     * associated resources become invalid.
     *
     * @param dsde the <code>DragSourceDropEvent</code>
     *
     */
    public void dragDropEnd(DragSourceDropEvent dsde)
    {   /*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dragDropEnd(DragSourceDropEvent dsde) :") ;
	   debugOutput(dsde.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }

    /** Called as the cursor's hotspot enters a platform-dependent drop site.
     * This method is invoked when all the following conditions are true:
     * <UL>
     * <LI>The cursor's hotspot enters the operable part of a platform-
     * dependent drop site.
     * <LI>The drop site is active.
     * <LI>The drop site accepts the drag.
     * </UL>
     *
     * @param dsde the <code>DragSourceDragEvent</code>
     *
     */
    public void dragEnter(DragSourceDragEvent dsde)
    {   /*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dragEnter(DragSourceDragEvent dsde) ") ;
	   debugOutput(dsde.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }
    /** Called while a drag operation is ongoing, when the mouse pointer enters the
     * operable part of the drop site for the DropTarget registered with this listener.
     * @param dtde the event data
     */
    public void dragEnter(DropTargetDragEvent dtde)
    {   /*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dragEnter(DropTargetDragEvent dtde)") ;
	   debugOutput(dtde.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }

    /** Called as the cursor's hotspot exits a platform-dependent drop site.
     * This method is invoked when any of the following conditions are true:
     * <UL>
     * <LI>The cursor's hotspot no longer intersects the operable part
     * of the drop site associated with the previous dragEnter() invocation.
     * </UL>
     * OR
     * <UL>
     * <LI>The drop site associated with the previous dragEnter() invocation
     * is no longer active.
     * </UL>
     * OR
     * <UL>
     * <LI> The current drop site has rejected the drag.
     * </UL>
     *
     * @param dse the <code>DragSourceEvent</code>
     *
     */
    public void dragExit(DragSourceEvent dse)
    {   /*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dragExit(DragSourceEvent dse) ") ;
	   debugOutput(dse.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }
    /** Called while a drag operation is ongoing, when the mouse pointer has exited the
     * operable part of the drop site for the DropTarget registered with this listener.
     * @param dte the event data
     */
    public void dragExit(DropTargetEvent dte)
    {   /*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dragExit(DropTargetEvent dte)") ;
	   debugOutput(dte.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }

    /** A <code>DragGestureRecognizer</code> has detected
     * a platform-dependent drag initiating gesture and
     * is notifying this listener
     * in order for it to initiate the action for the user.
     * <P>
     * @param dge the <code>DragGestureEvent</code> describing
     * the gesture that has just occurred
     *
     */
    public void dragGestureRecognized(DragGestureEvent dge)
    {   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
	debugOutput("public void dragGestureRecognized(DragGestureEvent dge) ");
	debugOutput(dge.toString());
	debugOutput("-----------------------------------------------------------------------------\n");
	Vector items = getSelectedListItemFile();
	if (items.size() > 1)
        {   return;
	}
	String transfer = "";
	for (int i = 0; i < items.size(); i++)
        {   transfer = transfer + ((ListItemFile) items.elementAt(i)).getFullFilePath() + "\n";
	}
	dge.startDrag(DragSource.DefaultCopyDrop,		// cursor 
		      new StringSelection(transfer),		// transferable 
		      this);					// drag source listener 
	LTOOLSgui.myProg.copyListItemFiles();
    }

    /** Called as the cursor's hotspot moves over a platform-dependent drop site.
     * This method is invoked when all the following conditions are true:
     * <UL>
     * <LI>The cursor's hotspot has moved, but still intersects the
     * operable part of the drop site associated with the previous
     * dragEnter() invocation.
     * <LI>The drop site is still active.
     * <LI>The drop site accepts the drag.
     * </UL>
     *
     * @param dsde the <code>DragSourceDragEvent</code>
     *
     */
    public void dragOver(DragSourceDragEvent dsde)
    {   // debugOutput(this.getComponentAt(dsde.getLocation()).toString() + "\n") ; 
	/*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dragOver(DragSourceDragEvent dsde) ") ;
	   debugOutput(dsde.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }
    /** Called when a drag operation is ongoing, while the mouse pointer is still over
     * the operable part of the drop site for the DropTarget registered with this listener.
     * @param dtde the event data
     */
    public void dragOver(DropTargetDragEvent dtde)
    {   DropTargetContext context = dtde.getDropTargetContext();
	/*
	   // CHANGE THE COLOR under the MOUSE !!??? 
	// Rectangle r = jTree.getPathBounds(path) ; 
	// jTree.setBackground(Color.ORANGE) ; 
	// setBackground(sel ? this.bkSelectionColor :  this.bkNonSelectionColor); 
	TreeCellRenderer renderer = jTree.getCellRenderer();
	if (renderer instanceof LToolGuiTreeIconCellRenderer)
        {   debugOutput("instanceof LToolGuiTreeIconCellRenderer");
	    ((LToolGuiTreeIconCellRenderer) renderer).setMyColor();
	    // renderer.getTreeCellRendererComponent(jTree, ).setBackground(Color.CYAN) ; 
	}
	*/

	if (context.getComponent() == jTree)
        {   int x = (int) dtde.getLocation().getX();
	    int y = (int) dtde.getLocation().getY();
	    if (jTree.getRowForLocation(x, y) != -1)
            {   int row = jTree.getRowForLocation(x, y);
		TreePath path = jTree.getPathForRow(row);
		String dir;
		if (isLinux())
                {   dir = getLdirPath(path);
		} else
                {   dir = getDOSLinuxPath(path);
		}
		if (!path.equals(LTOOLSgui.getCopyToDirectory()))	// (!dir.equals(LTOOLSgui.getCopyToDirectory())) 
                {   LTOOLSgui.setCopyToDirectory(path);		// reset the copyToDirectory 
		    debugOutput("DragOver - LTOOLSgui.getCopyToDirectory(): " + LTOOLSgui.getCopyToDirectory());
		}
	    }
	} else if (context.getComponent() == jTable)
        {   LTOOLSgui.setCopyToDirectory(null);
	    // debugOutput("DragOver - LTOOLSgui.getCopyToDirectory(): " + LTOOLSgui.getCopyToDirectory()) ; 
	}
	// debugOutput(this.getComponentAt(dtde.getLocation()).toString() + "\n") ; 
	/*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dragOver(DropTargetDragEvent dtde)") ;
	   debugOutput(dtde.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }
    /** Called when the user has modified the drop gesture.
     * This method is invoked when the state of the input
     * device(s) that the user is interacting with changes.
     * Such devices are typically the mouse buttons or keyboard
     * modifiers that the user is interacting with.
     *
     * @param dsde the <code>DragSourceDragEvent</code>
     *
     */
    public void dropActionChanged(DragSourceDragEvent dsde)
    {   /*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dropActionChanged(DragSourceDragEvent dsde) ") ;
	   debugOutput(dsde.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }
    /** Called if the user has modified the current drop gesture.
     * @param dtde the event data
     */
    public void dropActionChanged(DropTargetDragEvent dtde)
    {   /*
	   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") ;
	   debugOutput("public void dropActionChanged(DropTargetDragEvent dtde)") ;
	   debugOutput(dtde.toString()) ;
	   debugOutput("-----------------------------------------------------------------------------\n") ;
	 */
    }
    /** Called when the drag operation has terminated with a drop on the operable part
     * of the drop site for the DropTarget registered with this listener.
     * This method is responsible for undertaking the transfer of the data associated
     * with the gesture. The DropTargetDropEvent provides a means to obtain a
     * Transferable object that represents the data object(s) to be transfered.
     *
     * From this method, the DropTargetListener shall accept or reject the drop via the
     * acceptDrop(int dropAction) or rejectDrop() methods of the DropTargetDropEvent
     * parameter.
     *
     * Subsequent to acceptDrop(), but not before, DropTargetDropEvent's
     * getTransferable() method may be invoked, and data transfer may be performed via
     * the returned Transferable's getTransferData() method.
     *
     * At the completion of a drop, an implementation of this method is required to
     * signal the success/failure of the drop by passing an appropriate boolean to the
     * DropTargetDropEvent's dropComplete(boolean success) method.
     *
     * Note: The data transfer should be completed before the call to the
     * DropTargetDropEvent's dropComplete(boolean success) method. After that, a call
     * to the getTransferData() method of the Transferable returned by
     * DropTargetDropEvent.getTransferable() is guaranteed to succeed only if the data
     * transfer is local; that is, only if DropTargetDropEvent.isLocalTransfer()
     * returns true. Otherwise, the behavior of the call is implementation-dependent.
     * @param dtde the event data
     */
    public void drop(DropTargetDropEvent dtde)
    {   debugOutput(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
	debugOutput("public void drop(DropTargetDropEvent dtde):");
	debugOutput(dtde.toString());

	try
        {   DataFlavor stringFlavor = DataFlavor.stringFlavor;
	    Transferable trans = dtde.getTransferable();
	    if (isLinux() && LTOOLSgui.myProg.isLinuxReadOnly)	// isLinux=true and read only 
            {   // check this, because jdk < 1.3 is dead by dropping a file in a directory, when this file exists 
		// or linux is read only 
		debugOutput("linux is readonly - reject drop");
		dtde.rejectDrop();
		String msg = "Your Linux filesystem is set to read only - change in menu 'File - Linux read only' first.";
		 JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, "LTOOLS", JOptionPane.ERROR_MESSAGE);

	    } else if (fileExists(LTOOLSgui.getCopyToDirectory()))	// File exists 
            {   // check this, because jdk < 1.3 is dead by dropping a file in a directory, when this file exists 
		// or linux is read only 
		debugOutput("file exists - reject drop");
		dtde.rejectDrop();
		String msg = "A file with that name already exists in the target directory - delete or rename it first.";
		JOptionPane.showMessageDialog(LTOOLSgui.myProg, msg, "LTOOLS", JOptionPane.ERROR_MESSAGE);
	    } else if (dtde.isDataFlavorSupported(stringFlavor))
            {   debugOutput((String) trans.getTransferData(stringFlavor));
		dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);

		DropTargetContext context = dtde.getDropTargetContext();

		if (context.getComponent() == jTree)
                {   debugOutput("JTREE");
		    debugOutput("dtde.getLocation(): " + dtde.getLocation());
		    int x = (int) dtde.getLocation().getX();
		    int y = (int) dtde.getLocation().getY();
		    int row = jTree.getRowForLocation(x, y);

		    if (row != -1)
                    {   TreePath path = jTree.getPathForRow(row);
			String dir;
			if (isLinux())
                        {   dir = getLdirPath(path);
			    debugOutput("PASTE TO LINUX");
			    LTOOLSgui.myProg.setActiveDirFilePane(LTOOLSgui.myProg.getLinuxFilePane());
			} else
                        {   dir = getDOSLinuxPath(path);
			    debugOutput("PASTE TO DOS");
			    LTOOLSgui.myProg.setActiveDirFilePane(LTOOLSgui.myProg.getDOSFilePane());
			}
			// DefaultMutableTreeNode node = getTreeNode(path) ; 
			// debugOutput("node.toString():" + node.toString()) ; 
			LTOOLSgui.setCopyToDirectory(path);
			debugOutput("copy file(s) to directory: \"" + LTOOLSgui.getCopyToDirectory() + "\"");

			dtde.dropComplete(true);
			LTOOLSgui.myProg.pasteListItemFiles();
		    }
		} else if (context.getComponent() == jTable)
                {   debugOutput("JTABLE");
		    if (isLinux())
                    {   debugOutput("PASTE TO LINUX");
			LTOOLSgui.myProg.setActiveDirFilePane(LTOOLSgui.myProg.getLinuxFilePane());
		    } else
                    {   debugOutput("PASTE TO DOS");
			LTOOLSgui.myProg.setActiveDirFilePane(LTOOLSgui.myProg.getDOSFilePane());
		    }

		    dtde.dropComplete(true);
		    LTOOLSgui.myProg.pasteListItemFiles();
		} else
                {   debugOutput("?????");
		}
		dtde.dropComplete(true);
	    } else
            {   dtde.rejectDrop();
	    }
	    LTOOLSgui.copyFileIsValid = false;
	    LTOOLSgui.copyListItemFiles.removeAllElements();
	}
	catch(IOException ioe)
        {   ioe.printStackTrace();
	}
	catch(UnsupportedFlavorException ufe)
        {   ufe.printStackTrace();
	}
	catch(Exception e)
        {   e.printStackTrace();
	}
	LTOOLSgui.setCopyToDirectory(null);			// reset the LTOOLSgui.copyToDirectory 
	debugOutput("-----------------------------------------------------------------------------\n");
    }

    /** the fileExists()-method checks if the file dropped in JTree or in JTable exists
     * in the directory the file was dropped in
     * @param path the TreePath of the JTree when drop or null when drop in JTable
     * @return true, if the file exists in the Directory of path
     */
    public boolean fileExists(TreePath path)
    {   boolean flag = false;

	// file to copy 
	ListItemFile item = (ListItemFile) LTOOLSgui.copyListItemFiles.elementAt(0);

	if (path == null)					// copy to JTable 
        {   debugOutput("path = null");
	    path = getTreeSelectionPath();
	    debugOutput("path: " + path.toString());

	    for (int i = 0; i < tableModel.getRowCount(); i++)
            {   ListItemFile itemTable = tableModel.getListItemFile(i);

		if (item.getFileName().equals(itemTable.getFileName()))
                {   flag = true;
		    break;
		}
	    }
	} else
	    // copy to JTree 
        {   // get all files in the path 
	    // debugOutput("path: " + path.toString()) ; 
	    if (isLinux())					// to LinuxTree 
            {   String linuxPath = getDOSLinuxPath(path);
		// debugOutput("linuxPath: " + linuxPath) ; 

		String command = "ldir -x -s" + getLinuxDrive(linuxPath) + " \"" + getLinuxPath(linuxPath) + "\"";
		String response = execOperatingSystemCommand(command, !LTOOLSgui.isConnected());
		if (!(response.startsWith("d") && ("" + response.charAt(startColumnLinuxFileName)).equals(".")))
                {   JOptionPane.showMessageDialog(LTOOLSgui.myProg, "ERROR: " + response, "LTOOLSgui", JOptionPane.ERROR_MESSAGE);
		    return false;
		}
		StringTokenizer st = new StringTokenizer(response, "\n\r");

		while (st.hasMoreTokens())
                {   String token = st.nextToken();

		    if (token.length() > startColumnLinuxFileName)
                    {   String fileName = getLdirField(token, 9);
			if (item.getFileName().equals(fileName))
                        {   flag = true;
			    break;
			}
		    }
		}
	    } else
		// To DosTree 
            {   String dosPath = getDOSLinuxPath(path);
		// debugOutput("dosPath: " + dosPath) ; 
		File dir = new File(dosPath);
		String[]files = dir.list();
		for (int i = 0; i < files.length; i++)
                {   if (item.getFileName().equals(files[i]))
                    {   flag = true;
			break;
		    }
		}
	    }
	}
	// debugOutput("fileExists(): " + flag) ; 
	return flag;
    }
}

