/*
JujuCalc
Copyright ©2001-2005 etc
Mark Pursey
A wacky JujuScript
application
Note that because the eval function
is used,
(see function Eval()
below)
this is more powerful than it
looks...
eg you could type "5! *
sin(pi/3)"
*/
var apptext = "jujucalc 1.0";
// globals
dialog win; // the calculator window
object state; // this will hold variables created
within the eval loop
if (true)
{
var rc =
rect(0,0,200,240);
with win
{
: "color 0.5 0.5
1";
: "size %d %d"
<< [rc.Width(), rc.Height()];
: "set text "
+ apptext;
: "new button close
set text X";
: "item close set
pos %g %g %g %g" << rc.([hi.x -
20,
lo.y+4, 15,15]);
}
// title bar
rc.lo.y += 20;
// allow margins
rc.Expand(-4);
var rc2 =
rect(0, 0, 1, 0.32);
with win
{
: "new text
lcd";
: "item lcd set pos
%g %g %g %g" << (rc*rc2).(Expand(-1),[lo.x, lo.y, Width(), Height()]);
}
//rc.lo.y = 100;
var rowSet =
[
[7,8,9,"+","ac"],
[4,5,6,"-","ms"],
[1,2,3,"*","m+"],
[0, ".", "=", "/","mr"]
];
for (var r = 0; r <
rowSet.Length();
r++)
{
var &row = rowSet[r];
for (var c = 0; c <
row.Length();
c++)
{
with rc2
{
lo = point(c, r+2);
hi = lo + point(1,1);
}
with rc2
with (lo, hi) x /= 5, y /= 6;
string id =
row[c];
string txt =
id.Upper();// == "*" ? "x" : id;
//rc2 = rect(0,0,1,1);
with win
{
: "new button %s set
text %s" << [id,txt];
: "item %s set pos %g
%g %g %g" << (rc*rc2).(Expand(-1),[id, lo.x, lo.y, Width(), Height()]);
}
}
}
}
// find the display
("lcd")
control textControl = win.Find("lcd");
with textControl
{
if (IsEmpty())
throw "ERROR: failed to find display!";
: "set font size
40";
//Command("set para align
0.5");
// allow display to change size to
fit
: "set shrink
0.35";
//Command("set font bold 1");
if (commandline.Length() > 0)
SetText(commandline);
else
SetText("");
}
string g_memory = textControl.GetText(); // remembers thingy
// display the
calculator
win.Start();
// focus on the display, so key
presses will go there
textControl.SetFocus();
// a counter for messages, for
interest's sake
if (true)
{
int i =
0;
while (win.Wait() !=
0) // while there is a useful message
here
{
string mess =
win.Message().Lower();
if (mess >> "cancel")
// ESC
{
if (textControl.GetText() == "")
win.Close();
else
textControl.SetText("");
}
else if (mess >> "ok")
Eval(textControl);
else if (mess >> "click")
{
if (mess >> "ac")
textControl.SetText("");
else if
(mess >> "close")
win.Close();
else if
(mess >> "=")
Eval(textControl);
else if
(mess >> "link") // the hyperlink
{
win: "color "
+ Math.random() + " " +
Math.random() + " " +
Math.random();
}
else if
(mess >> "mr")
textControl.SetText(System.ReadClipboard());
else if
(mess >> "m+")
{
Eval(textControl);
System.WriteClipboard(eval(System.ReadClipboard()
+ "+" + textControl.GetText()));
}
else if
(mess >> "ms")
{
if (textControl.GetText().Length() > 0) // only save if not
nothing!
System.WriteClipboard(textControl.GetText());
}
else if
(mess.Length() == 1)
{
if ("-+/*".Find(mess,0) >= 0)
Eval(textControl);
textControl: "paste "
+ mess; //
SetText(textControl.GetText()+mess);
}
}
i++;
textControl.SetFocus(); // refocus on display
}
}
var a_ret = textControl.GetText();
// end modal dialog
win.End();
// return number of messages
received, just for fun
return a_ret;
/*
Following are functions used by the
main body above
*/
// eval contents of the control and
the put result back
function Eval(control &textControl)
{
// now execute the eval within
state's context, for access to variables
with
state
{
var a_res =
eval(textControl.GetText().Lower());
string a_str =
dump(a_res);
if (a_res is
string)
{
if (a_res[0] == '#')
{
//a_str = "ERROR";
a_str = a_res;
a_str = "ERROR:\n"
+ a_str.Mid(2);
//a_str += "\nPress AC to
clear";
}
}
else if (a_res is
void)
{
a_str = "";
}
textControl.SetText(a_str);
}
}
// add a factorial function (eg 5! =
120)
function operator!postfix(int a)
{
for (real a_ret =
1; a
> 1;
)
{
a_ret *= a;
a--;
}
return
a_ret;
}
// force ints to real precision for
muliplies and divides
function operator/(int a, int b) { return
(real)a / (real)b; }
function operator*(int a, int b) { return
(real)a * (real)b; }
// add some math functions for
convenience [no namespace support yet]
function sin(a) { return Math.sin(a); }
function cos(a) { return Math.cos(a); }
function tan(a) { return Math.tan(a); }
function log(a,b) { return Math.log(a,b); }
function ln(a) { return Math.ln(a); }
function sqrt(a) { return Math.sqrt(a); }
// polynomial solver [real roots
only]
function operator!(array a)
{
real v[];
for (var e in a)
v += e;
return Math.Solve(v);
}
// constants
static real pi = Math.PI;
// miscellaneous
function quad(a,b,c)
{
var det =
b*b - 4*a*c;
if (det < 0) // no roots
return []; //void;
array
root;
root[0] = (-b - sqrt(det)) / (2*a);
root[1] = (-b + sqrt(det)) / (2*a);
return
root;
}