/* Java Applet source code for "RPN calculator on Java" * * This is an applet to realize "RPN caculator" on a Web browser. * The author, T. Nakatsuka, does not insist any right on this program, * i.e., free to re-distribute to any place with/without any modification. * The author acknowledges Hewlett-Packard Corp. for their intelligent * product of micro-calculators, which were borne in mind during designing. */ import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class calcj extends Applet implements MouseListener, KeyListener, ItemListener, FocusListener { Image barea; Font font, fontb; CheckboxGroup degrad; Checkbox degree, radian; int kdeg; double y, z, t; Label regY, regZ, regT; double x; TextField regX; StringBuffer xstr; int key, kf, l, lce; double r, tmp; /* * key : Status for Register-X * = 0 : Register-X shall be cleared by New-Value entry * [after ENTER/CLR/CLX/STO operation] * = 1 : CHS input after key=0 * = 2 : Register-X shall be pushed (on stack) by New-Value entry * [after Arithmetic or SWAP/ROT operation, * or definite value entry by RCL/'pi'/'e'] * = 3 : CHS input after key=2 * =4-7: on the way of New-Value entry * [after Numeric input keys (0-9/./EEX)] * =4 : neither . nor EEX input yet * =5 : . already input but EEX not yet * =6 : EEX already input but no exponent digit yet * =7 : at least 1 exponent digit input already * = 9 : error detected (use CLR/CLX to reset) */ String sz(String v) { int len = v.length(); if ((v.charAt(--len) != '0') || (v.charAt(--len) != '.')) { return v; } else { return v.substring(0,len); } } void showt() { regT.setText(sz(Double.toString(t))); } void showz() { regZ.setText(sz(Double.toString(z))); } void showy() { regY.setText(sz(Double.toString(y))); } void showx() { if (Double.isNaN(x) || Double.isInfinite(x)) error(); else { String s = sz(Double.toString(x)); regX.setText(s); xstr.setLength(0); xstr.append(s); l = s.length(); key=2; } } void push(int k) { t = z; z = y; if (k==0) y = x; else y = -x; showy(); showz(); showt(); } void pop() { x = y; y = z; z = t; showz(); showy(); showx(); } void rad0() { if (kdeg==1) x /= Math.PI/180.; } void rad1() { if (kdeg==1) x *= Math.PI/180.; } void num(int i) { if (key<4) { if (key==2) push(0); else if (key==3) push(1); xstr.setLength(0); l=0; if ((key==1) || (key==3)) { xstr.append("-"); l++; } key=4; } xstr.append(Integer.toString(i)); l++; if (key==6) key=7; x = Double.valueOf(xstr.toString()).doubleValue(); regX.setText(xstr.toString()); } void dot() { if (key<4) { if (key==2) push(0); else if (key==3) push(1); xstr.setLength(0); x = 0.; if ((key==1) || (key==3)) { xstr.append("-0"); l=2; } else { xstr.append("0"); l=1; } } xstr.append("."); l++; key=5; regX.setText(xstr.toString()); } void eex() { if (key<4) { if (key==2) push(0); else if (key==3) push(1); xstr.setLength(0); if ((key==1) || (key==3)) { xstr.append("-1."); x = -1.; l=3; } else { xstr.append("1."); x = 1.; l=2; } } xstr.append("E"); lce=l++; key=6; regX.setText(xstr.toString()); } void chs() { if (key<6) { if (key==0) key=1; else if (key==1) key=0; if (key==2) key=3; else if (key==3) key=2; if (xstr.charAt(0) == '-') { String s = xstr.toString().substring(1); --l; xstr.setLength(0); xstr.append(s); } else { xstr.insert(0, "-"); l++; } x = -x; } else if (key==6) { if (xstr.charAt(lce) == 'E') { lce++; xstr.append("-"); l++; } else { xstr.setLength(--l); lce--; } } else if (key==7) { if (xstr.charAt(lce) == 'E') { xstr.insert(++lce, "-"); l++; } else { String s = xstr.toString().substring(lce+1); l--; xstr.setLength(lce); xstr.append(s); lce--; } x = Double.valueOf(xstr.toString()).doubleValue(); } regX.setText(xstr.toString()); } void error() { regX.setText(" E R R O R !!"); x = 0.; key=9; } /*************************************************************************** * The Register-X field can be pasted by any value, which is evaluated * * at the "focusGained" event when coming back from regX TextField. * * Accordingly, the process of literal input to Register-X is finalized * * by the temporal loss of focus, which may cause unexpected result. * ***************************************************************************/ public void focusGained(FocusEvent fe) { kf = 1; repaint(); try { String s = regX.getText(); if (s.length() == 0) x = 0.; else x = Double.valueOf(s).doubleValue(); showx(); } catch (NumberFormatException nfe) { error(); } } public void focusLost(FocusEvent fe) { kf = 0; repaint(); } public void itemStateChanged(ItemEvent ie) { if (((Checkbox) ie.getItemSelectable()) == degree) { kdeg = 1; requestFocus(); } else { kdeg = 0; requestFocus(); } } public void keyPressed(KeyEvent ke) {} public void keyReleased(KeyEvent ke) {} public void keyTyped(KeyEvent ke) { char kc = ke.getKeyChar(); if (key < 9) { switch (kc) { /* Only limited key inputs are supported */ case '0': num(0); break; /* '0'-'9' */ case '1': num(1); break; case '2': num(2); break; case '3': num(3); break; case '4': num(4); break; case '5': num(5); break; case '6': num(6); break; case '7': num(7); break; case '8': num(8); break; case '9': num(9); break; case '^': chs(); break; /* ^ for ch +/- */ case 'E': /* E(e) for Eex */ case 'e': if (key<6) eex(); break; case '.': if (key<5) dot(); break; /* decimal point */ case '*': y *= x; pop(); break; /* arithmetic *,/,+,- */ case '/': y /= x; pop(); break; case '+': y += x; pop(); break; case '-': if (key == 6) chs(); /* Only after Eex, '-' */ else { y -= x; pop(); } /* may be used to ch +/- */ break; case KeyEvent.VK_ENTER: /* 'Enter' or 'ctrl-R' */ case '\r': showx(); break; /* finalizes regX input.*/ } } } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseClicked(MouseEvent e) { int fx, fy, m; int px = e.getX() - 12; int py = 337 - e.getY(); if ((px<0) || (205<px) || (py<0) || (195<py)) m = 20; else { fx = px%42; fy = py%25; m = (px-fx)/42 + (py-fy)/5; if (m == 20) m = 21; else if ((37<fx) || (20<fy)) m = 20; } if (m == 20) {} else if (m == 19) { x = 0.; showx(); key=0; } /* CLX */ else if (m == 24) { x = 0.; y = 0.; z = 0.; t = 0.; /* CLR */ showx(); showy(); showz(); showt(); r = 0.; key=0; } else if (key < 9) { switch (m) { case 22: chs(); break; /* ch +/- */ case 23: if (key<6) eex(); break; /* Eex */ case 2: if (key<5) dot(); break; /* decimal point */ case 1: num(0); break; /* numerical digit 0-9 */ case 6: num(1); break; case 7: num(2); break; case 8: num(3); break; case 11: num(4); break; case 12: num(5); break; case 13: num(6); break; case 16: num(7); break; case 17: num(8); break; case 18: num(9); break; case 3: if (key==3) push(1); else if (key>=2) push(0); /* 'PI' */ x = Math.PI; if ((key==1) || (key==3)) x = -x; showx(); break; case 4: if (key==3) push(1); else if (key>=2) push(0); /* 'e' */ x = Math.E; if ((key==1) || (key==3)) x = -x; showx(); break; case 14: r = x; showx(); key=0; break; /* STO */ case 9: if (key==3) push(1); else if (key>=2) push(0); /* RCL */ x = r; if ((key==1) || (key==3)) x = -x; showx(); break; case 0: y += x; pop(); break; /* arithmetic +,-,*,/ */ case 5: y -= x; pop(); break; case 10: y *= x; pop(); break; case 15: y /= x; pop(); break; case 25: if (y <= 0.) error(); /* y**x */ else { y = Math.exp(Math.log(y)*x); pop(); } break; case 21: push(0); showx(); key=0; break; /* Enter */ case 29: tmp = x; pop(); t = tmp; showt(); break; /* rot */ case 28: tmp = x; x = y; y = tmp; /* swap */ showy(); showx(); break; case 26: x = 1./x; showx(); break; /* 1./x */ case 27: x = Math.sqrt(x); showx(); break; /* sqrt */ case 30: x = Math.exp(x); showx(); break; /* exp */ case 31: x = Math.log(x); showx(); break; /* ln */ case 35: x = Math.pow(10., x); showx(); break; /* 10**x */ case 36: if (x <= 0.) error(); /* Log10 */ else { x = Math.log(x)/Math.log(10.); showx(); } break; case 32: rad1(); x = Math.sin(x); showx(); break; /* sin */ case 33: rad1(); x = Math.cos(x); showx(); break; /* cos */ case 34: rad1(); x = Math.tan(x); showx(); break; /* tan */ case 37: if ((x>1.) || (x<-1.)) error(); /* arcsin */ else { x = Math.asin(x); rad0(); showx(); } break; case 38: if ((x>1.) || (x<-1.)) error(); /* arccos */ else { x = Math.acos(x); rad0(); showx(); } break; case 39: x = Math.atan(x); rad0(); showx(); break; /* arctan */ } } } public void paint(Graphics g) { g.setColor(Color.lightGray); g.fillRect(0, 0, 230, 30); g.setColor(Color.black); g.setFont(font); g.drawString("Angle:", 35, 22); g.fillRect(0, 30, 230, 320); g.setColor(Color.white); g.setFont(fontb); g.drawString("T", 10, 53); g.drawString("Z", 10, 78); g.drawString("Y", 10,103); g.drawString("X", 10,128); g.drawImage(barea, 10,140, this); if (kf == 0) { g.setColor(Color.red); g.fillRect(0, 0, 90, 35); g.setColor(Color.white); g.drawString("Focus", 3, 17); g.drawString("Lost", 53, 17); g.drawString("click me!", 9, 32); } } public void init() { String courier = "Courier"; fontb = new Font(courier, Font.BOLD, 16); font = new Font(courier, Font.PLAIN, 16); barea = getImage(getDocumentBase(), "calc.gif"); setLayout(null); regT = new Label("0", Label.LEFT); regT.setSize(194,18); regT.setLocation(26,36); regT.setFont(font); add(regT); regZ = new Label("0", Label.LEFT); regZ.setSize(194,18); regZ.setLocation(26,61); regZ.setFont(font); add(regZ); regY = new Label("0", Label.LEFT); regY.setSize(194,18); regY.setLocation(26,86); regY.setFont(font); add(regY); regX = new TextField(30); regX.setSize(195,22); regX.setLocation(25,110); regX.setFont(font); regX.setText("0"); add(regX); degrad = new CheckboxGroup(); degree = new Checkbox("Degree", true, degrad); degree.setSize(58,14); degree.setLocation(90,10); add(degree); kdeg = 1; degree.addItemListener(this); radian = new Checkbox("Radian", false, degrad); radian.setSize(58,14); radian.setLocation(150,10); add(radian); radian.addItemListener(this); addMouseListener(this); addKeyListener(this); requestFocus(); addFocusListener(this); kf = 1; xstr = new StringBuffer(32); xstr.setLength(0); xstr.append("0"); l=1; lce=0; x = 0.; y = 0.; z = 0.; t = 0.; r = 0.; key=0; } }