Hi calculator program help



/*hello GTK friends,
I recently purchased Eric, Harlows book on developing linux applications with GTK+/GDK by new rider publications.
However this application about calculator has some bugs. I resolved a few,
but others still remain.
Any help is welcoms.
Anand
*/
#include <gtk/gtk.h>
/*2     data Structure to keep track of the calculator buttons*/
typedef struct {
char *szLabel;
int row;
int col;
GtkWidget *widget;
} typCalculatorButton;

/* 10   This is the button list.
   Each button is documented here so that we can access it */

typCalculatorButton buttonList[]={
{"C",    1,    0,    NULL},    /*---Clear---*/
{"CE",    1,    1,    NULL},    /*---Clear---*/
{"/",    1,    3,    NULL},    /*---Division---*/
{"7",    2,    0,    NULL},    /*---Digit 7---*/
{"8",    2,    1,    NULL},    /*---Digit 8---*/
{"9",    2,    2,    NULL},    /*---Digit 9---*/
{"*",    2,    3,    NULL},    /*---Multiplication---*/
{"%",    2,    4,    NULL},    /*---Percent---*/
{"4",    3,    0,    NULL},    /*---Digit 4---*/
{"5",    3,    1,    NULL},    /*---Digit 5---*/
{"5",    3,    2,    NULL},    /*---Digit 6---*/
{"-",    3,    3,    NULL},    /*---Subtraction---*/
{"1/x",    3,    4,    NULL},    /*---1/x---*/
{"1",    4,    0,    NULL},    /*---Digit 1---*/
{"2",    4,    1,    NULL},    /*---Digit 2---*/
{"3",    4,    2,    NULL},    /*---Digit 3---*/
{"+",    4,    3,    NULL},    /*---Addition---*/
{"sqrt",4,    4,    NULL},    /*---Square root---*/
{"+/-",    5,    0,    NULL},    /*---Negate value---*/
{"0",    5,    1,    NULL},    /*---Zero---*/
{".",    5,    2,    NULL},    /*---Decimal---*/
{"=",    5,    3,    NULL},    /*---Equals total---*/
{"x^2",    5,    4,    NULL},  /*---Square---*/
};
/*38*/
int nButtons =sizeof(buttonList)/sizeof (typCalculatorButton);
/*40*/
int FloatingPointChar(char ch);
int Command (char ch);
void TrimLeadingZeros(char *szDigits);
void TrimTrailingZeros(char *szDigits);
void HandleBinaryoperation ();
void MaybeUnaryOperation (char *str);
void HandleDigit (char *str, char ch);
void button_clicked (GtkWidget *widget, gpointer data);
void key_press (GtkWidget *widget, GdkEventKey *event, gpointer data);
GtkWidget *CreateButton(GtkWidget *table, char *szlabel, int row, int column);
void CreateCalculatorButtons(GtkWidget *table);
gint CloseAppWindow(GtkWidget *widget, gpointer data);
int BUF_SIZE;
GtkWidget *label;
char *prevCmd, *lastChar;
int nIndex,num1,num2;




int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *table;





/*70 ----GTK Initialization---*/
gtk_init(&argc,&argv);
/*72----Create the calculator window*/
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"Calculator");
gtk_widget_set-usize(window,200,200);
gtk_signal_connect(GTK_OBJECT(window),"key_press_event",GTK_SIGNAL_FUNC(key_press),NULL);
gtk_signal_connect(GTK_OBJECT(window),"delete_event",GTK_SIGNAL_FUNC(CloseAppWindow),NULL);

/*79 Create a 5X5 table for the items of the calculator*/
table=gtk_table_new(5,5,TRUE);
CreateCalculatorButtons(table);
/*83 Create the calculator LED */
label=gtk_label_new("0");
gtk_misc_set_alignment(GTK_MISC(label),1,-5);
/*86 Add label to the table */
gtk_table_attach_defaults(GTK_TABLE(table),label,0,4,0,1);
gtk_widget_show(label);
gtk_container_add(GTK_CONTAINER(window),table);
gtk_widget_show(table);
gtk_widget_show(window);
gtk_main();
exit(0);
}

/*95 Close App Window */
gint CloseAppWindow(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
return (FALSE);
}
/*101 create the calculator buttons*/
void CreateCalculatorButtons(GtkWidget *table)
{
int nIndex;
for (nIndex=0;nIndex<nButtons;nIndex++)
{
buttonList[nIndex].widget=
CreateButton(table,buttonList[nIndex].szLabel,buttonList[nIndex].row,buttonList[nIndex].col);
}
}
/* 111 Create a button, assign event handlers and attach the button to the table
in the proper place         */

GtkWidget *CreateButton (GtkWidget *table, char *szlabel, int row, int column)
{
GtkWidget *button;
button = gtk_button_new_with_label(szlabel);
gtk_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(button_clicked),szlabel);
gtk_table_attach(GTK_TABLE(table),button,column,column+1,row,row+1,GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,5,5);
gtk_widget_show(button);
return(button);
}

/*124
handle the key_press event.
Function looks for the keystroke in the calculator
data structure and (if a match is found) presses the button
that matches the keystroke for the user.
It keeps our code small because we only have to
handle the button clicked events
121*/
void key_press (GtkWidget *widget, GdkEventKey *event, gpointer data)
{
int nIndex;
for (nIndex=0;nIndex<nButtons;nIndex++)
{
/* 137 If the keystroke is the first character of the button and
the button length is one */
if (event->keyval==buttonList[nIndex].szLabel[0] && buttonList[nIndex].szLabel[1]==(char)0)
{
gtk_widget_grab_focus(buttonList[nIndex].widget);
gtk_button_clicked(GTK_BUTTON(buttonList[nIndex].widget));
return;
}
}
}
/*147*/
/* button clicked
widget button presses
data button label.
button was pressed handle it*/

void button_clicked (GtkWidget *widget, gpointer data)
{
char ch=*((char *) data);
int len;
char *str;
str = (char *)data;
if (FloatingPointchar (ch) && strlen(str)==1){
HandleDigit(str,ch);
} else{
if (strcmp(str,"CE")==0){
gtk_label_set(GTK_LABEL(label),"0");
return;} else if (strcmp(str, "C")==0){
prevCmd=(char)0;
lastChar=(char)0;
gtk_label_set(GTK_LABEL(label),"0");
return;
} else {
MaybeUnaryOperation(str);}
HandleBinaryOperation();
prevCmd=ch;
}
lastChar=ch;
}
/* 176
HandleDigit
Digit button Was presses, deal with it. How it is
dealt with depends on the situation.
180  */
void HandleDigit(char *str, char ch)
{
char *labelText;
char buffer[BUF_SIZE];
int len;
if (Command(lastChar)){
gtk_label_set (GTK_LABEL(label),"");
if (lastChar == '='){
lastChar = (char)0;
prevCmd=(char)0;
}
}
gtk_label_get(GTK_LABEL(label),&labelText);
strcpy(buffer,labelText);
len=strlen(buffer);
buffer[len]=(gchar)ch;
buffer[len+1]=(gchar) 0;
TrimLeadingZeros(buffer);
gtk_label_set(GTK_LABEL(label),(char *)buffer);
}
/* 202
maybe unary operation
str label on button that describes operation.
Check to see if the user hit a unary operator button
like %, sqrt, 1/x etc. that should be dealt with NOW,
not later*/
void MaybeUnaryOperation (char *str)
{
char *labelText;
char *buffer[BUF_SIZE];
float num2;
gtk_label_get(GTK_LABEL(label),&labelText);
num2=atof(labelText);
if (strcmp(str, "%")==0){num2=num2/100;}
else {if (strcmp(str, "1/x")==0){if (num2==0){return;}else {num2=1/num2;}}}
else {if (strcmp(str, "sqrt")==0){num2=sqrt((double)num2);}}
else {if (strcmp(str, "x^2")==0){num2 = num2*num2;}}
sprintf (buffer, "%f",(float)num2);
TrimTrailingZeros(buffer);
TrimLeadingZeros(buffer);
gtk_label_set (GTK_LABEL(label),buffer);
}

/*225
Handle binary operation
perform a calculation with two sets of digits. one set is in
the LED display and the other set is saved in the
global variable (num1)
*/
void HandleBinaryoperation ()
{
char *labelText;
char *buffer[BUF_SIZE];
float num2;
gtk_label_get(GTK_LABEL(label),&labelText);
num2=atof(labelText);
switch (prevCmd){
case'+':
num1=num2+num1;
break;
case'-':
num1=num1-num2;
break;
case'*':
num1=num2*num1;
break;
case'/':
num1=num1/num2;
break;
case'=':
num1=num2;
break;
default:
num1=num2;
break;
}
sprintf (buffer, "%f",(float)num1);
TrimTrailingZeros(buffer);
TrimLeadingZeros (buffer);
gtk_label_set (GTK_LABEL(label),buffer);
}

/*264*/
/* TrimTrailingZeros
get rid of trailing zeros
takes the string and removes the trailing zeros*/
void TrimTrailingZeros(char *szDigits)
{
int nIndex;
int bDecimal=FALSE;
int npos=-1;
for(nIndex=0;nIndex<strlen(szDigits);nIndex++)
{
if(szDigits[nIndex]=='.'){
           bDecimal=TRUE;}
if(bDecimal){
       if(szDigits[nIndex]=='0'){
           if(nPos<0 ){
               nPos=nIndex;
               }
                   }
} else {
           nPos=-1;
            }
}

if (nPos>0) {
   szDigits[nPos]=(char)0;
       }
}
/* 291
Trim leading Zeros
Converts numbers like 000012 to 12
*/
void TrimLeadingZeros(char *szDigits)
{
int nPos;
if (szDigits==NULL) return;
for (nPos=0;(szDigits[nPos] && szDigits[nPos]=='0');nPos++)
   { if(isdigit(szDigits[nPos+1])){
               szDigits[nPos]=' ';
               }
   }
}

int Command (char ch)
{
switch (ch) {
case '+':
case '-':
case '/':
case '*':
case '=':
return(TRUE);
}
return (FALSE);
}
int FloatingPointChar(char ch)
{
return(isdigit(ch)||ch=='.');
}






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]