home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / software / varie / simplecalc / calc.math.c < prev    next >
C/C++ Source or Header  |  2000-01-28  |  9KB  |  361 lines

  1. /* -----------------------------------------------------------
  2.   $VER: calc.math.c 1.01 (28.01.1999)
  3.  
  4.   maths core for calculator project
  5.  
  6.   (C) Copyright 2000 Matthew J Fletcher - All Rights Reserved.
  7.   amimjf@connectfree.co.uk - www.amimjf.connectfree.co.uk
  8.   ------------------------------------------------------------ */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include <dos/dos.h>
  16. #include <exec/types.h>
  17. #include <exec/exec.h>
  18. #include <graphics/gfxmacros.h>
  19. #include <graphics/gfxbase.h>
  20.  
  21. #include <intuition/intuition.h>
  22. #include <intuition/intuitionbase.h>
  23.  
  24. #include <clib/intuition_protos.h>
  25. #include <clib/graphics_protos.h>
  26. #include <clib/exec_protos.h>
  27.  
  28. #include "Calc.h"
  29.  
  30. #define MAX 255 /* max char precision */
  31.  
  32. /* buffers for maths core preserved betwen calls */
  33. long double result=0; /* final total */
  34. char number1[MAX];    /* first number */
  35. char op;              /* math op */
  36. char number2[MAX];    /* second number */
  37. int i=0,y=0;
  38. int flag=0,sflag=0;  /* control flags */
  39.  
  40. /* tape history */
  41. extern int UseTape;
  42. /* maths mode */
  43. extern int mode;
  44. /* whats on screen */
  45. extern char buffer[100];
  46.  
  47. double do_math(char inchar)
  48. { /* maths core for calculator */
  49. char *t1,*t2;
  50. static long double realnumber1,realnumber2,realresult;
  51.  
  52. /* if previous result exists & op is first gad pressed */
  53. if ( ((inchar == '+' ) || (inchar == '-' ) || (inchar == '/' ) ||
  54.      (inchar == '*' )) && (result != 0)
  55.    )
  56.    /* second or more calc */
  57.    {
  58.     op = inchar; /* store */
  59.     // printf("operation (%c)\n",op);
  60.     draw_op(op);
  61.     flag =1;  /* now only fill second number */
  62.     sflag =1; /* calc, uses stored number as number1 */
  63.  
  64.     /* copy previous result to number1 store */
  65.     realnumber1 = result;
  66.    }
  67.  
  68. /* if input is number and op is blank store */
  69. if ( ((isdigit(inchar) != 0) || (inchar =='.')) && (flag ==0))
  70.    /* make sure we are first number */
  71.    {
  72.     /* first distroy, old result, cos user did NOT, want */
  73.     /* to perform an operation on it (they started to type */
  74.     /* a new number !!) */
  75.     result=0;
  76.  
  77.     number1[i] = inchar; /* add next input */
  78.     i++;
  79.     // printf("1stored (%c), number1 (%s)\n",inchar, number1);
  80.     clear_display();
  81.     draw_display(number1,NULL);
  82.    }
  83.  
  84. /* if input is number and op is NOT blank store */
  85. if (((isdigit(inchar) != 0) || (inchar =='.')) && (flag ==1))
  86.    /* make sure we are second number */
  87.    {
  88.     number2[y] = inchar; /* add next input */
  89.     y++;
  90.     // printf("2stored (%c), number2 (%s)\n",inchar, number2);
  91.     clear_display();
  92.     draw_display(number2,NULL);
  93.    }
  94.  
  95.  
  96. /* if we get a operations store */
  97. if ( (inchar == '+' ) || (inchar == '-' ) || (inchar == '/' ) ||
  98.      (inchar == '*' ) || (inchar == '(' ) || (inchar == ')' ) ||
  99.      (inchar == '<' ) && (sflag == 0) /* skip if op allready parsed */
  100.    ) /* its an operation */
  101.  
  102.    {
  103.     op = inchar; /* store */
  104.     // printf("operation (%c)\n",op);
  105.     clear_display();
  106.     draw_op(op);
  107.     draw_display(NULL,NULL); /* a refresh basicly */
  108.     flag =1; /* now only fill second number */
  109.    }
  110.  
  111.  
  112. /* if = pressed */
  113. if (inchar == '=')
  114.     {
  115.     /* we work out result imedieatly */
  116.  
  117.     /* convert to numbers */
  118.     if (sflag ==0) realnumber1 = strtod(number1, &t1);
  119.     /* or not if one is available */
  120.     if (sflag ==1) realnumber1 = result;
  121.  
  122.     realnumber2 = strtod(number2, &t2);
  123.     /* second number always input */
  124.  
  125.     if (UseTape ==1)
  126.         printf("%.25Lg %c %.25Lg\n ",realnumber1,op,realnumber2);
  127.  
  128.     switch (op)
  129.     {
  130.     case '+':
  131.     realresult = (realnumber1 + realnumber2);
  132.     break;
  133.  
  134.     case '-':
  135.     realresult = (realnumber1 - realnumber2);
  136.     break;
  137.  
  138.     case '/':
  139.     realresult = (realnumber1 / realnumber2);
  140.     break;
  141.  
  142.     case '*':
  143.     realresult = (realnumber1 * realnumber2);
  144.     break;
  145.  
  146.     default:
  147.     printf("Something broke, couldent get operand ! got (%c)\n",op);
  148.     break;
  149.     };
  150.  
  151.     /* copy to store */
  152.     result = realresult;
  153.  
  154.     /* output conversion depends on mode selected */
  155.     /* ALL maths done internally as decimal */
  156.  
  157.     switch (mode)
  158.     {
  159.     case 0: /* DEC */
  160.     /* copy data for display */
  161.     sprintf(buffer, "%-.25Ld",realresult);
  162.     /* tape display */
  163.     if (UseTape ==1)
  164.         printf("=%s %.25Ld%s\n",BOLD,realresult,NORMAL);
  165.     break;
  166.     case 1: /* FLT */
  167.     sprintf(buffer, "%-.25Lg",realresult);
  168.     if (UseTape ==1)
  169.         printf("=%s %.25Lg%s\n",BOLD,realresult,NORMAL);
  170.     break;
  171.     case 2: /* HEX */
  172.     sprintf(buffer, "%-.25Lx",realresult);
  173.     if (UseTape ==1)
  174.         printf("=%s %.25Lx%s\n",BOLD,realresult,NORMAL);
  175.     break;
  176.     case 3: /* OCT */
  177.     sprintf(buffer, "%-.25Lo",realresult);
  178.     if (UseTape ==1)
  179.         printf("=%s %.25Lo%s\n",BOLD,realresult,NORMAL);
  180.     break;
  181.     case 4: /* BIN */
  182.     sprintf(buffer, "%-.25Ld",realresult);
  183.     /* display return from atob (int) */
  184.     if (UseTape ==1)
  185.         printf("=%s %.25Ld%s\n",BOLD,atob(buffer),NORMAL);
  186.     break;
  187.     case 5: /* EXPO */
  188.     sprintf(buffer, "%-.25Le",realresult);
  189.     if (UseTape ==1)
  190.         printf("=%s %.25Le%s\n",BOLD,realresult,NORMAL);
  191.     break;
  192.     };
  193.  
  194.     /* check for overload */
  195.     if (stricmp(buffer,"NaN")==0)
  196.         strcpy(buffer,"Overload !!");
  197.  
  198.     /* clean our mess */
  199.     clear_buffers();
  200.     clear_display();
  201.     draw_display(buffer,NULL);
  202.     /* we are safe to call again now */
  203.  
  204.     } /* end calculation */
  205.  
  206.  
  207. } /* end do_math */
  208.  
  209.  
  210. int draw_display(char *inchar, int mode)
  211. { /* re-draw display */
  212. static int smode =0;
  213.  
  214. /* poss maths modes */
  215. struct IntuiText dec_mode = {
  216.     1, 0, JAM1, 0, 0, NULL, (UBYTE *)"DEC", NULL, };
  217. struct IntuiText flt_mode = {
  218.     1, 0, JAM1, 0, 0, NULL, (UBYTE *)"FLT", NULL, };
  219. struct IntuiText hex_mode = {
  220.     1, 0, JAM1, 0, 0, NULL, (UBYTE *)"HEX", NULL, };
  221. struct IntuiText oct_mode = {
  222.     1, 0, JAM1, 0, 0, NULL, (UBYTE *)"OCT", NULL, };
  223. struct IntuiText bin_mode = {
  224.     1, 0, JAM1, 0, 0, NULL, (UBYTE *)"BIN", NULL, };
  225. struct IntuiText expo_mode = {
  226.     1, 0, JAM1, 0, 0, NULL, (UBYTE *)"EXPO", NULL, };
  227.  
  228. /* display structure */
  229. struct IntuiText display = {
  230.     1, 0, JAM1,0, 0, NULL, (UBYTE *)inchar, NULL };
  231.  
  232.     /* store untill, user changes */
  233.     if (mode != NULL)
  234.     smode = mode;
  235.     /* NULL for no change */
  236.  
  237.     /* print maths mode */
  238.     switch (smode)
  239.     {
  240.     case 0: /* DEC */
  241.     PrintIText(CalcWnd->RPort,&dec_mode,11,14);
  242.     break;
  243.     case 1: /* FLT */
  244.     PrintIText(CalcWnd->RPort,&flt_mode,11,14);
  245.     break;
  246.     case 2: /* HEX */
  247.     PrintIText(CalcWnd->RPort,&hex_mode,11,14);
  248.     break;
  249.     case 3: /* OCT */
  250.     PrintIText(CalcWnd->RPort,&oct_mode,11,14);
  251.     break;
  252.     case 4: /* BIN */
  253.     PrintIText(CalcWnd->RPort,&bin_mode,11,14);
  254.     break;
  255.     case 5: /* EXPO */
  256.     PrintIText(CalcWnd->RPort,&expo_mode,11,14);
  257.     break;
  258.     };
  259.  
  260.     /* print display */
  261.     if (inchar != NULL)
  262.     PrintIText(CalcWnd->RPort,&display,11,22);
  263.  
  264.     /* NULL passed, if no change required */
  265.     /* note we dont buffer the display buffer!! */
  266.     /* so it needs to be re-passed, if you want */
  267.     /* a display and/or an update */
  268.  
  269. }  /* end draw_display */
  270.  
  271.  
  272. void clear_display(void)
  273. {
  274. /* just draw a filed rectangle over display */
  275. /* re-calc each time for font size change */
  276. BYTE BorderLeft = CalcWnd->BorderLeft;
  277. BYTE BorderTop = CalcWnd->BorderTop;
  278. BYTE BorderRight = CalcWnd->BorderRight;
  279. BYTE BorderBottom = CalcWnd->BorderBottom;
  280.  
  281.     SetAPen(CalcWnd->RPort,4); /* dark grey */
  282.     RectFill(CalcWnd->RPort,11,13,210,27);
  283.  
  284.     /*
  285.     RectFill(CalcWnd->RPort,((CalcLeft+BorderLeft)+1),
  286.                             ((CalcTop+BorderTop)+1),
  287.  
  288.                             ((CalcWidth-BorderRight)-1),
  289.                             ((CalcHeight-BorderBottom)-1)
  290.             );
  291.     */
  292.  
  293. } /* end clear display */
  294.  
  295.  
  296. void clear_buffers(void)
  297. {
  298. int x=0;
  299. /* if erase selected or CA, we flush all internal */
  300. /* data stores, so we can start again */
  301.  
  302.     i=0,y=0;
  303.     flag=0;  /* pointers */
  304.     sflag=0;
  305.  
  306.     for (x=0; x != MAX; x++) /* stores */
  307.         { number1[x] =0;
  308.           number2[x] =0;
  309.         }
  310.     /* we are safe to call again now */
  311.  
  312. } /* end clear buffers */
  313.  
  314.  
  315. void draw_op(char op)
  316. { /* place operation on display */
  317. struct IntuiText add = {
  318. 1, 0, JAM1,0, 0, NULL, (UBYTE *)"+", NULL };
  319. struct IntuiText sub = {
  320. 1, 0, JAM1,0, 0, NULL, (UBYTE *)"-", NULL };
  321. struct IntuiText div = {
  322. 1, 0, JAM1,0, 0, NULL, (UBYTE *)"/", NULL };
  323. struct IntuiText mul = {
  324. 1, 0, JAM1,0, 0, NULL, (UBYTE *)"*", NULL };
  325.  
  326.     switch (op)
  327.     { /* print op type */
  328.     case '+':
  329.     PrintIText(CalcWnd->RPort,&add,200,14);
  330.     break;
  331.     case '-':
  332.     PrintIText(CalcWnd->RPort,&sub,200,14);
  333.     break;
  334.     case '/':
  335.     PrintIText(CalcWnd->RPort,&div,200,14);
  336.     break;
  337.     case '*':
  338.     PrintIText(CalcWnd->RPort,&mul,200,14);
  339.     break;
  340.     };
  341.  
  342. } /* end print op */
  343.  
  344.  
  345. int atob(char *str)
  346. /* ASCII-to-binary conversion */
  347. {
  348. int val;
  349.  
  350.     for (val = 0; *str; str++)
  351.     {
  352.     val *= 2;
  353.  
  354.     if (*str == '1')
  355.         val++;
  356.         else if (*str != '0')
  357.         return(-1);
  358.     }
  359.     return(val);
  360. }
  361.