diff options
Diffstat (limited to 'kspread/plugins/calculator/kcalc_core.cpp')
| -rw-r--r-- | kspread/plugins/calculator/kcalc_core.cpp | 2192 |
1 files changed, 2192 insertions, 0 deletions
diff --git a/kspread/plugins/calculator/kcalc_core.cpp b/kspread/plugins/calculator/kcalc_core.cpp new file mode 100644 index 000000000..43221b210 --- /dev/null +++ b/kspread/plugins/calculator/kcalc_core.cpp @@ -0,0 +1,2192 @@ +/* + $Id: kcalc_core.cpp 541875 2006-05-17 14:42:51Z zander $ + + kCalculator, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + The stack engine conatined in this file was take from + Martin Bartlett's xfrmcalc + + portions: Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + portions: Copyright (C) 1995 Martin Bartlett + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + +*/ + +#include <config.h> +#include <assert.h> +#include <stdio.h> +#include <errno.h> +#include <limits.h> +#include <math.h> +#include <signal.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <knotifyclient.h> + +#include "kcalc.h" + +//What's that?!? (Werner) +//#define i18n( x ) x + +// Undefine HAVE_LONG_DOUBLE for Beta 4 since RedHat 5.0 comes with a borken +// glibc + +#ifdef HAVE_LONG_DOUBLE +#undef HAVE_LONG_DOUBLE +#endif + +#ifndef HAVE_FUNC_ISINF +#ifdef HAVE_IEEEFP_H +#include <ieeefp.h> +#else +#include <math.h> +#endif + +int isinf(double x) { return !finite(x) && x==x; } +#endif + +extern QPtrList<CALCAMNT> temp_stack; +last_input_type last_input; +char display_str[DSP_SIZE+1]; + +stack_ptr top_of_stack = NULL; +stack_ptr top_type_stack[2] = { NULL, NULL }; +int stack_next, stack_last; +stack_item process_stack[STACK_SIZE]; + +int inverse = FALSE; +int precedence_base = 0; +num_base current_base = NB_DECIMAL; +int input_limit = 0; +int input_count = 0; + +//item_contents display_data = { ITEM_AMOUNT, 0 }; +item_contents display_data; + +int display_size = DEC_SIZE; + +int hyp_mode = 0; +int angle_mode = ANG_DEGREE; +int refresh_display; // if 1 we start a new number +int display_error = 0; +int decimal_point = 0; +int percent_mode = 0; +bool eestate = false; // if true then we are in ee input mode + +CALCAMNT pi; +CALCAMNT memory_num = 0.0; + +int precedence[14] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 6 }; + + int adjust_op[14][3] = { + {FUNC_NULL, FUNC_NULL, FUNC_NULL}, + {FUNC_OR, FUNC_OR, FUNC_XOR }, + {FUNC_XOR, FUNC_XOR, FUNC_XOR }, + {FUNC_AND, FUNC_AND, FUNC_AND }, + {FUNC_LSH, FUNC_LSH, FUNC_RSH }, + {FUNC_RSH, FUNC_RSH, FUNC_RSH }, + {FUNC_ADD, FUNC_ADD, FUNC_ADD }, + {FUNC_SUBTRACT, FUNC_SUBTRACT, FUNC_SUBTRACT}, + {FUNC_MULTIPLY, FUNC_MULTIPLY, FUNC_MULTIPLY}, + {FUNC_DIVIDE, FUNC_DIVIDE, FUNC_DIVIDE}, + {FUNC_MOD, FUNC_MOD, FUNC_INTDIV }, + {FUNC_POWER, FUNC_POWER, FUNC_PWR_ROOT}, + {FUNC_PWR_ROOT, FUNC_PWR_ROOT, FUNC_PWR_ROOT}, + {FUNC_INTDIV, FUNC_INTDIV, FUNC_INTDIV}, + }; +/* + char *function_desc[] = { + + "Null", + "Or", + "Exclusive Or", + "And", + "Left Shift", + "Right Shift", + "Add", + "Subtract", + "Multiply", + "Divide", + "Modulus" + "Power" + "Reciprocal Power" + "Integer Division" + }; + */ + Arith Arith_ops[14] = { NULL, + ExecOr, + ExecXor, + ExecAnd, + ExecLsh, + ExecRsh, + ExecAdd, ExecSubtract, + ExecMultiply, + ExecDivide, ExecMod, + ExecPower, ExecPwrRoot, + ExecIntDiv + }; + + Prcnt Prcnt_ops[14] = { NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ExecAddSubP, ExecAddSubP, + ExecMultiplyP, + ExecDivideP, ExecDivideP, + ExecPowerP, ExecPwrRootP, + ExecDivideP + }; + + +void QtCalculator::InitializeCalculator(void) { + + // + // Basic initialization involves initializing the calcultion + // stack, forcing the display to refresh to zero, and setting + // up the floating point excetion signal handler to trap the + // errors that the code can/has not been written to trap. + // + // We also calculate pi as double the arc sine of 1. + // + + display_data.s_item_type = ITEM_AMOUNT; + display_data.s_item_data.item_amount = 0.0; + display_data.s_item_data.item_func_data.item_function = 0; + display_data.s_item_data.item_func_data.item_precedence = 0; + + void fpe_handler(int fpe_parm); + struct sigaction fpe_trap; + + fpe_trap.sa_handler = &fpe_handler; +#ifdef SA_RESTART + fpe_trap.sa_flags = SA_RESTART; +#endif + + sigaction(SIGFPE, &fpe_trap, NULL); + + RefreshCalculator(); + pi = ASIN(1.0) * 2L; +} + +void fpe_handler(int fpe_parm) +{ + (void) fpe_parm; + + display_error = 1; + DISPLAY_AMOUNT = 0L; + +} + +void QtCalculator::setData( const QRect& _range, const char *_sheet ) +{ + sheet_range = _range; + sheet_name = _sheet; +} + +void QtCalculator::setValue( double _value ) +{ + last_input = DIGIT; + DISPLAY_AMOUNT = _value; + decimal_point = 0; + refresh_display = 1; + input_count = 0; + + UpdateDisplay(); +} + +void QtCalculator::setLabel( const char *_text ) +{ + last_input = DIGIT; + DISPLAY_AMOUNT = 0L; + decimal_point = 0; + refresh_display = 0; + input_count = 0; + + calc_display->setText( _text ); +} + +void QtCalculator::RefreshCalculator(void) +{ + InitStack(); + display_error = 0; + DISPLAY_AMOUNT = 0L; + inverse = FALSE; + UpdateDisplay(); + last_input = DIGIT; // must set last to DIGIT after Update Display in order + // not to get a display holding e.g. 0.000 + input_count = 0; + decimal_point = 0; +} + +void QtCalculator::EnterDigit(int data) +{ + + if(eestate){ + + QString string; + string.setNum(data); + strcat(display_str, string.latin1()); + DISPLAY_AMOUNT = (CALCAMNT) strtod(display_str,0); + UpdateDisplay(); + return; + + } + + last_input = DIGIT; + if (refresh_display) { + DISPLAY_AMOUNT = 0L; + decimal_point = 0; + refresh_display = 0; + input_count = 0; + } + + if (!(input_limit && input_count >= input_limit)) + if (DISPLAY_AMOUNT < 0) + DISPLAY_AMOUNT = decimal_point ? + DISPLAY_AMOUNT - ((CALCAMNT)data / + POW((float)current_base, decimal_point++)) : + (current_base * DISPLAY_AMOUNT) - data; + else + DISPLAY_AMOUNT = decimal_point ? + DISPLAY_AMOUNT + ((CALCAMNT)data / + POW((float)current_base, decimal_point++)) : + (current_base * DISPLAY_AMOUNT) + data; + + if (decimal_point){ + input_count ++; + +#ifdef MYDEBUG + printf("EnterDigit() inc dec.point:%d\n",input_count); +#endif + + } + UpdateDisplay(); +} + +void QtCalculator::button0() +{ + EnterDigit(0); +} + +void QtCalculator::button1() +{ + EnterDigit(1); + } + +void QtCalculator::button2() +{ + if (current_base == NB_BINARY) + return; + EnterDigit(2); +} + +void QtCalculator::button3() +{ + if (current_base == NB_BINARY) + return; + EnterDigit(3); +} + +void QtCalculator::button4() +{ + if (current_base == NB_BINARY) + return; + EnterDigit(4); +} + +void QtCalculator::button5() +{ + if (current_base == NB_BINARY) + return; + EnterDigit(5); +} + +void QtCalculator::button6() +{ + if (current_base == NB_BINARY) + return; + EnterDigit(6); +} + +void QtCalculator::button7() +{ + if (current_base == NB_BINARY) + return; + EnterDigit(7); +} + +void QtCalculator::button8() +{ + if ((current_base == NB_BINARY) || (current_base == NB_OCTAL)) + return; + EnterDigit(8); +} + +void QtCalculator::button9() +{ + if ((current_base == NB_BINARY) || (current_base == NB_OCTAL)) + return; + EnterDigit(9); +} + + +void QtCalculator::buttonA() +{ + if ((current_base == NB_BINARY) || (current_base == NB_OCTAL) + || (current_base == NB_DECIMAL)) + return; + EnterDigit(10); +} + + +void QtCalculator::buttonB() +{ + if ((current_base == NB_BINARY) || (current_base == NB_OCTAL) + || (current_base == NB_DECIMAL)) + return; + EnterDigit(11); +} + + +void QtCalculator::buttonC() +{ + if ((current_base == NB_BINARY) || (current_base == NB_OCTAL) + || (current_base == NB_DECIMAL)) + return; + EnterDigit(12); +} + + +void QtCalculator::buttonD() +{ + if ((current_base == NB_BINARY) || (current_base == NB_OCTAL) + || (current_base == NB_DECIMAL)) + return; + EnterDigit(13); +} + + +void QtCalculator::buttonE() +{ + if ((current_base == NB_BINARY) || (current_base == NB_OCTAL) + || (current_base == NB_DECIMAL)) + return; + EnterDigit(14); +} + +void QtCalculator::buttonF() +{ + if ((current_base == NB_BINARY) || (current_base == NB_OCTAL) + || (current_base == NB_DECIMAL)) + return; + EnterDigit(15); +} + + + +void QtCalculator::EnterDecimal() +{ + + if(eestate){ + KNotifyClient::beep(); + return; + } + + decimal_point = 1; + if (refresh_display) { + DISPLAY_AMOUNT = 0L; + refresh_display = 0; + input_count = 0; + } + + if (last_input == DIGIT && !strpbrk( display_str,".")){ + + // if the last input was a DIGIT and we don't have already a period in our + // display string then display a period + + calc_display->setText(strcat(display_str, ".")); + } + else { + + // the last input wasn't a DIGIT so we are about to + // input a new number in particular we neet do display a "0.". + + DISPLAY_AMOUNT = 0L; + refresh_display = 0; + // decimal_point = 1; + // input_count = 1; + strcpy(display_str, "0."); + calc_display->setText(display_str); + } +} + + +void QtCalculator::Or() +{ + eestate = false; + if (inverse){ + EnterStackFunction(2); // XOR + inverse = FALSE; + } + else { + EnterStackFunction(1); // OR + } + last_input = OPERATION; +} + +void QtCalculator::And() +{ + eestate = false; + last_input = OPERATION; + EnterStackFunction(3); +} + + +void QtCalculator::Shift() +{ + eestate = false; + last_input = OPERATION; + if (inverse){ + EnterStackFunction(5); // Rsh + inverse = FALSE; + } + else { + EnterStackFunction(4); // Lsh + } + +} + +void QtCalculator::Plus() +{ + eestate = false; + last_input = OPERATION; + EnterStackFunction(6); +} + +void QtCalculator::Minus() +{ + eestate = false; + last_input = OPERATION; + EnterStackFunction(7); + +} + +void QtCalculator::Multiply() +{ + eestate = false; + last_input = OPERATION; + EnterStackFunction(8); +} + +void QtCalculator::Divide() +{ + eestate = false; + last_input = OPERATION; + EnterStackFunction(9); +} + +void QtCalculator::Mod() +{ + eestate = false; + last_input = OPERATION; + if (inverse){ + EnterStackFunction(13); // InvMod + inverse = FALSE; + } + else { + EnterStackFunction(10); // Mod + } +} + +void QtCalculator::Power() +{ + eestate = false; + last_input = OPERATION; + if (inverse){ + EnterStackFunction(12); // InvPower + inverse = FALSE; + } + else { + EnterStackFunction(11); // Power + } + +} + + + +void QtCalculator::EnterStackFunction(int data) +{ + item_contents new_item; + int new_precedence; + int dummy; + + dummy = 0; + + /* + if (inverse ) { + dummy = 3; + inverse = FALSE; + } + else { + dummy = 1; + } + */ + + // printf("data %d dummy %d\n",data,dummy); + data = adjust_op[data][dummy]; + // printf("data %d \n",data ); + + PushStack(&display_data); + + new_item.s_item_type = ITEM_FUNCTION; + new_item.s_item_data.item_func_data.item_function = data; + new_item.s_item_data.item_func_data.item_precedence = + new_precedence = precedence[data] + precedence_base; + + refresh_display = 1; + if (UpdateStack(new_precedence)) + UpdateDisplay(); + PushStack(&new_item); +} + +void QtCalculator::EnterNegate() +{ + + if(eestate){ + QString string; + string = display_str; + int pos; + pos = string.findRev('e',-1,false); + if(pos == -1) + return; + + if(display_str[pos+1] == '+') + display_str[pos+1] = '-'; + else{ + if(display_str[pos+1] == '-') + display_str[pos+1] = '+'; + else{ + string.insert(pos +1,'-'); + strncpy(display_str,string.latin1(),DSP_SIZE); + } + } + DISPLAY_AMOUNT = (CALCAMNT)strtod(display_str,0); + UpdateDisplay(); + } + else{ + // last_input = OPERATION; + if (DISPLAY_AMOUNT != 0) { + DISPLAY_AMOUNT *= -1; + UpdateDisplay(); + } + } + last_input = DIGIT; +} + +void QtCalculator::EnterOpenParen() +{ + eestate = false; + last_input = OPERATION; + precedence_base += PRECEDENCE_INCR; + refresh_display = 1; + +} + +void QtCalculator::EnterCloseParen() +{ + eestate = false; + last_input = OPERATION; + PushStack(&display_data); + refresh_display = 1; + if (UpdateStack(precedence_base)) + UpdateDisplay(); + if ((precedence_base -= PRECEDENCE_INCR) < 0) + precedence_base = 0; + +} + +void QtCalculator::EnterRecip() +{ + eestate = false; + last_input = OPERATION; + DISPLAY_AMOUNT = 1 / DISPLAY_AMOUNT; + refresh_display = 1; + UpdateDisplay(); +} + +void QtCalculator::EnterInt() +{ + eestate = false; + CALCAMNT work_amount1 = 0.0, work_amount2 = 0.0; + + last_input = OPERATION; + if (!inverse){ + work_amount2 = MODF(DISPLAY_AMOUNT, &work_amount1); + DISPLAY_AMOUNT = work_amount2 ; + } + else { + DISPLAY_AMOUNT = work_amount1; + inverse = FALSE; + } + + refresh_display = 1; + UpdateDisplay(); + +} + +void QtCalculator::EnterFactorial() +{ + eestate = false; + CALCAMNT work_amount1, work_amount2; + int incr; + + MODF(DISPLAY_AMOUNT, &work_amount1); + + incr = work_amount1 < 0 ? -1 : 1; + work_amount2 = work_amount1 - incr; + while (work_amount1 != 0 && work_amount2 != 0 && !display_error) { + work_amount1 *= work_amount2; + work_amount2 -= incr; + if(isinf(work_amount1)) { + display_error=1; + break; + } + } + + if( work_amount1 == 0.0) + work_amount1 = 1.0; + + DISPLAY_AMOUNT = work_amount1; + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + +} + +void QtCalculator::EnterSquare() +{ + eestate = false; + if (!inverse){ + DISPLAY_AMOUNT *= DISPLAY_AMOUNT; + } + else if (DISPLAY_AMOUNT < 0) + display_error = 1; + else + DISPLAY_AMOUNT = SQRT(DISPLAY_AMOUNT); + refresh_display = 1; + inverse = FALSE; + last_input = OPERATION; + UpdateDisplay(); + +} + +void QtCalculator::EnterNotCmp() +{ + eestate = false; + CALCAMNT boh_work_d; + long boh_work; + + MODF(DISPLAY_AMOUNT, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) + display_error = 1; + else { + boh_work = (long int) boh_work_d; + DISPLAY_AMOUNT = ~boh_work; + } + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + +} + +void QtCalculator::EnterHyp() +{ + + switch(kcalcdefaults.style){ + case 2: + case 1:{ + if ( !sheet_name.isEmpty() ) + useData(); + + if(!inverse){ + eestate = false; // terminate ee input mode + DISPLAY_AMOUNT = stats.count(); + last_input = OPERATION; + refresh_display = 1; + UpdateDisplay(); + } + else{ + inverse = false; + eestate = false; // terminate ee input mode + DISPLAY_AMOUNT = stats.sum(); + last_input = OPERATION; + refresh_display = 1; + UpdateDisplay(); + } + + break; + } + + case 0: { + // toggle between hyperbolic and standart trig functions + hyp_mode = !hyp_mode; + + if (hyp_mode){ + statusHYPLabel->setText("HYP"); + } + else{ + statusHYPLabel->setText(""); + } + break; + } + } +} + + +void QtCalculator::ExecSin(){ + + switch(kcalcdefaults.style){ + + case 0:{ // trig mode + + ComputeSin(); + break; + } + + case 1:{ // stats mode + if ( !sheet_name.isEmpty() ) + useData(); + + ComputeMean(); + break; + } + + case 2:{ // sheet mode + if ( !sheet_name.isEmpty() ) + useData(); + + ComputeMin(); + break; + } + + } + +} + +void QtCalculator::ComputeSum() +{ + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.sum(); + if (stats.error()) + display_error = 1; + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); +} + +void QtCalculator::ComputeMul() +{ + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.mul(); + if (stats.error()) + display_error = 1; + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); +} + +void QtCalculator::ComputeMin() +{ + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.min(); + if (stats.error()) + display_error = 1; + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); +} + +void QtCalculator::ComputeMax() +{ + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.max(); + if (stats.error()) + display_error = 1; + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); +} + +void QtCalculator::ComputeMean(){ + + if(!inverse){ + eestate = false; + DISPLAY_AMOUNT = stats.mean(); + if (stats.error()) + display_error = 1; + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + } + else{ + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.sum_of_squares(); + if (stats.error()) + display_error = 1; + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + + } + +} + +void QtCalculator::ComputeSin() +{ + CALCAMNT work_amount; + eestate = false; + work_amount = DISPLAY_AMOUNT; + + if (hyp_mode){ + // sinh or arcsinh + if (!inverse){ + DISPLAY_AMOUNT = SINH( work_amount); + } + else { + DISPLAY_AMOUNT = ASINH( work_amount); + if (errno == EDOM || errno == ERANGE) + display_error = 1; + inverse = FALSE; // reset the inverse flag + } + } + else { + // sine or arcsine + if (!inverse){ + // sine + switch (angle_mode) { + case ANG_DEGREE: + work_amount = DEG2RAD(DISPLAY_AMOUNT); + break; + case ANG_GRADIENT: + work_amount = GRA2RAD(DISPLAY_AMOUNT); + break; + case ANG_RADIAN: + work_amount = DISPLAY_AMOUNT; + break; + } + DISPLAY_AMOUNT = SIN( work_amount); + } + else { + // arcsine + DISPLAY_AMOUNT = ASIN(work_amount); + switch (angle_mode) { + case ANG_DEGREE: + work_amount = RAD2DEG(DISPLAY_AMOUNT); + break; + case ANG_GRADIENT: + work_amount = RAD2GRA(DISPLAY_AMOUNT); + break; + case ANG_RADIAN: + work_amount = DISPLAY_AMOUNT; + break; + } + DISPLAY_AMOUNT = work_amount; + if (errno == EDOM || errno == ERANGE) + display_error = 1; + inverse = FALSE; // reset the inverse flag + } + } + +// Now a cheat to help the weird case of COS 90 degrees not being 0!!! + + if (DISPLAY_AMOUNT < POS_ZERO && DISPLAY_AMOUNT > NEG_ZERO) + DISPLAY_AMOUNT=0; + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + +} + +void QtCalculator::ExecCos(){ + + switch(kcalcdefaults.style){ + + case 0:{ // trig mode + + ComputeCos(); + break; + } + + case 1:{ // stats mode + if ( !sheet_name.isEmpty() ) + useData(); + + ComputeStd(); + break; + } + + case 2:{ // sheet mode + if ( !sheet_name.isEmpty() ) + useData(); + + ComputeMax(); + break; + } + + } + +} + +void QtCalculator::ComputeStd(){ + + if(!inverse){ // std (n-1) + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.std(); + + if (stats.error()){ + display_error = 1; + } + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + } + else{ // std (n) + + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.sample_std(); + + if (stats.error()) + display_error = 1; + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + + + + } + +} + +void QtCalculator::ComputeCos() +{ + CALCAMNT work_amount; + eestate = false; + work_amount = DISPLAY_AMOUNT; + + if (hyp_mode){ + // cosh or arccosh + if (!inverse){ + DISPLAY_AMOUNT = COSH( work_amount); + } + else { + DISPLAY_AMOUNT = ACOSH( work_amount); + if (errno == EDOM || errno == ERANGE) + display_error = 1; + inverse = FALSE; // reset the inverse flag + } + } + else { + // cosine or arccosine + if (!inverse){ + // sine + switch (angle_mode) { + case ANG_DEGREE: + work_amount = DEG2RAD(DISPLAY_AMOUNT); + break; + case ANG_GRADIENT: + work_amount = GRA2RAD(DISPLAY_AMOUNT); + break; + case ANG_RADIAN: + work_amount = DISPLAY_AMOUNT; + break; + } + DISPLAY_AMOUNT = COS( work_amount); + } + else { + // arccosine + DISPLAY_AMOUNT = ACOS(work_amount); + switch (angle_mode) { + case ANG_DEGREE: + work_amount = RAD2DEG(DISPLAY_AMOUNT); + break; + case ANG_GRADIENT: + work_amount = RAD2GRA(DISPLAY_AMOUNT); + break; + case ANG_RADIAN: + work_amount = DISPLAY_AMOUNT; + break; + } + + DISPLAY_AMOUNT = work_amount; + + if (errno == EDOM || errno == ERANGE) + display_error = 1; + inverse = FALSE; // reset the inverse flag + } + } + +// Now a cheat to help the weird case of COS 90 degrees not being 0!!! + + + if (DISPLAY_AMOUNT < POS_ZERO && DISPLAY_AMOUNT > NEG_ZERO) + DISPLAY_AMOUNT=0; + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + +} + +void QtCalculator::ExecTan(){ + + switch(kcalcdefaults.style){ + + case 0:{ // trig mode + + ComputeTan(); + break; + } + + case 2: + case 1:{ // stats mode + + if ( !sheet_name.isEmpty() ) + useData(); + + ComputeMedean(); + break; + } + + } + +} + +void QtCalculator::ComputeMedean(){ + + if(!inverse){ // std (n-1) + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.median(); + + if (stats.error()){ + display_error = 1; + } + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + } + else{ // std (n) + + inverse = false; + eestate = false; + DISPLAY_AMOUNT = stats.median(); + + if (stats.error()) + display_error = 1; + + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + + } +} + + +void QtCalculator::ComputeTan() +{ + CALCAMNT work_amount; + eestate = false; + work_amount = DISPLAY_AMOUNT; + + if (hyp_mode){ + // tanh or arctanh + if (!inverse){ + DISPLAY_AMOUNT = TANH( work_amount); + } + else { + DISPLAY_AMOUNT = ATANH( work_amount); + if (errno == EDOM || errno == ERANGE) + display_error = 1; + inverse = FALSE; // reset the inverse flag + } + } + else { + // tan or arctan + if (!inverse){ + // tan + switch (angle_mode) { + case ANG_DEGREE: + work_amount = DEG2RAD(DISPLAY_AMOUNT); + break; + case ANG_GRADIENT: + work_amount = GRA2RAD(DISPLAY_AMOUNT); + break; + case ANG_RADIAN: + work_amount = DISPLAY_AMOUNT; + break; + } + DISPLAY_AMOUNT = TAN( work_amount); + if (errno == EDOM || errno == ERANGE) + display_error = 1; + } + else { + // arctan + DISPLAY_AMOUNT = ATAN(work_amount); + switch (angle_mode) { + case ANG_DEGREE: + work_amount = RAD2DEG(DISPLAY_AMOUNT); + break; + case ANG_GRADIENT: + work_amount = RAD2GRA(DISPLAY_AMOUNT); + break; + case ANG_RADIAN: + work_amount = DISPLAY_AMOUNT; + break; + } + + DISPLAY_AMOUNT = work_amount; + + if (errno == EDOM || errno == ERANGE) + display_error = 1; + inverse = FALSE; // reset the inverse flag + } + } + +// Now a cheat to help the weird case of COS 90 degrees not being 0!!! + + if (DISPLAY_AMOUNT < POS_ZERO && DISPLAY_AMOUNT > NEG_ZERO) + DISPLAY_AMOUNT=0; + refresh_display = 1; + last_input = OPERATION; + UpdateDisplay(); + +} + + +void QtCalculator::EnterPercent() +{ + eestate = false; + last_input = OPERATION; + percent_mode = 1; + EnterEqual(); + percent_mode = 0; + +} + +void QtCalculator::EnterLogr() +{ + + switch(kcalcdefaults.style){ + case 2: + { + if ( !sheet_name.isEmpty() ) + useData(); + + ComputeSum(); + break; + } + case 1:{ + + if ( !sheet_name.isEmpty() ) + useData(); + + if(!inverse){ + eestate = false; // terminate ee input mode + stats.enterData(DISPLAY_AMOUNT); + last_input = OPERATION; + refresh_display = 1; + DISPLAY_AMOUNT = stats.count(); + UpdateDisplay(); + } + else{ + inverse = false; + last_input = OPERATION; + refresh_display = 1; + stats.clearLast(); + setStatusLabel("Last stat item erased"); + DISPLAY_AMOUNT = stats.count(); + UpdateDisplay(); + + } + + break; + } + case 0:{ + + eestate = false; + last_input = OPERATION; + + if (!inverse) { + if (DISPLAY_AMOUNT <= 0) + display_error = 1; + else + DISPLAY_AMOUNT = LOG_TEN(DISPLAY_AMOUNT); + refresh_display = 1; + UpdateDisplay(); + } else if (inverse) { + DISPLAY_AMOUNT = POW(10, DISPLAY_AMOUNT); + refresh_display = 1; + inverse = FALSE; + UpdateDisplay(); + } + break; + } + } +} + +void QtCalculator::EnterLogn() +{ + + switch(kcalcdefaults.style){ + case 2:{ + + if ( !sheet_name.isEmpty() ) + useData(); + + ComputeMul(); + + break; + } + case 1:{ + + if ( !sheet_name.isEmpty() ) + useData(); + + if(!inverse){ + + stats.clearAll(); + setStatusLabel(i18n("Stat mem cleared")); + + } + else{ + inverse = false; + UpdateDisplay(); + } + + break; + } + case 0:{ + eestate = false; + last_input = OPERATION; + if (!inverse) { + if (DISPLAY_AMOUNT <= 0) + display_error = 1; + else + DISPLAY_AMOUNT = LOG(DISPLAY_AMOUNT); + refresh_display = 1; + UpdateDisplay(); + } else if (inverse) { + DISPLAY_AMOUNT = EXP(DISPLAY_AMOUNT); + refresh_display = 1; + inverse =FALSE; + UpdateDisplay(); + } + break; + } + } + +} + + +void QtCalculator::base_selected(int number){ + + switch(number){ + case 0: + SetHex(); + break; + case 1: + SetDec(); + break; + case 2: + SetOct(); + break; + case 3: + SetBin(); + break; + default: // we shouldn't ever end up here + SetDec(); + } +} + + +void QtCalculator::angle_selected(int number){ + + switch(number){ + case 0: + SetDeg(); + break; + case 1: + SetRad(); + break; + case 2: + SetGra(); + break; + default: // we shouldn't ever end up here + SetRad(); + } +} + +void QtCalculator::SetInverse(){ + + inverse = ! inverse; + if (inverse){ + statusINVLabel->setText("INV"); + } + else{ + statusINVLabel->setText("NORM"); + } +} + + +void QtCalculator::SetDeg() { + angle_mode = ANG_DEGREE; +} + +void QtCalculator::SetGra() { + angle_mode = ANG_GRADIENT; +} + +void QtCalculator::SetRad() { + angle_mode = ANG_RADIAN; + +} + +void QtCalculator::SetHex() { + /* + * Set Hex Mode + */ + + current_base = NB_HEX; + display_size = BOH_SIZE; + decimal_point = 0; + input_limit = 8; + + UpdateDisplay(); +} + +void QtCalculator::SetOct() { + /* + * Set Oct Mode + */ + + current_base = NB_OCTAL; + display_size = BOH_SIZE; + decimal_point = 0; + input_limit = 11; + + UpdateDisplay(); +} + +void QtCalculator::SetBin() { + /* + * Set Bin Mode + */ + + current_base = NB_BINARY; + display_size = BOH_SIZE; + decimal_point = 0; + input_limit = 16; + + UpdateDisplay(); +} + +void QtCalculator::SetDec() +{ + /* + * Set Dec Mode + */ + + current_base = NB_DECIMAL; + display_size = DEC_SIZE; + input_limit = 0; + + + UpdateDisplay(); +} + + +void QtCalculator::EE() +{ + if(inverse){ + DISPLAY_AMOUNT = pi; + inverse = FALSE; + UpdateDisplay(); + } + else{ + if(eestate == true) + eestate = false; + else{ + eestate = true; + strcat(display_str,"e"); + } + + UpdateDisplay(); + } + +} + +void QtCalculator::MR() +{ + eestate = false; + last_input = OPERATION; + DISPLAY_AMOUNT = memory_num; + refresh_display = 1; + UpdateDisplay(); + +} + +void QtCalculator::Mplusminus() +{ + + eestate = false; + EnterEqual(); + if (!inverse) + memory_num += DISPLAY_AMOUNT; + else { + memory_num -= DISPLAY_AMOUNT; + inverse = FALSE; + } +} + +void QtCalculator::MC() +{ + + memory_num = 0; + refresh_display = 1; +} + +void QtCalculator::EnterEqual() +{ + eestate = false; + last_input = OPERATION; + PushStack(&display_data); + refresh_display = 1; + + /* if (UpdateStack(0))*/ + UpdateStack(0); + + UpdateDisplay(); + precedence_base = 0; + + CALCAMNT* number ; + + if(temp_stack.count() > TEMP_STACK_SIZE){ + + number = temp_stack.getFirst(); + temp_stack.removeFirst(); + + if(number) + free(number); + } + + number = (CALCAMNT*) malloc(sizeof(CALCAMNT)); + *number = DISPLAY_AMOUNT; + + //printf("appending %Lg\n",*number); + + temp_stack.append(number); + + +} + +void QtCalculator::Clear(){ + + eestate = false; + + input_count = 0; + decimal_point = 0; + + if(last_input == OPERATION){ + // printf("LAST_INPUT = OPERATION\n"); + last_input = DIGIT; + PopStack(); + } + else{ + // printf("LAST_INPUT = DIGIT\n"); + last_input = DIGIT; + } + + + if( display_error){ + display_error = 0; + refresh_display = 0; + } + + if (!refresh_display) { + DISPLAY_AMOUNT = 0L; + UpdateDisplay(); + } + +} + +void QtCalculator::ClearAll() +{ + + eestate = false; + // last_input = OPERATION; + last_input = DIGIT; + RefreshCalculator(); + refresh_display = 1; + +} + + + +void QtCalculator::UpdateDisplay() +{ + + // this needs to be rewritten based on whether we are currently + // inputting a number so that the period and the 0 after a period + // are correctly displayed. + + CALCAMNT boh_work_d; + long boh_work = 0; + int str_size = 0; + + if(eestate && (current_base == NB_DECIMAL)){ + + calc_display->setText(display_str); + return; + } + + if (current_base != NB_DECIMAL) { + MODF(DISPLAY_AMOUNT, &boh_work_d); + if (boh_work_d < LONG_MIN || boh_work_d > ULONG_MAX) + display_error = 1; + + /* + * We may be in that never-never land where boh numbers + * turn from positive to negative - if so then we do + * just that, allowing boh negative numbers to be entered + * as read (from dumps and the like!) + */ + else if (boh_work_d > LONG_MAX) { + DISPLAY_AMOUNT = + LONG_MIN+(boh_work_d-LONG_MAX-1); + boh_work = (long)DISPLAY_AMOUNT; + } + else { + DISPLAY_AMOUNT = boh_work_d; + boh_work = (long) boh_work_d; + } + } + + if (!display_error) { + + if (current_base == NB_BINARY) + str_size = cvb(display_str, + boh_work, + BOH_SIZE); + else if (current_base == NB_OCTAL) + str_size = sprintf(display_str, + "%lo", + boh_work); + else if (current_base == NB_DECIMAL) { + + if(!kcalcdefaults.fixed || last_input == DIGIT + || (DISPLAY_AMOUNT > 1.0e+16)){ + + // if I don't guard against the DISPLAY_AMOUNT being too large + // kcalc will segfault on larger amount. Such as from typing + // from 5*5******* + + str_size = sprintf(display_str, + +#ifdef HAVE_LONG_DOUBLE + "%.*Lg", // was *Lg + + kcalcdefaults.precision +1, +#else + "%.*g", + + kcalcdefaults.precision +1, +#endif + DISPLAY_AMOUNT); + } + else{//fixed + + str_size = sprintf(display_str, + +#ifdef HAVE_LONG_DOUBLE + "%.*Lf", // was *Lg + + kcalcdefaults.fixedprecision , +#else + "%.*f", + + kcalcdefaults.fixedprecision , +#endif + DISPLAY_AMOUNT); + + }// fixed + + if ( input_count > 0 && !strpbrk(display_str,"e") && + last_input == DIGIT ) { + +#ifdef HAVE_LONG_DOUBLE + str_size = sprintf(display_str, + "%.*Lf", + (kcalcdefaults.precision +1 > input_count)? + input_count : kcalcdefaults.precision , + DISPLAY_AMOUNT); +#else + str_size = sprintf(display_str, + "%.*f", + (kcalcdefaults.precision +1 > input_count)? + input_count : kcalcdefaults.precision , + DISPLAY_AMOUNT); +#endif + } + + } + else + if (current_base == NB_HEX) + str_size = sprintf(display_str, + "%lX", + boh_work); + else + display_error = 1; + } + + if (display_error || str_size < 0) { + display_error = 1; + strcpy(display_str,"Error"); + if(kcalcdefaults.beep) + KNotifyClient::beep(); + } + calc_display->setText(display_str); + + + if (inverse){ + statusINVLabel->setText("INV"); + } + else{ + statusINVLabel->setText("NORM"); + } + + if (hyp_mode){ + statusHYPLabel->setText("HYP"); + } + else{ + statusHYPLabel->setText(""); + } + + +} + +int cvb(char *out_str, long amount, int max_digits) +{ + /* + * A routine that converts a long int to + * binary display format + */ + + char work_str[(sizeof(amount) * CHAR_BIT) + 1]; + int work_char = 0, + lead_zero = 1, + lead_one = 1, + lead_one_count = 0, + work_size = sizeof(amount) * CHAR_BIT; + unsigned long bit_mask = (1 << ((sizeof(amount) * CHAR_BIT) - 1)); + + while (bit_mask) { + + if (amount & bit_mask) { + if (lead_one) + lead_one_count++; + lead_zero = 0; + work_str[work_char++] = '1'; + } else { + lead_one = 0; + if (!lead_zero) + work_str[work_char++] = '0'; + } + bit_mask >>= 1; + } + if (!work_char) + work_str[work_char++] = '0'; + work_str[work_char] = '\0'; + + if (work_char-lead_one_count < max_digits) + return strlen(strcpy(out_str, + &work_str[lead_one_count ? + work_size - max_digits : + 0])); + else + return -1; +} + +int UpdateStack(int run_precedence) +{ + item_contents new_item, *top_item , *top_function; + CALCAMNT left_op =0.0 , right_op =0.0; + int op_function= 0, return_value = 0; + + new_item.s_item_type = ITEM_AMOUNT; + while ((top_function = TopTypeStack(ITEM_FUNCTION)) && + top_function->s_item_data.item_func_data.item_precedence >= + run_precedence) { + + return_value = 1; + + if ((top_item = PopStack())->s_item_type != ITEM_AMOUNT){ + KMessageBox::error( 0, "Stack processing error - right_op"); + + } + right_op = top_item->s_item_data.item_amount; + + if (!((top_item = PopStack()) && + top_item->s_item_type == ITEM_FUNCTION)) { + KMessageBox::error( 0, "Stack processing error - function"); + + } + op_function = + top_item->s_item_data.item_func_data.item_function; + + if (!((top_item = PopStack()) && + top_item->s_item_type == ITEM_AMOUNT)) { + KMessageBox::error( 0, "Stack processing error - left_op"); + } + left_op = top_item->s_item_data.item_amount; + + new_item.s_item_data.item_amount = + (Arith_ops[op_function])(left_op, right_op); + PushStack(&new_item); + + } + if (return_value && + percent_mode && + !display_error && + Prcnt_ops[op_function] != NULL){ + new_item.s_item_data.item_amount = + (Prcnt_ops[op_function])(left_op, + right_op, + new_item.s_item_data.item_amount); + PushStack(&new_item); + } + if (return_value) + DISPLAY_AMOUNT = new_item.s_item_data.item_amount; + + return return_value; +} + +int isoddint(CALCAMNT input) +{ + CALCAMNT dummy; + /* + * Routine to check if CALCAMNT is an Odd integer + */ + return (MODF(input, &dummy) == 0.0 && + MODF(input/2, &dummy) == 0.5); +} + +CALCAMNT ExecOr(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecOr\n"); + CALCAMNT boh_work_d; + long boh_work_l, boh_work_r; + + MODF(left_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_l = (long int)boh_work_d; + MODF(right_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_r = (long int) boh_work_d; + return (boh_work_l | boh_work_r); +} + +CALCAMNT ExecXor(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecXOr\n"); + CALCAMNT boh_work_d; + long boh_work_l, boh_work_r; + + MODF(left_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_l = (long int) boh_work_d; + MODF(right_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_r = (long int) boh_work_d; + return (boh_work_l ^ boh_work_r); +} + +CALCAMNT ExecAnd(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecAnd\n"); + CALCAMNT boh_work_d; + long boh_work_l, boh_work_r; + + MODF(left_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_l = (long int ) boh_work_d; + MODF(right_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_r = (long int ) boh_work_d; + return (boh_work_l & boh_work_r); +} + +CALCAMNT ExecLsh(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecLsh\n"); + CALCAMNT boh_work_d; + long boh_work_l, boh_work_r; + + MODF(left_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_l = (long int) boh_work_d; + MODF(right_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_r = (long int ) boh_work_d; + return (boh_work_l << boh_work_r); +} + +CALCAMNT ExecRsh(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecRsh\n"); + CALCAMNT boh_work_d; + long boh_work_l, boh_work_r; + + MODF(left_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_l = (long int ) boh_work_d; + MODF(right_op, &boh_work_d); + if (FABS(boh_work_d) > LONG_MAX) { + display_error = 1; + return 0; + } + boh_work_r = ( long int ) boh_work_d; + return (boh_work_l >> boh_work_r); +} + +CALCAMNT ExecAdd(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecAdd\n"); + return left_op + right_op; +} + +CALCAMNT ExecSubtract(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecSubtract\n"); + return left_op - right_op; +} + +CALCAMNT ExecMultiply(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecMulti\n"); + return left_op * right_op; +} + +CALCAMNT ExecDivide(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecDivide\n"); + if (right_op == 0) { + display_error = 1; + return 0L; + } else + return left_op / right_op; +} + +CALCAMNT ExecMod(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("ExecMod\n"); + CALCAMNT temp =0.0; + + if (right_op == 0) { + display_error = 1; + return 0L; + } else { + + // x mod y should be the same as x mod -y, thus: + right_op = FABS(right_op); + + temp = FMOD(left_op, right_op); + + // let's make sure that -7 mod 3 = 2 and NOT -1. + // In other words we wand x mod 3 to be a _positive_ number + // that is 0,1 or 2. + + if( temp < 0 ) temp = right_op + temp; + temp = FABS(temp); + + return temp; + } +} + +CALCAMNT ExecIntDiv(CALCAMNT left_op, CALCAMNT right_op) +{ + // printf("IndDiv\n"); + if (right_op == 0) { + display_error = 1; + return 0L; + } else { + MODF(left_op / right_op, &left_op); + return left_op; + } +} + +CALCAMNT ExecPower(CALCAMNT left_op, CALCAMNT right_op) +{ + + // printf("ExecPowser %g left_op, %g right_op\n",left_op, right_op); + if (right_op == 0) + return 1L; + if (left_op < 0 && isoddint(1/right_op)) + left_op = -1L * POW((-1L * left_op), right_op); + else + left_op = POW(left_op, right_op); + if (errno == EDOM || errno == ERANGE) { + display_error = 1; + return 0; + } else + return left_op; +} + +CALCAMNT ExecPwrRoot(CALCAMNT left_op, CALCAMNT right_op) +{ + + // printf("ExecPwrRoot %g left_op, %g right_op\n", left_op, right_op); + if (right_op == 0) { + display_error = 1; + return 0L; + } + if (left_op < 0 && isoddint(right_op)) + left_op = -1L * POW((-1L * left_op), (1L)/right_op); + else + left_op = POW(left_op, (1L)/right_op); + if (errno == EDOM || errno == ERANGE) { + display_error = 1; + return 0; + } + else + return left_op; +} + + +CALCAMNT ExecAddSubP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result) +{ + // printf("ExecAddsubP\n"); + (void) left_op; + + if (result == 0) { + display_error = 1; + return 0; + } else + return (result * 100L) / right_op; +} + +CALCAMNT ExecMultiplyP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result) +{ + // printf("ExecMultiplyP\n"); + (void) left_op; + (void) right_op; + + return (result / 100L); +} + +CALCAMNT ExecDivideP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result) +{ + // printf("ExecDivideP\n"); + (void) left_op; + (void) right_op; + + return (result * 100L); +} + +CALCAMNT ExecPowerP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result) +{ + // printf("ExecPowerP\n"); + (void) result; + return ExecPower(left_op, (right_op / 100L)); +} + +CALCAMNT ExecPwrRootP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result) +{ + // printf("ExePwrRootP\n"); + (void) result; + + if (right_op == 0) { + display_error = 1; + return 0; + } else + return ExecPower(left_op, (100L / right_op)); +} + + + +stack_ptr AllocStackItem (void) { + + if (stack_next <= stack_last) { + + process_stack[stack_next].prior_item = NULL; + process_stack[stack_next].prior_type = NULL; + return &process_stack[stack_next++]; + } + + KMessageBox::error( 0, "Stack Error !"); + return &process_stack[stack_next]; +} + +void UnAllocStackItem (stack_ptr return_item) { + + if (return_item != &process_stack[--stack_next]) { + + KMessageBox::error( 0, "Stack Error !"); + } + +} +void PushStack(item_contents *add_item) +{ + /* + * Add an item to the stack + */ + + stack_ptr new_item = top_of_stack; + + if (!(new_item && + new_item->item_value.s_item_type == add_item->s_item_type)) { + + new_item = AllocStackItem(); /* Get a new item */ + + /* + * Chain new item to existing stacks + */ + + new_item->prior_item = top_of_stack; + top_of_stack = new_item; + new_item->prior_type = top_type_stack[add_item->s_item_type]; + top_type_stack[add_item->s_item_type] = new_item; + } + + new_item->item_value = *add_item; /* assign contents*/ + +} + +item_contents *PopStack(void) +{ + /* + * Remove and return the top item in the stack + */ + + static item_contents return_item; + item_contents *return_item_ptr = NULL; + stack_ptr return_stack_ptr; + + if ((return_stack_ptr = top_of_stack)) { + return_item = top_of_stack->item_value; + + top_type_stack[return_item.s_item_type] + = top_of_stack->prior_type; + top_of_stack = top_of_stack->prior_item; + + UnAllocStackItem(return_stack_ptr); + return_item_ptr = &return_item; + } + + return return_item_ptr; +} + +item_contents *TopOfStack(void) +{ + /* + * Return the top item in the stack without removing + */ + + item_contents *return_item_ptr = NULL; + + if (top_of_stack) { + return_item_ptr = &top_of_stack->item_value; + } + + return return_item_ptr; +} + +item_contents *TopTypeStack(item_type rqstd_type) +{ + /* + * Return the top item in the stack without removing + */ + + item_contents *return_item_ptr = NULL; + + if (top_type_stack[rqstd_type]) { + return_item_ptr = &top_type_stack[rqstd_type]->item_value; + } + + return return_item_ptr; +} + + +/* + * Stack storage management Data and Functions + */ + + + +void InitStack (void) { + + stack_next = 0; + stack_last = STACK_SIZE - 1; + top_of_stack = top_type_stack[0] = top_type_stack[1] = NULL; +} + + |
