// Programmer's RPN Calculator
// Karl L. Barrus <karl at klbarrus dot com>
// July 2, 1996
//
// Copyright (c) 1996 Karl L. Barrus
//
// 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 of the License, 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.

import java.awt.*;

public class ProgCalc extends java.applet.Applet
{
  LCDDisplay display;
  CalcKeyboard keyboard;

  long lcdValue[];
  TextField lcdDisplay[];
  Component calcKeys[];

  int radix;
  CheckboxGroup radixMode;

  int inputMode;

  final int numLines = 4;

  public boolean action( Event event, Object arg )
  {
	if ( event.target instanceof Button )
	{
	  String key = ( String ) arg;

	  if ( key.equals( "-> K" ) || key.equals( "-> M" ) || key.equals( "K ->" ) || key.equals( "M ->" ) )
	    DoConvert( key );
	  else if ( key.equals( "AND" ) || key.equals( "OR" ) || key.equals( "NOT" ) || key.equals( "XOR" ) )
		DoLogicalOp( key );
	  else if ( key.equals( "enter" ) || key.equals( "drop" ) || key.equals( "swap" ) )
	    DoStackAction( key );
	  else if ( key.equals( "+" ) || key.equals( "-" ) || key.equals( "*" ) || key.equals( "/" ) || key.equals( "^" ) )
	    DoMathOp( key );
	  else
	    DoInput( key );

	  UpdateLCDDisplay();

	  return true;
	}
	else if ( event.target instanceof Checkbox )
	{
	  DoDisplayModeChange( radixMode.getCurrent().getLabel() );

	  UpdateLCDDisplay();

	  return true;
	}
	else
	{
	  return false;
	}
  }

  void DoConvert( String key )
  {
    long in = Long.parseLong( lcdDisplay[ 0 ].getText(), radix );
	    
    if ( key.equals( "-> K" ) )
      lcdValue[ 0 ] = in / 1024;
    else if ( key.equals( "-> M" ) )
      lcdValue[ 0 ] = in / 1024 / 1024;
    else if ( key.equals( "K ->" ) )
      lcdValue[ 0 ] = in * 1024;
    else if ( key.equals( "M ->" ) )
      lcdValue[ 0 ] = in * 1024 * 1024;

	inputMode = 0;
  }

  void DoDisplayModeChange( String key )
  {
    lcdValue[ 0 ] = Long.parseLong( lcdDisplay[ 0 ].getText(), radix );
	
	if ( key.equals( "HEX" ) )
	  SetBase( 16 );
	else if ( key.equals( "DEC" ) )
	  SetBase( 10 );
	else if ( key.equals( "OCT" ) )
	  SetBase( 8 );
	else if ( key.equals( "BIN" ) )
	  SetBase( 2 );

	inputMode = 0;
  }

  void DoInput( String key )
  {
    if ( inputMode == 0 )
	{
	  inputMode = 1;
	
	  PushStack( key );
	}
	else
	{
	  long keyval = Long.parseLong( key, radix );

	  if ( ( Long.MAX_VALUE - keyval ) / radix >= lcdValue[ 0 ] )
	    lcdValue[ 0 ] = lcdValue[ 0 ] * radix + Long.parseLong( key, radix );
	}
  }

  void DoLogicalOp( String key )
  {
	if ( key.equals( "NOT" ) )
	{
	  long arg1 = Long.parseLong( lcdDisplay[ 0 ].getText(), radix );

	  lcdValue[ 0 ] = ~arg1;
	}
	else
	{
	  long arg1 = lcdValue[ 1 ];
	  long arg2 = Long.parseLong( lcdDisplay[ 0 ].getText(), radix );
	  long result = 0;

	  if ( key.equals( "AND" ) )
	    result = arg1 & arg2;
      else if ( key.equals( "OR" ) )
	    result = arg1 | arg2;
	  else if ( key.equals( "XOR" ) )
        result = arg1 ^ arg2;

	  PopStack( result );
	}
  
	inputMode = 0;
  }

  void DoMathOp( String key )
  {
    long arg1 = lcdValue[ 1 ];
	long arg2 = Long.parseLong( lcdDisplay[ 0 ].getText(), radix );
	long result = 0;

	if ( key.equals( "+" ) )
	  result = arg1 + arg2;
	else if ( key.equals( "-" ) )
	  result = arg1 - arg2;
	else if ( key.equals( "*" ) )
	  result = arg1 * arg2;
	else if ( key.equals( "/"  ) )
	{
	  try
	  {
	    result = arg1 / arg2;
	  }
	  catch ( ArithmeticException ae )
	  {
	  	result = 0;
	  }
	}
	else if ( key.equals( "^" ) )
	{
	  try
	  {
	    result = ( long ) Math.pow( ( double ) arg1, ( double ) arg2 );
	  }
	  catch ( ArithmeticException ae )
	  {
	  	result = 0;
	  }
	}

	PopStack( result );

	inputMode = 0;
  }

  void DoStackAction( String key )
  {
    if ( key.equals( "enter" ) )
	{
	  if ( inputMode == 1 )
	  {
		inputMode = 0;
	  }
	  else
	  {
	    PushStack( lcdDisplay[ 0 ].getText() );
	  }
	}
	else if ( key.equals( "drop" ) )
	{
	  PopStack( lcdValue[ 1 ] );
	}
	else if ( key.equals( "swap" ) )
	{
	  long temp = Long.parseLong( lcdDisplay[ 0 ].getText(), radix );
	  lcdValue[ 0 ] = lcdValue[ 1 ];
	  lcdValue[ 1 ] = temp;
	}

    inputMode = 0;
  }

  public void init()
  {
	setLayout( new GridLayout( 2, 1 ) );

	display = new LCDDisplay( this );
	keyboard = new CalcKeyboard( this );

    inputMode = 0;
	SetBase( 10 );

	add( display );
	add( keyboard );
  }

  public boolean keyDown( Event event, int key )
  {
	boolean handled = false;

	switch( key )
	{
	  case 42:
	    DoMathOp( "*" );
		handled = true;
		break;
	  case 43:
	    DoMathOp( "+" );
		handled = true;
		break;
	  case 45:
	    DoMathOp( "-" );
		handled = true;
		break;
	  case 47:
	    DoMathOp( "/" );
		handled = true;
		break;
	  case 94:
	    DoMathOp( "^" );
		handled = true;
		break;
	  case 10:
	    DoStackAction( "enter" );
		handled = true;
		break;
	  case 48:
	  case 49:
		DoInput( String.valueOf( key - 48 ) );
		handled = true;
		break;
	  case 50:
	  case 51:
	  case 52:
	  case 53:
	  case 54:
	  case 55:
		if ( radix >= 8 )
		{
		  DoInput( String.valueOf( key - 48 ) );
		  handled = true;
		}
	    break;
	  case 56:
	  case 57:
		if ( radix >= 10 )
		{
		  DoInput( String.valueOf( key - 48 ) );
		  handled = true;
		}
		break;
	  case 65:
	  case 66:
	  case 67:
	  case 68:
	  case 69:
	  case 70:
	  case 97:
	  case 98:
	  case 99:
	  case 100:
	  case 101:
	  case 102:
		if ( radix >= 16 )
		{
	      DoInput( String.valueOf( ( char ) key ) );
		  handled = true;
		}
		break;
	};

	UpdateLCDDisplay();

    return handled;
  }

  void PopStack( long result )
  {
    lcdValue[ 0 ] = result;

	for ( int i = 1; i <= numLines - 2; i++ )
	  lcdValue[ i ] = lcdValue[ i + 1 ];

	lcdValue[ numLines - 1 ] = 0;
  }

  void PushStack( String value )
  {
	for ( int i = numLines - 1; i > 0; i-- )
	  lcdValue[ i ] = lcdValue[ i - 1 ];

	lcdValue[ 0 ] = Long.parseLong( value, radix );
  }

  void SetBase( int base )
  {
	radix = base;

	int[] keyIndex =
	{
	  32, 26, 27, 28, 20, 21, 22, 14, 15, 16, 8, 9, 10, 2, 3, 4
	};

	switch( base )
	{
	  case 2:
	    calcKeys[ keyIndex[ 2 ] ].disable();
	    calcKeys[ keyIndex[ 3 ] ].disable();
	    calcKeys[ keyIndex[ 4 ] ].disable();
	    calcKeys[ keyIndex[ 5 ] ].disable();
	    calcKeys[ keyIndex[ 6 ] ].disable();
	    calcKeys[ keyIndex[ 7 ] ].disable();
		// fall through
	  case 8:
	    calcKeys[ keyIndex[ 8 ] ].disable();
	    calcKeys[ keyIndex[ 9 ] ].disable();
		// fall through
	  case 10:
	    calcKeys[ keyIndex[ 10 ] ].disable();
	    calcKeys[ keyIndex[ 11 ] ].disable();
	    calcKeys[ keyIndex[ 12 ] ].disable();
	    calcKeys[ keyIndex[ 13 ] ].disable();
	    calcKeys[ keyIndex[ 14 ] ].disable();
	    calcKeys[ keyIndex[ 15 ] ].disable();
	}

	switch( base )
	{
	  case 16:
		calcKeys[ keyIndex[ 15 ] ].enable();
		calcKeys[ keyIndex[ 14 ] ].enable();
		calcKeys[ keyIndex[ 13 ] ].enable();
		calcKeys[ keyIndex[ 12 ] ].enable();
		calcKeys[ keyIndex[ 11 ] ].enable();
		calcKeys[ keyIndex[ 10 ] ].enable();
		// fall through
	  case 10:
		calcKeys[ keyIndex[ 9 ] ].enable();
		calcKeys[ keyIndex[ 8 ] ].enable();
		// fall through
	  case 8:
		calcKeys[ keyIndex[ 7 ] ].enable();
		calcKeys[ keyIndex[ 6 ] ].enable();
		calcKeys[ keyIndex[ 5 ] ].enable();
		calcKeys[ keyIndex[ 4 ] ].enable();
		calcKeys[ keyIndex[ 3 ] ].enable();
		calcKeys[ keyIndex[ 2 ] ].enable();
		// fall through
	  case 2:
		calcKeys[ keyIndex[ 1 ] ].enable();
		calcKeys[ keyIndex[ 0 ] ].enable();
	}
  }

  void UpdateLCDDisplay()
  {
	for ( int i = 0; i < numLines; i++ )
	  lcdDisplay[ i ].setText( Long.toString( lcdValue[ i ], radix ) );
  }
}

class LCDDisplay extends Panel
{
  ProgCalc app;

  LCDDisplay( ProgCalc target )
  {
	app = target;

	setLayout( new GridLayout( app.numLines, 1 ) );

    app.lcdValue = new long[ app.numLines ];
	app.lcdDisplay = new TextField[ app.numLines ];

	for ( int i = app.numLines - 1; i >= 0; i-- )
	{
	  app.lcdValue[ i ] = 0;
	  app.lcdDisplay[ i ] = new TextField( String.valueOf( app.lcdValue[ i ] ), 64 );
	  app.lcdDisplay[ i ].setEditable( false );

	  add( app.lcdDisplay[ i ] );
	}
  }
}

class CalcKeyboard extends Panel
{
  ProgCalc app;

  String[] keyLabels =
  {
    "HEX",  "AND",  "D", "E",     "F",     "+",
	"DEC",  "OR",   "A", "B",     "C",     "-",
	"OCT",  "NOT",  "7", "8",     "9",     "*",
	"BIN",  "XOR",  "4", "5",     "6",     "/",
	"-> K", "K ->", "1", "2",     "3",     "^",
	"-> M", "M ->", "0", "drop",  "swap",  "enter"
  };

  CalcKeyboard( ProgCalc target )
  {
	app = target;

	setLayout( new GridLayout( 6, 6, 2, 2 ) );

	app.calcKeys = new Component[ 36 ];
	app.radixMode = new CheckboxGroup();

	for ( int i = 0; i < 36; i++ )
	{
	  if ( i == 0 || i == 6 || i == 12 || i == 18 )
	    app.calcKeys[ i ] = ( Component ) new Checkbox( keyLabels[ i ], app.radixMode, false );
	  else
	    app.calcKeys[ i ] = ( Component ) new Button( keyLabels[ i ] );

	  app.radixMode.setCurrent( ( Checkbox ) app.calcKeys[ 6 ] );

	  add( app.calcKeys[ i ] );
	}
  }
}
Hosted by www.Geocities.ws

1