This is Calculator.m in view mode; [Download] [Up]
/*
** 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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.