//*
*****************************************************************
//*
*
//Currency
Spreadv2.0a For MS Visual C++ 6.0 *
//********************************************************************/
// By Salim
Meghani.BSc(Hons) (c) 2006
// User
documentation: Use = for formulas, $ for text
// Cursor keys or
scroll bars to move to cells.
// Enter numbers
(accuracy to 2 dp only).
// Cell
references are entered using lowercase column
// and a numeric
row value.
// Scientific
notation isn't supported.
/*
Attention : This
version is on test with a Reverse Polish Parser
By Salim Meghani.
*/
// All debug
assertion failures have been disabled.
// A note about
calculations.
// The way I
carry out formulae calculations are as follows:
// 1. First I
breakdown a formula to its equivalent numeric formula (string).
// 2. Then, I
pass the numeric formula to the reverse polish parser to
// evaluate it.
// An example.
// 1. Suppose
a1=1, a2,=2, b1=a1+a2, c1=b1*2.
// Then when
evaluating cells, the formula : b1=1+2
// c1=(1+2)*2
// is the
breakdown in numerical form of the expression in c1.
// NB: How when I
evaluate a formula within a formula, I insert brackets (you don't have to).
// recursive
formulae will make the application crash!
// Numerics must
also be bracketed, because --1 is an error and -(-1) is legal.
// So, --a1 with
a negative in a1 won't work without adequate bracketing, i.e. -(-a1).
// Division by
zero, crashes application.
// Mismatched
brackets makes application crash.
// A note about
the Reverse Polish Parser.
//
// It is on test
and may not function properly.
// The evaluation
of a formula is dependant on size of certain arrays:
// These are:
/*
char
texas[65536]; This is the texas line stack.
char
calif[65536]; This is the California string
char* newyk=NULL;
This is the New York line.
char stak[65536];
char star[65536];
char previous;
char number[50];
char bop;
double num[10000];
*/
//
#define
_CRT_SECURE_NO_DEPRECATE 1
#include
"stdafx.h"
#include
"resource.h"
#include
<malloc.h>
#include
<string.h>
#include
<math.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<ctype.h>
#include
<crtdbg.h>
//
#define MAX_LOADSTRING
100
#define ID_EDIT 1
#define DELIMETER
1
#define VARIABLE
2
#define NUMBER 3
// Declare Global
Variables:
WNDPROC
wpOrigEditProc;
HINSTANCE hInst;
// current instance
TCHAR
szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];
// The title bar text
static char
szInputStr[2048];
static char
szOutputStr[2048];
static char
szBuffer[2048];
static char
szName[256];
int input=0,
fcol=0,
frow=0,
scol=0,
srow=0,
ecol=0,
erow=0,
dcol=0,
drow=0,
column=1,
row=1,
fitem=0,
cval=0,
rval=0,
hredraw=1,
vredraw=1,
credraw=1,
dscroll=0,
scroll=0,
stxpos=1,
endxpos=8,
stypos=1,
endypos=24,
ctxpos=1,
ctypos=1,
curxpos=1,
curypos=1,
olrxpos=1,
olrypos=1,
cvalx=0,
cvaly=0,
c_input=0,
istat=0,
istat2=0,
fcat=1,left=0,right=0,up=0,down=0,
setcursor=0,
scrolled=0,
newscroll=0,
preced=1,
errflag=0;
char switc; //
This is the switch
char
texas[65536]; // This is the texas line's stack.
char
calif[65536]; // This is the California string
char* newyk=NULL;
// This is the New York line.
char star[65536];
// Used to hold a number.
char previous; //
The previous operator
char bop;
double
num[10000];
char frop;
double answer=0;
double ans=0;
double right1=0;
double left1=0;
double no=0;
char rgt;
char lft;
char blop;
char check;
char op;
char rop;
char lop;
int x=0;
int s=0;
int c=0;
int n=0;
int g=0;
int notrue=0;
int str=0;
int start=0;
int end=0;
int bracket=0;
int length=0;
double sol=0;
char* form3=NULL;
char* form2=NULL;
int error=0;
//
static short
cxChar,cyChar,cxClient,cyClient, NUMLINES,NUMCHARS,NUMD,NUMCOLS,MAXROW;
// Define array
pointers for numbers and strings and formulae.
// For example a
cell is a pointer of type pointer of char.
// If you have an
address for cell, and it belongs to an address of type char,
// then it is a
two dimensional structure and can be traversed by setting the
// cells address
in scell, the same goes for type and stype, numeruc and stype .
char* *cell;
char* *scell;
char *type;
char *stype;
double* *numeric;
double*
*snumeric;
GLOBALHANDLE
hGlobalMemory, hGlobalMemory2, hGlobalMemory3;
double value;
char fch=0;
char sch=0;
static short
nVscrollPos=1,
nHscrollPos=1;
HWND hwndEdit;
// Foward
declarations of functions included in this code module:
//int
find_optr(int start, char *form);
void clr_str(char
*source);
void
current_column(char *fch, char *sch, int column);
//void
find_brkt(int *error, char *form, int *start, int *end, int *brcket, int
*length);
void cleanup(char
*output, char *input);
//void
eval_brkt(int *error, char *form, int start, int end, int bracket, int length);
//double
eval_form(int *error, char *form);
double expr_p(int
*error,char *form);
int
isbracket(char c);
int isstop(char
c);
int
isoperator(char c);
int moreops(char
*c);
void parser(int
*error, char *source, char *dest);
void
evaluate_cell(int column, int row, char type, char *szBuffer);
void
pushtexas(char switcd); // Pushes a character onto the stack.
void poptexas(int
st1); // Pops a character off the stack.
void fpdel(void);
// Deletes both a char from the stack and switch.
void
putcalif(char switcd); // Puts a character on the California line.
void fperror(int
*error); // If there is an unbalanced expression,
void
pushstk(double num);
double
popstk(void);
void
find_brkt(int *error, char *form, int *start, int *end, int *bracket, int
*length);
void
eval_brkt(int *error, char *form, int start, int end, int bracket, int length);
void clr_str(char
*source);
double
eval_form(int *error, char *form);
double
eval_parser(char* newyk, int *error);
void
clear_vars(void);
ATOM
MyRegisterClass(HINSTANCE hInstance);
BOOL
InitInstance(HINSTANCE, int);
LRESULT CALLBACK
EditSubclassProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK
WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK
About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK
Input(HWND, UINT, WPARAM, LPARAM);
//
int APIENTRY
WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
_CrtSetReportMode(_CRT_ASSERT,0);
//
form2=(char *) calloc((unsigned long)
65535, sizeof(char));
// TODO: Place
code here.
MSG msg;
HACCEL hAccelTable;
// Initialize
global strings
LoadString(hInstance, IDS_APP_TITLE,
szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_SALIMHELLO,
szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform
application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance,
(LPCTSTR)IDC_SALIMHELLO);
// Main message
loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd,
hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//
//
// FUNCTION:
MyRegisterClass()
//
// PURPOSE:
Registers the window class.
//
// COMMENTS:
//
// This function
and its usage is only necessary if you want this code
// to be
compatible with Win32 systems prior to the 'RegisterClassEx'
// function that
was added to Windows 95. It is important to call this function
// so that the
application will get 'well formed' small icons associated
// with it.
//
ATOM
MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance,
(LPCTSTR)IDI_SALIMHELLO);
wcex.hCursor = LoadCursor(NULL,
IDC_ARROW);
wcex.hbrBackground = (HBRUSH)
GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName =
(LPCSTR)IDC_SALIMHELLO;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance,
(LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION:
InitInstance(HANDLE, int)
//
// PURPOSE: Saves
instance handle and creates main window
//
// COMMENTS:
//
// In this
function, we save the instance handle in a global variable and
// create and
display the main program window.
//
BOOL
InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance
handle in our global variable
hWnd = CreateWindow(szWindowClass,
szTitle, WS_OVERLAPPEDWINDOW | WM_VSCROLL| WM_HSCROLL,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION:
WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE:
Processes messages for the main window.
//
// WM_COMMAND -
process the application menu
// WM_PAINT -
Paint the main window
// WM_DESTROY -
post a quit message and return
//
//
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
HDC hdc;
PAINTSTRUCT ps;
RECT lprect;
static HWND hwndButtonP;
static HWND hwndButtonX;
short i,a;
short scrlval;
//
TEXTMETRIC tm;
unsigned long pvalue=0;
static HWND hwndEdit;
//
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst,
(LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case 0:
if
(wmEvent==BN_CLICKED)
{
SetFocus(hWnd);
preced=1;
InvalidateRect(hWnd,
NULL, FALSE);
}
break;
case 1:
if
(wmEvent==BN_CLICKED)
{
SetFocus(hWnd);
preced=0;
InvalidateRect(hWnd,
NULL, FALSE);
}
break;
default:
return
DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
hGlobalMemory=GlobalAlloc(0,
0x9F64L);
hGlobalMemory2=GlobalAlloc(0,
0x9F64L);
hGlobalMemory3=GlobalAlloc(0,
0x9F64L);
cell=(char* *)GlobalLock
(hGlobalMemory);
scell=cell;
numeric=(double*
*)GlobalLock(hGlobalMemory2);
snumeric=numeric;
type=(char
*)GlobalLock(hGlobalMemory3);
stype=type;
SetScrollRange(hWnd,
SB_VERT, 1,100,FALSE);
SetScrollPos(hWnd,SB_VERT,
nVscrollPos,TRUE);
SetScrollRange(hWnd,
SB_HORZ, 1,100,FALSE);
SetScrollPos(hWnd,SB_HORZ,
nHscrollPos,TRUE);
//
// Set all the
cells types to Empty.
for(i=1;i<=100;i++)
for(a=1;a<=100;a++)
{
int
pvalue=0;
pvalue=((i-1)*100)+a;
type=stype+pvalue;
*type='E';
}
//
cxChar=LOWORD(GetDialogBaseUnits());
cyChar=HIWORD(GetDialogBaseUnits());
hwndButtonP
= CreateWindow(TEXT("button"), TEXT("Calc"),
WS_CHILD | WS_VISIBLE |
BS_PUSHBUTTON,
cxChar,4,5*cxChar,7*cyChar/4,hWnd,(HMENU)
0,
((LPCREATESTRUCT)
lParam)->hInstance, NULL);
//
hwndButtonX =
CreateWindow(TEXT("button"), TEXT("XCal"),
WS_CHILD | WS_VISIBLE |
BS_PUSHBUTTON,
cxChar*6,4,5*cxChar,7*cyChar/4,hWnd,(HMENU)
1,
((LPCREATESTRUCT)
lParam)->hInstance, NULL);
//
//
//
break;
//
case WM_PAINT:
hdc=BeginPaint(hWnd,
&ps);
SelectObject(hdc,GetStockObject(SYSTEM_FIXED_FONT));
current_column(&fch,
&sch, column);
if(column<=26)
{
sprintf(szBuffer,"%c
",fch);
TextOut(hdc,
cxChar*1, cyChar*3, szBuffer,2);
}
else
{
sprintf(szBuffer,"%c%c",fch,sch);
TextOut(hdc,
cxChar*1, cyChar*3, szBuffer,2);
}
sprintf(szBuffer,"%-3d
",row);
if(column<=26)
TextOut(hdc,
cxChar*2, cyChar*3, szBuffer,4);
else
TextOut(hdc,
cxChar*3, cyChar*3, szBuffer,4);
sprintf(szBuffer,"
");
TextOut(hdc,cxChar*6,cyChar*3,szBuffer,NUMCHARS-2);
pvalue=((column-1)*100)+row;
type=stype+pvalue;
if (*type=='S' ||
*type=='F')
{
cell=scell+pvalue;
sprintf(szBuffer,
"%s", *cell);
if
((strlen(szBuffer))<(NUMCHARS-10))
NUMD=strlen(szBuffer);
else
NUMD=NUMCHARS-10;
if (*type=='F')
TextOut(hdc,
cxChar*7, cyChar*3, szBuffer, NUMD-1);
else
TextOut(hdc,
cxChar*7, cyChar*3, szBuffer, NUMD);
if
(NUMD==NUMCHARS-10)
TextOut(hdc,
cxChar*(NUMD+8), cyChar*3," OV",3);
}
if (*type=='N')
{
numeric=snumeric+pvalue;
sprintf(szBuffer,"%f",*(*numeric));
TextOut(hdc,
cxChar*7, cyChar*3, szBuffer,strlen(szBuffer));
}
//
SetBkColor(hdc,
RGB(200,200,200));
SetTextColor(hdc,
RGB(0,0,0));
if (hredraw || vredraw
|| credraw || (dscroll==5))
goto doitselect;
else
{
cval=nHscrollPos;
sprintf(szBuffer," ");
TextOut(hdc,cxChar*1,cyChar*4,szBuffer,3);
a=4;
//
// Display the
column values.
for(i=1;i<=NUMCOLS;i++)
{
sprintf(szBuffer," ");
TextOut(hdc,cxChar*a,cyChar*4,szBuffer,6);
a+=6;
current_column(&fch,
&sch, cval);
sprintf(szBuffer,"%2c%c",fch,sch);
TextOut(hdc,cxChar*a,cyChar*4,
szBuffer,3);
a+=3;
cval++;
}
sprintf(szBuffer,"
");
TextOut(hdc,cxChar*a,
cyChar*4, szBuffer,1);
hredraw=0;
//
cval=nVscrollPos;
// Display the
row values.
for
(i=4;i<=NUMLINES;i++)
{
sprintf(szBuffer," ");
TextOut(hdc,0,
cyChar*(1+i),szBuffer,4);
sprintf(szBuffer,"%3d",cval);
TextOut(hdc,0,cyChar*(1+i),szBuffer,3);
cval++;
}
vredraw=0;
SetTextColor(hdc,
RGB(0,0,0));
SetBkColor(hdc, RGB(255,255,255));
rval=nVscrollPos;
cval=nHscrollPos;
// Display the
contents of the Worksheet.
for(i=1;i<=MAXROW;i++)
{
cvaly=cyChar*(4+i);
for (a=1;
a<=NUMCOLS;a++)
{
int
pvalue=0;
pvalue=((cval-1)*100)+rval;
type=stype+pvalue;
cvalx=5+((a-1)*9);
evaluate_cell(cval,rval,(char)*type,szBuffer);
//
TextOut(hdc,
0.25+cxChar*cvalx, cvaly,szBuffer,9);
cval++;
}
cval=nHscrollPos;
rval++;
}
{
int
pvalue=0;
pvalue=((column-1)*100)+row;
type=stype+pvalue;
cvalx=5+((curxpos-1)*9);
cvaly=cyChar*(4+curypos);
SetTextColor(hdc,
RGB(255,255,255));
SetBkColor(hdc,
RGB(0,0,200));
evaluate_cell(column,row,(char)*type,szBuffer);
TextOut(hdc,
0.25+cxChar*cvalx, cvaly, szBuffer,9);
SetTextColor(hdc,
RGB(0,0,0));
SetBkColor(hdc,
RGB(255,255,255));
credraw=0;
}
goto finished;
}
doitselect :
if (hredraw)
{
cval=nHscrollPos;
sprintf(szBuffer," ");
TextOut(hdc,cxChar*1,cyChar*4,szBuffer,3);
a=4;
for(i=1;i<=NUMCOLS;i++)
{
sprintf(szBuffer," ");
TextOut(hdc,cxChar*a,cyChar*4,szBuffer,6);
a+=6;
current_column(&fch,
&sch, cval);
sprintf(szBuffer,"%2c%c",fch,sch);
TextOut(hdc,cxChar*a,cyChar*4,
szBuffer,3);
a+=3;
cval++;
}
sprintf(szBuffer,"
");
TextOut(hdc,cxChar*a,
cyChar*4, szBuffer,1);
hredraw=0;
}
if (vredraw)
{
cval=nVscrollPos;
for
(i=4;i<=NUMLINES;i++)
{
sprintf(szBuffer," ");
TextOut(hdc,0,
cyChar*(1+i),szBuffer,4);
sprintf(szBuffer,"%3d",cval);
TextOut(hdc,0,cyChar*(1+i),szBuffer,3);
cval++;
}
vredraw=0;
}
if (dscroll==5)
{
SetTextColor(hdc,
RGB(0,0,0));
SetBkColor(hdc,
RGB(255,255,255));
rval=nVscrollPos;
cval=nHscrollPos;
for(i=1;i<=MAXROW;i++)
{
cvaly=cyChar*(4+i);
for
(a=1; a<=NUMCOLS;a++)
{
int
pvalue=0;
pvalue=((cval-1)*100)+rval;
type=stype+pvalue;
cvalx=5+((a-1)*9);
evaluate_cell(cval,rval,(char)*type,szBuffer);
//
TextOut(hdc,
0.25+cxChar*cvalx, cvaly,szBuffer,9);
cval++;
}
cval=nHscrollPos;
rval++;
}
dscroll=0;
}
if (credraw)
{
int pvalue=0;
pvalue=((column-1)*100)+row;
type=stype+pvalue;
cvalx=5+((curxpos-1)*9);
cvaly=cyChar*(4+curypos);
SetTextColor(hdc,
RGB(255,255,255));
SetBkColor(hdc,
RGB(0,0,200));
evaluate_cell(column,row,(char)*type,szBuffer);
TextOut(hdc,
0.25+cxChar*cvalx, cvaly, szBuffer,9);
SetTextColor(hdc,
RGB(0,0,0));
SetBkColor(hdc,
RGB(255,255,255));
credraw=0;
}
finished:
EndPaint(hWnd, &ps);
//
break;
// Called when
performing a scroll by a row.
case WM_VSCROLL:
hdc=GetDC(hWnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc,
&tm);
cxChar=tm.tmAveCharWidth;
cyChar=tm.tmHeight;
scroll=0;
switch (LOWORD(wParam))
{
case SB_LINEUP:
ctypos--;
if
(ctypos<1)
ctypos=1;
else
{
if
(ctypos<stypos)
{
endypos--;
stypos--;
curypos=1;
nVscrollPos-=1;
scroll=1;
dscroll=1;
vredraw=1;
}
else
curypos--;
}
scrlval=+cyChar;
break;
case SB_LINEDOWN:
ctypos++;
if
(ctypos>100)
ctypos=100;
else
{
if
(ctypos>endypos)
{
endypos++;
stypos++;
curypos=MAXROW;
nVscrollPos+=1;
scroll=1;
dscroll=2;
vredraw=1;
}
else
curypos++;
}
scrlval=-cyChar;
break;
}
SetScrollPos(hWnd,SB_VERT,ctypos,TRUE);
cvalx=5+((olrxpos-1)*9);
cvaly=cyChar*(4+olrypos);
SetTextColor(hdc,
RGB(0,0,0));
SetBkColor(hdc,
RGB(255,255,255));
{
int pvalue=0;
pvalue=((column-1)*100)+row;
type=stype+pvalue;
evaluate_cell(column,row,(char)*type,szBuffer);
TextOut(hdc,
0.25+cxChar*cvalx, cvaly, szBuffer,9);
}
if (scroll)
{
dscroll=5;
}
ReleaseDC(hWnd,hdc);
olrxpos=curxpos;
olrypos=curypos;
credraw=1;
hredraw=1;
//
row=ctypos; column=ctxpos;
InvalidateRect(hWnd,
NULL, FALSE);
break;
// Called when
performing a scroll by a column.
case WM_HSCROLL:
hdc=GetDC(hWnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc,
&tm);
cxChar=tm.tmAveCharWidth;
cyChar=tm.tmHeight;
scroll=0;
switch (LOWORD(wParam))
{
case SB_LINEUP:
ctxpos--;
if
(ctxpos<1)
ctxpos=1;
else
{
if
(ctxpos<stxpos)
{
endxpos--;
stxpos--;
curxpos=1;
nHscrollPos-=1;
scroll=1;
dscroll=3;
hredraw=1;
}
else
curxpos--;
}
scrlval=+(0.25+cxChar*9);
break;
case SB_LINEDOWN:
ctxpos++;
if
(ctxpos>100)
ctxpos=100;
else
{
if
(ctxpos>endxpos)
{
endxpos++;
stxpos++;
curxpos=NUMCOLS;
nHscrollPos+=1;
scroll=1;
dscroll=4;
hredraw=1;
}
else
curxpos++;
}
scrlval=-(0.25+cxChar*9);
break;
}
SetScrollPos(hWnd,SB_HORZ,ctxpos,TRUE);
cvalx=5+((olrxpos-1)*9);
cvaly=cyChar*(4+olrypos);
SetTextColor(hdc,
RGB(0,0,0));
SetBkColor(hdc,
RGB(255,255,255));
{
int pvalue=0;
pvalue=((column-1)*100)+row;
type=stype+pvalue;
evaluate_cell(column,row,(char)*type,szBuffer);
TextOut(hdc,
0.25+cxChar*cvalx, cvaly, szBuffer,9);
}
if (scroll)
{
dscroll=5;
}
ReleaseDC(hWnd,hdc);
olrxpos=curxpos;
olrypos=curypos;
credraw=1;
vredraw=1;
//
row=ctypos;
column=ctxpos;
InvalidateRect(hWnd,
NULL, FALSE);
break;
// Translate
cursor keys to scroll messages.
case WM_KEYDOWN:
switch(wParam)
{
case VK_UP:
SendMessage(hWnd,
WM_VSCROLL, SB_LINEUP,0L);
break;
case VK_DOWN:
SendMessage(hWnd,
WM_VSCROLL, SB_LINEDOWN,0L);
break;
case VK_LEFT:
SendMessage(hWnd,
WM_HSCROLL, SB_LINEUP,0L);
break;
case VK_RIGHT:
SendMessage(hWnd,
WM_HSCROLL, SB_LINEDOWN,0L);
break;
}
break;
// Called when
resizing the worksheet.
case WM_SIZE:
cxClient=LOWORD(lParam);
cyClient=HIWORD(lParam);
hdc=GetDC(hWnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc,
&tm);
cxChar=tm.tmAveCharWidth;
cyChar=tm.tmHeight;
ReleaseDC(hWnd,hdc);
NUMCHARS=(cxClient/cxChar);
NUMCHARS=(NUMCHARS/9)*8;
NUMLINES=(cyClient/cyChar)-2;
NUMCOLS=NUMCHARS/9;
MAXROW=NUMLINES-3;
column=1;
row=1;
cval=0;
rval=0;
hredraw=1;
vredraw=1;
credraw=1;
stxpos=1;
endxpos=NUMCOLS;
stypos=1;
endypos=MAXROW;
ctxpos=1;
ctypos=1;
curxpos=1;
curypos=1;
olrxpos=1;
olrypos=1;
cvalx=0;
c_input=0;
scroll=0;
dscroll=5;
cvaly=0;
nVscrollPos=1;
nHscrollPos=1;
scrlval=0;
SetScrollPos(hWnd,
SB_VERT, nVscrollPos, TRUE);
SetScrollPos(hWnd,
SB_HORZ, nHscrollPos, TRUE);
break;
// Called when
inputting information.
case WM_CHAR:
if ((wParam!='\r')
&& (istat==0))
{
szInputStr[0]=wParam;
szInputStr[1]='\0';
//
//
input=1;
istat=1;
credraw=1;
DialogBox(hInst,
(LPCTSTR)IDD_DIALOG1, hWnd, (DLGPROC)Input);
cleanup(szBuffer,szOutputStr);
}
setcursor=0;
if (istat==1)
{
c_input=strlen(szBuffer);
istat=0;
switch(szBuffer[0])
{
case '=':
case '$':
{
int
pvalue=0;
pvalue=((column-1)*100)+row;
cell=scell+pvalue;
*cell=(char
*) calloc((unsigned long) strlen(szBuffer)+4, sizeof(char));
strncpy(*cell,
szBuffer+1, strlen(szBuffer));
if
(szBuffer[0]=='=') strcat(*cell, "#");
type=stype+pvalue;
if
(szBuffer[0]=='$')
*type='S';
else
*type='F';
dscroll=5;
//
break;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
case '+':
case '.':
case '(':
{
int
pvalue=0;
pvalue=((column-1)*100)+row;
if
(moreops(szBuffer))
{
cell=scell+pvalue;
*cell=(char
*) calloc((unsigned long) strlen(szBuffer)+4, sizeof(char));
strncpy(*cell,
szBuffer+0, strlen(szBuffer));
strcat(*cell,
"#");
type=stype+pvalue;
*type='F';
}
else
{
numeric=snumeric+pvalue;
*numeric=(double
*) calloc ((unsigned long) 1, sizeof(double));
*(*numeric)=atof(szBuffer);
type=stype+pvalue;
*type='N';
}
//
dscroll=5;
break;
}
//
}
//
if (up) { up=0;
SendMessage(hWnd, WM_VSCROLL, SB_LINEUP,0L);}
if (down) {
down=0; SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN,0L);}
if (left) {left=0;
SendMessage(hWnd, WM_HSCROLL, SB_LINEUP,0L);}
if (right)
{right=0; SendMessage(hWnd, WM_HSCROLL, SB_LINEDOWN,0L);}
}
//
dscroll=5;
credraw=1;
InvalidateRect(hWnd,
NULL, FALSE);
break;
case WM_DESTROY:
GlobalUnlock(hGlobalMemory);
GlobalFree(hGlobalMemory);
GlobalUnlock(hGlobalMemory2);
GlobalFree(hGlobalMemory2);
GlobalUnlock(hGlobalMemory3);
GlobalFree(hGlobalMemory3);
PostQuitMessage(0);
break;
default:
return
DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Mesage handler
for about box.
LRESULT CALLBACK
About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK ||
LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg,
LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
LRESULT CALLBACK
EditSubclassProc(HWND hwnd, UINT UMsg, WPARAM wParam, LPARAM lParam)
{
if (UMsg==WM_GETDLGCODE)
{
return DLGC_WANTALLKEYS;
}
if (UMsg==WM_KEYDOWN)
{
if (wParam==VK_UP)
{
UMsg=WM_CHAR;
setcursor=2;
scrolled=0;
wParam='Ç';
}
}
if (UMsg==WM_KEYDOWN)
{
if (wParam==VK_DOWN)
{
UMsg=WM_CHAR;
setcursor=3;
wParam='Ç';
scrolled=0;
}
}
if (UMsg==WM_KEYDOWN)
{
if (wParam==VK_LEFT)
{
UMsg=WM_CHAR;
setcursor=4;
wParam='Ç';
scrolled=0;
}
}
if (UMsg==WM_KEYDOWN)
{
if (wParam==VK_RIGHT &&
scrolled)
{
UMsg=WM_CHAR;
setcursor=5;
scrolled=0;
wParam='Ç';
}
}
//
//
if (UMsg==WM_CHAR)
{
if (wParam=='\r')
{
UMsg=WM_CHAR;
setcursor=1;
wParam='Ç';
scrolled=0;
}
}
return CallWindowProc(wpOrigEditProc,
hwnd, UMsg, wParam, lParam);
}
//
//
LRESULT CALLBACK
Input(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
hwndEdit=GetDlgItem(hDlg,EDITTAB);
wpOrigEditProc= (WNDPROC)
SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG) EditSubclassProc);
SendMessage(hwndEdit,WM_CLEAR,0,0);
SendMessage(hwndEdit,
EM_REPLACESEL,FALSE,(LPARAM) szInputStr);
newscroll=1;
scrolled=1;
return TRUE;
break;
}
if (setcursor>=1)
{
if (setcursor==2) up=1;
if (setcursor==3) down=1;
if (setcursor==4) left=1;
if (setcursor==5) right=1;
input=0;
setcursor=0;
GetDlgItemText(hDlg, EDITTAB,
szOutputStr, 2047);
EndDialog(hDlg,0);
}
//
return FALSE;
}
//
// Workout
current column lettering dependant on integer column.
void
current_column(char *fch, char *sch, int column)
{
div_t x;
if (column<=26)
{
*fch=96+column;
*sch=32;
}
else
{
x=div(column,26);
if(x.rem)
{
*sch=x.rem+96;
*fch=x.quot+96;
}
else
{
*sch=x.rem+122;
*fch=(x.quot-1)+96;
}
}
}
void cleanup(char
*output, char *input)
{
int loop=0, yloop=0;
for (loop=0;loop<=strlen(input);loop++)
{
if (input[loop]!='Ç')
{
output[yloop]=input[loop];
yloop++;
}
}
}
void clr_str(char
*source)
{
int loop;
for (loop=0;
loop<=sizeof(source);loop++)
source[loop]=' ';
}
int find_optr(int
start, char *form)
{
while(form[start]!='*' &&
form[start]!='+' && form[start]!='/' && form[start]!='-'
&& form[start]!='#' && form[start]!=')')
start++;
return(start);
}
// Convert a
formula to its raw native numeric form (including brackets).
double expr_p(int
*error, char *form)
{
char *source=NULL,
*dest=NULL;
int start=0,
end=0,
bracket=0,
length=0;
double answer=0;
source=(char *) calloc((unsigned long)
32767, sizeof(char));
dest=(char *) calloc((unsigned long)
32767, sizeof(char));
strcpy(source, form);
while ((fcat)&&(*error==0))
{
fcat=0;
parser(error, source,dest);
strcpy(source,dest);
strcat(source,"#");
free(dest);
dest=(char *) calloc((unsigned long)
32767, sizeof(char));
}
fcat=1;
//
if ((!*error) && (preced==1))
{
newyk=(char *) calloc((unsigned
long) 32767, sizeof(char));
length=strlen(source)-1;
source[length]='\0';
clr_str(newyk);
length=0;
strcpy(newyk,"%");
strcat(newyk,source);
strcat(newyk,"%\0");
ans=eval_parser(newyk, error);
free(newyk);
clear_vars();
}
else
ans=0;
free(source);
free(dest);
if (*error==0)
return (ans);
else
return (0);
}
int
isbracket(char c)
{
if (c=='('||c==')') return 1; else return
0;
}
//
int isstop(char
c)
{
if (c=='.') return 1; else return 0;
}
int
isoperator(char c)
{
switch(c)
{
case '*':return 1;
case '+':return 1;
case '-':return 1;
case '/':return 1;
default : return 0;
}
}
int moreops(char
*c)
{
int loop=0;
for (loop=0;loop<=strlen(c);loop++)
if ((loop>0) && (c[loop]=='*'
|| c[loop]=='/' || c[loop]=='+' || c[loop]=='-' || c[loop]=='(' || c[loop]==')'
|| c[loop]=='a'
|| c[loop]=='b'
|| c[loop]=='c' || c[loop]=='d' || c[loop]=='e' || c[loop]=='f' || c[loop]=='g'
|| c[loop]=='h'
|| c[loop]=='i'
|| c[loop]=='j' || c[loop]=='k' || c[loop]=='l' || c[loop]=='m' || c[loop]=='n'
|| c[loop]=='o'
|| c[loop]=='p'
|| c[loop]=='q' || c[loop]=='r' || c[loop]=='s' || c[loop]=='t' || c[loop]=='u'
|| c[loop]=='v'
|| c[loop]=='w'
|| c[loop]=='x' || c[loop]=='y' || c[loop]=='z')) return(1);
return(0);
}
// Does the
conversion from formula to a string of numbers.
void parser(int
*error, char *source, char *dest)
{
int loop=0;
int dloop=0;
int crloop=0;
int alloop=0;
int locx=0;
int locy=0;
int pvalue=0;
char cref[20];
char alpp[20];
char num[20];
while (source[loop]!='#')
{
while(isdigit(source[loop]) ||
isstop(source[loop]) || isoperator(source[loop]) || isbracket(source[loop]))
{
dest[dloop]=source[loop];
dloop++;
loop++;
}
if (source[loop]=='#') break;
if (isalpha(source[loop]))
{
crloop=0;
do
{
cref[crloop]=source[loop];
crloop++; loop++;
}
while
(isdigit(source[loop])||isalpha(source[loop]));
}
crloop=0;
alloop=0;
while(isalpha(cref[crloop]))
{
alpp[alloop]=cref[crloop];
crloop++;
alloop++;
}
if (alloop==1)
locx=alpp[0]-96;
else
if (alloop==2)
locx=((alpp[0]-96)*26)+alpp[1]-96;
else
{
locx=0;
*error=1;
return;
}
alloop=0;
clr_str(alpp);
while (isdigit(cref[crloop]))
{
alpp[alloop]=cref[crloop];
crloop++;
alloop++;
}
locy=atoi(alpp);
clr_str(alpp);
clr_str(cref);
if ((locx<1)||(locx>100))
{
*error=1;
return;
}
if ((locy<1)||(locy>100))
{
*error=1;
return;
}
pvalue=((locx-1)*100)+locy;
type=stype+pvalue;
if (*type=='N')
{
dest[dloop]='(';
dloop+=1;
numeric=snumeric+pvalue;
sprintf(num, "%f",*(*numeric));
strcat(dest,num);
dloop+=strlen(num);
dest[dloop]=')';
dloop+=1;
}
if (*type=='F')
{
dest[dloop]='(';
dloop+=1;
cell=scell+pvalue;
strncat(dest,*cell,(strlen(*cell)-1));
dloop+=strlen(*cell)-1;
dest[dloop]=')';
dloop+=1;
fcat=1;
}
if (*type=='E'|| *type=='S')
{
*error=1;
return;
}
}
}
// Evaluate and
store contents of a cell in szBuffer.
void
evaluate_cell(int column, int row, char type, char *szBuffer)
{
errflag=0;
switch(type)
{
case 'S':
{
int pvalue=0;
pvalue=((column-1)*100)+row;
cell=scell+pvalue;
sprintf(szBuffer,
"%9s", *cell);
break;
}
case 'N':
{
int pvalue=0;
pvalue=((column-1)*100)+row;
numeric=snumeric+pvalue;
sprintf(szBuffer,
"%9.2f",*(*numeric));
break;
}
case 'F':
{
int pvalue=0;
pvalue=((column-1)*100)+row;
cell=scell+pvalue;
value=expr_p(&errflag,
*cell);
if (!errflag)
sprintf(szBuffer,
"%9.2f",value);
else
{
sprintf(szBuffer,
"%s"," Error ");
}
break;
}
default:
sprintf(szBuffer," ");
break;
}
}
//
double
eval_parser(char* newyk, int *error)
{
double answer=0;
switc=newyk[x];
if ((switc=='%') && (x==0)) // In
the beginning we push the % terminator
// onto the texas
stack
{
previous=switc;
pushtexas(switc);
}
if ((previous=='%') &&
(((switc>='0') && (switc<='9')) || switc=='.'))
{
calif[c]='P';
c++;
calif[c]=',';
c++;
}
else if (switc=='-')
{
calif[c]='M';
c++;
calif[c]=',';
c++;
x++;
switc=newyk[x];
}
else if (switc=='+')
{
calif[c]='P';
c++;
calif[c]=',';
c++;
x++;
switc=newyk[x];
}
do
{
if ((previous=='+' || previous=='-'
|| previous=='/' || previous=='*' || previous=='(') && (switc=='+' ||
switc=='-'))
{
if (switc=='+')
{
previous='u';
x++;
switc=newyk[x];
}
else
{
previous='u';
putcalif('M');
calif[c]=',';
c++;
}
goto done;
}
else
if (switc=='(')
{
calif[c]=switc;
c++;
}
while (((switc>='0') &&
(switc<='9')) || switc=='.')
{
previous=switc;
putcalif(switc);
notrue=1;
}
if (notrue==1) goto done;
if (switc=='M' || switc=='P')
{
putcalif(switc);
goto done;
}
if ((switc=='%' || switc=='+' ||
switc=='-' || switc==')') && (texas[s-1]=='+' || texas[s-1]=='*' ||
texas[s-1]=='-' || texas[s-1]=='/'))
{
poptexas(s-1);
goto done;
}
if ((switc=='*' || switc=='/')
&& (texas[s-1]=='*' || texas[s-1]=='/'))
{
poptexas(s-1);
goto done;
}
if (switc=='%' &&
texas[s-1]=='(')
{
fperror(error);
break;
goto done;
}
if ((switc=='+' || switc=='-' ||
switc=='*' || switc=='/' || switc=='(') && (texas[s-1]=='(' ||
texas[s-1]=='%'))
{
previous=switc;
pushtexas(switc);
goto done;
}
if ((switc=='*' || switc=='/')
&& (texas[s-1]=='+' || texas[s-1]=='-'))
{
previous=switc;
pushtexas(switc);
goto done;
}
if ((switc=='(') &&
(texas[s-1]=='+' || texas[s-1]=='*' || texas[s-1]=='-' || texas[s-1]=='/' ||
texas[s-1]=='('))
{
previous=switc;
pushtexas(switc);
goto done;
}
if (switc==')' && texas[s-1]=='%')
{
fperror(error);
break;
goto done;
}
if (switc==')' &&
texas[s-1]=='(')
{
calif[c]=switc;
c++;
calif[c]=',';
c++;
fpdel();
goto done;
}
done:;
if (notrue==1)
{
calif[c]=',';
c++;
notrue=0;
}
if (switc=='%' &&
texas[s-1]=='%')
{
putcalif('%');
break;
}
}
while (!(switc=='%' &&
texas[s-1]=='%'));
//
form3=(char *) calloc ((unsigned
long)32767, sizeof(char));
find_brkt(error, calif,&start,&end,&bracket,&length);
//
if ((bracket) && (!*error))
{
eval_brkt(error, calif, start, end,
bracket, length);
}
else
if (!*error)
{
strcpy(form3, calif);
}
if (!*error)
{
answer=eval_form(error, form3);
}
//
free(form3);
//
return answer;
}
//
void
pushtexas(char switcd)
{
texas[s]=switcd;
s++;
x++;
switc=newyk[x];
}
void poptexas(int
st1)
{
calif[c]=texas[st1];
s--;
c=c+1;
calif[c]=',';
c++;
//
}
//
void fpdel(void)
{
x++;
switc=newyk[x];
s--;
}
void
putcalif(char switcd)
{
calif[c]=switcd;
c++;
x++;
switc=newyk[x];
}
void fperror(int
*error)
{
*error=1;
}
void
pushstk(double nu)
{
num[s]=nu;
s++;
}
double popstk()
{
s--;
return(num[s]);
}
//
void
find_brkt(int *error, char *form, int *start, int *end, int *bracket, int
*length)
{
int loop,
loop2,
rgtbrac=0;
loop=loop2=0;
*length=strlen(form);
*bracket=0;
for (loop=0; loop<=*length; loop++)
{
if (form[loop]=='(')
{
*bracket=1;
*start=loop;
}
if (form[loop]==')')
rgtbrac=1;
//
}
if (*bracket)
{
loop2=*start+1;
*bracket=0;
do
{
if (form[loop2]==')')
{
*end=loop2;
*bracket=1;
}
loop2++;
}
while ((!*bracket) &&
(form[loop2]!='%'));
}
//
}
void
eval_brkt(int *error, char *form, int start, int end, int bracket, int length)
{
int loop=0,size=0;
char *ecopy=NULL;
char *nbrac=NULL;
char *number=NULL;
//
double answer=0;
strcpy(form3,form);
while ((bracket) && (!*error))
{
nbrac=(char *) calloc ((unsigned
long)32767, sizeof(char));
number=(char * ) calloc((unsigned
long) 100, sizeof(char));
ecopy=(char *) calloc((unsigned
long)32767,sizeof(char));
//
size=((end)-(start+1))+2;
clr_str(nbrac);
strncpy(nbrac, form3+(start+1),
((end)-(start+1)));
nbrac[end-start+1]='%';
answer = eval_form(error,nbrac);
//
if (answer<0)
{
strcpy(nbrac, "M,");
sprintf(number,
"%-5.3f", -answer);
strcat(nbrac,number);
}
else
{
sprintf(number,
"%-5.3f", answer);
clr_str(nbrac);
strcpy(nbrac, number);
}
if (start !=0)
{
strncpy(ecopy, form3+0,
start);
}
strcat(ecopy, nbrac);
loop=end+1;
strcat(ecopy, form3+loop);
clr_str(form3);
strcpy(form3, ecopy);
strcat(form3, ",");
free(ecopy);
free(number);
free(nbrac);
if (bracket)
find_brkt(error, form3,
&start, &end, &bracket, &length);
}
}
double
eval_form(int *error, char *form)
{
double answer =0,
no1=0,
no2=0;
int loop=0,
nega=0,
opvalid=0,
place=0;
c=0; s=0;
while(form[c]!='%')
{
int fm=0;
if (form[c]=='P') c++;
if (form[c]==',') c++;
while(form[c]==' ') { c++; }
//
if (form[c]=='%') break;
while((form[c]>='0') &&
(form[c]<='9') || form[c]==' ' || form[c]=='M' || form[c]=='.')
{
while (form[c]=='M')
{
if (fm==1) fm=0; else
fm=1;
c++;
if (form[c]==',') c++;
}
str=0;
clr_str(star);
while ((form[c]>='0')
&& (form[c]<='9') || (form[c]=='.'))
{
star[str]=form[c];
str++;
c++;
notrue=1;
}
if (notrue==1)
{
if (fm!=1)
{
pushstk(atof(star));
}
else
{
pushstk(-atof(star));
fm=0;
}
notrue=0;
}
c++;
}
//
while(form[c]==0) {c++;}
if (form[c]=='%') break;
right1=popstk();
left1=popstk();
if (form[c]=='+')
answer=left1+right1;
else
if (form[c]=='-')
answer=left1-right1;
else
if (form[c]=='*')
answer=left1*right1;
else
if (form[c]=='/')
if
(right1==0) {
*error=1;
answer=0;}
else
answer=left1/right1;
pushstk(answer);
c++;
}
//
answer=popstk();
return(answer);
}
//
void clear_vars(void)
{
clr_str(calif);
clr_str(texas);
//clr_str(form3);
//clr_str(newyk);
clr_str(star);
switc=NULL; // This is the switch
previous=NULL;
bop=NULL;
frop=NULL;
right1=NULL;
left1=NULL;
no=0;
rgt=NULL;
lft=NULL;
blop=NULL;
check=NULL;
op=NULL;
rop=NULL;
lop=NULL;
x=0;
s=0;
c=0;
n=0;
g=0;
notrue=0;
str=0;
start=0;
end=0;
bracket=0;
length=0;
sol=0;
}
//