/* LREADgui.java
   
   Java based graphical user interface for the LTOOLS toolkit.
   
   Requires Java 1.1 or newer. Does run as a standalone application, not as an applet.
   

   Copyright (C) 1999-2000 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   For further information please see file README.TXT.
   
   ---History, Changes:-----------------------------------------------------------
   V1.0: First release for public alpha test.
	 W. Zimmermann, 15 April 1999
   V1.1: Comments update.
         W. Zimmermann, 28 Mai 1999
   V1.2: Changed symbolic link handling
   	 W. Zimmermann, 01 Aug 1999
   V1.3: Resolved compatibility issue with JDK 1.2
   	 W. Zimmermann, 29 Aug. 1999
   V1.4: Supports file renaming now, needs LTOOLS V4.0 or newer.
   	 W. Zimmermann, 30 Nov. 1999
   V1.5: Supports creating directories and symlinks now, needs LTOOLS V4.2 or newer.
   	 W. Zimmermann, 15 Dec. 1999

*/


import java.applet. *;
import java.awt. *;
import java.awt.event. *;
import java.io. *;
import java.lang.Thread.*;
import java.net. *;
import java.text.*;
import java.util. *;

public class lreadgui extends Applet implements ActionListener, KeyListener, MouseListener
{   
    static final String VERSION = "V1.5";

    static final boolean DEBUG = false;				//set to 'true', if you want to get all these debug messages
								//start column of DOS filename in dirListing's lines
    static final int stDOSfn = 23; 				//note, if the date string does not have 10 chars, this will fail ???
    static final int stLINfn = 56;				//start column of LINUX filename in dirListing's lines
    static final int BUFSIZE = 32768;				//size of various buffers
    
    static Socket qSocket = null;				//Socket for remote connection
    static BufferedInputStream bReceive = null;			//Receive stream
    static BufferedOutputStream bSend = null;			//Transmit stream
    static BufferedReader qReceive = null;			//Receive stream
    static BufferedWriter qSend = null;				//Transmit stream
    static String hostname = "localhost";
    static int port = 1605;					//Server port number
    static boolean Connected=false;

    String hostPathDelimiter="\\";

    boolean LINmode=true;					//Mode variable for switching between DOS and LINUX
 
    String LINlisting = "";					//Contains LINUX directory listing
    String DOSlisting = "";					//Contains DOS directory listing
    String currentLINdirectory = "/";				//Name of current LINUX directory
    String oldLINdirectory = "/";				//Name of previous LINUX directory
    String currentDOSdirectory = hostPathDelimiter;             //Name of current DOS directory
    String currentLINfile="";					//Name of current selected LINUX file
    String currentDOSfile="";					//Name of current selected DOS file
    String currentLINdrive="/dev/hda";				//Name of current LINUX drive
    String currentDOSdrive="c:";                                //Name of current DOS drive
   
    Label dirTxt, driveTxt, emptyTxt;				//Various labels for non-editable text
    TextField drive;						//Input text field for drive selection
    java.awt.List dirListing;					//List field for directory listing
    
    MenuBar menuBar;						//Menu bar
    Menu    fileMenu;						//--File menu
    Menu    editMenu;						//--Edit menu
    Menu    remoteMenu;						//--Remote menu
    Menu    helpMenu;						//--Help menu   
								//Buttons
    Button buttonDOS;						//--Switch to DOS 
    Button buttonLIN;						//--Switch to LINUX
    Button driveButton;						//--Set drive
    Button exitButton;						//--Exit
    
    Panel  drivePanel;						//Panel (takes all the buttons)

    Frame ourFrame = new Frame("LTOOLS GUI");                   //Frame (our root window)


//################################################################################################ 
//HIGH LEVEL FUNCTIONS
//################################################################################################ 
//
//######Startup and building the graphical user interface#########################################
//
//---- Main function (Entry point) --------------------------------------------
    static public void main(String args[])
    {   debugOutput("Started main()");

	lreadgui myProg = new lreadgui();			//Make an instance of our main class
								//(needed, as main() is static)
        								        								
        System.out.println("LTOOLS GUI " + myProg.VERSION + " (C) 1999-2000 Werner.Zimmermann@fht-esslingen.de\n"
	                 + "Operating System: " + System.getProperty("os.name") + " " + System.getProperty("os.arch") + " " 
	                                        + System.getProperty("os.version") + "\n"
	                 + "Java VM         : " + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + "\n");
	    									
	myProg.hostPathDelimiter=System.getProperty("file.separator");
	if (myProg.hostPathDelimiter.equals("/"))		//Unix-like systems do not use disk drive names
	{   myProg.currentDOSdrive="";				//in their pathnames
            myProg.currentDOSdirectory="/";
        }
	if (args.length>0) 
	{   if ((args[0].startsWith("-h")) || (args[0].startsWith("-?")))
            { System.out.println("LTOOLS Graphical User Interface " + myProg.VERSION + "\n(C) 1999-2000 Werner.Zimmermann@fht-esslingen.de\n\n"
	    			+"Usage:  LREADgui [Linux_drive [LINUX_directory [DOS_drive [DOS_directory]]]]\n"
	    			+"Note:   Java 1.1 or newer needed\n"
	    			+"        set DOS_drive to \"\" if running LREADgui on a UNIX host\n\n");
	      myProg.closeConnection();
	      System.exit(0);	    			
	    } else
	    { myProg.currentLINdrive=args[0];
	    }
            if (args.length>1)
                myProg.currentLINdirectory=args[1];
            if (args.length>2)
                myProg.currentDOSdrive=args[2];
            if (args.length>3)
                myProg.currentDOSdirectory=args[3];
        }

	myProg.init();
	myProg.ourFrame.add(myProg);					//Bind applet to frame 
	myProg.ourFrame.setSize(600, 400);
	myProg.ourFrame.setVisible(true);				//Show frame 

	myProg.ourFrame.addWindowListener(new WindowAdapter()
                                       {   public void windowClosing(WindowEvent e)
                                           {   closeConnection();   
                                               System.exit(0);
				       	   }
				       });
	myProg.showLINdirectory();
	myProg.repaint();    
    }
//
//----- Build the graphical user interface ------------------------------------
    public void init()					 
    {    debugOutput("Started init()");
    
    	 Font font = new Font("Monospaced", Font.PLAIN, 12);
	 this.setFont(font);    
 	 this.setLayout(new BorderLayout());
 	    
	 //Menus-------------------------------------------
         menuBar = new MenuBar();
         ourFrame.setMenuBar(menuBar);

     	 fileMenu = new Menu("File");
     	 fileMenu.add("Exit");
         fileMenu.addActionListener(this);
	 fileMenu.setFont(new Font("Dialog", Font.BOLD, 12));
     	 menuBar.add(fileMenu);

     	 editMenu = new Menu("Edit");
     	 editMenu.add("Delete");
	 editMenu.add("New");
	 editMenu.add("File properties");
         editMenu.addActionListener(this);
	 editMenu.setFont(new Font("Dialog", Font.BOLD, 12));
     	 menuBar.add(editMenu);
       
	 remoteMenu=new Menu("Remote");
	 remoteMenu.add("Set remote host");
	 remoteMenu.addActionListener(this);
	 remoteMenu.setFont(new Font("Dialog", Font.BOLD, 12));
     	 menuBar.add(remoteMenu);
	 
         helpMenu = new Menu("Help");
         helpMenu.add("Help");
         helpMenu.addSeparator();
         helpMenu.add("About");
         helpMenu.addActionListener(this);   
	 helpMenu.setFont(new Font("Dialog", Font.BOLD, 12));
 	 menuBar.setHelpMenu(helpMenu);
     	 
	 //Title bar--------------------------------------- 
	 dirTxt = new Label("   LINUX Directory  " + currentLINdirectory + "   on " + currentLINdrive);
	 add("North",dirTxt);
	 dirTxt.setFont(new Font("Dialog", Font.BOLD, 12));

	 //Button panel------------------------------------
	 buttonDOS = new Button(" DOS ");			//DOS/LINUX Buttons
	 buttonLIN = new Button("LINUX");
	 buttonDOS.setFont(new Font("Dialog", Font.BOLD, 12));
	 buttonLIN.setFont(new Font("Dialog", Font.BOLD, 12));
	 buttonLIN.setEnabled(false);
	 buttonDOS.addActionListener(this);
	 buttonLIN.addActionListener(this);

    	 driveTxt = new Label("      Current LINUX disk:    ");
	 driveTxt.setFont(new Font("Dialog", Font.BOLD, 12));
	 driveTxt.setAlignment(Label.RIGHT);

    	 drive = new TextField(currentLINdrive, 10);		//Input field for LINUX or DOS drive
	 drive.addKeyListener(this);

	 driveButton = new Button("SET DRIVE");
	 driveButton.setFont(new Font("Dialog", Font.BOLD, 12));
	 driveButton.addActionListener(this);

	 emptyTxt = new Label(" ");

	 exitButton = new Button("EXIT");
	 exitButton.setFont(new Font("Dialog", Font.BOLD, 12));
	 exitButton.addActionListener(this);
	 
    	 drivePanel = new Panel();
	 drivePanel.add(buttonDOS);
	 drivePanel.add(buttonLIN);
	 drivePanel.add(driveTxt);
	 drivePanel.add(drive);
	 drivePanel.add(driveButton);
	 drivePanel.add(emptyTxt);
	 drivePanel.add(exitButton);
	 add("South",drivePanel);
	 	 
	 //Directory listing-------------------------------
	 dirListing = new java.awt.List(20, false);
	 dirListing.add("                                                                              ");
	 add("Center",dirListing);
	 dirListing.addActionListener(this);
	 dirListing.addMouseListener(this);
	 dirListing.addKeyListener(this);

    }
//    
//----- Switch to the DOS directory view --------------------------------------
    void DOSwindow()
    {    debugOutput("Started DOSwindow()");
    
    	 LINmode=false;
    	 dirTxt.setText("   DOS Directory  " + currentDOSdrive + currentDOSdirectory);
	 driveTxt.setText("Current DOS disk:    ");
	 drive.setText(currentDOSdrive);
	 buttonDOS.setEnabled(false);
	 buttonLIN.setEnabled(true);
         dirListing.removeAll();
//       editMenu.disable();
         showDOSdirectory();
         repaint();
    }
//----- Switch to the LINUX directory view ------------------------------------
    void LINwindow()
    {    debugOutput("Started LINwindow()");
    
         checkLINpathname();
	 if (LINmode==false)
	 {  LINmode=true;
	    dirListing.removeAll();
	    driveTxt.setText("Current LINUX disk:    ");
	    drive.setText(currentLINdrive);
            buttonDOS.setEnabled(true);
            buttonLIN.setEnabled(false);
	 }
    	 dirTxt.setText("   LINUX Directory  " + currentLINdirectory +  "   on " + currentLINdrive);
//       editMenu.enable();
         showLINdirectory();
         repaint();        
    }
//

//---- Remove '..' from LINUX pathnames ---------------------------------------
    void checkLINpathname()
    {	int i;
    	String tempStart, tempEnd;
    
    	while ((i=currentLINdirectory.indexOf("/../"))!=-1)
    	{    debugOutput("Removing '/../ from pathname "+currentLINdirectory);
    	     tempStart=currentLINdirectory.substring(0,i);		//the start of the pathname before /../
    	     tempEnd=currentLINdirectory.substring(i+3);		//the end of the pathname after /../
    	     i=tempStart.lastIndexOf("/");
    	     if (i==-1) 
    	         break;
    	     currentLINdirectory=tempStart.substring(0,i)+tempEnd;
    	}
    }

//######Viewing directories#######################################################################
//
//---- Show LINUX directory ---------------------------------------------------
    void showLINdirectory()			
    {   debugOutput("Started showLINdirectory(): " + currentLINdirectory);

	String command;
	int i = 0;

  	command = "ldir -x -s" + currentLINdrive + " " + currentLINdirectory;	

	LINlisting=execOperatingSystemCommand(command);

	StringTokenizer token = new StringTokenizer(LINlisting, "\n\r");
        
        command=token.nextToken();
        if ((command.length()<stLINfn) || (command.substring(stLINfn).equals(".")==false))
        {   currentLINdirectory=oldLINdirectory;      
    	    dirTxt.setText("   LINUX Directory  " + currentLINdirectory +  "   on " + currentLINdrive);
            new MessageBox(ourFrame, true, LINlisting.substring(0,LINlisting.length()-2), "LTOOLS",1).setVisible(true);
  	    return;
        }
        dirListing.removeAll();
        
        while (token.hasMoreTokens())
        {   dirListing.add(token.nextToken(), i);
	    i++;
	}
   }

//---- Show DOS directory -----------------------------------------------------
    void showDOSdirectory()			
    {   debugOutput("Started showDOSdirectory(): " + currentDOSdrive + currentDOSdirectory);

	int i;
	
	File DOSdir = new File(currentDOSdrive+currentDOSdirectory);
	if(DOSdir.exists()==false)
	{    currentDOSdrive="";
	     currentDOSdirectory=hostPathDelimiter;
	     DOSdir = new File(currentDOSdrive+currentDOSdirectory);
	}

        String[] files = DOSdir.list();
        		
	DOSlisting="<DIR>                  ..\n";
	
	for (i=0; i<files.length;i++)
	{   //debugOutput("file=" + currentDOSdrive+currentDOSdirectory+files[i]);
	
	    File fd= new File(currentDOSdrive+currentDOSdirectory+files[i]);

	    Date date=new Date(fd.lastModified()); 
	    
	    String tempLength = new Long(fd.length()).toString();
            String fileLength="";

            if (fd.isDirectory()==true)
            {   fileLength = "<DIR>    ";
            } else
            {   for (int j=0; j<(9-tempLength.length()); j++)
                fileLength=fileLength+" ";
	        fileLength=fileLength+fd.length();
	    }
	    DOSlisting = DOSlisting + fileLength + "  " + DateFormat.getDateInstance().format(date)
	                            			+ "  "  + files[i] + "\n";
	}
	
	i=0;
	StringTokenizer token= new StringTokenizer(DOSlisting, "\n\r");
 	dirListing.removeAll();
	while (token.hasMoreTokens())
        {   dirListing.add(token.nextToken(), i);
	    i++;
	}	
	
    }
//
//######Navigating in directories and selecting files#############################################
//
//---- Handle LINUX directory or file selection -------------------------------
    void selectLINhandler()
    {   debugOutput("Started selectLINhandler()");
        
        String item = "", tempDir, temp="";
	int i;
        	
        item = dirListing.getSelectedItem();
        if (item==null)
        {  new MessageBox(ourFrame, true, "Select a file or directory first", "LTOOLS",1).setVisible(true);
           return;
        }

	if (item.startsWith("d"))				//Directory selected -> show it 
        {   temp = item.substring(stLINfn, item.length());

	    if (temp.equals("."))
            {   return;						//do nothing, its the current directory 
	    } else if (temp.equals(".."))
            {   temp = currentLINdirectory;			//it's the parent directory 
		i = temp.lastIndexOf('/');
		if (i > 0)
		    i = temp.lastIndexOf('/', i - 1);
		oldLINdirectory=currentLINdirectory;
		currentLINdirectory = temp.substring(0, i + 1);
	    } else
            {   tempDir = currentLINdirectory + temp + "/";	//it's a relative directory 
                oldLINdirectory=currentLINdirectory;
		currentLINdirectory = tempDir;
	    }
	    LINwindow();
	} else if (item.startsWith("b") || item.startsWith("c"))//Block or character device 
        {   new MessageBox(ourFrame, true, "Sorry, can't read block or character device", "LTOOLS",1).setVisible(true);
	} else if (item.startsWith("l"))			//Symbolic link 
        {   //new MessageBox(ourFrame, true, "Sorry, LTOOLS's symbolic link handling is buggy. It works only with directories, not with files. If it fails, please go to target directly.", "LTOOLS",1).setVisible(true);     
	    temp = item.substring(item.indexOf("->",stLINfn)+3, item.length());
            debugOutput("symbolic link: "+temp);
            if (temp.startsWith("/"))
            	tempDir = temp;					//Absolute path
            else
            	tempDir=currentLINdirectory+temp;		//Relative path
            if (temp.endsWith("/"))				
            	;						//It's a directory
            else
            	tempDir = tempDir+"/";				//Maybe a file or a directory
	    oldLINdirectory=currentLINdirectory;
            currentLINdirectory=tempDir;
            LINwindow();
	} else if (item.startsWith("-"))			//Normal file 
        {   copyLINfile(item);
        }
    }

//---- Handle DOS directory or file selection -------------------------------
    void selectDOShandler()
    {   debugOutput("Started selectDOShandler()");
    	
    	String item = "", tempDir, temp="";
	int i;
	
        item = dirListing.getSelectedItem();
        if (item==null)
        {  new MessageBox(ourFrame, true, "Select a file or directory first", "LTOOLS",1).setVisible(true);
           return;
        }
	
	if (item.startsWith("<DIR>"))				//Directory selected -> show it 
        {   temp = item.substring(stDOSfn, item.length());

	    if (temp.equals(".."))
            {   temp = currentDOSdirectory;			//it's the parent directory 
		i = temp.lastIndexOf(hostPathDelimiter);
		if (i > 0)
		    i = temp.lastIndexOf(hostPathDelimiter, i - 1);
		currentDOSdirectory = temp.substring(0, i + 1);
	    } else
            {   tempDir = currentDOSdirectory + temp + hostPathDelimiter;	//it's a relative directory 
		currentDOSdirectory = tempDir;
	    }
	    DOSwindow();    
	} else 
        {   copyDOSfile(item);
        }
    }

//
//######Copying, deleting and changing properties of files########################################
//
//---- Copying a LINUX file ---------------------------------------------------
    void copyLINfile(String item)
    {   debugOutput("Started copyLINfile()");
    
        String temp="";
	String command;
	int     bytesRead=0, bytesToRead,i,j;
	byte[]  buffer= new byte[BUFSIZE];

        currentLINfile=item.substring(stLINfn, item.length());
        currentDOSfile=currentLINfile;
        FileDialog saveDialog=new FileDialog(ourFrame,"LTOOLS Copy file from LINUX to DOS", FileDialog.SAVE);
	saveDialog.setDirectory(currentDOSdrive+currentDOSdirectory);
	saveDialog.setFile(currentLINfile);
	saveDialog.setVisible(true);
	    
	currentDOSdrive=saveDialog.getDirectory().substring(0,2);
	currentDOSdirectory=saveDialog.getDirectory().substring(2);   

	if (saveDialog.getFile()==null) 
	{   return;
	}
	currentDOSfile=saveDialog.getFile();

        if (Connected==false)
        {   command = "ldir -READ -x -s"+ currentLINdrive + " " 
                     + currentLINdirectory + currentLINfile + " " 
                     + currentDOSdrive + currentDOSdirectory + currentDOSfile;	
	} else
	{   command = "ldir -READ -x -s"+ currentLINdrive + " " 
                     + currentLINdirectory + currentLINfile + " " 
                     + "zzz.xxx";	
	}

   	temp=execOperatingSystemCommand(command);

	if (temp.length()>0)
	{   debugOutput(temp);
            //if LTOOLS's command line tool issues an error message, show first line of response in message box
            new MessageBox(ourFrame, true, temp.substring(0, temp.lastIndexOf('\n')), "LTOOLS",1).setVisible(true);
        } else
        {   
            if (Connected==true)
            {	//Transport file zzz.xxx via TCP/IP and store as currentDOSdrive+currentDOSdirectory+currentDOSfile
		try
		{   temp="SENDFILE"+"\n";
		    qSend.write(temp,0,temp.length());			//Send command to server
		    qSend.flush();
		    
		    i=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
		    {   //debugOutput("j="+j+" buffer[j]="+buffer[j]+"  "+buffer[j+1]); 	//complicated to deal with
		    	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(currentDOSdrive+currentDOSdirectory+currentDOSfile);
		    bytesRead=i-j;
	            fd.write(buffer,j,bytesRead);
	            
	            while(bytesRead<bytesToRead)
	            {   i=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;
	    	}
            }
            DOSwindow();
            //new MessageBox(ourFrame, true, "Copy operation successfull","LTOOLS",1).setVisible(true);
        }
    }

//---- Copying a DOS file ---------------------------------------------------
    void copyDOSfile(String item)
    {   debugOutput("Started copyDOSfile()");

    	String temp="";
	String command;
	int     bytesRead=0, i;
	byte[]  buffer= new byte[BUFSIZE];
 
        currentDOSfile=item.substring(stDOSfn, item.length());
        currentLINfile=currentDOSfile;

	CopyDOSfileBox fbox=new CopyDOSfileBox(ourFrame, true);
	fbox.setVisible(true);
     	if (fbox.copyDOSfileBoxStatus!=fbox.OK)
     	    return;    

	if (Connected==false)
	{   command = "ldir -WRITE -x -s"+ currentLINdrive + " -copy " 
                     + currentDOSdrive+currentDOSdirectory + currentDOSfile + " " 
                     + currentLINdirectory + currentLINfile;
        } else
        {   //Transport file currentDOSdrive+currentDOSdirectory+currendDOSfile via TCP/IP and store as zzz.xxx
            //send command RECEIVEFILE\n filelength\n  file
	
	    try
            {  File DOSfile = new File(currentDOSdrive+currentDOSdirectory+currentDOSfile);
            
               FileInputStream fd = new FileInputStream(currentDOSdrive+currentDOSdirectory+currentDOSfile);
          
               temp="RECEIVEFILE\n"+DOSfile.length()+"\n";
               qSend.write(temp,0,temp.length());			//Send command to remote server
               qSend.flush();

	       do
	       {   i = fd.read(buffer,0, BUFSIZE);
		   if (i<0) break;
	           bSend.write(buffer,0,i);
	           bytesRead=bytesRead+i;
	       } while (i>0);    
               bSend.flush();
	       fd.close();
    
	    } catch(IOException excpt)
            {   System.err.println("Failed I/O " + excpt);
	        return;
	    }
            
            command = "ldir -WRITE -x -s"+ currentLINdrive + " -copy " 
                     + "zzz.xxx" + " " 
                     + currentLINdirectory + currentLINfile;	
        }   

 	temp=execOperatingSystemCommand(command);

	if (temp.length()>0)
	{   debugOutput(temp);
            //if LTOOLS's command line tool issues an error message, show first line of response in message box
            new MessageBox(ourFrame, true, temp.substring(0, temp.lastIndexOf('\n')), "LTOOLS",1).setVisible(true);
        } else
        {   LINwindow();
        }
    }

//---- Delete a LINUX file ----------------------------------------------------
    void deleteLINfile()
    {   debugOutput("Started deleteLINfile()");

    	String item = "", temp="";
	String command;
       	
        item = dirListing.getSelectedItem();
        if (item==null)
        {  new MessageBox(ourFrame, true, "Select a file or directory first", "LTOOLS",1).setVisible(true);
           return;
        }

/*	if (item.startsWith("d"))				//Directory selected -> show it 
        {   new MessageBox(ourFrame, true, "Sorry, can't delete a directory", "LTOOLS",1).setVisible(true);
	    return;
	} else
*/      {   currentLINfile=item.substring(stLINfn, item.length());

            MessageBox mbox=new MessageBox(ourFrame, true, "Do you really want to delete  \"" + currentLINfile + "\" ?   ", "LTOOLS Delete file",2);
	    mbox.setVisible(true);
     	    if (mbox.messageBoxStatus!=mbox.OK)
     	        return;    

            command = "ldir -WRITE -x -del -s"+ currentLINdrive + " " 
                     + currentLINdirectory + currentLINfile;	

 	    temp=execOperatingSystemCommand(command);

	    if (temp.length()>0)
	    {   debugOutput(temp);
                //if LTOOLS's command line tool issues an error message, show first line of response in message box
                new MessageBox(ourFrame, true, temp.substring(0, temp.lastIndexOf('\n')), "LTOOLS",1).setVisible(true);
            } else
            {   currentLINfile="";
        	LINwindow();
            }
        }
    }

//---- Delete a DOS file ------------------------------------------------------
    void deleteDOSfile()
    {   debugOutput("Started deleteDOSfile()");

        String item = "";
	        	
        item = dirListing.getSelectedItem();
        if (item==null)
        {  new MessageBox(ourFrame, true, "Select a file or directory first", "LTOOLS",1).setVisible(true);
           return;
        }

/*	if (item.startsWith("<DIR>"))				//Directory selected -> show it 
        {   new MessageBox(ourFrame, true, "Sorry, can't delete a directory", "LTOOLS",1).setVisible(true);
	    return;
	} else
*/      {   currentDOSfile=item.substring(stDOSfn, item.length());

            MessageBox mbox=new MessageBox(ourFrame, true, "Do you really want to delete  \"" + currentDOSfile + "\" ?   ", "LTOOLS Delete File",2);
	    mbox.setVisible(true);
     	    if (mbox.messageBoxStatus!=mbox.OK)
     	        return;    

            File fd = new File(currentDOSdrive+currentDOSdirectory+currentDOSfile);
            
            if (fd.delete()==false)
                new MessageBox(ourFrame, true, "Could not delete "+ item, "LTOOLS",1).setVisible(true);
	    else
	    {	currentDOSfile="";
        	DOSwindow();
            }
        }
    }

//---- Create a LINUX directory or symlink ------------------------------------
    void newLINdir()
    {	debugOutput("Started newLINdir()");

    	String temp="";
	String command;
        String item = "";
	        	
        NewFileBox fbox=new NewFileBox(ourFrame, true);
	
	fbox.setVisible(true);
     	if (fbox.NewFileBoxStatus!=fbox.OK)
     	    return;    
        if (currentLINfile.equals("")==true)
        {   new MessageBox(ourFrame, true, "You must specify the name of the new directory or symlink", "LTOOLS",1).setVisible(true);
            return;
        }
            
        if (fbox.NewFileBoxDirectory==true)	//create a directory
        {   command = "ldir -WRITE -x -mkdir -s"+ currentLINdrive + " ldirtmpl " 
            		+ currentLINdirectory + currentLINfile;	
	} else					//create a symlink
	{   if (currentDOSfile.equals("")==false)
	    {   command = "ldir -WRITE -x -link -s"+ currentLINdrive+" "+ currentDOSfile+" "
			+ currentLINdirectory + currentLINfile;
	    } else
	    {	new MessageBox(ourFrame, true, "You must specify the target of the symlink", "LTOOLS",1).setVisible(true);
	    	return;
	    }
	}
 	
 	temp=execOperatingSystemCommand(command);

	if (temp.length()>0)
	{   debugOutput(temp);
                //if LTOOLS's command line tool issues an error message, show first line of response in message box
                new MessageBox(ourFrame, true, temp.substring(0, temp.lastIndexOf('\n')), "LTOOLS",1).setVisible(true);
        } else
        {   currentLINfile="";
            LINwindow();
        }
	
}

//---- Create a DOS directory ---------------------------------------
    void newDOSdir()
    {	debugOutput("Started newDOSdir()");

    	String temp="";
	String command;
        String item = "";
	        	
        NewFileBox fbox=new NewFileBox(ourFrame, true);
	
	fbox.setVisible(true);
     	if (fbox.NewFileBoxStatus!=fbox.OK)
     	    return;    
        if (currentLINfile.equals("")==true)
        {   new MessageBox(ourFrame, true, "You must specify the name of the new directory", "LTOOLS",1).setVisible(true);
            return;
        }
            
        if (fbox.NewFileBoxDirectory==true)	//create a directory
        {   
            File fd = new File(currentDOSdrive+currentDOSdirectory+currentLINfile);
	    if (fd.mkdir()==false)
                new MessageBox(ourFrame, true, "Creating the directory failed", "LTOOLS",1).setVisible(true);
            else
            {   currentDOSfile="";
            	DOSwindow();
            }
	}
}

//
//---- Modify LINUX file properties -------------------------------------------
    void modifyLINfile()
    {   debugOutput("Started modifyLINfile()");
    	
    	String item = "", temp="";
	String command;
 
        item = dirListing.getSelectedItem();
        if (item==null)
        {  new MessageBox(ourFrame, true, "Select a file or directory first", "LTOOLS",1).setVisible(true);
           return;
        }

	currentLINfile=item.substring(stLINfn, item.length());

	ChangePropertiesBox pbox= new ChangePropertiesBox(ourFrame, currentLINfile, true, true);
	pbox.setVisible(true);
     	if (pbox.ChangePropertiesBoxStatus!=pbox.OK)
     	    return;    

        command = "ldir -WRITE -x -s"+ currentLINdrive + " ";
	if (pbox.uid.equals("")==false)
            command = command + "-u" + pbox.uid + " ";
	if (pbox.gid.equals("")==false)
            command = command + "-g" + pbox.gid + " ";
	if (pbox.acc.equals("")==false)
            command = command + "-f" + pbox.acc + " ";
	command = command + currentLINdirectory + currentLINfile;	

	temp=execOperatingSystemCommand(command);

    	if (temp.length()>0)
	{   debugOutput(temp);
            //if LTOOLS's command line tool issues an error message, show first line of response in message box
            new MessageBox(ourFrame, true, temp.substring(0, temp.lastIndexOf('\n')), "LTOOLS",1).setVisible(true);
        } else if (pbox.name.equals(currentLINfile)==false)
        {   command= "ldir -WRITE -ren -x -s"+ currentLINdrive + " " + currentLINdirectory + currentLINfile + " " + pbox.name;

	    temp=execOperatingSystemCommand(command);
	        
       	}
        if (temp.length()>0)
	{   debugOutput(temp);
            //if LTOOLS's command line tool issues an error message, show first line of response in message box
            new MessageBox(ourFrame, true, temp.substring(0, temp.lastIndexOf('\n')), "LTOOLS",1).setVisible(true);
        } else 
        {    currentLINfile="";
             LINwindow();
	}
    }
//
//---- Modify DOS file properties -------------------------------------------
    void modifyDOSfile()
    {   debugOutput("Started modifyDOSfile()");
    	
    	String item = "", temp="";
	String command;
 
        item = dirListing.getSelectedItem();
        if (item==null)
        {  new MessageBox(ourFrame, true, "Select a file or directory first", "LTOOLS",1).setVisible(true);
           return;
        }

	currentDOSfile=item.substring(stDOSfn, item.length());

	ChangePropertiesBox pbox= new ChangePropertiesBox(ourFrame, currentDOSfile, false, true);
	pbox.setVisible(true);
     	if (pbox.ChangePropertiesBoxStatus!=pbox.OK)
     	    return;    

        if (pbox.name.equals(currentDOSfile)==false)	//user has set a new filename
        {   File oldfd = new File(currentDOSdrive+currentDOSdirectory+currentDOSfile);
            File newfd = new File(currentDOSdrive+currentDOSdirectory+pbox.name);

            if (oldfd.renameTo(newfd)==false)
            	new MessageBox(ourFrame, true, "Could not rename "+item, "LTOOLS",1).setVisible(true);
	    else
	    {   currentDOSfile="";
            	DOSwindow();
            }
       	}
    }

//################################################################################################
//LOW LEVEL FUNCTIONS
//################################################################################################ 
//
//######Refresh the window########################################################################
//
    public void paint(Graphics g)
    {   StringTokenizer token;
	int i = 0;

        if (LINmode==true)
        {   token = new StringTokenizer(LINlisting, "\n\r");
            dirTxt.setText("   LINUX Directory  " + currentLINdirectory +  "   on " + currentLINdrive);
            drive.setText(currentLINdrive);
        } else
        {   token = new StringTokenizer(DOSlisting, "\n\r");
 	    dirTxt.setText("   DOS Directory  " + currentDOSdrive + currentDOSdirectory);
 	    drive.setText(currentDOSdrive);
	}
    }

//
//######Event interface for button, menu, mouse and key events####################################
//
//----ActionListener - Interface for buttons and menu items--------------------
    public void actionPerformed(ActionEvent evt)		
    { 
	if (evt.getSource() instanceof Button)			//Deals with the buttons 
	{   if (evt.getActionCommand() == " DOS ")
            {    DOSwindow();
            } else if (evt.getActionCommand() == "LINUX")
     	    {    LINwindow();
     	    } else if (evt.getActionCommand() == "SET DRIVE")
     	    {  if (LINmode==true)
                {   currentLINdrive=drive.getText();
                    oldLINdirectory="/";
		    currentLINdirectory="/";
            	    LINwindow();
            	} else
            	{   currentDOSdrive=drive.getText();
            	    currentDOSdirectory=hostPathDelimiter;
            	    DOSwindow();
            	}        
     	    } else if (evt.getActionCommand() == "EXIT")
     	    {   closeConnection();
     	    	System.exit(0);
     	    }
        }

	if (evt.getSource() instanceof java.awt.List)		//Deals with the mouse
    	{   if (LINmode==true)				
                selectLINhandler();
            else
                selectDOShandler();
	}

        if (evt.getSource() instanceof MenuComponent)		//Deals with the menus 
        {   if (evt.getActionCommand() == "Exit")
	    {   closeConnection(); 
	    	System.exit(0);
	    } else if (evt.getActionCommand() == "Delete")
 	    {    if (LINmode==true)
	            deleteLINfile();
		 else
		    deleteDOSfile();
	    } else if (evt.getActionCommand() == "New")
 	    {    if (LINmode==true)
                    newLINdir();
		 else
                    newDOSdir();
	    } else if (evt.getActionCommand() == "File properties")
	    {    if (LINmode==true)
		    modifyLINfile();
		 else
                    modifyDOSfile();
	    } else if (evt.getActionCommand() == "Set remote host")
	    {    RemoteBox rbox = new RemoteBox(ourFrame, true);
	         rbox.setVisible(true);
	         if (rbox.RemoteBoxStatus==rbox.REMOTE)
	         {   oldLINdirectory="/";
	             currentLINdirectory="/";
	             closeConnection();
	             openConnection();
	             LINwindow();
	         } else if (rbox.RemoteBoxStatus==rbox.LOCAL)
	         {   oldLINdirectory="/";
	             currentLINdirectory="/";
	             if (Connected==true) closeConnection();
	             DOSwindow();
	         }
	    } else if (evt.getActionCommand() == "About")
            {    new MessageBox(ourFrame, true, "LTOOLS Graphical User Interface " + VERSION + "\n(C) 1999-2000 Werner.Zimmermann@fht-esslingen.de", "LTOOLS About",1).setVisible(true);
	    } else if (evt.getActionCommand() == "Help")
	    {    new HelpBox(ourFrame, false).setVisible(true);
	    }
        }

    }

//----MouseListener - Interface for mouse clicks ------------------------------
    public void mouseClicked(MouseEvent evt)
    {	if (evt.paramString().indexOf("mods=4")>0)	//Single right click invokes change file properties
        {   if (LINmode==true)
	    	modifyLINfile();
	    else
                modifyDOSfile();
	}
    }

    public void mousePressed(MouseEvent evt)	
    {   
    }
    public void mouseReleased(MouseEvent evt)	
    {   
    }
    public void mouseEntered(MouseEvent evt)
    {   
    }
    public void mouseExited(MouseEvent evt)
    {   
    }
    
//----KeyListener - Interface for keyboard events------------------------------
    public void keyPressed(KeyEvent evt)			
    {  	if (evt.getSource() instanceof TextField)
	{   if (evt.getKeyCode() == KeyEvent.VK_ENTER)		//ENTER - key in drive TextField
            {   if (LINmode==true)
                {   currentLINdrive=drive.getText();
		    oldLINdirectory="/";
		    currentLINdirectory="/";
            	    LINwindow();
            	} else
            	{   currentDOSdrive=drive.getText();
            	    currentDOSdirectory=hostPathDelimiter;
            	    DOSwindow();
            	}
	    }
	} else if (evt.getSource() instanceof java.awt.List)
	{   if (evt.getKeyCode() == KeyEvent.VK_ENTER)		//ENTER - key in directory LIST
            {   if (LINmode==true)
                    selectLINhandler();
                else
                    selectDOShandler();    
	    } else if (evt.getKeyCode() == KeyEvent.VK_DELETE) 	//DEL - key in directory LIST
	    {    if (LINmode==true)
	            deleteLINfile();
		 else
		    deleteDOSfile();
	    }         
	}          
    }

    public void keyReleased(KeyEvent evt)
    {
    }

    public void keyTyped(KeyEvent evt)
    {
    }


//################################################################################################ 
//UTILITY FUNCTIONS
//################################################################################################ 
//
//----Execute an operating system command and return commands response---------
    String execOperatingSystemCommand(String command)
    {   
	String  response="";
	Runtime r = Runtime.getRuntime();
	Process myProcess;
	
	int i=0;
	byte[] buffer=new byte[BUFSIZE];
	
	
	if (Connected==true)
	{   response=remoteOperatingSystemCommand(command);
	    return response;
	}
	
	debugOutput("Executing operating system command: \n   " + command);
	    
	try
        {   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);
            return "Executing operating system command failed:\n   " + command;
	}
    	return response;
    }

/* The following works under the Symantec VM 1.1.x, but does not work with JDK 1.2.
   The failing code is in isProcessRunning(), which does not work reliably with Suns VM 1.2.
   On the other hand waitFor() does block sometimes with Symantec VM 1.1.x.
   
//----Execute an operating system command and return commands stdout response--   
    String execOperatingSystemCommand(String command, boolean waitForData)
    {   debugOutput("Executing operating system command: \n   " + command);

	String  response="";
	Runtime r = Runtime.getRuntime();
	Process myProcess;
	InputStream inExec;
	
	int i=0;
	byte[] b=new byte[BUFSIZE];
	
	try
        {   myProcess = r.exec(command);                       	//Execute operating system command as external command
	    inExec = myProcess.getInputStream();		//Connect to external program's stdout
	   
	    while (true)					//Wait, until command is finished
	    {   while (inExec.available() > 0)			
                {   i=inExec.read(b,0,inExec.available()); 	//---Read command's output
		    response = response + new String(b,0,i);
		    //debugOutput("READ " + i);
	        }	
	        //debugOutput("Running");

 		if (isProcessRunning(myProcess)==false)		//---If process is no longer running
 		{   if (inExec.available()==0)			//---...break out of loop if no more data
		    {   if (waitForData==false)			//---......and we do not have to wait for data
		            break;
		        else if (i>0)				//---......if we should wait for data and there was data
		        {   sleep(1000);			//---............wait 1000ms
		            if (inExec.available()==0)		
		                break;		        	//---............and break out of loop if still no more data
		        }
		    }    
		}
	    }
 	    inExec.close();
	    myProcess.destroy();
	}
	catch(IOException excpt)
        {   System.err.println("Failed I/O " + excpt);
            return "Executing operating system command failed:\n   " + command;
	}
   	
    	return response;
    }

//######Functions for process control#############################################################
//
    boolean isProcessRunning(Process process)			//Tests if a given process is still running
    {   int i;							//--- if no,  return 'false'
    	boolean running;					//--- if yes, return 'true'
    	
    	try 
   	{   i=process.exitValue();
            running = false;
        } catch(IllegalThreadStateException excpt)
        {   running=true;
        }
        return running;
    }

    public void sleep(long time)				//(Non busy) wait for 'time' milliseconds
    {   Thread myThread = Thread.currentThread();
        try 
        {   myThread.sleep(time); 
        }   catch (InterruptedException excpt)
        {
        }
    }
*/

//----Execute an operating system command on a remote computer and return commands response---------
    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];
	
	try
        {   temp="EXECUTE\n"+command+"\n";
            qSend.write(temp,0,temp.length());			//Send command to remote server
            qSend.flush();

	    temp=qReceive.readLine();
   	    i = Integer.parseInt(temp);
	    
	    bytesRead=0;
	    while (bytesRead<i)
	    { j=qReceive.read(buffer,0,i);
	      temp= new String(buffer, 0, j);
	      bytesRead=bytesRead+j;	    
	      response = response + temp;
	    }
	}
	catch(IOException excpt)
        {   System.err.println("Failed I/O to " + excpt);
	}
 
 	return response;
    }

//----Open connection to remote server-----------------------------------------    
    void openConnection()
    {   debugOutput("Started openConnection()");
	
	try
        {   qSocket = new Socket(hostname, port);		// Open a socket to the server. 
	    qReceive = new BufferedReader(new InputStreamReader(qSocket.getInputStream()));
	    bReceive = new BufferedInputStream(qSocket.getInputStream());
	    qSend = new BufferedWriter(new OutputStreamWriter(qSocket.getOutputStream()));
	    bSend = new BufferedOutputStream(qSocket.getOutputStream());
	    
	    if ((qSocket != null) && (qReceive != null) && (qSend != null))
            {   Connected=true;
            	debugOutput("Client connected to server");
	    } else
            {   debugOutput("Client connect to server failed");
                Connected=false;
                new MessageBox(ourFrame, true, "Client connect to server failed", "LTOOLS Connect to server",1).setVisible(true);
 	    }
	}
	catch(UnknownHostException excpt)
        {   System.err.println("Unknown host " + excpt);
            new MessageBox(ourFrame, true, "Unknown hostname \"" + hostname + "\"", "LTOOLS Connect to server",1).setVisible(true);
	    hostname="";
	}
	catch(IOException excpt)
        {   System.err.println("Failed I/O to " + excpt);
            new MessageBox(ourFrame, true, "Client connect to server failed: " + excpt, "LTOOLS Connect to server",1).setVisible(true);
            hostname="";
	}
    }

//----Close connection to remote server----------------------------------------
    static void closeConnection()
    {   debugOutput("Started closeConnection()");

	if (Connected==false)
	    return;
	    
	try
        {   if (qSend!=null)
            {   qSend.write("ESC",0,3);				//Send close command (ESC) to server 
		qSend.close();
		bSend.close();
		qSend = null;					//Close transmit stream
	    }
	    if (qReceive!=null)
            {   qReceive.close();
                bReceive.close();
		qReceive = null;				//Close receive stream
	    }
	    if (qSocket!=null)
            {   qSocket.close();
		qSocket = null;					//Close socket
	    }
	    Connected=false;
	    debugOutput("Connection closed");
	}
	catch(IOException excpt)
        {   System.err.println("Failed I/O to " + excpt);
	}
    }


//
//######Debugging#################################################################################
//
    static void debugOutput(String text)			//Debug output to console 
    {   if (DEBUG==true) 
            System.out.println(text);
    }
//
//
//######Message Box (implemented as inner class)##################################################
    class MessageBox extends Dialog
    {   Button okButton = new Button();
        Button cancelButton = new Button();
	Label label1 = new Label();
	TextArea textArea = new TextArea(3,70);
	
	public final int CANCEL = 0;
	public final int OK = 1;
		
	public int messageBoxStatus=CANCEL;
	
	public MessageBox(Frame parent, boolean modal, String text, String title, int noButtons)
        {   super(parent, modal);

	    setLayout(new GridBagLayout());
	    setBackground(Color.lightGray);
	    setVisible(false);
//	    label1.setText(text);
//	    label1.setAlignment(Label.CENTER);
//	    add(label1);
	    textArea.append(text);
	    textArea.setEditable(false);
	    add(textArea);

	    okButton.setLabel("   OK   ");
	    add(okButton);
	    okButton.setFont(new Font("Dialog", Font.BOLD, 12));

	    okButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == okButton)
				       	       {   setVisible(false);
				       	           messageBoxStatus=OK;
				       	       }
				           }
				       });
		
	    if (noButtons>1)
	    {   cancelButton.setLabel("CANCEL");
	        add(cancelButton);
	        cancelButton.setFont(new Font("Dialog", Font.BOLD, 12));
	        cancelButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == cancelButton)
				       	       {   setVisible(false);
				       	           messageBoxStatus=CANCEL;
				       	       }
				           }
				       });
	    }
	    pack();

	    setTitle(title);

	}

	public void setVisible(boolean b)	//open the dialog box centered in the parent window
        {   if (b == true)
            {   Rectangle bounds = getParent().getBounds();
		Rectangle abounds = getBounds();

		 setLocation(bounds.x + (bounds.width - abounds.width) / 2,
			     bounds.y + (bounds.height - abounds.height) / 2);
	    }
	    super.setVisible(b);
	}

    }
//
//######Help dialog box (implemented as inner class)##################################################
    class HelpBox extends Dialog
    {   Button closeButton = new Button();
	TextArea text = new TextArea(20,75);

	public HelpBox(Frame parent, boolean modal)
        {   super(parent, modal);

	    setLayout(new GridBagLayout());
	    setBackground(Color.white);
	    setVisible(false);
	    text.setEditable(false);
	    text.setFont(new Font("Monospaced", Font.BOLD, 12));
            text.setText("LTOOLS Graphical User Interface - Usage\n\n"
	        +"When LREADgui starts, you should see a listing of the root directory '/'\non your default LINUX drive. The current directory and drive are shown\nat the top of the window.\n\n"
		+"Connecting and disconnecting to a remote host (host must be running LREADjav)\n"
		+"* Select menu item 'Remote' and 'Set remote host'.\n"
		+"* Enter hostname (and portnumber) and click on 'Set host'.\n"
		+"* Click on 'Local', to stay local or disconnect if connected.\n\n" 
	        +"Change the default drive\n"
	        +"* Enter a valid LINUX disk device name in the text field at the bottom of\n  the window and click the 'SET DRIVE' button or press the ENTER key.\n"
	        +"  If viewing a DOS directory (see below), enter a valid DOS drive name.\n"
       	        +"* When starting LREADgui, the default LINUX drive may be specified on the\n  command line, e.g. 'lreadgui /dev/hdb8'.\n\n"
	        +"Navigating\n"
	        +"* Double clicking on a directory will change to this directory.\n"
	        +"  Directories start with 'd' or <DIR> in the first column.\n"
	        +"  Directory '..' is the parent directory of the current directory.\n\n"
	        +"Change to DOS (if viewing a LINUX directory)\n"
	        +"* Click on the 'DOS' button.\n\n"
	        +"Change to LINUX (if viewing a DOS directory)\n"
	        +"* Click on the 'LINUX' button.\n\n"
	        +"Renaming files or modifying UID, GID and access rights\n"
	        +"* Select a file by clicking the left mouse button, when the cursor is in\n  the line of the file.\n"
	        +"* Click the right mouse button or select menu items 'Edit' and \n  'File properties'.\n"
	        +"* Enter the appropriate values in the popup menu. Properties with empty\n  fields will remain unchanged.\n\n"
	        +"Deleting files (DOS and LINUX files, symlinks or empty directories)\n"
	        +"* Select a file by clicking the left mouse button, when the cursor is in\n  the line of the file.\n"
	        +"* Press the 'DEL' key or select menu items 'Edit' and 'Delete'.\n\n"
		+"Creating new LINUX directories or symlinks\n"
		+"* Select menu item 'Edit - New'.\n"
		+"* In the pop up dialog box enter the new directory or symlink name.\n"
		+"* Select either 'is directory' or 'is symlink'\n"
		+"* If it is a symlink, enter the symlink target's name.\n\n"
		+"Copying files from LINUX to DOS\n"
		+"* If not viewing a LINUX directory, change to LINUX (see above).\n"
		+"* Double click on the file, which you want to copy.\n"
		+"* In the pop up file select dialog box select the target DOS\n  directory and filename.\n\n"
		+"Copying files from DOS to LINUX\n"
		+"* If not viewing a DOS directory, change to DOS (see above).\n"
		+"* Double click on the file, which you want to copy.\n"
		+"  The file will be copied to LINUX with its original DOS filename.\n\n"
	        +"Exiting\n"
	     	+"* Click on the EXIT button or select menu items 'File' and 'Exit'.\n\n"
	     	+"LINUX symbolic links\n"
	     	+"* If the link points to a directory, the contents of this directory\n  will be shown.\n"
	     	+"* If the link points to a file, the file's directory entry\n  will be shown in a message box.\n  To copy the file, go to the link's target first."
	    ); 	
	    
	    add(text);
	    closeButton.setLabel("CLOSE");
	    add(closeButton);
	    closeButton.setFont(new Font("Dialog", Font.BOLD, 12));
	    pack();

            setTitle("LTOOLS Help");

	    closeButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == closeButton)
				       		   setVisible(false);
				           }
				       });
	    addWindowListener(new WindowAdapter()
                                       {   public void windowClosing(WindowEvent e)
                                           {   setVisible(false);
				       	   }
				       });

	}

	public void setVisible(boolean b)	//open the dialog box centered in the parent window
        {   if (b == true)
            {   Rectangle bounds = getParent().getBounds();
		Rectangle abounds = getBounds();

		 setLocation(bounds.x + (bounds.width - abounds.width) / 2,
			     bounds.y + (bounds.height - abounds.height) / 2);
	    }
	    super.setVisible(b);
	}

    }

//
//######Change file properties dialog box (implemented as inner class)############################
    class ChangePropertiesBox extends Dialog
    {   Button okButton = new Button();
        Button cancelButton = new Button();
        Label labelName = new Label();
	Label labelUID = new Label();
	Label labelGID = new Label();
	Label labelACC = new Label();
	TextField fieldName = new TextField(16);
	TextField fieldUID = new TextField(5);
	TextField fieldGID = new TextField(5);
	TextField fieldACC = new TextField(3);

	String uid, gid, acc, name;
		
	public final int CANCEL = 0;
	public final int OK = 1;
		
	public int ChangePropertiesBoxStatus=CANCEL;
	
	public ChangePropertiesBox(Frame parent, String filename, boolean isLinux, boolean modal)
        {   super(parent, modal);

	    setLayout(new GridLayout(5,2));
	    setBackground(Color.white);
	    setVisible(false);
	    labelName.setText("New name");
	    labelName.setAlignment(Label.CENTER);
	    fieldName.setText(filename);
	    fieldName.selectAll();
	    name = filename;
	    add(labelName);
	    add(fieldName);
	    if (isLinux==true)
	    {	labelUID.setText("UID");
	    	labelUID.setAlignment(Label.CENTER);
	    	add(labelUID);
	    	add(fieldUID);
	    	labelGID.setText("GID");
	    	labelGID.setAlignment(Label.CENTER);
	    	add(labelGID);
	    	add(fieldGID);
	    	labelACC.setText("Access rights");
	    	labelACC.setAlignment(Label.CENTER);
	    	add(labelACC);
	    	add(fieldACC);
		setTitle("LTOOLS Change LINUX file properties");
	    } else
	    {	add(new Label());
	        add(new Label());
	        add(new Label());
	        add(new Label());
	        add(new Label());
	        add(new Label());
	        setTitle("LTOOLS Change DOS file properties");
	    }
    
	    cancelButton.setLabel("CANCEL");
	    add(cancelButton);
	    cancelButton.setFont(new Font("Dialog", Font.BOLD, 12));

	    okButton.setLabel("   OK   ");
	    add(okButton);
	    okButton.setFont(new Font("Dialog", Font.BOLD, 12));

	    cancelButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == cancelButton)
				       	       {   setVisible(false);
						   gid="";
						   uid="";
						   acc="";				   
				       	           ChangePropertiesBoxStatus=CANCEL;
				       	       }
				           }
				       });

	    okButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == okButton)
				       	       {   setVisible(false);
						   
						   uid=fieldUID.getText();
				       	           gid=fieldGID.getText();
				       	           acc=fieldACC.getText();
				       	           
				       	           name=fieldName.getText();
				       	           ChangePropertiesBoxStatus=OK;
				       	       }
				           }
				       });
	    pack();

	}

	public void setVisible(boolean b)	//open the dialog box centered in the parent window
        {   if (b == true)
            {   Rectangle bounds = getParent().getBounds();
		Rectangle abounds = getBounds();

		 setLocation(bounds.x + (bounds.width - abounds.width) / 2,
			     bounds.y + (bounds.height - abounds.height) / 2);
	    }
	    super.setVisible(b);
	}

    }
//
//######Copy DOS file dialog box (implemented as inner class)############################
    class CopyDOSfileBox extends Dialog
    {   Button okButton = new Button();
        Button cancelButton = new Button();
        Label labelDOSfilename = new Label();
	Label labelLINfilename = new Label();
	Label labelTxt = new Label();
	TextField fieldLINfilename = new TextField(32);
	
	public final int CANCEL = 0;
	public final int OK = 1;
		
	public int copyDOSfileBoxStatus=CANCEL;
	
	public CopyDOSfileBox(Frame parent, boolean modal)
        {   super(parent, modal);

	    setLayout(new GridLayout(6,0));
	    setBackground(Color.white);
	    setVisible(false);
	    
	    labelDOSfilename.setText("Copying DOS file   " + currentDOSdrive + currentDOSdirectory + currentDOSfile);
	    add(labelDOSfilename);
	    
	    labelLINfilename.setText("to LINUX directory " + currentLINdirectory);
	    add(labelLINfilename);

	    labelTxt.setText("as file");
	    add(labelTxt);
	    
	    fieldLINfilename.setText(currentLINfile);
	    add(fieldLINfilename);

	    okButton.setLabel("   OK   ");
	    add(okButton);
	    okButton.setFont(new Font("Dialog", Font.BOLD, 12));
	    
	    cancelButton.setLabel("CANCEL");
	    add(cancelButton);
	    cancelButton.setFont(new Font("Dialog", Font.BOLD, 12));
	    cancelButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == cancelButton)
				       	       {   setVisible(false);
						   copyDOSfileBoxStatus=CANCEL;
					       }
				           }
				       });

	    okButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == okButton)
				       	       {   setVisible(false);
				       	           currentLINfile=fieldLINfilename.getText();
				       	           copyDOSfileBoxStatus=OK;
				       	       }
				           }
				       });
	    pack();

            setTitle("LTOOLS Copy DOS file");
	}

	public void setVisible(boolean b)	//open the dialog box centered in the parent window
        {   if (b == true)
            {   Rectangle bounds = getParent().getBounds();
		Rectangle abounds = getBounds();

		 setLocation(bounds.x + (bounds.width - abounds.width) / 2,
			     bounds.y + (bounds.height - abounds.height) / 2);
	    }
	    super.setVisible(b);
	}

    }
//
//######New file dialog box (implemented as inner class)##############################
    class NewFileBox extends Dialog
    {   Button okButton = new Button();
        Button cancelButton = new Button();
	Label labelNewFilename = new Label();
	TextField fieldNewFilename = new TextField(32);
	CheckboxGroup myGroup = new CheckboxGroup();
	Checkbox isDir = new Checkbox("... is directory",myGroup,true);
	Checkbox isSym = new Checkbox("... is symlink",myGroup,false);
	Label labelTarget = new Label("Symlink target");
	TextField fieldTarget = new TextField(32);
	
	public final int CANCEL = 0;
	public final int OK = 1;
		
	public int NewFileBoxStatus=CANCEL;
	public boolean NewFileBoxDirectory=true;
		
	public NewFileBox(Frame parent, boolean modal)
        {   super(parent, modal);

	    setLayout(new GridLayout(8,0));
	    setBackground(Color.white);
	    setVisible(false);
	    labelNewFilename.setText("Name");
	    add(labelNewFilename);
	    add(fieldNewFilename);
	    
	    if (LINmode==true)
	    { 	add(isDir);
	    	add(isSym);
	    	add(labelTarget);
	    	add(fieldTarget);
		setTitle("LTOOLS New LINUX directory or symlink");
	    } else
		setTitle("LTOOLS New DOS directory");
	

	    okButton.setLabel("   OK   ");
	    add(okButton);
	    okButton.setFont(new Font("Dialog", Font.BOLD, 12));
	    
	    cancelButton.setLabel("CANCEL");
	    add(cancelButton);
	    cancelButton.setFont(new Font("Dialog", Font.BOLD, 12));
	    cancelButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == cancelButton)
				       	       {   setVisible(false);
						   NewFileBoxStatus=CANCEL;
					       }
				           }
				       });

	    okButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == okButton)
				       	       {   setVisible(false);
				       	           currentLINfile=fieldNewFilename.getText();
				       	           if (myGroup.getSelectedCheckbox()==isSym)
				       	           {	currentDOSfile=fieldTarget.getText();
				       	                NewFileBoxDirectory=false;
				       	           }
				       	           else
				       	           	NewFileBoxDirectory=true;
				       	           NewFileBoxStatus=OK;
				       	       }
				           }
				       });
	    pack();
	}

	public void setVisible(boolean b)	//open the dialog box centered in the parent window
        {   if (b == true)
            {   Rectangle bounds = getParent().getBounds();
		Rectangle abounds = getBounds();

		 setLocation(bounds.x + (bounds.width - abounds.width) / 2,
			     bounds.y + (bounds.height - abounds.height) / 2);
	    }
	    super.setVisible(b);
	}

    }
//
//######Remote connect box#####################################################
    class RemoteBox extends Dialog
    {   Button remoteButton = new Button();
        Button localButton = new Button();
	Label labelHost = new Label();
	Label labelPort = new Label();
	Label labelTxt = new Label();
	TextField fieldHost = new TextField(20);
	TextField fieldPort = new TextField(5);
		
	public final int LOCAL  = 0;
	public final int REMOTE = 1;
		
	public int RemoteBoxStatus=LOCAL;
	
	public RemoteBox(Frame parent, boolean modal)
        {   super(parent, modal);

	    setLayout(new GridBagLayout());
	    setBackground(Color.white);
	    setVisible(false);
	    labelHost.setText("For remote operation set hostname:  ");
	    labelHost.setAlignment(Label.CENTER);
	    add(labelHost);
	    fieldHost.setText(hostname);
	    add(fieldHost);
	    
	    labelPort.setText("  port:");
	    add(labelPort);
	    fieldPort.setText(""+port);
	    add(fieldPort);
	    	    
	    remoteButton.setLabel("SET HOST");
	    add(remoteButton);
	    remoteButton.setFont(new Font("Dialog", Font.BOLD, 12));

	    labelTxt.setText("  For local operation click:  ");
	    labelTxt.setAlignment(Label.CENTER);
	    add(labelTxt);
	    
	    localButton.setLabel("LOCAL");
	    add(localButton);
	    localButton.setFont(new Font("Dialog", Font.BOLD, 12));
	    localButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == localButton)
				       	       {   setVisible(false);
				       	           RemoteBoxStatus=LOCAL;
				       	       }
				           }
				       });

	    remoteButton.addActionListener(new ActionListener()
                                       {   public void actionPerformed(ActionEvent event)
                                           {   Object object = event.getSource();
				       	       if (object == remoteButton)
				       	       {   setVisible(false);
				       	           hostname=fieldHost.getText();
				       	           port=Integer.parseInt(fieldPort.getText());
				       	           RemoteBoxStatus=REMOTE;
				       	       }
				           }
				       });
	    pack();

            setTitle("LTOOLS Set remote host");
	}

	public void setVisible(boolean b)	//open the dialog box centered in the parent window
        {   if (b == true)
            {   Rectangle bounds = getParent().getBounds();
		Rectangle abounds = getBounds();

		 setLocation(bounds.x + (bounds.width - abounds.width) / 2,
			     bounds.y + (bounds.height - abounds.height) / 2);
	    }
	    super.setVisible(b);
	}

    }

}

