'app-plug-in 'menu Calculator ' ' $Id: calc.bas,v 1.5 2005-05-11 23:30:14 zeeb90au Exp $ ' calc.bas Copyright (c) Chris Warren-Smith April 2005 ' Demonstration for html user interfaces ' ' Version 2.0 ' ' This program is distributed under the terms of the GPL v2.0 or later ' Download the GNU Public License (GPL) from www.gnu.org ' ' option predef grmode 390X290 out_x = 0 out_y = 0 func compute(byref operator, lval, rval) local result = 0 if (operator = "+") then result = lval + rval elseif (operator = "-") then result = lval - rval elseif (operator = "/") then if (rval == 0) then rval = 1 fi result = lval / rval elseif (operator = "*") then result = lval * rval elseif (lval > 0) then result = lval else result = rval fi compute = result end ' evaluate the expression string func eval(byref expr) local strl,num,pt,result,operator,inner,endb,i,j,nbracket strl = len(expr) num = 0 pt = 0 result = 0 operator = "" for i = 0 to strl if (i < strl) ch = mid(expr, i+1, 1) else ' end of last operand eval = compute(operator, result, num) exit func fi if ch = "." then pt = 1 elseif isnumber(ch) then if pt > 0 then num = num + (ch/(10^pt)) pt++ else num = num*10+ch fi else ' non number if ch = "(" then ' find the matching ) if (len(operator) = 0) then ' short form notation eg 3(1+1) operator = "*" if (result = 0) then result = num else result = compute(operator, result, num) fi else ' complete the previous expression result = compute(operator, result, num) fi nbracket = 1 endb = 0 i++ for j = i to strl-1 ch = mid(expr, j+1, 1) if ch = "(" then nbracket++ elseif ch = ")" then nbracket-- if nbracket = 0 then endb = j exit for fi fi next j if (endb = 0) then eval = "ERR" exit func endif inner = mid(expr, i+1, endb-i) if len(operator) = 0 then result = eval(inner) else num = eval(inner) result = compute(operator, result, num) fi i = endb if (i+1 = strl) then ' nothing more to process eval = result exit func fi ' scan for next operator operator = "" elseif ch = ")" then eval = result exit func else ' operator character if (len(operator) = 0) then ' first operand result = num else ' resolve the current expression result = compute(operator, result, num) endif operator = ch fi ' scan for next number num = 0 pt = 0 fi next i eval = result end sub mk_bn(byref f, fgc, bgc, x, y, w, h, caption) local button button.x = x button.y = y button.width = w button.height = h button.label = caption button.color = fgc button.backgroundColor = bgc button.noFocus = true f.inputs << button end func createForm local w = 60 local h = 60 local y = 40 local x = 10 local fcb = 3 local ncb = 4 local ocb = 5 local fcf = 1 local ncf = 15 local ocf = 7 out_x = x + 3 out_y = 5 mk_bn(f, fcf, fcb, x, y, w, h, "MC") mk_bn(f, ncf, ncb, -1, y, w, h, "7") mk_bn(f, ncf, ncb, -1, y, w, h, "8") mk_bn(f, ncf, ncb, -1, y, w, h, "9") mk_bn(f, ocf, ocb, -1, y, w, h, "+") mk_bn(f, ocf, ocb, -1, y, w, h, "-") y += h mk_bn(f, fcf, fcb, x, y, w, h, "MR") mk_bn(f, ncf, ncb, -1, y, w, h, "4") mk_bn(f, ncf, ncb, -1, y, w, h, "5") mk_bn(f, ncf, ncb, -1, y, w, h, "6") mk_bn(f, ocf, ocb, -1, y, w, h, "*") mk_bn(f, ocf, ocb, -1, y, w, h, "/") y += h mk_bn(f, fcf, fcb, x, y, w, h, "MS") mk_bn(f, ncf, ncb, -1, y, w, h, "1") mk_bn(f, ncf, ncb, -1, y, w, h, "2") mk_bn(f, ncf, ncb, -1, y, w, h, "3") mk_bn(f, ocf, ocb, -1, y, w, h, "(") mk_bn(f, ocf, ocb, -1, y, w, h, ")") y += h mk_bn(f, fcf, fcb, x, y, w, h, "EXIT") mk_bn(f, ncf, ncb, -1, y, w, h, "0") mk_bn(f, ncf, ncb, -1, y, w, h, ".") mk_bn(f, fcf, fcb, -1, y, w, h, "BS") mk_bn(f, fcf, fcb, -1, y, w, h, "CE") mk_bn(f, ocf, ocb, -1, y, w, h, "=") f = form(f) createForm = f end sub showResult(result) local bgnd = 3 local w = 362 local h = 30 rect out_x, out_y STEP w, h, COLOR bgnd FILLED rect out_x - 1, out_y - 1 STEP w + 1, h + 1, COLOR 2 local out_str = result local out_str_w = textwidth(result) local x = (out_x + w) - out_str_w - textwidth("0") if (x < out_x) then x = out_x out_str = " ERR" fi color 15, bgnd at x, out_y + 7 print cat(1) + out_str end sub main local result = "0" local mem = "" rect 0, 0, xmax, ymax, 1 FILLED f = createForm showResult result while 1 f.doEvents() k = inkey form_var = f.value if (len(k) == 1) then if (asc(k) == 8) then form_var = "BS" else if (asc(k) == 127) then form_var = "CE" else form_var = k fi fi select case form_var case "CE" ' clear all result = "0" case "BS" ' back space if len(result) > 1 then result = left(result, len(result)-1) else result = "0" fi case "MC" mem = "" case "MR" if (mem != "") then result = mem fi case "MS" mem = result case "EXIT" exit loop case "." if len(result) > 0 && right(result, 1) != "." then result += "." fi case "=" if (instr(result, "=") == 0) then result = result + form_var + eval(result) fi case else ' expression input if (result = "0") then result = "" fi if (instr(result, "=") > 0) then result = "" fi result = result + form_var end select showResult result wend end main