home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / DeveloperLabs / Lab1 / Solution / Calculator.m < prev    next >
Encoding:
Text File  |  1989-09-25  |  3.6 KB  |  193 lines

  1. /*     
  2. **     Solution to Calculator exercise, lab #1.
  3. **     Authors: Bruce Blumberg and Doug Keislar, NeXT Technical Support
  4. */
  5.  
  6.  
  7. #import "Calculator.h"
  8. #import <string.h>
  9. #import <math.h>    /* for extensions to existing functionality */    
  10. #import <appkit/Application.h>
  11. #import <appkit/TextField.h>
  12.  
  13. @implementation Calculator
  14.  
  15. +new;
  16. {    
  17.     self = [super new];        /* create new instance of calculator */
  18.     strcpy(viewerStr,"");        /* initialize string for viewer */
  19.     topOfStack = -1;        /* initialize stack */
  20.     frozen = NO;
  21.     return self;
  22. }
  23.  
  24. -(double)pop
  25. {
  26.     if(topOfStack>-1)     
  27.         return(stack[topOfStack--]);
  28.     else {
  29.         [self stackError:"stack underflow"];
  30.         return(0);
  31.     }
  32. }
  33.  
  34. -push:(double)aNum
  35. {
  36.     if(topOfStack<STACKSIZE-1)
  37.         stack[++topOfStack] = aNum;
  38.     else [self stackError:"stack overflow"];
  39.     return self;
  40. }
  41.  
  42. -(double)getOperand
  43. {    
  44.     if (frozen)
  45.         return (0.0);
  46.         if (viewerStr[0]) 
  47.         [self enter:self];    /* push displayed value to stack,
  48.                     if it hasn't already been done */
  49.     return ([self pop]);
  50. }
  51.  
  52. -displayValue:(double)aNum
  53. {
  54.     if (frozen)
  55.         return self;
  56.     [viewer setFloatValue:aNum];     /* display current value */
  57.     strcpy(viewerStr,"");        /* and empty out string for next */
  58.     return self;
  59. }
  60.  
  61. -pushAndDisplay:(double)aNum
  62. {
  63.     if (frozen)
  64.         return self;
  65.     [self push:aNum];
  66.     [self displayValue:aNum];
  67.     return self;
  68. }
  69.  
  70. -enter:(id)sender
  71. {    
  72.     if (frozen)
  73.         return self;
  74.     [self push:[viewer floatValue]];
  75.     strcpy(viewerStr,"");        
  76.     return self;
  77. }
  78.  
  79. -clearDisplay:(id)sender
  80. {
  81.     if (frozen)  
  82.         frozen = NO;         
  83.     strcpy(viewerStr,"");
  84.     [self displayValue:0.0];
  85.     return self;
  86. }
  87.  
  88. -digit:(id)sender
  89. {
  90.     char    digitBuf[2];
  91.     
  92.     if (frozen)
  93.         return self;
  94.             /* get the new digit from the  button's tag and 
  95.               append it to the displayed string */
  96.     sprintf(digitBuf,"%d",[sender selectedTag]);  
  97.             /* we use selectedTag instead of tag, in case the
  98.             button is part of a matrix */    
  99.     strcat(viewerStr,digitBuf);          
  100.     [viewer setStringValue:viewerStr];
  101.     return self;
  102. }
  103.     
  104. -period:(id)sender
  105. {
  106.     if (!frozen)    {    
  107.         strcat(viewerStr,".");
  108.         [viewer setStringValue:viewerStr];
  109.     }
  110.     return self;
  111. }
  112.     
  113. -add:(id)sender
  114. {    
  115.  
  116.     if (!frozen) 
  117.         [self pushAndDisplay:[self getOperand] + [self getOperand]];
  118.     return self;
  119. }
  120.  
  121. -subtract:(id)sender
  122. {
  123.     if (!frozen)        
  124.         [self pushAndDisplay:-[self getOperand] + [self getOperand]];
  125.     return self;
  126. }
  127.  
  128. -multiply:(id)sender
  129. {
  130.     if (!frozen)        
  131.         [self pushAndDisplay:[self getOperand] * [self getOperand]];
  132.     return self;
  133. }
  134.  
  135. -divide:(id)sender
  136. {    
  137.     double firstOp;
  138.     
  139.     if (!frozen)
  140.     {        
  141.         firstOp = [self getOperand];
  142.         [self pushAndDisplay:[self getOperand]/firstOp];
  143.     }
  144.     return self;
  145. }
  146.  
  147. -changeSign:(id)sender        /* we don't  push to stack here, so digits
  148.                  can be appended after sign is changed */
  149. {
  150.     if (!frozen)
  151.     {
  152.         [viewer setFloatValue:(-[viewer floatValue])];
  153.         strcpy (viewerStr,[viewer stringValue]);
  154.     }
  155.     return self;
  156. }
  157.  
  158. -stackError:(STR)errorMsg;
  159. {
  160.     [viewer setStringValue:errorMsg];
  161.     frozen = YES;
  162.     topOfStack = -1;         /* stack errors re-initialize stack */
  163.     return self;
  164. }
  165.  
  166.  
  167. - setAWindow:anObject        /* associate the outlet "aWindow" with
  168.                    the user-interface window, "anObject"  */
  169. {
  170.       aWindow = anObject;
  171.        [aWindow setDelegate:self];      /* needed for windowWillClose: */
  172.        return self;
  173. }
  174.  
  175. - setViewer:anObject        /*  initialize the other outlet, viewer  */
  176. {
  177.       viewer = anObject;
  178.       return self;
  179. }
  180.  
  181. - windowWillClose:sender     /* needed only if calculator has a close
  182.                button that will be used for quitting the application,
  183.                as a supplement to the "Quit" menu item. This is
  184.                not recommended; normally only the "Quit" menu
  185.                item should cause an application to quit. */
  186. {
  187.     [NXApp terminate:self];
  188.     return self;
  189. }
  190.     
  191. @end
  192.  
  193.