gt: 	setSelection( oldLen, this.fileLen - 1 );
context: /*
   * (c) 2008-2017 Jens Mueller
   *
   * Kleincomputer-Emulator
   *
   * Hex-Editor
   */
  
  package jkcemu.tools.hexedit;
  
  import java.awt.Dimension;
  import java.awt.Event;
  import java.awt.Frame;
  import java.awt.GridBagConstraints;
  import java.awt.GridBagLayout;
  import java.awt.Insets;
  import java.awt.dnd.DropTarget;
  import java.awt.dnd.DropTargetDragEvent;
  import java.awt.dnd.DropTargetDropEvent;
  import java.awt.dnd.DropTargetEvent;
  import java.awt.dnd.DropTargetListener;
  import java.awt.event.InputEvent;
  import java.awt.event.KeyEvent;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.util.EventObject;
  import javax.naming.SizeLimitExceededException;
  import javax.swing.JButton;
  import javax.swing.JMenu;
  import javax.swing.JMenuBar;
  import javax.swing.JMenuItem;
  import javax.swing.JOptionPane;
  import javax.swing.JToolBar;
  import javax.swing.KeyStroke;
  import jkcemu.Main;
  import jkcemu.base.BaseDlg;
  import jkcemu.base.EmuUtil;
  import jkcemu.base.HelpFrm;
  import jkcemu.base.ReplyBytesDlg;
  import jkcemu.print.PrintOptionsDlg;
  import jkcemu.print.PrintUtil;
  
  
  public class HexEditFrm
  		extends AbstractHexCharFrm
  		implements DropTargetListener
  {
    private static final String HELP_PAGE  = "/help/tools/hexeditor.htm";
    private static final int    BUF_EXTEND = 0x2000;
  
    private static HexEditFrm instance = null;
  
    private File      file;
    private byte[]    fileBytes;
    private int       fileLen;
    private int       savedPos;
    private boolean   dataChanged;
    private JMenuItem mnuNew;
    private JMenuItem mnuOpen;
    private JMenuItem mnuSave;
    private JMenuItem mnuSaveAs;
    private JMenuItem mnuPrintOptions;
    private JMenuItem mnuPrint;
    private JMenuItem mnuClose;
    private JMenuItem mnuBytesCopyHex;
    private JMenuItem mnuBytesCopyAscii;
    private JMenuItem mnuBytesCopyDump;
    private JMenuItem mnuBytesInvert;
    private JMenuItem mnuBytesReverse;
    private JMenuItem mnuBytesSave;
    private JMenuItem mnuBytesAppend;
    private JMenuItem mnuBytesInsert;
    private JMenuItem mnuBytesOverwrite;
    private JMenuItem mnuBytesRemove;
    private JMenuItem mnuFileInsert;
    private JMenuItem mnuFileAppend;
    private JMenuItem mnuSavePos;
    private JMenuItem mnuGotoSavedPos;
    private JMenuItem mnuSelectToSavedPos;
    private JMenuItem mnuSelectAll;
    private JMenuItem mnuChecksum;
    private JMenuItem mnuFind;
    private JMenuItem mnuFindNext;
    private JMenuItem mnuHelpContent;
    private JButton   btnNew;
    private JButton   btnOpen;
    private JButton   btnSave;
    private JButton   btnFind;
  
  
    public static void open()
    {
      if( instance != null ) {
        if( instance.getExtendedState() == Frame.ICONIFIED ) {
          instance.setExtendedState( Frame.NORMAL );
        }
      } else {
        instance = new HexEditFrm();
      }
      instance.toFront();
      instance.setVisible( true );
    }
  
  
    public static void open( byte[] data )
    {
      open();
      if( (data != null) && instance.confirmDataSaved() ) {
        instance.newFileInternal( data );
      }
    }
  
  
    public static void open( File file )
    {
      open();
      if( file != null ) {
        instance.openFile( file );
      }
    }
  
  
    public void openFile( File file )
    {
      if( instance.confirmDataSaved() )
        instance.openFileInternal( file );
    }
  
  
  	/* --- DropTargetListener --- */
  
    @Override
    public void dragEnter( DropTargetDragEvent e )
    {
      if( !EmuUtil.isFileDrop( e ) )
        e.rejectDrag();
    }
  
  
    @Override
    public void dragExit( DropTargetEvent e )
    {
      // leer
    }
  
  
    @Override
    public void dragOver( DropTargetDragEvent e )
    {
      // leer
    }
  
  
    @Override
    public void drop( DropTargetDropEvent e )
    {
      File file = EmuUtil.fileDrop( this, e );
      if( file != null ) {
        openFile( file );
      }
    }
  
  
    @Override
    public void dropActionChanged( DropTargetDragEvent e )
    {
      // leer
    }
  
  
  	/* --- ueberschriebene Methoden --- */
  
    @Override
    protected boolean doAction( EventObject e )
    {
      boolean rv  = false;
      Object  src = e.getSource();
      if( src != null ) {
        if( (src == this.btnNew) || (src == this.mnuNew) ) {
  	rv = true;
  	if( confirmDataSaved() ) {
  	  newFileInternal( null );
  	}
        } else if( (src == this.btnOpen) || (src == this.mnuOpen) ) {
  	rv = true;
  	doOpen();
        } else if( (src == this.btnSave) || (src == this.mnuSave) ) {
  	rv = true;
  	doSave( false );
        } else if( src == this.mnuSaveAs ) {
  	rv = true;
  	doSave( true );
        } else if( src == this.mnuPrintOptions ) {
  	rv = true;
  	PrintOptionsDlg.showPrintOptionsDlg( this, true, true );
        } else if( src == this.mnuPrint ) {
  	rv = true;
  	PrintUtil.doPrint( this, this, "JKCEMU Hex-Editor" );
        } else if( src == this.mnuClose ) {
  	rv = true;
  	doClose();
        } else if( src == this.mnuBytesAppend ) {
  	rv = true;
  	doBytesAppend();
        } else if( src == this.mnuBytesCopyHex ) {
  	rv = true;
  	this.hexCharFld.copySelectedBytesAsHex();
        } else if( src == this.mnuBytesCopyAscii ) {
  	rv = true;
  	this.hexCharFld.copySelectedBytesAsAscii();
        } else if( src == this.mnuBytesCopyDump ) {
  	rv = true;
  	this.hexCharFld.copySelectedBytesAsDump();
        } else if( src == this.mnuBytesInvert ) {
  	rv = true;
  	doBytesInvert();
        } else if( src == this.mnuBytesReverse ) {
  	rv = true;
  	doBytesReverse();
        } else if( src == this.mnuBytesSave ) {
  	rv = true;
  	doBytesSave();
        } else if( src == this.mnuBytesInsert ) {
  	rv = true;
  	doBytesInsert();
        } else if( src == this.mnuBytesOverwrite ) {
  	rv = true;
  	doBytesOverwrite();
        } else if( src == this.mnuBytesRemove ) {
  	rv = true;
  	doBytesRemove();
        } else if( src == this.mnuFileAppend ) {
  	rv = true;
  	doFileAppend();
        } else if( src == this.mnuFileInsert ) {
  	rv = true;
  	doFileInsert();
        } else if( src == this.mnuSavePos ) {
  	rv = true;
  	doSavePos();
        } else if( src == this.mnuGotoSavedPos ) {
  	rv = true;
  	doGotoSavedPos( false );
        } else if( src == this.mnuSelectToSavedPos ) {
  	rv = true;
  	doGotoSavedPos( true );
        } else if( src == this.mnuSelectAll ) {
  	rv = true;
  	doSelectAll();
        } else if( src == this.mnuChecksum ) {
  	rv = true;
  	doChecksum();
        } else if( (src == this.btnFind) || (src == this.mnuFind) ) {
  	rv = true;
  	doFind();
        } else if( src == this.mnuFindNext ) {
  	rv = true;
  	doFindNext();
        } else if( src == this.mnuHelpContent ) {
  	rv = true;
  	HelpFrm.open( HELP_PAGE );
        } else {
  	rv = super.doAction( e );
        }
      }
      return rv;
    }
  
  
    @Override
    public boolean doClose()
    {
      boolean rv = confirmDataSaved();
      if( rv ) {
        rv = super.doClose();
      }
      if( rv ) {
        if( !Main.checkQuit( this ) ) {
  	// damit beim erneuten Oeffnen der Editor leer ist
  	newFileInternal( null );
        }
      }
      return rv;
    }
  
  
    @Override
    public int getDataByte( int idx )
    {
      int rv = 0;
      if( this.fileBytes != null ) {
        if( (idx >= 0) && (idx < this.fileBytes.length) ) {
  	rv = (int) this.fileBytes[ idx ] & 0xFF;
        }
      }
      return rv;
    }
  
  
    @Override
    public int getDataLength()
    {
      return this.fileLen;
    }
  
  
    @Override
    protected void setContentActionsEnabled( boolean state )
    {
      this.mnuSaveAs.setEnabled( state );
      this.mnuPrint.setEnabled( state );
      this.mnuSelectAll.setEnabled( state );
      this.mnuFind.setEnabled( state );
      this.btnFind.setEnabled( state );
    }
  
  
    @Override
    protected void setFindNextActionsEnabled( boolean state )
    {
      this.mnuFindNext.setEnabled( state );
    }
  
  
    @Override
    protected void setSelectedByteActionsEnabled( boolean state )
    {
      this.mnuBytesCopyHex.setEnabled( state );
      this.mnuBytesCopyAscii.setEnabled( state );
      this.mnuBytesCopyDump.setEnabled( state );
      this.mnuBytesInvert.setEnabled( state );
      this.mnuBytesReverse.setEnabled( state );
      this.mnuBytesSave.setEnabled( state );
      this.mnuBytesInsert.setEnabled( state );
      this.mnuBytesOverwrite.setEnabled( state );
      this.mnuBytesRemove.setEnabled( state );
      this.mnuFileInsert.setEnabled( state );
      this.mnuChecksum.setEnabled( state );
      this.mnuSavePos.setEnabled( state );
      this.mnuSelectToSavedPos.setEnabled( state && (this.savedPos >= 0) );
    }
  
  
  	/* --- Aktionen --- */
  
    private void doBytesAppend()
    {
      ReplyBytesDlg dlg = new ReplyBytesDlg(
  					this,
  					"Bytes anh\u00E4ngen",
  					this.lastInputFmt,
  					this.lastBigEndian,
  					null );
      dlg.setVisible( true );
      byte[] a = dlg.getApprovedBytes();
      if( a != null ) {
        if( a.length > 0 ) {
  	int oldLen = this.fileLen;
  	this.lastInputFmt  = dlg.getApprovedInputFormat();
  	this.lastBigEndian = dlg.getApprovedBigEndian();
  	try {
  	  insertBytes( this.fileLen, a, 0 );
  	}
  	catch( SizeLimitExceededException ex ) {
  	  BaseDlg.showErrorDlg( this, ex.getMessage() );
  	}
  	setDataChanged( true );
  	updView();
  