/* Placed in the public domain 1997 Lawrence Leinnweber, Cleveland, Ohio USA */ import java.applet.*; import java.awt.*; import java.io.*; import java.net.*; import java.util.*; import java.awt.image.*; class hp25bw extends Frame { int w, h; boolean noparent; Scrollbar sb; hp25b hp25b; Object mutex; public hp25bw(Image icon, hp25b a) { super(); hp25b = a; setTitle("HP-25 Calculator"); setIconImage(icon); sb = new Scrollbar(Scrollbar.VERTICAL, 0, 100, 0, 100); setResizable(false); /* do this right away: changes border width! */ setLayout(null); add(a); add(sb); w = (getToolkit().getScreenSize().width - a.preferredSize().width) / 2; h = (getToolkit().getScreenSize().height- a.preferredSize().height)/ 2; move(w < 0? 0: w, h < 0? 0: h); mutex = new Object(); } public void layout() { Insets is; Dimension s, p, a, f; int off; is = insets(); s = getToolkit().getScreenSize(); p = hp25b.preferredSize(); f = new Dimension(); f.width = Math.min(s.width, p.width + is.left + is.right); f.height= Math.min(s.height,p.height+ is.top + is.bottom); a = new Dimension(); a.width = f.width - is.left - is.right; a.height= f.height - is.top - is.bottom; off = 0; if (a.height >= p.height) sb.show(false); else { off = sb.getValue(); if (sb.getVisible() != a.height || sb.getMinimum() != 0 || sb.getMaximum() != p.height - a.height) { if (off > p.height - a.height) off = p.height -a.height; sb.setValues(off, a.height, 0, p.height - a.height); } if (sb.location().x != is.left + a.width || sb.location().y != is.top || sb.size().width != 16 || sb.size().height != a.height) sb.reshape(is.left + a.width, is.top, 16, a.height); f.width += 16; sb.show(true); } hp25b.scroll = off; off = 0; if (hp25b.location().x != is.left || hp25b.location().y != is.top - off || hp25b.size().width != a.width || hp25b.size().height!= a.height) hp25b.reshape(is.left, is.top - off, a.width, a.height + off); if (size().width != f.width || size().height != f.height) resize(f); repaint(); } public void update(Graphics g) { paint(g); } public boolean handleEvent(Event e) { if (e.id == e.WINDOW_MOVED) layout(); if (e.id == e.SCROLL_ABSOLUTE || e.id == e.SCROLL_LINE_UP || e.id == e.SCROLL_LINE_DOWN || e.id == e.SCROLL_PAGE_UP || e.id == e.SCROLL_PAGE_DOWN) { hp25b.scroll = sb.getValue(); hp25b.repaint(); } if (e.id != e.WINDOW_DESTROY) return (super.handleEvent(e)); show(false); if (noparent) dispose(); return (true); } public void bye() { noparent = true; } } /* end of class */ public class hp25b extends Applet implements Runnable { private Thread thread = null; Frame diagframe; TextArea diagtext; public int keystate; /* 0=java not ready, 1=ready, 2=do key up, 3=do key down*/ int keycode, over; Image face, butn, leds, slid, keys, newface; Image ledtab[], slitab0[], slitab1[], keytab0[], keytab1[]; MediaTracker mt; int mtcnt0, mtcnt1; int pbuf[], ppnt, pled; int pkey, dkey; int facew, faceh; int ledx[], ledy, ledw, ledh; int slidw, slidh, slidew, sliden, dslid[], mslid[]; int keyx[], keyy[], keyw[], keyh; int keyc[], mapx[], mapy[]; Object mutex; hp25b hp25b; hp25bw hp25bw; String statstr; public int scroll; /* violates the structure but gets the job done */ private void makediag() { if (this.getParameter("diag") == null) return; diagframe = new Frame("Diagnostic"); diagframe.show(); diagframe.resize(250, 400); diagframe.move(310, 25); diagtext = new TextArea(); diagtext.setFont(new Font("Courier", Font.PLAIN, 14)); diagframe.add(diagtext); diag("diagnostics..."); } private void diag(String s) { if (diagframe == null) return; diagtext.appendText(s + "\r\n"); diagframe.show(); } protected void finalize() { if (hp25b == null && hp25bw != null) hp25bw.bye(); } private void stat(String s) { if (hp25b != null) showStatus(statstr = s); else if (statstr == null || statstr.compareTo(s) != 0) { statstr = s; hp25bw.setTitle(s.compareTo("") == 0? "HP-25": "HP-25 ["+s+"]"); } } public boolean handleEvent(Event e) { if (e.id == e.MOUSE_ENTER) { stat(statstr); return (true); } if (e.id == e.MOUSE_EXIT && keystate != 0 && butn == null) { over = -1; stat(""); return (true); } return (super.handleEvent(e)); } public void start() { synchronized (mutex) { if (thread != null) return; thread = new Thread(this); thread.setPriority(thread.MIN_PRIORITY); thread.start(); } } public void stop() { synchronized (mutex) { if (thread != null && thread.isAlive()) thread.stop(); thread = null; } } public Dimension preferredSize() { return (getPreferredSize()); } public Dimension minimumSize() { return (getPreferredSize()); } public Dimension getPreferredSize() { Dimension d; d = new Dimension(); d.width = facew; d.height = faceh; return (d); } public void init() { URL u; InputStream is; StreamTokenizer st; int c; super.init(); makediag(); u = null; is = null; try { u = new URL(getDocumentBase(), getParameter("data")); } catch (MalformedURLException e) {}; try { is = u.openStream(); } catch (IOException e) {}; st = new StreamTokenizer(is); st.commentChar('#'); st.parseNumbers(); c = getint(st); c <<= 8; c |= getint(st); c <<= 8; c |= getint(st); facew = getint(st); faceh = getint(st); mt = new MediaTracker(this); gw_u = new URL[5]; gw_s = new String[5]; gw_i = new Image[5]; gw_m = new int[5]; gw_u[0] = getDocumentBase(); gw_s[0] = getParameter("leds"); gw_u[1] = getDocumentBase(); gw_s[1] = getParameter("slid"); gw_u[2] = getDocumentBase(); gw_s[2] = getParameter("keys"); gw_u[3] = getDocumentBase(); gw_s[3] = getParameter("face"); if (getParameter("butn") != null) { setBackground(Color.darkGray); gw_u[4] = getDocumentBase(); gw_s[4] = getParameter("butn"); getwhole_videomom(5); butn = gw_i[4]; } else getwhole_videomom(4); leds = gw_i[0]; slid = gw_i[1]; keys = gw_i[2]; face = gw_i[3]; newface = createImage(facew, faceh); hp25b = butn == null? this: new hp25b(); hp25b.init2(st, c, facew, faceh, mt, leds, slid, keys, newface); try { is.close(); } catch (IOException e) {}; mt = new MediaTracker(this); if (butn != null) { hp25bw = new hp25bw(butn, hp25b); hp25b.init3(face, hp25bw); hp25b.start(); mutex = new Object(); } showStatus(statstr = "hp25 applet initializing graphics, please wait..."); } public void init2(StreamTokenizer st, int c, int fw, int fh, MediaTracker m, Image il, Image is, Image ik, Image nf) { int i, x, y, w, h, l, n; facew = fw; faceh = fh; mt = m; leds = il; slid = is; keys = ik; newface = nf; setBackground(new Color(c)); ledw = getint(st); ledh = getint(st); ledx = new int[12]; ledy = getint(st); for (i = 0; i < 12; i++) ledx[i] = getint(st); keyx = new int[32]; keyy = new int[32]; keyw = new int[30]; keyc = new int[30]; keyx[30] = getint(st); keyx[31] = getint(st); keyy[30] = keyy[31] = getint(st); slidw = getint(st); slidh = getint(st); slidew = getint(st); sliden = slidw - slidew + 1; keyh = getint(st); mapx = new int[facew]; mapy = new int[faceh]; for (i = 0, l = 1; i < 30; i++, l <<= 1) { x = keyx[i] = getint(st); y = keyy[i] = getint(st); w = keyw[i] = getint(st); h = keyh; keyc[i] = getint(st); while (w-- != 0) mapx[x++] |= l; while (h-- != 0) mapy[y++] |= l; } for (; i < 32; i++, l <<= 1) { x = keyx[i]; y = keyy[i]; w = slidw; h = slidh; while (w-- != 0) mapx[x++] |= l; while (h-- != 0) mapy[y++] |= l; } pbuf = new int[12]; dslid = new int[2]; mslid = new int[2]; ledtab = new Image[32]; slitab0 = new Image[sliden]; slitab1 = new Image[sliden]; keytab0 = new Image[30]; keytab1 = new Image[30]; n = 32 + sliden * 2 + 30 * 2; gc_f = new FilteredImageSource[n]; gc_s = new ImageProducer[n]; gc_c = new CropImageFilter[n]; gc_x = new int[n]; gc_y = new int[n]; gc_w = new int[n]; gc_h = new int[n]; gc_i = new Image[n]; gc_m = new int[n]; n = 0; for (i = 0; i < 32; i++) { gc_s[n] = leds.getSource(); gc_x[n] = 0; gc_y[n] = i * ledh; gc_w[n] = ledw; gc_h[n] = ledh; n++; } for (i = 0; i < sliden; i++) { gc_s[n] = slid.getSource(); gc_x[n] = 0; gc_y[n] = i * slidh; gc_w[n] = slidw; gc_h[n] = slidh; n++; gc_s[n] = slid.getSource(); gc_x[n] = slidw; gc_y[n] = i * slidh; gc_w[n] = slidw; gc_h[n] = slidh; n++; } for (i = 0, x = 0; i < 30; x += keyw[i++]) { gc_s[n] = keys.getSource(); gc_x[n] = x; gc_y[n] = 0; gc_w[n] = keyw[i]; gc_h[n] = keyh; n++; gc_s[n] = keys.getSource(); gc_x[n] = x; gc_y[n] = keyh; gc_w[n] = keyw[i]; gc_h[n] = keyh; n++; } mutex = new Object(); over = -1; } public void init3(Image f, hp25bw a) { face = f; hp25bw = a; } private int getint(StreamTokenizer st) { try { st.nextToken(); } catch (IOException e) {}; return (new Double(st.nval).intValue()); } private void initimage() { int i, n; stat("hp25 applet initializing graphics, please wait..."); if (butn != null) { while (hp25b.keystate == 0) thread.yield(); stat("Click to run/stop HP-25 Calculator window"); return; } getcrop_videomom(32 + sliden * 2 + 30 * 2); n = 0; for (i = 0; i < 32; i++) ledtab[i] = gc_i[n++]; for (i = 0; i < sliden; i++) { slitab0[i] = gc_i[n++]; slitab1[i] = gc_i[n++]; } for (i = 0; i < 30; i++) { keytab0[i] = gc_i[n++]; keytab1[i] = gc_i[n++]; } leds.flush(); slid.flush(); keys.flush(); newface.getGraphics().drawImage(face, 0, 0, this); for (i = 0; i < 12; i++) pbuf[i] = -1; ppnt = -1; dslid[0] = dslid[1] = sliden - 1; pkey = 0xC0000000; powerswitch(true); stat("HP-25 Calculator"); } /* ...videomom() routines to work-around mysterious image loading problems */ /* let's just say Java wasn't designed for blitting and leave it at that */ private URL gw_u[]; private String gw_s[]; private Image gw_i[]; private int gw_m[]; private void getwhole_videomom(int n) { int m, i; boolean flag; m = 0; flag = true; while (flag) { flag = false; for (i = 0; i < n; i++) if (gw_i[i] == null || mt.isErrorID(gw_m[i])) { flag = true; gw_i[i] = this.getImage(gw_u[i], gw_s[i]); mt.addImage(gw_i[i], gw_m[i] = m++); } if (flag) wait_videomom(); } } private FilteredImageSource gc_f[]; private ImageProducer gc_s[]; private CropImageFilter gc_c[]; private int gc_x[], gc_y[], gc_w[], gc_h[]; private Image gc_i[]; private int gc_m[]; private void getcrop_videomom(int n) { int m, i; boolean flag; m = 0; flag = true; while (flag) { flag = false; for (i = 0; i < n; i++) if (gc_i[i] == null || mt.isErrorID(gc_m[i])) { flag = true; gc_i[i] = createImage(gc_f[i] = new FilteredImageSource(gc_s[i], gc_c[i] = new CropImageFilter(gc_x[i], gc_y[i], gc_w[i], gc_h[i]))); mt.addImage(gc_i[i], gc_m[i] = m++); } if (flag) wait_videomom(); } } private void wait_videomom() { while (true) { try { if (mt.checkAll(true)) return; mt.waitForAll(); } catch (NullPointerException e) {} catch (InterruptedException e) {} ; /* end of try */ } } private void paintled() { int i, m; if (!drawled) return; cvtput(); if (diagframe != null) dumpled(); for (i = 0, m = 1; i < 12; i++, m <<= 1) if (pbuf[i] != dbuf[i] || (ppnt == i) != (dpnt == i)) pled |= m; if (pled != 0) repaint(); drawled = false; } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { Graphics h; int i, j, m; if (butn != null) { if (keystate != 0) g.drawImage(butn, 0, 0, this); return; } if (keystate == 0) { g.drawImage(face, 0, -scroll, this); return; } if (pkey != 0) { h = newface.getGraphics(); for (i = 0, m = 1; i < 30; i++, m <<= 1) if ((pkey & m) != 0) { h.clipRect(keyx[i], keyy[i], keyw[i], keyh); h.drawImage((dkey & m) != 0? keytab1[i]: keytab0[i], keyx[i], keyy[i], this); pkey &= ~m; } if ((pkey & m) != 0) { h.clipRect(keyx[i], keyy[i], slidw, slidh); h.drawImage(slitab0[dslid[0]], keyx[i], keyy[i], this); pkey &= ~m; } i++; m <<= 1; if ((pkey & m) != 0) { h.clipRect(keyx[i], keyy[i], slidw, slidh); h.drawImage(slitab1[dslid[1]], keyx[i], keyy[i], this); pkey &= ~m; } } if (pled != 0) { h = newface.getGraphics(); h.clipRect(ledx[0], ledy, ledx[11] - ledx[0] + ledw, ledh); for (i = 0, m = 1; i < 12; i++, m <<= 1) if ((pled & m) != 0) { j = dbuf[i]; if (dpnt == i) j += 16; h.drawImage(ledtab[j], ledx[i], ledy, this); pbuf[i] = dbuf[i]; pled &= ~m; } ppnt = dpnt; } g.drawImage(newface, 0, -scroll, this); } public boolean mouseMove(Event e, int x, int y) { int i, j, k, m; start(); if (butn != null) showStatus(statstr); if (keystate == 0 || butn != null) return (true); y += scroll; i = p1; j = p2; if (x < 0 || y < 0 || x >= facew || y >= faceh) over = -1; else if ((m = mapx[x] & mapy[y]) == 0) over = -1; else { k = 0; if ((m & 0xFFFF0000) != 0) k |= 0x10; if ((m & 0xFF00FF00) != 0) k |= 0x08; if ((m & 0xF0F0F0F0) != 0) k |= 0x04; if ((m & 0xCCCCCCCC) != 0) k |= 0x02; if ((m & 0xAAAAAAAA) != 0) k |= 0x01; over = k; } synchronized (thread) { thread.notify(); } return (true); } public boolean mouseDown(Event e, int x, int y) { int i, j, k, m, t, s; Graphics h; start(); if (butn != null) showStatus(statstr); if (keystate == 0) return (true); if (butn != null) { hp25bw.show(!hp25bw.isVisible()); hp25bw.repaint(); if (hp25bw.isVisible()) hp25b.requestFocus(); return (true); } y += s = scroll; over = -1; synchronized (thread) { thread.notify(); } if (x < 0 || y < 0 || x >= facew || y >= faceh) return (true); if ((m = mapx[x] & mapy[y]) == 0) return (true); k = 0; if ((m & 0xFFFF0000) != 0) k |= 0x10; if ((m & 0xFF00FF00) != 0) k |= 0x08; if ((m & 0xF0F0F0F0) != 0) k |= 0x04; if ((m & 0xCCCCCCCC) != 0) k |= 0x02; if ((m & 0xAAAAAAAA) != 0) k |= 0x01; if (k >= 30) return (mouseDrag(e, x, y - s)); h = newface.getGraphics(); h.clipRect(keyx[k], keyy[k], keyw[k], keyh); h.drawImage(keytab1[k], keyx[k], keyy[k], this); getGraphics().drawImage(newface, 0, -scroll, this); t = dkey; dkey = 1 << k; pkey |= dkey ^ t; repaint(); synchronized (thread) { keystate = 2; keycode = keyc[k]; } while (keystate > 1) synchronized (thread) { thread.notify(); } return (true); } public boolean mouseUp(Event e, int x, int y) { int t; start(); if (butn != null) showStatus(statstr); if (keystate == 0 || butn != null) return (true); over = -1; synchronized (thread) { thread.notify(); } if ((t = dkey) != 0) { dslid[0] = dslid[0] <= (sliden >> 1)? 0: sliden - 1; dslid[1] = dslid[1] <= (sliden >> 1)? 0: sliden - 1; dkey = 0; pkey = t; repaint(); } keystate = 3; while (keystate > 1) synchronized (thread) { thread.notify(); } return (true); } public boolean mouseDrag(Event e, int x, int y) { int i, j, m, t, s; start(); if (butn != null) showStatus(statstr); if (keystate == 0 || butn != null) return (true); y += s = scroll; over = -1; synchronized (thread) { thread.notify(); } if (x < 0 || y < 0 || x >= facew || y >= faceh) return (mouseUp(e, x, y - s)); if (((m = mapx[x] & mapy[y]) & dkey) == (m | dkey) && ((m | dkey) & 0xC0000000) == 0) return (true); if (((m | dkey) & 0x3FFFFFFF) != 0 || (m | dkey) == 0xC0000000) return (mouseUp(e, x, y - s)); i = ((m | dkey) & 0x80000000) != 0? 1: 0; if (dkey == 0) mslid[i] = x - (keyx[i + 30] + dslid[i]); /* new */ else { /* old */ j = x - (keyx[i + 30] + mslid[i]); if (j < 0) { mslid[i] += j; j = 0; } /* skid left */ if (j >= sliden) { mslid[i] -= sliden - 1 - j; j = sliden - 1; } /* skid right */ dslid[i] = j; if ((dslid[i] <= sliden >> 1) != (i == 0? running == 0: prgm)) { synchronized (thread) { if (i == 0) powerswitch(running == 0); if (i == 1) prgmswitch(!prgm); thread.notify(); } } } if (m == 0 || mslid[i] < 0 || mslid[i] >= slidew) return (mouseUp(e, x, y - s)); /* off slide */ t = dkey; dkey = m; pkey |= dkey | t; repaint(); return (true); } public void run() { int m, i; String h0, h1; if (keystate == 0) initimage(); keystate = 1; if (butn != null) { repaint(); return; } stat(h0 = ""); i = 0; while (true) { paintled(); while (running > 1 || keystate > 1) { stat(h0 = ""); m = 0; synchronized (thread) { if (keystate == 2) keydown(keycode); if (keystate == 3) keyup(); keystate = 1; if (running > 1) { dokey(prog[step][0]); dokey(prog[step][1]); dokey(prog[step++][2]); m = running == 3? 1000: 100; paintled(); } } if (m != 0) try { thread.sleep(m); } catch (InterruptedException e) {}; synchronized (thread) { if (running == 3) { running = 2; if (keystate == 1) { drawled = true; paintled(); } } } } paintled(); synchronized (thread) { h1 = over == 30? "OFF--ON": over == 31? "PRGM--RUN": running == 0? "": over == -1? "": hint(p1, p2, keyc[over]); if (h1.compareTo("") == 0 || (i == 0 && h0.compareTo(h1) == 0)) { i = 0; stat(h0 = h1); try { thread.wait(); } catch (InterruptedException e) {}; } else { if (h0.compareTo(h1) != 0) { i = 10; h0 = h1; stat(""); } if (i != 0) { try { thread.sleep(100); } catch (InterruptedException e) {}; if (--i == 0) stat(h0); } } } } } private void dumpled() { int i, j; String s; s = new String(); s = s + "<"; for (i = 0; i < 12; i++) { j = dbuf[i]; if (j == 0) s = s + "0"; else if (j == 1) s = s + "1"; else if (j == 2) s = s + "2"; else if (j == 3) s = s + "3"; else if (j == 4) s = s + "4"; else if (j == 5) s = s + "5"; else if (j == 6) s = s + "6"; else if (j == 7) s = s + "7"; else if (j == 8) s = s + "8"; else if (j == 9) s = s + "9"; else if (j == 10) s = s + " "; else if (j == 11) s = s + "-"; else if (j == 12) s = s + "o"; else if (j == 13) s = s + "r"; else if (j == 14) s = s + "E"; else s = s + "F"; /* putchar("0123456789 -orEF"[dbuf[i]]) */ s = s + (i == dpnt? ".": " "); } s = s + ">"; diag(s); } /* C code */ int running; /* run state: 0=off, 1=on, 2=prgm running, 3=prgm pausing */ boolean prgm; /* pgrm switch */ boolean minus; /* weird minus sign -0.00 */ int entry; /* data entry state: 0=stack lift to start, 1=no lift to start, 2=before decimal point, 3=after point, 3=exponent */ boolean error; /* "Error" message flag */ boolean regop; /* is a register operation */ boolean regover;/* "OF message flag */ boolean overflow;/* any overflow */ boolean stopover;/* stop on overflow */ int umode; /* on button up do: 0=nothing, 1=sst, 2=bst, 3=run pgrm */ double circle2; /* 1/2 circle in current angle mode: DEG=180, RAD=pi, GRD=200 */ static final double LN10 = 2.3025850929940456840179914546843642076011; static final double PI = 3.1415926535897932384626433832795028841972; int p1, p2; /* first, second prefix key codes, or -1 */ double x, y, z, t, l; double reg[] = new double[8]; int prog[][] = new int[50][3]; int step; /* program step */ int format; /* 0-9 fix, 10-19 sci, 20-29 eng */ int dpnt, epnt; /* display and data entry decimal point pos's */ int dbuf[] = new int[12]; /* display buffer */ int ebuf[] = new int[12]; /* data entry buffer */ static final int BLANK = 0xA; static final int MINUS = 0xB; static final int LOWRO = 0xC; static final int LOWRR = 0xD; static final int UPPRE = 0xE; static final int UPPRF = 0xF; boolean drawled; /* char *keychar = "0123456789obtfgxdsrm\rhec-+/*.n"; int keymap[] = { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,21,22,23,24,25, 31,32,33,34,41,51,71,61,73,74 }; main() { int c, i; drawled = 1; while (1) { if (kbhit()) { if ((c = getch()) == 27) break; for (i = 0; keychar[i] && keychar[i] != c; i++); if (umode) keyup(); else if (c == 'p') prgmswitch(!prgm); else if (c == 'q') powerswitch(running == 0); else if (keychar[i]) keydown(keymap[i]); else putchar(7); } else if (drawled) { drawled = 0; cvtput(); putchar('<'); for (i = 0; i < 12; i++) putchar("0123456789 -orEF"[dbuf[i]]), putchar(" ."[i == dpnt]); putchar('>'); if (running == 3) printf(" pause"), running = 2, drawled = 1; if (umode) printf(" key down"); putchar('\n'); } else if (running == 2) { dokey(prog[step][0]), dokey(prog[step][1]), dokey(prog[step++][2]); } } exit(0); } */ private void parserr() { diag("parse error"); } private void powerswitch(boolean code) { int i; if ((running != 0) == code) return; running = code? 1: 0; drawled = true; if (running == 0) return; minus = false; entry = 0; error = regover = false; circle2 = 180.0; umode = 0; x = y = z = t = l = 0.0; for (i = 0; i < 8; i++) reg[i] = 0.0; for (i = 0; i < 50; i++) { prog[i][0] = 13; prog[i][1] = prog[i][2] = 0; } step = 0; p1 = p2 = -1; format = 2; } private void prgmswitch(boolean code) { if (prgm == code) return; prgm = code; if (running == 0) return; drawled = true; if (running < 2) { entry = 0; error = regover = minus = false; p1 = p2 = -1; } } private void keydown(int code) { int i; if (running == 0) return; drawled = true; if (running < 2) dokey(code); else { running = 1; entry = 0; error = regover = minus = false; p1 = p2 = -1; } } private void keyup() { if (umode == 1) { dokey(prog[step][0]); dokey(prog[step][1]); dokey(prog[step++][2]); } if (umode == 3) running = 2; if (umode != 0) { umode = 0; drawled = true; } } private void dokey(int code) { int i; if (code == -1) return; if (code == 14 || code == 15 || code == 23 || code == 24 || code == 13 && (p1 != 14 || p2 != -1)) /* first prefix */ { p1 = code; p2 = -1; return; } if (p2 == -1 && (p1 == 14 && code >= 11 && code <= 13 || p1 == 23 && code >= 41 && code <= 71 || p1 == 13 && code <= 4)) /* second prefix */ { p2 = code; return; } if (p1 == 15 && code >= 10 && code <= 15 || p1 >= 23 && code > 7 || p2 != -1 && code >= 10 || p1 == 13 && (p2 == -1 || code >= 10)) /* abort prefix */ { p1 = p2 = -1; entry = 0; } if (prgm && running == 1) programkey(code); else { if (p1 != -1 || code != 11 && code != 12 && code != 74 && code != 32) if (p1 != -1 || code >= 10 && code != 33 && code != 73) entry = 0; else if (entry < 2 || code == 73 && entry == 4) { op(0.0, entry != 1? 1: 0, 0); for (i = 0; i < 12; ebuf[i++] = BLANK); epnt = 0; entry = 2; } error = false; regover = false; stopover = true; regop = false; overflow = false; if (entry < 2 && p1 == -1 && code == 32 && x == 0.0) minus = !minus; else if (minus) if (p1 == 14 && p2 == -1 && code == 2) { error = true; minus = false; } else if (p1 == 15 && code == 41) { step--; minus = false; } else if (p1 == 15 && code == 51) { step++; minus = false; } else if (running > 1? p1 != 14 || code != 74: p1 != -1 || code != 12 && code != 74) minus = false; runkey(code); if (running > 1 && error) { running = 1; step--; drawled = true; } if (entry > 1) { cvtget(); if (running > 1 && x != 0.0 && (x > 0.0? x < 1.0e-99: x > -1.0e-99)) { x = 0.0; entry = 0; running = 1; step--; drawled = true; } else x = rangecheck(x); minus = ebuf[0] == MINUS; } } p1 = p2 = -1; if (step <= 0 || step >= 50) { step = 0; running = 1; drawled = true; } } private void programkey(int code) { int i; if ((p1 == 14 || p1 == 15) && code == 31) return; if (p1 == -1 && (code == 11 || code == 12)) { /* SST or BST */ if (code == 11) step++; else step--; return; } if (p1 == 14 && code == 32) { /* clr PRGM */ for (i = 0; i < 50; i++) { prog[i][0] = 13; prog[i][1] = prog[i][2] = 0; } step = 0; return; } if (++step >= 50) return; prog[step][0] = -1; prog[step][1] = p1; prog[step][2] = code; if (p2 != -1) { prog[step][0] = p1; prog[step][1] = p2; } } private void runkey(int code) { double d; int i; boolean f; if (p1 == -1) /* no prefix */ switch (code) { /* digits */ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: if (entry == 4) { ebuf[10] = ebuf[11]; ebuf[11] = code; } else { for (i = 1; i < 11 && ebuf[i] != BLANK; i++); if (i < 11) { ebuf[i] = code; if (entry == 2) epnt = i; } } break; /* SST */ case 11: if (step == 0) step = 1; umode = 1; break; /* BST */ case 12: step--; umode = 2; break; /* xy swap */ case 21: d = y; y = x; x = d; break; /* roll down */ case 22: d = x; x = y; y = z; z = t; t = d; break; /* sum+ */ case 25: regop = true; d = x * x; d = rangecheck(d); if (regover) { reg[6] = d; break; } reg[6] += d; reg[6] = rangecheck(reg[6]); if (regover) break; reg[7] += x; reg[7] = rangecheck(reg[7]); if (regover) break; d = x * y; d = rangecheck(d); if (regover) { reg[5] = d; break; } reg[5] += d; reg[5] = rangecheck(reg[5]); if (regover) break; reg[4] += y; reg[4] = rangecheck(reg[4]); if (regover) break; op(reg[3] += 1.0, 0, 1); entry = 1; break; /* ENTER */ case 31: op(x, 1, 0); entry = 1; break; /* CHS */ case 32: if (entry > 1) { i = entry == 4? 9: 0; ebuf[i] = BLANK + MINUS - ebuf[i]; } else op(-x, 0, 0); break; /* EEX */ case 33: for (i = 0; i < 11 && (ebuf[i]==0 || ebuf[i] > 9); i++); if (i == 11) { for (i = 0; i < 12; ebuf[i++] = BLANK); ebuf[1] = 1; epnt = 1; } if (epnt < 9) { ebuf[9] = BLANK; ebuf[10] = ebuf[11] = 0; entry = 4; } break; /* CLX */ case 34: op(0.0, 0, 0); entry = 1; break; /* - */ case 41: op(y - x, -1, 1); break; /* + */ case 51: op(y + x, -1, 1); break; /* * */ case 61: op(y * x, -1, 1); break; /* / */ case 71: if (x == 0.0) error = true; op(error? 0.0: y / x, -1, 1); break; /* . */ case 73: if (epnt == 0) { ebuf[1] = 0; epnt = 1; } entry = 3; break; /* R/S */ case 74: if (running == 1) { if (step == 0) step = 1; umode = 3; } running = 1; drawled = true; break; default: parserr(); } else if (p1 == 14 && p2 == -1) /* prefix f */ switch (code) { /* to H.MS */ case 0: if (x < 0.0) { x = -x; d = -1.0; } else d = 1.0; if (x >= 100000.0) error = true; op(d * (x * 0.36 + floor(x * 60) * 0.004 + floor(x) * 0.4), 0, 1); break; /* INT */ case 1: op(x < 0.0? -floor(-x): floor(x), 0, 1); break; /* sqrt */ case 2: if (x < 0.0) error = true; op(error? 0.0: sqrt(x), 0, 1); break; /* y^x */ case 3: d = 0.0; /* java wants this initialized */ if (y <= 0.0) error = true; else d = x * log(y); op(error? 0.0: d > 100 * LN10? 1e100: d < -99 * LN10? 1e-99: exp(d), -1, 1); break; /* sin */ case 4: d = x / circle2; d -= floor(d / 2.0) * 2.0; if (d == 0.0) x = 0.0; else if (d == 0.5) x = 1.0; else if (d == 1.0) x = 0.0; else if (d == 1.5) x = -1.0; else x = sin(d * PI); op(x, 0, 1); break; /* cos */ case 5: d = x / circle2; d -= floor(d / 2.0) * 2.0; if (d == 0.0) x = 1.0; else if (d == 0.5) x = 0.0; else if (d == 1.0) x = -1.0; else if (d == 1.5) x = 0.0; else x = cos(d * PI); op(x, 0, 1); break; /* tan */ case 6: d = x / circle2; d -= floor(d / 2.0) * 2.0; if (d == 0.0) x = 0.0; else if (d == 0.5) x = 9.9999999e99; else if (d == 1.0) x = 0.0; else if (d == 1.5) x = -9.9999999e99; else x = tan(d * PI); op(x, 0, 1); break; /* ln */ case 7: if (x <= 0.0) error = true; op(error? 0.0: log(x), 0, 1); break; /* log */ case 8: if (x <= 0.0) error = true; op(error? 0.0: log(x) / LN10, 0, 1); break; /* to rect */ case 9: d = y / circle2; d -= floor(d / 2.0) * 2.0; if (d == 0.0) { y = 0.0; x = x; } else if (d == 0.5) { y = x; x = 0.0; } else if (d == 1.0) { y = 0.0; x = -x; } else if (d == 1.5) { y = -x; x = 0.0; } else { y = sin(d * PI) * x; x = cos(d * PI) * x; } y = rangecheck(y); op(x, 0, 1); break; /* mean */ case 21: if(reg[3] == 0.0) error = true; op(error? 0.0: reg[7] / reg[3], 1, 0); break; /* std dev */ case 22: stopover = false; d = 0.0; if (overflow = reg[3] == 0.0 || reg[3] == 1.0) error = true; if (!overflow) d = rangecheck(reg[7] * reg[7]); if (!overflow) d = rangecheck(d / reg[3]); if (!overflow) d = rangecheck(reg[6] - d); if (!overflow) d = rangecheck(d / (reg[3] - 1.0)); op(overflow? d: sqrt(d < 0.0? -d: d), 1, 0); break; /* sum- */ case 25: regop = true; d = x * x; d = rangecheck(d); if (regover) { reg[6] = -d; break; } reg[6] -= d; reg[6] = rangecheck(reg[6]); if (regover) break; reg[7] -= x; reg[7] = rangecheck(reg[7]); if (regover) break; d = x * y; d = rangecheck(d); if (regover) { reg[5] = -d; break; } reg[5] -= d; reg[5] = rangecheck(reg[5]); if (regover) break; reg[4] -= y; reg[4] = rangecheck(reg[4]); if (regover) break; op(reg[3] -= 1.0, 0, 1); entry = 1; break; /* clr PREFIX*/ case 31: break; /* clr PRGM */ case 32: step = 0; break; /* clr REG */ case 33: for (i = 0; i < 8; reg[i++] = 0.0); break; /* clr STACK */ case 34: x = y = z = t = 0.0; break; /* x < y */ case 41: if (!(compare(x, y) < 0)) step++; break; /* x >= y */ case 51: if (!(compare(x, y) >= 0)) step++; break; /* x != y */ case 61: if (!(compare(x, y) != 0)) step++; break; /* x = y */ case 71: if (!(compare(x, y) == 0)) step++; break; /* LAST x */ case 73: op(l, 1, 0); break; /* PAUSE */ case 74: if (running == 2) { running = 3; drawled = true; } break; default: parserr(); } else if (p1 == 15) /* prefix g */ switch (code) { /* to H */ case 0: if (x < 0.0) { x = -x; d = -1.0; } else d = 1.0; if (x >= 100000.0) error = true; op(d * (x / 0.36 - floor(x * 100) / 90 - floor(x) * 2 / 3), 0, 1); break; /* FRAC */ case 1: op(x < 0.0? -(-x - floor(-x)): x - floor(x), 0, 1); break; /* x^2 */ case 2: op(x * x, 0, 1); break; /* ABS */ case 3: op(x < 0.0? -x: x, 0, 1); break; /* arc sin */ case 4: if (x < -1.0 || x > 1.0) error = true; op(error? 0.0: asin(x) / PI * circle2, 0, 1); break; /* arc cos */ case 5: if (x < -1.0 || x > 1.0) error = true; op(error? 0.0: acos(x) / PI * circle2, 0, 1); break; /* arc tan */ case 6: op(atan(x) / PI * circle2, 0, 1); break; /* e^x */ case 7: op(x > 100 * LN10? 1e100: x < -99 * LN10? 1e-99: exp(x), 0, 1); break; /* 10^x */ case 8: op(x > 100? 1e100: x < -99? 1e-99: exp(x * LN10), 0, 1); break; /* to polar */ case 9: stopover = false; d = sqrt(x * x + y * y); y = atan2(y, x) / PI * circle2; y = rangecheck(y); op(d, 0, 1); break; /* % */ case 21: op(y * x / 100.0, 0, 1); break; /* 1 / x */ case 22: if (x == 0.0) error = true; op(error? 0.0: 1.0 / x, 0, 1); break; /* (nop) */ case 25: break; /* clr PREFIX */case 31: break; /* DEG */ case 32: circle2 = 180.0; break; /* RAD */ case 33: circle2 = PI; break; /* GRD */ case 34: circle2 = 200.0; break; /* x < 0 */ case 41: if (!(compare(x, 0.0) < 0)) step++; break; /* x >= 0 */ case 51: if (!(compare(x, 0.0) >= 0)) step++; break; /* x != 0 */ case 61: if (!(compare(x, 0.0) != 0)) step++; break; /* x = 0 */ case 71: if (!(compare(x, 0.0) == 0)) step++; break; /* pi */ case 73: op(PI, 1, 0); break; /* NOP */ case 74: break; default: parserr(); } else if (p1 == 14) /* prefix f */ format = code + (p2 - 11) * 10; else if (p1 == 13) /* prefix GTO */ step = p2 * 10 + code; else if (p1 == 24) /* prefix RCL */ op(reg[code], 1, 0); else if (p1 == 23) /* prefix STO */ if (p2 == -1) reg[code] = x; else if (p2 == 71 && x == 0.0) error = true; else { switch (p2) { case 41: reg[code] -= x; break; case 51: reg[code] += x; break; case 61: reg[code] *= x; break; case 71: reg[code] /= x; break; default: parserr(); break; } regop = true; reg[code] = rangecheck(reg[code]); } else parserr(); } private void op(double d, int len, int lastflag) { if (len < 0) { y = z; z = t; } if (len > 0) { t = z; z = y; y = x; } if (lastflag != 0) l = x; x = d; x = rangecheck(x); } private int compare(double a, double b) { double d; d = a - b; if (a < 0.0) a = -a; if (b < 0.0) b = -b; if (a < b) a = b; a *= 1e-9; return (d > a? 1: d < -a? -1: 0); } private double rangecheck(double d) { if (d == 0.0) return (d); if (d > 9.9999999e99 || d < -9.9999999e99) { entry = 0; overflow = true; if (regop) regover = true; if (stopover && running > 1) { step--; running = 1; drawled = true; } return (d > 0.0? 9.9999999e99: -9.9999999e99); } if (d > 0.0? d < 1.0e-99: d > -1.0e-99) return (0.0); return (d); } private char buf[] = new char[100]; private int bif[] = new int[20]; private void cvtget() { int i, s; s = 0; if (ebuf[0] == MINUS) buf[s++] = '-'; for (i = 1; ebuf[i] <= 9; i++) { buf[s++] = Character.forDigit(ebuf[i], 10); if (epnt == i) buf[s++] = '.'; } if (epnt >= i) buf[s++] = '.'; if (entry == 4) { buf[s++] = 'E'; if (ebuf[9] == MINUS) buf[s++] = '-'; for (i = 10; i < 12; i++) buf[s++] = Character.forDigit(ebuf[i], 10); } x = Double.valueOf(new String(buf, 0, s)).doubleValue(); } private void cvtput() { int i, j, k, l, f, g; boolean c; String s; char bof[]; for (i = 0; i < 12; i++) dbuf[i] = BLANK; dpnt = -1; if (running == 0) return; if (running == 2) { dbuf[0] = MINUS; for (i = 1; i < 12; dbuf[i++] = 8); return; } if (error) { dbuf[1] = UPPRE; dbuf[4] = LOWRO; dbuf[2] = dbuf[3] = dbuf[5] = LOWRR; return; } if (regover) { dbuf[1] = 0; dbuf[2] = UPPRF; return; } if (prgm && running == 1 && p1 != -1) { if (p1 == 13 && p2 != -1) { dbuf[8] = 1; dbuf[9] = 3; dbuf[11] = p2; return; } if (p2 == -1) { dbuf[10] = p1 / 10; dbuf[11] = p1 % 10; return; } dbuf[7] = p1 / 10; dbuf[8] = p1 % 10; dbuf[10] = p2 / 10; dbuf[11] = p2 % 10; return; } if (prgm && running == 1 || umode != 0) { dbuf[0] = step / 10; dbuf[1] = step % 10; if (step == 0) return; if ((i = prog[step][0]) == 13) { dbuf[7] = 1; dbuf[8] = 3; dbuf[10] = prog[step][1]; dbuf[11] = prog[step][2]; return; } if (i != -1) { dbuf[4] = i / 10; dbuf[5] = i % 10; } i = prog[step][1]; if (i != -1) { dbuf[7] = i / 10; dbuf[8] = i % 10; } i = prog[step][2]; dbuf[10] = i / 10; dbuf[11] = i % 10; return; } if (entry > 1) { for (i = 0; i < 12; i++) dbuf[i] = ebuf[i]; dpnt = epnt; return; } dbuf[0] = x < 0.0? MINUS: BLANK; for (i = 1; i < 12; i++) dbuf[i] = BLANK; s = sprintf(x == 0.0? 0.0: (x < 0.0? -x: x) * 1.000000000000001); bof = s.toCharArray(); bof[1] = bof[0]; bif[0] = 0; for (i = 1; bof[i] >= '0' && bof[i] <= '9'; i++) bif[i] = Character.digit(bof[i], 10); j = 0; if (bof[i] == 'E' || bof[i] == 'e') j = Integer.valueOf(s.substring( bof[i + 1] == '+'? i + 2: i + 1)).intValue(); while (i < 12) bif[i++] = 0; f = format / 10; g = format % 10; k = l = 0; /* java wants these initialized */ if (f == 0) { l = j + g + 2; if (l > 11) { g -= l - 11; l = 11; } k = l; if (l > 0 && bif[l] >= 5) while (bif[--k] == 9); if (k == 0 && l > 11) { g -= 1; l -= 1; } if (k > 1) k = 1; if (l - k <= 0 || l - k > 10 || g < 0) { f = 1; g = 7; } else { if (k > j + 1) k = j + 1; dpnt = j + 2 - k <= 0? 1: j + 2 - k; } } if (f != 0) { l = g + 2; if (f == 2) l += 2; if (l > 11) l = 11; k = l; if (bif[l] >= 5) while (bif[--k] == 9); if (k > 1) k = 1; if (k == 0) if (j == 99) { f = 1; k = 1; l = 9; } else { j++; l--; } dpnt = 1; if (f == 2) { j += 99; dpnt = 1 + j % 3; j = j / 3 * 3 - 99; } } for (i = 1 + l - k, c = bif[l--] >= 5; --i != 0; --l) if (c) if (c = bif[l] == 9) dbuf[i] = 0; else dbuf[i] = bif[l] + 1; else dbuf[i] = l < 0? 0: bif[l]; if (minus) dbuf[0] = MINUS; if (f == 0) return; dbuf[9] = j < 0? MINUS: BLANK; if (j < 0) j = -j; dbuf[10] = j / 10; dbuf[11] = j % 10; } /* A printf, a printf, my kingdom for a printf! */ private String sprintf(double d) { double ptens[] = { 1e1,1e2,1e4,1e8,1e16,1e32,1e64,1e128,1e256 }; double ntens[] = { 1e-1,1e-2,1e-4,1e-8,1e-16,1e-32,1e-64,1e-128,1e-256}; int i, j, k; double e; boolean over, under; j = 0; if (d < 1.0) { for (k = 8; k >= 0; k--) if (d < ntens[k]) { d /= ntens[k]; j -= 1 << k; } d *= 10.0; j--; } else for (k = 8; k >= 0; k--) if (d > ptens[k]) { d /= ptens[k]; j += 1 << k; } over = false; under = false; for (i = 1; i < 13; i++) { e = Math.floor(d); d -= e; d *= 10.0; k = new Double(e).intValue(); if (over = k >= 10) break; if (under = k < 0) break; buf[i] = Character.forDigit(k, 10); } if (over) while (i < 13) buf[i++] = '9'; if (under) while (i < 13) buf[i++] = '0'; for (k = 1; k < i; k++) if (buf[k] != '0') break; if (k == i) j = 0; buf[0] = buf[1]; buf[1] = '.'; buf[i++] = 'e'; if (j < 0) { buf[i++] = '-'; j = -j; } if (j >= 100) { buf[i++] = Character.forDigit(j / 100, 10); j %= 100; } if (j >= 10) { buf[i++] = Character.forDigit(j / 10, 10); j %= 10; } buf[i++] = Character.forDigit(j, 10); return (new String(buf, 0, i)); } private int remap[] = { 27,23,24,25,19,20,21,15,16,17,-1,0,1,2,3,4,-1,-1,-1,-1, -1,5,6,7,8,9,-1,-1,-1,-1,-1,10,11,12,13,-1,-1,-1,-1,-1, -1,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,18,-1,-1,-1,-1,-1,-1,-1,-1, -1,22,-1,-1,-1,-1,-1,-1,-1,-1,-1,26,-1,28,29,-1,-1,-1,-1,-1 }; private String func[] = { "SST","BST","GTO","f","g","x<>y","roll dn","STO", "RCL","sum+","ENTER","CHS","EEX","CLx","-","7","8","9", "+","4","5","6","x","1","2","3","/","0","point","R/S" }; private String funcf[] = { "FIX","SCI","ENG","f","g","mean x","std dev","STO", "RCL","sum-","clr PREFIX","clr PRGM","clr REG","clr STK", "x < y","ln","log","->R","x >= y","sin","cos","tan","x != y ","INT", "sqrt","y^x","x = y","->H.MS","LAST x","PAUSE" }; private String funcg[] = { "","","","f","g","%","1/x","STO","RCL","(NOP)", "(clr PREFIX)","DEG","RAD","GRD","x < 0","e^x","10^x","->P","x >= 0", "arc sin","arc cos","arc tan","x != 0","FRAC","x^2","ABS","x = 0", "->H","pi","NOP" }; private String hint(int p1, int p2, int code) { int i, i1, i2; i = code == -1? -1: remap[code]; i1 = p1 == -1? -1: remap[p1]; i2 = p2 == -1? -1: remap[p2]; if (code == 14 || code == 15 || code == 23 || code == 24 || code == 13 && (p1 != 14 || p2 != -1)) /* first prefix */ return (func[i]); if (p2 == -1 && (p1 == 14 && code >= 11 && code <= 13 || p1 == 23 && code >= 41 && code <= 71 || p1 == 13 && code <= 4)) /* second prefix */ return (func[i1]+" "+ (p1 == 14? funcf[i]: func[i])); if (p1 == 15 && code >= 10 && code <= 15 || p1 >= 23 && code > 7 || p2 != -1 && code >= 10 || p1 == 13 && (p2 == -1 || code >= 10)) /* abort prefix */ return (func[i]); if (p1 == -1) return (func[i]); if (p1 == 13) return (func[i1]+" "+func[i2]+func[i]); if (p1 == 15) return (func[i1]+" "+funcg[i]); if (p1 == 14 && p2 == -1) return (func[i1]+" "+funcf[i]); if (p1 == 14) return (func[i1]+" "+funcf[i2]+" "+func[i]); if (p1 != 23 || p2 == -1) return (func[i1]+" "+func[i]); return (func[i1]+" "+func[i2]+" "+func[i]); } private double sqrt(double d) { return (Math.sqrt(d)); } private double atan2(double a, double b) { return (Math.atan2(a, b)); } private double sin(double d) { return (Math.sin(d)); } private double cos(double d) { return (Math.cos(d)); } private double tan(double d) { return (Math.tan(d)); } private double asin(double d) { return (Math.asin(d)); } private double acos(double d) { return (Math.acos(d)); } private double atan(double d) { return (Math.atan(d)); } private double log(double d) { return (Math.log(d)); } private double exp(double d) { return (Math.exp(d)); } private double floor(double d) { return (Math.floor(d)); } } /* end of class */