#include <errno.h>
#include <fastgl/fastgl.h>
#include <fastgl/widgets.h>
#define SIN 1
#define COS 2
#define TAN 3
#define ASIN 4
#define ACOS 5
#define ATAN 6
#define SQRT 7
#define NEG 8
#define ADD 1
#define SUB 2
#define MUL 3
#define DIV 4
#define CALC_STR 3
#define MAXNUM 18
char calc_str[80] = "0";
fgl::FGPixel col1, col2;
double calc_value;
int calc_operation;
int calc_clear_flag;
fgl::FGWindow *wndPtr;
void reset_calc()
{
calc_value = 0;
errno = 0;
calc_operation = 0;
calc_clear_flag = FALSE;
}
double get_calc_value()
{
return atof(calc_str);
}
void redraw()
{
wndPtr->WindowBox(16, 24, 320, 64, fgl::CBLACK);
wndPtr->WindowRect(16, 24, 320, 64, fgl::CYELLOW);
wndPtr->WindowText(320 - strlen(calc_str) * 16, 48, calc_str, fgl::CWHITED, fgl::CBLACK);
}
void right_text_proc(int key)
{
redraw();
}
void input_proc(int c)
{
int c1, c2;
char s[2];
*s = c;
s[1] = 0;
if ((calc_clear_flag) && (s[0] != '+'))
strcpy(calc_str, "0");
else if (strncmp(calc_str, "-E-", 3) == 0)
{
redraw();
}
calc_clear_flag = FALSE;
if (s[0] == '.')
{
for (c1 = 0; calc_str[c1]; c1++)
if (calc_str[c1] == '.')
break;
if (!calc_str[c1])
strcat(calc_str, ".");
}
else if (s[0] == '+')
{
if (calc_str[0] == '-')
memmove(calc_str, calc_str + 1, strlen(calc_str + 1) + 1);
else
{
memmove(calc_str + 1, calc_str, strlen(calc_str) + 1);
calc_str[0] = '-';
}
}
else
{
if (strcmp(calc_str, "0") == 0)
calc_str[0] = 0;
else if (strcmp(calc_str, "-0") == 0)
strcpy(calc_str, "-");
c2 = 0;
for (c1 = 0; calc_str[c1]; c1++)
if ((calc_str[c1] >= '0') && (calc_str[c1] <= '9'))
c2++;
if (c2 < MAXNUM)
strcat(calc_str, s);
}
redraw();
}
void set_calc_value(double d)
{
int c, l;
int has_dot;
char b[80], *p;
errno = 0;
sprintf(b, "%1.f", d);
if (strlen(b)>=MAXNUM) fgl::IError("Out of display!", 0);
b[18]=0;
if (errno)
sprintf(calc_str, "-E- (%.12s)", b);
else
strcpy(calc_str, b);
errno = 0;
}
void unary_operator(int op)
{
double x = get_calc_value();
switch (op)
{
case SIN:
x = sin(x);
break;
case COS:
x = cos(x);
break;
case TAN:
x = tan(x);
break;
case ASIN:
x = asin(x);
break;
case ACOS:
x = acos(x);
break;
case ATAN:
x = atan(x);
break;
case SQRT:
x = sqrt(x);
break;
case NEG:
x = -x;
break;
}
set_calc_value(x);
calc_clear_flag = TRUE;
redraw();
}
void work_out()
{
double x = get_calc_value();
switch (calc_operation)
{
case ADD:
x = calc_value + x;
break;
case SUB:
x = calc_value - x;
break;
case MUL:
x = calc_value * x;
break;
case DIV:
x = calc_value / x;
break;
}
set_calc_value(x);
reset_calc();
calc_clear_flag = TRUE;
redraw();
}
void equals_proc()
{
work_out();
redraw();
}
void binary_operator(int op)
{
work_out();
calc_value = get_calc_value();
calc_operation = op;
calc_clear_flag = TRUE;
redraw();
}
void clearer()
{
reset_calc();
strcpy(calc_str, "0");
redraw();
}
void clear_proc()
{
clearer();
redraw();
}
static void Sin(fgl::CallBack)
{
unary_operator(SIN);
}
static void Asin(fgl::CallBack)
{
unary_operator(ASIN);
}
static void Cos(fgl::CallBack)
{
unary_operator(COS);
}
static void Acos(fgl::CallBack)
{
unary_operator(ACOS);
}
static void Tan(fgl::CallBack)
{
unary_operator(TAN);
}
static void Atan(fgl::CallBack)
{
unary_operator(ATAN);
}
static void k1(fgl::CallBack)
{
input_proc('1');
}
static void k4(fgl::CallBack)
{
input_proc('4');
}
static void k7(fgl::CallBack)
{
input_proc('7');
}
static void k2(fgl::CallBack)
{
input_proc('2');
}
static void k5(fgl::CallBack)
{
input_proc('5');
}
static void k8(fgl::CallBack)
{
input_proc('8');
}
static void k3(fgl::CallBack)
{
input_proc('3');
}
static void k6(fgl::CallBack)
{
input_proc('6');
}
static void k9(fgl::CallBack)
{
input_proc('9');
}
static void Div(fgl::CallBack)
{
binary_operator(DIV);
}
static void Mul(fgl::CallBack)
{
binary_operator(MUL);
}
static void Minus(fgl::CallBack)
{
binary_operator(SUB);
}
static void k0(fgl::CallBack)
{
input_proc('0');
}
static void Dot(fgl::CallBack)
{
input_proc('.');
}
static void Sign(fgl::CallBack)
{
unary_operator(NEG);
}
static void Plus(fgl::CallBack)
{
binary_operator(ADD);
}
static void Assume(fgl::CallBack)
{
equals_proc();
}
static void C(fgl::CallBack)
{
clear_proc();
}
static void Off(fgl::CallBack)
{
fgl::App::AppDone();
}
static void Sqrt(fgl::CallBack)
{
unary_operator(SQRT);
}
static void wndProc(fgl::FGEvent * p)
{
switch (p->GetType())
{
case fgl::INITEVENT:
p->wnd->set_font(fgl::FONT1625);
p->wnd->AddPushButton(24, 112, 96, 28, "SIN", 0, Sin);
p->wnd->AddPushButton(24, 152, 96, 28, "ASIN", 0, Asin);
p->wnd->AddPushButton(128, 112, 96, 28, "COS", 0, Cos);
p->wnd->AddPushButton(128, 152, 96, 28, "ACOS", 0, Acos);
p->wnd->AddPushButton(232, 112, 96, 28, "TAN", 0, Tan);
p->wnd->AddPushButton(232, 152, 96, 28, "ATAN", 0, Atan);
p->wnd->AddPushButton(8, 200, 64, 23, "1", '1', k1);
p->wnd->AddPushButton(8, 228, 64, 23, "4", '4', k4);
p->wnd->AddPushButton(8, 256, 64, 23, "7", '7', k7);
p->wnd->AddPushButton(76, 200, 64, 23, "2", '2', k2);
p->wnd->AddPushButton(76, 228, 64, 23, "5", '5', k5);
p->wnd->AddPushButton(76, 256, 64, 23, "8", '8', k8);
p->wnd->AddPushButton(144, 200, 64, 23, "3", '3', k3);
p->wnd->AddPushButton(144, 228, 64, 23, "6", '6', k6);
p->wnd->AddPushButton(144, 256, 64, 23, "9", '9', k9);
p->wnd->AddPushButton(212, 200, 64, 23, "/", '/', Div);
p->wnd->AddPushButton(212, 228, 64, 23, "*", '*', Mul);
p->wnd->AddPushButton(212, 256, 64, 23, "-", '-', Minus);
p->wnd->AddPushButton(8, 284, 64, 23, "0", '0', k0);
p->wnd->AddPushButton(76, 284, 64, 23, ".", '.', Dot);
p->wnd->AddPushButton(144, 284, 64, 23, "- / +", ' ', Sign);
p->wnd->AddPushButton(212, 284, 64, 23, "+", '+', Plus);
p->wnd->AddPushButton(280, 284, 64, 23, "=", '=', Assume);
p->wnd->AddPushButton(280, 200, 64, 23, "C", 'c', C);
p->wnd->AddPushButton(280, 228, 64, 23, "OFF", 27, Off);
p->wnd->AddPushButton(280, 256, 64, 23, "SQRT", 's', Sqrt);
clear_proc();
break;
case fgl::KEYEVENT:
if (p->GetKey() == BACKSP)
clearer();
break;
}
}
int main(int argc, char **argv)
{
fgl::FGApp MyApp(fgl::G640x480, argc, argv, fgl::CBLACK, fgl::APP_ENABLEALTX);
col1 = fgl::CreateColor(50<<2, 21<<2, 3<<2, -1);
col2 = fgl::CreateColor(31<<2, 12<<2, 5<<2, -1);
fgl::CScheme->button_back = col2;
fgl::CScheme->button_fore = fgl::CWHITED;
wndPtr = new fgl::Window(&wndPtr, 288, 360, 360, 324, "wnd", wndProc, fgl::CBLACK, col1, fgl::WFRAMED | fgl::WNOPICTO | fgl::WCLICKABLE | fgl::WCENTRED | fgl::WESCAPE);
errno = 0;
MyApp.Run();
if (wndPtr)
delete wndPtr;
return 0;
}