|
|
1.1 ! root 1: /* ! 2: * SimpleCalc -- Randy Nelson ! 3: * A general class that directly supports a calculator interface ! 4: * Created 8-8-90 ! 5: * ! 6: * You may freely copy, distribute and reuse the code in this example. ! 7: * NeXT disclaims any warranty of any kind, expressed or implied, as to ! 8: * its fitness for any particular use. ! 9: */ ! 10: ! 11: #import "SimpleCalc.h" ! 12: #import <appkit/Application.h> ! 13: #import <objc/NXStringTable.h> ! 14: #import <appkit/Panel.h> ! 15: #import <appkit/Text.h> ! 16: #import <appkit/Button.h> ! 17: #import <appkit/publicWraps.h> ! 18: #import <stdio.h> ! 19: #import <strings.h> ! 20: ! 21: #define DECIMALPOINT 10 ! 22: #define DIVIDE 20 ! 23: #define MULTIPLY 21 ! 24: #define SUBTRACT 22 ! 25: #define ADD 23 ! 26: #define CLEAR 31 ! 27: #define CLEARALL 30 ! 28: ! 29: @implementation SimpleCalc ! 30: - init ! 31: { ! 32: [super init]; ! 33: [self doInit]; ! 34: return self; ! 35: } ! 36: ! 37: - doInit ! 38: { ! 39: accumulator = 0; ! 40: operator = 0; ! 41: numberHasADecimal = NO; ! 42: startingSecondNumber = NO; ! 43: treatingOperationKeyLikeEqualKey = NO; ! 44: noFirstNumber = YES; ! 45: return self; ! 46: } ! 47: ! 48: - numberKeys:sender ! 49: { ! 50: char aDigit[2]; ! 51: int digit = [sender selectedTag]; ! 52: ! 53: noFirstNumber = NO; ! 54: ! 55: /* clear the display in order to begin the second number */ ! 56: if(startingSecondNumber == YES){ ! 57: [display setStringValue:""]; ! 58: startingSecondNumber = NO; ! 59: } ! 60: if(digit == DECIMALPOINT){ ! 61: [self decimal]; ! 62: return self; ! 63: } ! 64: sprintf(aDigit, "%d", digit); ! 65: [self appendToDisplay:(const char *)aDigit]; ! 66: return self; ! 67: } ! 68: ! 69: - decimal ! 70: { ! 71: if(numberHasADecimal == YES){ ! 72: NXBeep(); ! 73: return self; ! 74: } ! 75: /* internationalizable strings */ ! 76: [self appendToDisplay:[stringSet valueForStringKey:"decimalPointString"]]; ! 77: numberHasADecimal = YES; ! 78: return self; ! 79: } ! 80: ! 81: - operationKeys:sender ! 82: { ! 83: //do nothing if noFirstNumber ! 84: if(noFirstNumber == YES){ ! 85: NXBeep(); ! 86: return self; ! 87: } ! 88: ! 89: /* if there's an operation and a first and second number ! 90: * act like the equal key was pressed ! 91: */ ! 92: if((treatingOperationKeyLikeEqualKey == YES) && ! 93: (startingSecondNumber == NO)){ ! 94: [self equalsKey:self]; ! 95: } ! 96: operator = [sender selectedTag]; ! 97: switch(operator){ ! 98: case DIVIDE: case MULTIPLY: case SUBTRACT: case ADD:{ ! 99: accumulator = [display doubleValue]; ! 100: numberHasADecimal = NO; ! 101: startingSecondNumber = YES; ! 102: treatingOperationKeyLikeEqualKey = YES; ! 103: break; ! 104: } ! 105: default:{ ! 106: return self; ! 107: } ! 108: } ! 109: return self; ! 110: } ! 111: ! 112: - equalsKey:sender ! 113: { ! 114: /* do nothing if noFirstNumber */ ! 115: if(noFirstNumber == YES){ ! 116: NXBeep(); ! 117: return self; ! 118: } ! 119: switch(operator){ ! 120: case DIVIDE:{ ! 121: if([display doubleValue] == 0){ ! 122: //can't divide by zero ! 123: NXBeep(); ! 124: return self; ! 125: } ! 126: [display setDoubleValue:(accumulator / [display doubleValue])]; ! 127: break; ! 128: } ! 129: case MULTIPLY:{ ! 130: [display setDoubleValue:(accumulator * [display doubleValue])]; ! 131: break; ! 132: } ! 133: case SUBTRACT:{ ! 134: [display setDoubleValue:(accumulator - [display doubleValue])]; ! 135: break; ! 136: } ! 137: case ADD:{ ! 138: [display setDoubleValue:(accumulator + [display doubleValue])]; ! 139: break; ! 140: } ! 141: default:{ ! 142: return self; ! 143: } ! 144: } ! 145: /* just lke doInit ! 146: * but startingSecondNumber gets YES ! 147: * and noFirstNumber continues to be NO (there is a first number) ! 148: */ ! 149: operator = 0; ! 150: accumulator = 0; ! 151: numberHasADecimal = NO; ! 152: startingSecondNumber = YES; ! 153: treatingOperationKeyLikeEqualKey = NO; ! 154: return self; ! 155: } ! 156: ! 157: - clearKeys:sender ! 158: { ! 159: switch([sender selectedTag]){ ! 160: case CLEAR:{ ! 161: [display setStringValue:[stringSet ! 162: valueForStringKey:"zeroString"]]; ! 163: numberHasADecimal = NO; ! 164: startingSecondNumber = YES; ! 165: break; ! 166: } ! 167: case CLEARALL:{ ! 168: [display setStringValue:[stringSet ! 169: valueForStringKey:"zeroString"]]; ! 170: [self doInit]; ! 171: break; ! 172: } ! 173: default:{ ! 174: break; ! 175: } ! 176: } ! 177: return self; ! 178: } ! 179: ! 180: - appendToDisplay:(const char *)theDigit ! 181: { ! 182: char *copyOfDisplay = NXCopyStringBuffer([display stringValue]); ! 183: ! 184: /* if the display's current value is zero */ ! 185: if([display doubleValue] == 0){ ! 186: ! 187: /* and the zero doesn't have a decimal point */ ! 188: if(numberHasADecimal == NO){ ! 189: ! 190: /* replace the display with the digit passed */ ! 191: [display setStringValue:theDigit]; ! 192: return self; ! 193: } ! 194: } ! 195: /* otherwise append the digit passed ! 196: * to the digits already in the display ! 197: */ ! 198: [display setStringValue:strcat(copyOfDisplay, theDigit)]; ! 199: ! 200: return self; ! 201: } ! 202: ! 203: - numberDirectFromDisplay:sender ! 204: { ! 205: noFirstNumber = NO; ! 206: startingSecondNumber = YES; ! 207: return self; ! 208: } ! 209: ! 210: - appDidInit:sender ! 211: { ! 212: /* enter key can't be set as key equivalent from IB */ ! 213: [enterKey setKeyEquivalent:3]; ! 214: [[display window] makeKeyAndOrderFront:self]; ! 215: return self; ! 216: } ! 217: ! 218: - windowWillClose:window ! 219: { ! 220: return [NXApp terminate:self]; ! 221: } ! 222: ! 223: - infoPanel:sender ! 224: { ! 225: if(infoPanel == nil){ ! 226: [NXApp loadNibSection:"Info.nib" owner:self]; ! 227: } ! 228: [infoPanel orderFront:sender]; ! 229: return self; ! 230: } ! 231: ! 232: - helpPanel:sender ! 233: { ! 234: if(helpPanel == nil){ ! 235: [NXApp loadNibSection:"Help.nib" owner:self]; ! 236: } ! 237: [helpPanel orderFront:sender]; ! 238: return self; ! 239: ! 240: } ! 241: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.