home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Solution to Calculator exercise, lab #1.
- ** Authors: Bruce Blumberg and Doug Keislar, NeXT Technical Support
- */
-
-
- #import "Calculator.h"
- #import <string.h>
- #import <math.h> /* for extensions to existing functionality */
- #import <appkit/Application.h>
- #import <appkit/TextField.h>
-
- @implementation Calculator
-
- +new;
- {
- self = [super new]; /* create new instance of calculator */
- strcpy(viewerStr,""); /* initialize string for viewer */
- topOfStack = -1; /* initialize stack */
- frozen = NO;
- return self;
- }
-
- -(double)pop
- {
- if(topOfStack>-1)
- return(stack[topOfStack--]);
- else {
- [self stackError:"stack underflow"];
- return(0);
- }
- }
-
- -push:(double)aNum
- {
- if(topOfStack<STACKSIZE-1)
- stack[++topOfStack] = aNum;
- else [self stackError:"stack overflow"];
- return self;
- }
-
- -(double)getOperand
- {
- if (frozen)
- return (0.0);
- if (viewerStr[0])
- [self enter:self]; /* push displayed value to stack,
- if it hasn't already been done */
- return ([self pop]);
- }
-
- -displayValue:(double)aNum
- {
- if (frozen)
- return self;
- [viewer setFloatValue:aNum]; /* display current value */
- strcpy(viewerStr,""); /* and empty out string for next */
- return self;
- }
-
- -pushAndDisplay:(double)aNum
- {
- if (frozen)
- return self;
- [self push:aNum];
- [self displayValue:aNum];
- return self;
- }
-
- -enter:(id)sender
- {
- if (frozen)
- return self;
- [self push:[viewer floatValue]];
- strcpy(viewerStr,"");
- return self;
- }
-
- -clearDisplay:(id)sender
- {
- if (frozen)
- frozen = NO;
- strcpy(viewerStr,"");
- [self displayValue:0.0];
- return self;
- }
-
- -digit:(id)sender
- {
- char digitBuf[2];
-
- if (frozen)
- return self;
- /* get the new digit from the button's tag and
- append it to the displayed string */
- sprintf(digitBuf,"%d",[sender selectedTag]);
- /* we use selectedTag instead of tag, in case the
- button is part of a matrix */
- strcat(viewerStr,digitBuf);
- [viewer setStringValue:viewerStr];
- return self;
- }
-
- -period:(id)sender
- {
- if (!frozen) {
- strcat(viewerStr,".");
- [viewer setStringValue:viewerStr];
- }
- return self;
- }
-
- -add:(id)sender
- {
-
- if (!frozen)
- [self pushAndDisplay:[self getOperand] + [self getOperand]];
- return self;
- }
-
- -subtract:(id)sender
- {
- if (!frozen)
- [self pushAndDisplay:-[self getOperand] + [self getOperand]];
- return self;
- }
-
- -multiply:(id)sender
- {
- if (!frozen)
- [self pushAndDisplay:[self getOperand] * [self getOperand]];
- return self;
- }
-
- -divide:(id)sender
- {
- double firstOp;
-
- if (!frozen)
- {
- firstOp = [self getOperand];
- [self pushAndDisplay:[self getOperand]/firstOp];
- }
- return self;
- }
-
- -changeSign:(id)sender /* we don't push to stack here, so digits
- can be appended after sign is changed */
- {
- if (!frozen)
- {
- [viewer setFloatValue:(-[viewer floatValue])];
- strcpy (viewerStr,[viewer stringValue]);
- }
- return self;
- }
-
- -stackError:(STR)errorMsg;
- {
- [viewer setStringValue:errorMsg];
- frozen = YES;
- topOfStack = -1; /* stack errors re-initialize stack */
- return self;
- }
-
-
- - setAWindow:anObject /* associate the outlet "aWindow" with
- the user-interface window, "anObject" */
- {
- aWindow = anObject;
- [aWindow setDelegate:self]; /* needed for windowWillClose: */
- return self;
- }
-
- - setViewer:anObject /* initialize the other outlet, viewer */
- {
- viewer = anObject;
- return self;
- }
-
- - windowWillClose:sender /* needed only if calculator has a close
- button that will be used for quitting the application,
- as a supplement to the "Quit" menu item. This is
- not recommended; normally only the "Quit" menu
- item should cause an application to quit. */
- {
- [NXApp terminate:self];
- return self;
- }
-
- @end
-
-