1#include <pthread.h> 2#include "calculator.h" 3#include "variables.h" 4#include "conversion.h" 5#include "ErrorController.h" 6#include "historyManager.h" 7#include "WcalcController.h" 8#include "string_manip.h" 9#include "files.h" 10#include "MyTextField.h" 11#include "simpleCalc.h" 12#include "list.h" 13#include "number.h" 14 15#define KEYPAD_HEIGHT 165 16#define MIN_WINDOW_WIDTH 171 17#define MIN_WINDOW_HEIGHT_TOGGLED 112 18#define MIN_WINDOW_HEIGHT_UNTOGGLED 277 19#define FIELD_WIDTH_DIFFERENCE 22 20#define MAX_WINDOW_SIZE 10000 21 22static char update_history = 0; 23NSButton *e; 24NSTextField *ef; 25static NSString *curFile = NULL; 26static pthread_mutex_t displayLock; 27 28@implementation WcalcController 29 30- (IBAction)toggleSize:(id)sender 31{ 32 static BOOL shrinking = TRUE; 33 NSRect mainwindow = [mainWindow frame]; 34 NSRect expr = [ExpressionField frame]; 35 NSRect prec = [PrecisionSlider frame]; 36 NSRect ans = [AnswerField frame]; 37 NSSize w; 38 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 39 40 if (shrinking) { 41 // if removing the keypad, change the window height 42 mainwindow.size.height -= KEYPAD_HEIGHT; 43 mainwindow.origin.y += KEYPAD_HEIGHT; 44 // this is set in case the calc starts up toggled (under other 45 // conditions it is not strictly necessary, because the ExpressionField 46 // has achieved the correct size automatically 47 expr.size.height = mainwindow.size.height 48 - ans.size.height 49 - prec.size.height 50 - 57 /* the size of the rest of the window, including title bar */; 51 [sizeToggleMenu setTitle:@"Show Keypad"]; 52 } else { 53 // if adding the keypad, change the window height 54 mainwindow.size.height += KEYPAD_HEIGHT; 55 mainwindow.origin.y -= KEYPAD_HEIGHT; 56 mainwindow.size.width = MIN_WINDOW_WIDTH; 57 [sizeToggleMenu setTitle:@"Hide Keypad"]; 58 } 59 60 expr.size.width = prec.size.width = mainwindow.size.width - FIELD_WIDTH_DIFFERENCE; 61 62 if (shrinking) { 63 [keypad removeFromSuperview]; 64 expr.origin.y -= KEYPAD_HEIGHT; 65 prec.origin.y -= KEYPAD_HEIGHT; 66 } else { 67 expr.origin.y += KEYPAD_HEIGHT; 68 prec.origin.y += KEYPAD_HEIGHT; 69 } 70 71 [ExpressionField removeFromSuperview]; 72 [PrecisionSlider removeFromSuperview]; 73 74 if (sender != 0) { 75 [mainWindow setFrame:mainwindow display:TRUE animate:TRUE]; 76 } else { 77 [mainWindow setFrame:mainwindow display:FALSE animate:FALSE]; 78 } 79 80 if (! shrinking) { 81 [superview addSubview:keypad]; 82 w.width = MIN_WINDOW_WIDTH; 83 w.height = MIN_WINDOW_HEIGHT_UNTOGGLED + (ans.size.height - 21); 84 [mainWindow setMinSize:w]; 85 w.width = MIN_WINDOW_WIDTH; 86 w.height = MAX_WINDOW_SIZE; 87 [mainWindow setMaxSize:w]; 88 [prefs setObject:@"NO" forKey:@"toggled"]; 89 } else { 90 w.width = MIN_WINDOW_WIDTH; 91 w.height = MIN_WINDOW_HEIGHT_TOGGLED + (ans.size.height - 21); 92 [mainWindow setMinSize:w]; 93 w.width = MAX_WINDOW_SIZE; 94 w.height = MAX_WINDOW_SIZE; 95 [mainWindow setMaxSize:w]; 96 [prefs setObject:@"YES" forKey:@"toggled"]; 97 } 98 99 [ExpressionField setFrame:expr]; 100 [PrecisionSlider setFrame:prec]; 101 102 [superview addSubview:ExpressionField]; 103 [superview addSubview:PrecisionSlider]; 104 105 [ExpressionField selectText:sender]; 106 107 shrinking = ! shrinking; 108} 109 110- (IBAction)clear:(id)sender 111{ 112 if ([[ExpressionField stringValue] length]) { 113 [ExpressionField setStringValue:@""]; 114 [ExpressionField selectText:self]; 115 } else if ([[AnswerField stringValue] length]) { 116 [AnswerField setStringValue:@""]; 117 [ExpressionField selectText:self]; 118 } 119} 120 121- (IBAction)menuConstant:(id)sender 122{ 123 NSString *str = [ExpressionField stringValue]; 124 NSString *str2 = @"error!"; 125 126 switch ([sender tag]) { 127 case 1: str2 = [NSString stringWithFormat:@"%C", 0x03c0]; break; 128 case 2: str2 = @"e"; break; 129 case 3: str2 = [NSString stringWithFormat:@"%C", 0x03b3]; break; 130 case 4: str2 = @"g"; break; 131 case 5: str2 = @"Cc"; break; 132 case 8: str = @"K"; break; 133 134 case 101: str2 = @"Z0"; break; 135 case 102: str2 = [NSString stringWithFormat:@"%C0", 0x03b5]; break; 136 case 103: str2 = [NSString stringWithFormat:@"%C0", 0x03bc]; break; 137 case 104: str2 = @"G"; break; 138 case 105: str2 = @"h"; break; 139 case 106: str2 = @"c"; break; 140 141 case 201: str2 = [NSString stringWithFormat:@"%CB", 0x03bc]; break; 142 case 202: str2 = [NSString stringWithFormat:@"%CN", 0x03bc]; break; 143 case 203: str2 = @"G0"; break; 144 case 204: str2 = @"ec"; break; 145 case 205: str2 = @"Kj"; break; 146 case 206: str2 = @"Rk"; break; 147 case 207: str2 = [NSString stringWithFormat:@"%C0", 0x03a6]; break; 148 149 case 301: str2 = [NSString stringWithFormat:@"M%C", 0x03b1]; break; 150 case 302: str2 = @"a0"; break; 151 case 303: str2 = @"Md"; break; 152 case 304: str2 = @"Me"; break; 153 case 305: str2 = @"re"; break; 154 case 306: str2 = @"eV"; break; 155 case 307: str2 = @"Gf"; break; 156 case 308: str2 = [NSString stringWithFormat:@"%C", 0x03b1]; break; 157 case 309: str2 = @"Eh"; break; 158 case 310: str2 = @"Mh"; break; 159 case 311: str2 = [NSString stringWithFormat:@"m%C", 0x03bc]; break; 160 case 312: str2 = @"Mn"; break; 161 case 313: str2 = @"Mp"; break; 162 case 314: str2 = [NSString stringWithFormat:@"R%C", 0x221E]; break; 163 case 315: str2 = [NSString stringWithFormat:@"M%C", 0x03c4]; break; 164 165 case 401: str2 = @"u"; break; 166 case 402: str2 = @"Na"; break; 167 case 403: str2 = @"k"; break; 168 case 404: str2 = @"F"; break; 169 case 405: str2 = @"c1"; break; 170 case 406: str2 = @"n0"; break; 171 case 407: str2 = @"R"; break; 172 case 408: str2 = @"Vm"; break; 173 case 409: str2 = @"c2"; break; 174 case 410: str2 = [NSString stringWithFormat:@"%C", 0x03c3]; break; 175 case 411: str2 = @"b"; break; 176 177 case 6: str2 = @"random"; break; 178 case 7: str2 = @"irandom"; break; 179 default: return; 180 } 181 if ([str length]) { 182 NSString *str3 = [NSString stringWithFormat:@"%C",0x00d7]; 183 [ExpressionField setStringValue:[str stringByAppendingString:[str3 stringByAppendingString:str2]]]; 184 } else { 185 [ExpressionField setStringValue:str2]; 186 } 187} 188 189- (IBAction)menuFunction:(id)sender 190{ 191 NSString *str = [[ExpressionField stringValue] stringByAppendingString:@")"]; 192 NSString *str2; 193 194 if ([str length] == 1) str = @""; 195 196 switch ([sender tag]) { 197 case 1: str2 = @"sin("; break; 198 case 2: str2 = @"cos("; break; 199 case 3: str2 = @"tan("; break; 200 case 4: str2 = @"asin("; break; 201 case 5: str2 = @"acos("; break; 202 case 6: str2 = @"atan("; break; 203 case 7: str2 = @"sinh("; break; 204 case 8: str2 = @"cosh("; break; 205 case 9: str2 = @"tanh("; break; 206 case 10: str2 = @"asinh("; break; 207 case 11: str2 = @"acosh("; break; 208 case 12: str2 = @"atanh("; break; 209 case 13: str2 = @"log("; break; 210 case 14: str2 = @"ln("; break; 211 case 15: str2 = @"round("; break; 212 case 16: str2 = @"abs("; break; 213 case 17: str2 = @"sqrt("; break; 214 case 18: str2 = @"floor("; break; 215 case 19: str2 = @"ceil("; break; 216 case 20: str2 = @"cbrt("; break; 217 case 21: str2 = @"logtwo("; break; 218 case 22: str2 = @"cot("; break; 219 case 23: str2 = @"acot("; break; 220 case 24: str2 = @"coth("; break; 221 case 25: str2 = @"acoth("; break; 222 case 26: str2 = @"rand("; break; 223 case 27: str2 = @"irand("; break; 224 case 28: str2 = @"Gamma("; break; 225 case 29: str2 = @"lnGamma("; break; 226 case 30: str2 = @"zeta("; break; 227 case 31: str2 = @"sec("; break; 228 case 32: str2 = @"csc("; break; 229 case 33: str2 = @"asec("; break; 230 case 34: str2 = @"acsc("; break; 231 case 35: str2 = @"sech("; break; 232 case 36: str2 = @"csch("; break; 233 case 37: str2 = @"asech("; break; 234 case 38: str2 = @"acsch("; break; 235 case 39: str2 = @"eint("; break; 236 case 40: str2 = @"sinc("; break; 237 case 41: str2 = @"exp("; break; 238 case 42: str2 = @"fact("; break; 239 case 43: str2 = @"comp("; break; 240 default: return; 241 } 242 [ExpressionField setStringValue:[str2 stringByAppendingString:str]]; 243} 244 245- (void)awakeFromNib 246{ 247 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 248 NSRect w; 249 NSSize bounds; 250 int prefsVersion; 251 252 Dprintf("awakeFromNib\n"); 253 prefsVersion = [prefs integerForKey:@"initialized"]; 254 Dprintf("prefsVersion: %i\n", prefsVersion); 255 if (prefsVersion < 1) { 256 Dprintf("Upgrading prefs to v1\n"); 257 [prefs setObject:@"-1" forKey:@"precision"]; 258 [prefs setObject:@"NO" forKey:@"historyDuplicatesAllowed"]; 259 [prefs setObject:@"NO" forKey:@"flagUndefinedVariables"]; 260 [prefs setObject:@"YES" forKey:@"useRadians"]; 261 [prefs setObject:@"0" forKey:@"outputFormat"]; 262 [prefs setObject:@"YES" forKey:@"printPrefixes"]; 263 [prefs setObject:@"NO" forKey:@"updateHistory"]; 264 [prefs setObject:@"YES" forKey:@"strictSyntax"]; 265 [prefs setObject:@"0" forKey:@"roundingIndication"]; 266 [prefs setObject:@"NO" forKey:@"historyShowing"]; 267 [prefs setObject:@"YES" forKey:@"rememberErrors"]; 268 [prefs setObject:@"NO" forKey:@"baseShowing"]; 269 [prefs setObject:@"YES" forKey:@"precisionGuard"]; 270 [prefs setObject:@"NO" forKey:@"historyLimit"]; 271 [prefs setObject:@"1000" forKey:@"historyLimitLength"]; 272 [prefs setObject:@"NO" forKey:@"printInts"]; 273 [prefs setObject:@"NO" forKey:@"simpleCalc"]; 274 [prefs setObject:@"NO" forKey:@"printDelimiters"]; 275 } 276 if (prefsVersion < 2) { 277 Dprintf("Upgrading prefs to v2\n"); 278 [prefs setObject:@"YES" forKey:@"livePrecision"]; 279 [prefs setObject:@"1024" forKey:@"internalPrecision"]; 280 [prefs setObject:@"YES" forKey:@"cModStyle"]; 281 } 282 if (prefsVersion < 3) { 283 Dprintf("Upgrading prefs to v3\n"); 284 [prefs setObject:@"3" forKey:@"initialized"]; 285 [prefs setObject:@"147" forKey:@"maxSliderPrecision"]; 286 } 287 if (prefsVersion < 4) { 288 Dprintf("Upgrading prefs to v4\n"); 289 [prefs setObject:@"4" forKey:@"initialized"]; 290 [prefs setObject:@"1" forKey:@"engineeringNotation"]; 291 } 292 if (prefsVersion < 5) { 293 Dprintf("Upgrading prefs to v5\n"); 294 [prefs setObject:@"5" forKey:@"initialized"]; 295 [prefs setObject:@"" forKey:@"alternateInputDecimalSeparator"]; 296 [prefs setObject:@"" forKey:@"alternateInputThousandsSeparator"]; 297 } 298 conf.precision = [prefs integerForKey:@"precision"]; 299 switch([prefs integerForKey:@"engineeringNotation"]) { 300 case 1: conf.engineering = automatic; break; 301 case 2: conf.engineering = never; break; 302 case 3: conf.engineering = always; break; 303 } 304 conf.picky_variables = [prefs boolForKey:@"flagUndefinedVariables"]; 305 conf.use_radians = [prefs boolForKey:@"useRadians"]; 306 conf.output_format = [prefs integerForKey:@"outputFormat"]; 307 conf.print_prefixes = [prefs boolForKey:@"printPrefixes"]; 308 /* conf.strict_syntax = [prefs boolForKey:@"strictSyntax"]; */ 309 conf.rounding_indication = [prefs integerForKey:@"roundingIndication"]; 310 conf.precision_guard = [prefs boolForKey:@"precisionGuard"]; 311 conf.print_ints = [prefs boolForKey:@"printInts"]; 312 conf.print_commas = [prefs boolForKey:@"printDelimiters"]; 313 conf.simple_calc = [prefs boolForKey:@"simpleCalc"]; 314 conf.live_precision = [prefs boolForKey:@"livePrecision"]; 315 [PrecisionSlider setMaxValue:[prefs floatForKey:@"maxSliderPrecision"]]; 316 /* history preferences */ 317 allow_duplicates = [prefs boolForKey:@"historyDuplicatesAllowed"]; 318 update_history = [prefs boolForKey:@"updateHistory"]; 319 conf.remember_errors = [prefs boolForKey:@"rememberErrors"]; 320 conf.history_limit = [prefs boolForKey:@"historyLimit"]; 321 conf.history_limit_len = [prefs integerForKey:@"historyLimitLen"]; 322 { 323 NSDictionary *temp = [prefs dictionaryForKey:@"persistentVariables"]; 324 NSEnumerator *enumerator = [temp keyEnumerator]; 325 id key; 326 327 while ((key = [enumerator nextObject])) { 328 putexp(strdup([key UTF8String]),strdup([[temp objectForKey:key] UTF8String]),"preloaded"); 329 } 330 } 331 if ([prefs integerForKey:@"internalPrecision"] < 32) { 332 [prefs setObject:@"1024" forKey:@"internalPrecision"]; 333 } 334 if ([prefs integerForKey:@"internalPrecision"] > 4096) { 335 [prefs setObject:@"4096" forKey:@"internalPrecision"]; 336 } 337 init_numbers(); 338 num_set_default_prec([prefs integerForKey:@"internalPrecision"]); 339 Dprintf("preferences read\n"); 340 341 [PrecisionSlider setIntValue:conf.precision]; 342 Dprintf("precision slider\n"); 343 just_answered = FALSE; 344 345 /* Set up the character translation */ 346 NSNumberFormatter *numFormat = [[[NSNumberFormatter alloc] init] autorelease]; 347 if ([[numFormat decimalSeparator] length] > 0) { 348 Dprintf("NSDecimalSeparator > 0\n"); 349 conf.dec_delimiter = [[numFormat decimalSeparator] characterAtIndex:0]; 350 } else { 351 conf.dec_delimiter = '.'; 352 } 353 Dprintf("NSDecimalSeparator set (%c)\n", conf.dec_delimiter); 354 if ([[numFormat groupingSeparator] length] > 0) { 355 Dprintf("NSGroupingSeparator > 0\n"); 356 conf.thou_delimiter = [[numFormat groupingSeparator] characterAtIndex:0]; 357 } else { 358 conf.thou_delimiter = 0; 359 } 360 Dprintf("NSGroupingSeparator set (%c)\n", conf.thou_delimiter); 361 if ([[prefs stringForKey:@"alternateInputDecimalSeparator"] length] > 0) { 362 conf.in_dec_delimiter = [[prefs stringForKey:@"alternateInputDecimalSeparator"] characterAtIndex:0]; 363 Dprintf("alternate input dec sep (%c)\n", conf.in_dec_delimiter); 364 } 365 if ([[prefs stringForKey:@"alternateInputThousandsSeparator"] length] > 0) { 366 conf.in_thou_delimiter = [[prefs stringForKey:@"alternateInputThousandsSeparator"] characterAtIndex:0]; 367 Dprintf("alternate input thou sep (%c)\n", conf.in_thou_delimiter); 368 } 369 if (conf.in_dec_delimiter != 0) { 370 [decimalKey setTitle:[NSString stringWithCString:&conf.in_dec_delimiter length:1]]; 371 } else { 372 [decimalKey setTitle:[numFormat decimalSeparator]]; 373 Dprintf("decimalKey title set\n"); 374 } 375 376 /* reset the window to the saved setting */ 377 superview = [keypad superview]; 378 [keypad retain]; 379 [PrecisionSlider retain]; 380 [ExpressionField retain]; 381 Dprintf("interface retained\n"); 382 [mainWindow useOptimizedDrawing:TRUE]; 383 [mainWindow setFrameAutosaveName:@"wcalc"]; 384 Dprintf("frame autosave set\n"); 385 w = [mainWindow frame]; 386 if ([prefs boolForKey:@"toggled"]) { 387 Dprintf("window is toggled\n"); 388 w.size.height += KEYPAD_HEIGHT; 389 w.origin.y -= KEYPAD_HEIGHT; 390 [mainWindow setFrame:w display:TRUE animate:FALSE]; 391 Dprintf("frame set\n"); 392 [self toggleSize:0]; 393 Dprintf("toggled\n"); 394 } else { 395 Dprintf("window not toggled\n"); 396 w.size.width = MIN_WINDOW_WIDTH; 397 [mainWindow setFrame:w display:TRUE animate:FALSE]; 398 bounds.width = MIN_WINDOW_WIDTH; 399 bounds.height = MIN_WINDOW_HEIGHT_UNTOGGLED; 400 [mainWindow setMinSize:bounds]; 401 bounds.width = MIN_WINDOW_WIDTH; 402 bounds.height = MAX_WINDOW_SIZE; 403 [mainWindow setMaxSize:bounds]; 404 Dprintf("window size restored\n"); 405 } 406 // w = [mainWindow frame]; 407 // bounds = [mainWindow minSize]; 408 409 e = enterKey; 410 ef = ExpressionField; 411 412 /* this restores the drawer states */ 413 if ([prefs boolForKey:@"historyShowing"]) { 414 Dprintf("history showing\n"); 415 [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(openIDrawer:) userInfo:nil repeats:NO]; 416 Dprintf("history drawer displayed\n"); 417 } 418 if ([prefs boolForKey:@"baseShowing"]) { 419 Dprintf("base showing\n"); 420 [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(openBDrawer:) userInfo:nil repeats:NO]; 421 Dprintf("base drawer displayed\n"); 422 } 423 Dprintf("done with drawers\n"); 424 425 /* set the correct expression display for simple_calc */ 426 if (conf.simple_calc) { 427 Dprintf("simple calc\n"); 428 [ExpressionField setStringValue:@"0"]; 429 [AnswerField setStringValue:@"0"]; 430 Dprintf("values zeroed\n"); 431 simpleClearAll(); 432 Dprintf("simple all cleared\n"); 433 } 434 num_init_set_ui(last_answer, 0); 435 Dprintf("last answer cleared\n"); 436 pthread_mutex_init(&displayLock,NULL); 437 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(quit:) name:NSWindowWillCloseNotification object:mainWindow]; 438 NSUpdateDynamicServices(); 439} 440 441- (void)openBDrawer: (id) sender 442{ 443 [baseDrawer open]; 444 [baseMenu setTitle:@"Close Base Drawer"]; 445} 446 447- (void)openIDrawer: (id) sender 448{ 449 [inspector openIt:sender]; 450} 451 452- (IBAction)setPrecision:(id)sender 453{ 454 int last_pres=0; 455 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 456 457 last_pres = [prefs integerForKey:@"precision"]; 458 459 if (last_pres == [PrecisionSlider intValue]) 460 return; 461 else 462 last_pres = [PrecisionSlider intValue]; 463 464 Dprintf("setPrecision: %i to %i\n",conf.precision,last_pres); 465 conf.precision = last_pres; 466 [prefs setObject:[NSString stringWithFormat:@"%i",conf.precision] forKey:@"precision"]; 467 Dprintf("setPrecision - prefs set\n"); 468 469 Dprintf("getting lock\n"); 470 pthread_mutex_lock(&displayLock); 471 Dprintf("locked\n"); 472 { 473 set_prettyanswer(last_answer); 474 Dprintf("setPrecision - set_prettyanswer\n"); 475 [self displayAnswer]; 476 Dprintf("setPrecision - done\n"); 477 } 478 pthread_mutex_unlock(&displayLock); 479 Dprintf("unlocked\n"); 480} 481 482- (IBAction)go:(id)sender 483{ 484 char * expression; 485 extern char * errstring; 486 487 expression = strdup([[ExpressionField stringValue] UTF8String]); 488 489 parseme(expression); 490 putval("a",last_answer,"previous answer"); 491 492 /* if it isn't an error (or if you want me to remember errors) record it in the history */ 493 if (!errstring || (errstring && !strlen(errstring)) || conf.remember_errors) { 494 addToHistory(expression, last_answer); 495 free(expression); 496 } 497 498 [self displayAnswer]; 499} 500 501- (void)displayAnswer 502{ 503 extern char * errstring; 504 505 Dprintf("displayAnswer\n"); 506 /* if there is an error, display it */ 507 if (errstring && strlen(errstring)) { 508 extern int scanerror; 509 scanerror = 0; 510 Dprintf("displayAnswer error %s\n",errstring); 511 [errorController throwAlert:[NSString stringWithUTF8String:errstring]]; 512 free(errstring); 513 errstring = NULL; 514 } 515 /* display the answer */ 516 Dprintf("displayAnswer - pretty_answer(%p)\n",pretty_answer); 517 Dprintf("displayAnswer - %s\n",pretty_answer); 518 [AnswerField setStringValue:[NSString stringWithFormat:@"%s",pretty_answer]]; 519 [AnswerField setTextColor:(not_all_displayed?[NSColor redColor]:[NSColor blackColor])]; 520 Dprintf("displayAnswer - changing size\n"); 521 { // Make the Answerfield big enough to display the answer 522 NSRect curFrame, newFrame; 523 curFrame = [AnswerField frame]; 524 Dprintf("displayAnswer - current size: %f x %f\n", curFrame.size.height, curFrame.size.width); 525 newFrame = curFrame; 526 // we set the height to a huge number because cellSizeForBounds only 527 // works "within" the specified bound, which we want because we want to 528 // limit the width. 529 newFrame.size.height = DBL_MAX; 530 newFrame.size = [[AnswerField cell] cellSizeForBounds:newFrame]; 531 Dprintf("displayAnswer - needed size: %f x %f\n", newFrame.size.height, newFrame.size.width); 532 if (curFrame.size.height != newFrame.size.height) { 533 size_t newHeight = newFrame.size.height; 534 int difference = newHeight - curFrame.size.height; 535 NSRect windowFrame = [mainWindow frame]; 536 int nonAnswerPixels = windowFrame.size.height - curFrame.size.height; 537 NSSize ms = [mainWindow minSize]; 538 539 newFrame = curFrame; 540 newFrame.size.height = newHeight; 541 ms.height += difference; 542 windowFrame.size.height += difference; 543 if (windowFrame.size.height < newFrame.size.height + nonAnswerPixels) { 544 windowFrame.size.height = newFrame.size.height + nonAnswerPixels; 545 } 546 windowFrame.origin.y -= difference; 547 curFrame = [ExpressionField frame]; 548 [AnswerField setHidden:TRUE]; 549 [ExpressionField setHidden:TRUE]; 550 [mainWindow setFrame:windowFrame display:YES animate:YES]; 551 windowFrame = [mainWindow frame]; 552 /* At this point, the windowFrame may not be *quite* what I wanted it to be, 553 screens being of finite size and all... so we have to recalculate the size 554 that the AnswerField should be. */ 555 newFrame.size.height = windowFrame.size.height - nonAnswerPixels; 556 [mainWindow setMinSize:ms]; 557 [AnswerField setFrame:newFrame]; 558 [ExpressionField setFrame:curFrame]; 559 [AnswerField setHidden:FALSE]; 560 [ExpressionField setHidden:FALSE]; 561 } 562 } 563 Dprintf("displayAnswer - refresh inspector\n"); 564 // if the drawer is open, refresh the data. 565 if ([inspectorWindow isVisible]) { 566 [variableList reloadData]; 567 [historyList reloadData]; 568 } 569 just_answered = TRUE; 570 // refresh the prefs if necessary 571 Dprintf("displayAnswer - refresh prefs\n"); 572 if ([thePrefPanel isVisible]) 573 [self displayPrefs:0]; 574 Dprintf("displayAnswer - cleaning up\n"); 575 [outputFormat2 selectCellWithTag:conf.output_format]; 576 [ExpressionField selectText:self]; 577 Dprintf("displayAnswer - done\n"); 578} 579 580- (IBAction)convert:(id)sender 581{ 582 int type = [convertType indexOfSelectedItem]; 583 int from = [convertFrom selectedRow]; 584 int to = [convertTo selectedRow]; 585 586 if (type < 0 || type > MAX_TYPE) return; 587 if (from < 0) return; 588 if (to < 0) return; 589 590 uber_conversion(last_answer, type, from, to, last_answer); 591 set_prettyanswer(last_answer); 592 [AnswerField setStringValue:[NSString stringWithUTF8String:(pretty_answer?pretty_answer:"Not Enough Memory")]]; 593 putval("a",last_answer,"previous answer"); 594 if ([inspectorWindow isVisible]) { 595 [variableList reloadData]; 596 } 597} 598 599- (IBAction)enterData:(id)sender 600{ 601 NSString * sent = [NSString stringWithString:[[sender attributedTitle] string]]; 602 static short shiftdown = 0, capsdown = 0; 603 int tag; 604 605 Dprintf("enterData\n"); 606 [ExpressionField setSelectable:FALSE]; 607 tag = [sender tag]; 608 switch (tag) { 609 case 101: /* delete key on the onscreen keyboard */ 610 if ([[ExpressionField stringValue] length] > 0) { 611 unsigned len = [[ExpressionField stringValue] length]; 612 [ExpressionField setStringValue:[[ExpressionField stringValue] substringToIndex:len-1]]; 613 } 614 break; 615 case 100: /* clear key on the onscreen keypad */ 616 if (!conf.simple_calc) { 617 if ([[ExpressionField stringValue] length] > 0) { 618 [ExpressionField setStringValue:@""]; 619 [ExpressionField selectText:self]; 620 } else if ([[AnswerField stringValue] length] > 0) { 621 [AnswerField setStringValue:@""]; 622 [ExpressionField selectText:self]; 623 } 624 } else { 625 if (! [[ExpressionField stringValue] isEqualToString:@"0"]) { 626 [ExpressionField setStringValue:@"0"]; 627 [ExpressionField selectText:self]; 628 simpleClearEntry(); 629 } else { 630 [AnswerField setStringValue:@"0"]; 631 [ExpressionField selectText:self]; 632 simpleClearAll(); 633 } 634 } 635 break; 636 case 102: /* caps lock key on onscreen keyboard */ 637 if (capsdown) { 638 [shiftKey1 setEnabled:true]; 639 [shiftKey2 setEnabled:true]; 640 capsdown = 0; 641 } else { 642 [shiftKey1 setEnabled:false]; 643 [shiftKey2 setEnabled:false]; 644 capsdown = 1; 645 } 646 break; 647 case 103: /* shift key on onscreen keyboard */ 648 if (shiftdown) { 649 [shiftKey1 setState:NSOffState]; 650 [shiftKey2 setState:NSOffState]; 651 shiftdown = 0; 652 } else { 653 [shiftKey1 setState:NSOnState]; 654 [shiftKey2 setState:NSOnState]; 655 shiftdown = 1; 656 } 657 break; 658 case 104: /* = key on onscreen keypad */ 659 if (! conf.simple_calc) { 660 [self go:sender]; 661 } else { 662 char * expr = strdup([[ExpressionField stringValue] UTF8String]); 663 char * ret; 664 ret = simpleCalc('=',expr); 665 if (ret) { 666 [ExpressionField setStringValue:[NSString stringWithUTF8String:ret]]; 667 free(ret); 668 } else { 669 [self displayAnswer]; 670 [ExpressionField setStringValue:[AnswerField stringValue]]; 671 } 672 free(expr); 673 } 674 break; 675 case 105: /* the divide key on the onscreen keypad */ 676 case 106: /* the minus key on the onscreen keypad */ 677 case 107: /* the times key on the onscreen keypad */ 678 default: 679 if (! conf.simple_calc) { /* the real power of Wcalc */ 680 if (just_answered == FALSE) { 681 [ExpressionField setStringValue:[[ExpressionField stringValue] stringByAppendingString:sent]]; 682 } else if ([sent isEqualToString:@"+"] || 683 [sent isEqualToString:@"-"] || 684 [sent isEqualToString:@"*"] || 685 [sent isEqualToString:@"/"] || 686 [sent isEqualToString:@"%"] || 687 [sent isEqualToString:@"("] || 688 [sent isEqualToString:@"&"] || 689 [sent isEqualToString:@"|"] || 690 [sent isEqualToString:[NSString stringWithFormat:@"%C",0x00f7]]) { 691 [ExpressionField setStringValue:[[@"a" self] stringByAppendingString:sent]]; 692 } else { 693 [ExpressionField setStringValue:sent]; 694 } 695 if (shiftdown) { 696 [shiftKey1 setState:NSOffState]; 697 [shiftKey2 setState:NSOffState]; 698 shiftdown = 0; 699 } 700 just_answered = FALSE; 701 } else { /* stupid calculator */ 702 char *ret, *expr; 703 expr = strdup([[ExpressionField stringValue] UTF8String]); 704 Dprintf("expr: %s\n",expr); 705 switch (tag) { 706 case 105: ret = simpleCalc('/', expr); break; 707 case 106: ret = simpleCalc('-', expr); break; 708 case 107: ret = simpleCalc('*', expr); break; 709 default: ret = simpleCalc([sent characterAtIndex:0], expr); 710 } 711 free(expr); 712 if (ret) { 713 [ExpressionField setStringValue:[NSString stringWithUTF8String:ret]]; 714 free(ret); 715 } else { 716 [self displayAnswer]; 717 [ExpressionField setStringValue:[AnswerField stringValue]]; 718 } 719 } 720 break; 721 } 722 [ExpressionField setEditable:TRUE]; 723} 724 725- (IBAction)shConversions:(id)sender 726{ 727 static char initialized = 0; 728 if (! [conversionWindow isVisible]) { 729 [conversionWindow makeKeyAndOrderFront:self]; 730 if (! initialized) { 731 [conversionWindow center]; 732 initialized = 1; 733 } 734 } else { 735 [conversionWindow close]; 736 } 737} 738 739- (IBAction)showKeyboardDrawer:(id)sender 740{ 741 static char initialized = 0; 742 if (! [theKeyboard isVisible]) { 743 [theKeyboard setBecomesKeyOnlyIfNeeded:YES]; 744 [theKeyboard orderFront:self]; 745 if (! initialized) { 746 [theKeyboard center]; 747 initialized = 1; 748 } 749 } else { 750 [theKeyboard close]; 751 } 752} 753 754- (IBAction)showBaseDrawer:(id)sender 755{ 756 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 757 if (! [baseDrawer state]) { 758 [baseDrawer open]; 759 [prefs setObject:@"YES" forKey:@"baseShowing"]; 760 [baseMenu setTitle:@"Close Base Drawer"]; 761 } else { 762 [baseDrawer close]; 763 [prefs setObject:@"NO" forKey:@"baseShowing"]; 764 [baseMenu setTitle:@"Open Base Drawer"]; 765 } 766} 767 768- (IBAction)setPrefs:(id)sender 769{ 770 short need_redraw = 0; 771 short olde; 772 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 773 int tag = [sender tag]; 774 775 switch (tag) { 776 case 1: // Flag Undefined Variables 777 olde = conf.picky_variables; 778 conf.picky_variables = ([pickyVariables state]==NSOnState); 779 if (olde != conf.picky_variables) { 780 [prefs setObject:(conf.picky_variables?@"YES":@"NO") forKey:@"flagUndefinedVariables"]; 781 } 782 break; 783 case 2: // Use Radians 784 olde = conf.use_radians; 785 conf.use_radians = ([useRadians state]==NSOnState); 786 if (olde != conf.use_radians) { 787 need_redraw = 2; 788 [prefs setObject:(conf.use_radians?@"YES":@"NO") forKey:@"useRadians"]; 789 } 790 break; 791 case 3: // Use Engineering Notation 792 { 793 int savedas = 1; 794 olde = conf.engineering; 795 printf("index: %i\n", [sender indexOfSelectedItem]); 796 switch([sender indexOfSelectedItem]) { 797 case 0: conf.engineering = automatic; savedas = 1; break; 798 case 1: conf.engineering = never; savedas = 2; break; 799 case 2: conf.engineering = always; savedas = 3; break; 800 } 801 if (olde != conf.engineering) { 802 need_redraw = 1; 803 printf("integet: %i\n", conf.engineering); 804 [prefs setObject:[NSString stringWithFormat:@"%i",savedas] forKey:@"engineeringNotation"]; 805 } 806 } 807 break; 808 case 4: // Allow Duplicates in History 809 olde = allow_duplicates; 810 allow_duplicates = ([historyDuplicates state]==NSOnState); 811 if (olde != allow_duplicates) { 812 [prefs setObject:(allow_duplicates?@"YES":@"NO") forKey:@"historyDuplicatesAllowed"]; 813 } 814 break; 815 case 5: // Output Format 816 olde = conf.output_format; 817 conf.output_format = [[sender selectedCell] tag]; 818 if (olde != conf.output_format) { 819 need_redraw = 1; 820 [prefs setObject:[NSString stringWithFormat:@"%i",conf.output_format] forKey:@"outputFormat"]; 821 [printPrefixes setEnabled:(conf.output_format!=DECIMAL_FORMAT)]; 822 [engineeringNotation setEnabled:(conf.output_format==DECIMAL_FORMAT)]; 823 } 824 [outputFormat selectCellWithTag:conf.output_format]; 825 [outputFormat2 selectCellWithTag:conf.output_format]; 826 break; 827 case 6: // Print Prefixes 828 olde = conf.print_prefixes; 829 conf.print_prefixes = ([sender state]==NSOnState); 830 if (olde != conf.print_prefixes) { 831 need_redraw = 1; 832 [prefs setObject:(conf.print_prefixes?@"YES":@"NO") forKey:@"printPrefixes"]; 833 } 834 break; 835 case 7: // Update History 836 olde = update_history; 837 update_history = ([sender state]==NSOnState); 838 if (olde != update_history) { 839 [prefs setObject:(update_history?@"YES":@"NO") forKey:@"updateHistory"]; 840 } 841 break; 842 case 10: // Rounding Indication 843 olde = conf.rounding_indication; 844 conf.rounding_indication = [sender indexOfSelectedItem]; 845 if (olde != conf.rounding_indication) { 846 need_redraw = 1; 847 [prefs setObject:[NSString stringWithFormat:@"%i",conf.rounding_indication] forKey:@"roundingIndication"]; 848 } 849 break; 850 case 11: // Record errors in history 851 olde = conf.remember_errors; 852 conf.remember_errors = ([sender state]==NSOnState); 853 if (olde != conf.remember_errors) { 854 [prefs setObject:(conf.remember_errors?@"YES":@"NO") forKey:@"rememberErrors"]; 855 } 856 break; 857 case 12: // Conservative precision 858 olde = conf.precision_guard; 859 conf.precision_guard = ([sender state]==NSOnState); 860 if (olde != conf.precision_guard) { 861 need_redraw = 2; 862 [prefs setObject:(conf.precision_guard?@"YES":@"NO") forKey:@"precisionGuard"]; 863 } 864 break; 865 case 13: // History length limit toggle 866 olde = conf.history_limit; 867 conf.history_limit = ([sender state]==NSOnState); 868 [limitHistoryLen setEnabled:conf.history_limit]; 869 [limitHistoryLenTag setEnabled:conf.history_limit]; 870 if (olde != conf.history_limit) { 871 [prefs setObject:(conf.history_limit?@"YES":@"NO") forKey:@"historyLimit"]; 872 } 873 break; 874 case 14: // History length limit 875 if ((unsigned)[sender intValue] != conf.history_limit_len) { 876 conf.history_limit_len = [sender intValue]; 877 [prefs setObject:[NSString stringWithFormat:@"%i",conf.history_limit_len] forKey:@"historyLimitLength"]; 878 } 879 break; 880 case 15: // Print ints 881 olde = conf.print_ints; 882 conf.print_ints = ([sender state]==NSOnState); 883 if (olde != conf.print_ints) { 884 need_redraw = 1; 885 [prefs setObject:(conf.print_ints?@"YES":@"NO") forKey:@"printInts"]; 886 } 887 break; 888 case 16: // Simple calculator 889 olde = conf.simple_calc; 890 conf.simple_calc = ([sender state]==NSOnState); 891 if (olde != conf.simple_calc) { 892 [prefs setObject:(conf.simple_calc?@"YES":@"NO") forKey:@"simpleCalc"]; 893 if (conf.simple_calc) { 894 [ExpressionField setStringValue:@"0"]; 895 [AnswerField setStringValue:@"0"]; 896 simpleClearAll(); 897 } else { 898 [ExpressionField setStringValue:@""]; 899 [AnswerField setStringValue:@""]; 900 } 901 /* disable irrelevant preferences */ 902 [historyDuplicates setEnabled:!conf.simple_calc]; 903 [limitHistory setEnabled:!conf.simple_calc]; 904 [limitHistoryLen setEnabled:!conf.simple_calc]; 905 [limitHistoryLenTag setEnabled:!conf.simple_calc]; 906 [pickyVariables setEnabled:!conf.simple_calc]; 907 [rememberErrors setEnabled:!conf.simple_calc]; 908 [updateHistory setEnabled:!conf.simple_calc]; 909 [useRadians setEnabled:!conf.simple_calc]; 910 } 911 break; 912 case 17: 913 olde = conf.print_commas; 914 conf.print_commas = ([sender state]==NSOnState); 915 if (olde != conf.print_commas) { 916 need_redraw = 1; 917 [prefs setObject:(conf.print_ints?@"YES":@"NO") forKey:@"printDelimiters"]; 918 } 919 break; 920 case 18: 921 if ((unsigned)[sender intValue] != num_get_default_prec()) { 922 [bitsStepper takeIntValueFrom:sender]; 923 num_set_default_prec([bitsStepper intValue]); // to handle limits placed on bitsStepper 924 [prefs setObject:[NSString stringWithFormat:@"%lu",num_get_default_prec()] forKey:@"internalPrecision"]; 925 } 926 break; 927 case 19: 928 if ((unsigned)[bitsStepper intValue] != num_get_default_prec()) { 929 num_set_default_prec([bitsStepper intValue]); 930 need_redraw = 2; 931 [bitsPref takeIntValueFrom:bitsStepper]; 932 [prefs setObject:[NSString stringWithFormat:@"%lu",num_get_default_prec()] forKey:@"internalPrecision"]; 933 } 934 break; 935 case 20: 936 olde = conf.live_precision; 937 conf.live_precision = ([sender state] == NSOnState); 938 if (olde != conf.print_commas) { 939 [prefs setObject:(conf.live_precision?@"YES":@"NO") forKey:@"livePrecision"]; 940 [PrecisionSlider setContinuous:(conf.live_precision?true:false)]; 941 } 942 break; 943 case 21: 944 olde = conf.c_style_mod; 945 conf.c_style_mod = ([sender state] == NSOnState); 946 if (olde != conf.c_style_mod) { 947 need_redraw = 2; 948 [prefs setObject:(conf.c_style_mod?@"YES":@"NO") forKey:@"cModStyle"]; 949 } 950 break; 951 case 22: 952 if ((unsigned)[sliderStepper intValue] != [PrecisionSlider maxValue]) { 953 unsigned long tmp = [sliderStepper intValue]; 954 [PrecisionSlider setMaxValue:(double)tmp]; 955 [sliderPref takeIntValueFrom:sliderStepper]; 956 [prefs setObject:[NSString stringWithFormat:@"%lu",tmp] forKey:@"maxSliderPrecision"]; 957 } 958 break; 959 case 23: 960 if ((double)[sender intValue] != [PrecisionSlider maxValue]) { 961 [sliderStepper takeIntValueFrom:sender]; 962 // these handle limits placed on sliderStepper 963 [sliderPref takeIntValueFrom:sliderStepper]; 964 [PrecisionSlider setMaxValue:[sliderStepper doubleValue]]; 965 [prefs setObject:[NSString stringWithFormat:@"%lu",[sliderStepper intValue]] forKey:@"maxSliderPrecision"]; 966 } 967 break; 968 case 24: 969 [altInputDecSep setEnabled:([sender state] == NSOnState)]; 970 [altInputThouSep setEnabled:([sender state] == NSOnState)]; 971 if ([sender state] != NSOnState) { 972 [altInputDecSep setStringValue:@""]; 973 [altInputThouSep setStringValue:@""]; 974 conf.in_dec_delimiter = 0; 975 conf.in_thou_delimiter = 0; 976 [decimalKey setTitle:[NSString stringWithCString:&conf.dec_delimiter length:1]]; 977 [prefs setObject:@"" forKey:@"alternateInputDecimalSeparator"]; 978 [prefs setObject:@"" forKey:@"alternateInputThousandsSeparator"]; 979 } 980 break; 981 case 25: 982 if ([[sender stringValue] length] > 0) { 983 conf.in_dec_delimiter = [[sender stringValue] characterAtIndex:0]; 984 [decimalKey setTitle:[NSString stringWithCString:&conf.in_dec_delimiter length:1]]; 985 [prefs setObject:[[sender stringValue] substringToIndex:1] forKey:@"alternateInputDecimalSeparator"]; 986 } else { 987 conf.in_dec_delimiter = 0; 988 [decimalKey setTitle:[NSString stringWithCString:&conf.dec_delimiter length:1]]; 989 [prefs setObject:@"" forKey:@"alternateInputDecimalSeparator"]; 990 } 991 break; 992 case 26: 993 if ([[sender stringValue] length] > 0) { 994 conf.in_thou_delimiter = [[sender stringValue] characterAtIndex:0]; 995 [prefs setObject:[[sender stringValue] substringToIndex:1] forKey:@"alternateInputThousandsSeparator"]; 996 } else { 997 conf.in_thou_delimiter = 0; 998 [prefs setObject:@"" forKey:@"alternateInputThousandsSeparator"]; 999 } 1000 break; 1001 default: return; 1002 } 1003 1004 switch (need_redraw) { 1005 case 2: 1006 if (update_history) 1007 recalculate = 1; 1008 [self go:sender]; 1009 break; 1010 case 1: 1011 set_prettyanswer(last_answer); 1012 [AnswerField setStringValue:[NSString stringWithUTF8String:(pretty_answer?pretty_answer:"Not Enough Memory")]]; 1013 [AnswerField setTextColor:((not_all_displayed)?([NSColor redColor]):([NSColor blackColor]))]; 1014 break; 1015 } 1016 if ([inspectorWindow isVisible] || recalculate) { 1017 [historyList reloadData]; 1018 } 1019 [ExpressionField selectText:self]; 1020} 1021 1022- (IBAction)showPrefs:(id)sender 1023{ 1024 //static char initialized = 0; 1025 [self displayPrefs:sender]; 1026 [thePrefPanel setBecomesKeyOnlyIfNeeded:TRUE]; 1027 [thePrefPanel orderFront:self]; 1028 // centering at first 1029 /*if (! initialized) { 1030 initialized=1; 1031 [thePrefPanel center]; 1032 }*/ 1033 // this should be redundant 1034 [thePrefPanel setFrameAutosaveName:@"wcalc_prefs"]; 1035 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(savePrefs:) name:NSWindowWillCloseNotification object:thePrefPanel]; 1036} 1037 1038- (IBAction)savePrefs:(id)sender 1039{ 1040 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 1041 1042 Dprintf("synching the prefs to disk\n"); 1043 [prefs synchronize]; 1044} 1045 1046- (IBAction)open:(id)sender 1047{ 1048 int result; 1049 NSArray *fileTypes = [NSArray arrayWithObjects:@"txt",@"text",@"wcalc", 1050 NSFileTypeForHFSTypeCode('TEXT'), nil]; 1051 NSOpenPanel *oPanel = [NSOpenPanel openPanel]; 1052 [oPanel setAllowsMultipleSelection:NO]; 1053 /* display the panel */ 1054 result = [oPanel runModalForDirectory:nil file:nil types:fileTypes]; 1055 /* if they clicked the OK button */ 1056 if (result == NSOKButton) { 1057 NSArray *filesToOpen = [oPanel filenames]; 1058 int i, count = [filesToOpen count]; 1059 /* loop through the files to open (there should only be one, but 1060 it's good to be able to handle multiple anyway */ 1061 for (i=0; i<count; i++) { 1062 int retval; 1063 extern char * errstring; 1064 curFile = [filesToOpen objectAtIndex:i]; 1065 retval = loadState(strdup([curFile UTF8String]),1); 1066 if ([inspectorWindow isVisible]) { 1067 [variableList reloadData]; 1068 [historyList reloadData]; 1069 } 1070 /* if there is an error, display it */ 1071 if (errstring && strlen(errstring)) { 1072 extern int scanerror; 1073 scanerror = 0; 1074 [errorController throwAlert:[NSString stringWithUTF8String:errstring]]; 1075 free(errstring); 1076 errstring = NULL; 1077 } 1078 // refresh the prefs if necessary 1079 if ([thePrefPanel isVisible]) 1080 [self displayPrefs:sender]; 1081 [outputFormat2 selectCellWithTag:conf.output_format]; 1082 if (retval) 1083 [self displayErrno:retval forFile:curFile]; 1084 } 1085 } 1086} 1087 1088- (void)displayErrno:(int)err forFile:(NSString*)filename 1089{ 1090 char * errstr; 1091 errstr = malloc(strlen(strerror(errno))+[filename length]+3); 1092 sprintf(errstr,"%s: %s",[filename UTF8String], strerror(errno)); 1093 [errorController throwAlert:[NSString stringWithUTF8String:errstr]]; 1094 free(errstr); 1095} 1096 1097- (IBAction)saveAs:(id)sender 1098{ 1099 NSSavePanel *sp; 1100 int runResult; 1101 /* create or get the shared instance of NSSavePanel */ 1102 sp = [NSSavePanel savePanel]; 1103 /* set up new attributes */ 1104 // [sp setAccessoryView:newView]; 1105 [sp setRequiredFileType:@"txt"]; 1106 /* display the NSSavePanel */ 1107 runResult = [sp runModalForDirectory:nil file:@""]; 1108 /* if successful, save file under designated name */ 1109 if (runResult == NSOKButton) { 1110 curFile = [sp filename]; 1111 [self save:sender]; 1112 // if (![textData writeToFile:[sp filename] atomically:YES]) 1113 // NSBeep(); 1114 } 1115} 1116 1117- (BOOL)validateMenuItem:(NSMenuItem *)anItem 1118{ 1119 switch ([anItem tag]) { 1120 case 1001: // save 1121 case 1002: // save as 1122 if (historyLength()) return YES; 1123 else return NO; 1124 break; 1125 default: 1126 return YES; 1127 } 1128} 1129 1130- (IBAction)save:(id)sender 1131{ 1132 if (! curFile) { 1133 [self saveAs:sender]; 1134 } else { 1135 int retval; 1136 retval = saveState(strdup([curFile UTF8String])); 1137 if (retval) 1138 [self displayErrno:retval forFile:curFile]; 1139 } 1140} 1141 1142- (IBAction)displayPrefs:(id)sender 1143{ 1144 switch (conf.engineering) { 1145 case automatic: [engineeringNotation selectItemAtIndex:0]; break; 1146 case never: [engineeringNotation selectItemAtIndex:1]; break; 1147 case always: [engineeringNotation selectItemAtIndex:2]; break; 1148 } 1149 [pickyVariables setState:(conf.picky_variables?NSOnState:NSOffState)]; 1150 [historyDuplicates setState:(allow_duplicates?NSOnState:NSOffState)]; 1151 [useRadians setState:(conf.use_radians?NSOnState:NSOffState)]; 1152 [outputFormat selectCellWithTag:conf.output_format]; 1153 [printPrefixes setState:(conf.print_prefixes?NSOnState:NSOffState)]; 1154 [roundingIndication selectItemAtIndex:conf.rounding_indication]; 1155 [rememberErrors setState:(conf.remember_errors?NSOnState:NSOffState)]; 1156 [limitHistory setState:(conf.history_limit?NSOnState:NSOffState)]; 1157 [printInts setState:(conf.print_ints?NSOnState:NSOffState)]; 1158 [precisionGuard setState:(conf.precision_guard?NSOnState:NSOffState)]; 1159 [simpleCalculator setState:(conf.simple_calc?NSOnState:NSOffState)]; 1160 [printDelimiters setState:(conf.print_commas?NSOnState:NSOffState)]; 1161 [bitsPref setIntValue:num_get_default_prec()]; 1162 [bitsStepper setIntValue:num_get_default_prec()]; 1163 [livePrecision setState:(conf.live_precision?NSOnState:NSOffState)]; 1164 [cModPref setState:(conf.c_style_mod?NSOnState:NSOffState)]; 1165 [sliderPref setIntValue:(int)[PrecisionSlider maxValue]]; 1166 [sliderStepper setIntValue:(int)[PrecisionSlider maxValue]]; 1167 [alternateInputPref setState:(conf.in_dec_delimiter != 0 || conf.in_thou_delimiter != 0)]; 1168 1169 /* disable irrelevant preferences */ 1170 [historyDuplicates setEnabled:!conf.simple_calc]; 1171 [limitHistory setEnabled:!conf.simple_calc]; 1172 [pickyVariables setEnabled:!conf.simple_calc]; 1173 [rememberErrors setEnabled:!conf.simple_calc]; 1174 [updateHistory setEnabled:!conf.simple_calc]; 1175 [useRadians setEnabled:!conf.simple_calc]; 1176 [printPrefixes setEnabled:(conf.output_format!=DECIMAL_FORMAT)]; 1177 [engineeringNotation setEnabled:(conf.output_format==DECIMAL_FORMAT)]; 1178 [limitHistoryLen setEnabled:conf.history_limit&&!conf.simple_calc]; 1179 [limitHistoryLenTag setEnabled:conf.history_limit&&!conf.simple_calc]; 1180 [altInputDecSep setEnabled:[alternateInputPref state]]; 1181 [altInputThouSep setEnabled:[alternateInputPref state]]; 1182 1183 [limitHistoryLen setStringValue:[NSString stringWithFormat:@"%lu",conf.history_limit_len]]; 1184 if ([alternateInputPref state]) { 1185 [altInputDecSep setStringValue:[NSString stringWithFormat:@"%c",conf.in_dec_delimiter]]; 1186 [altInputThouSep setStringValue:[NSString stringWithFormat:@"%c",conf.in_thou_delimiter]]; 1187 } 1188} 1189 1190- (IBAction)closeWindow:(id)sender 1191{ 1192 if ([inspectorWindow isKeyWindow]) { 1193 [inspectorWindow close]; 1194 } else if ([persVarsWindow isKeyWindow]) { 1195 [persVarsWindow close]; 1196 } else if ([mainWindow isKeyWindow]) { 1197 [mainWindow close]; 1198 } 1199} 1200 1201- (IBAction)quit:(id)sender 1202{ 1203 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 1204 1205 [prefs synchronize]; 1206 clearHistory(); 1207 cleanupvar(); 1208 if (pretty_answer) { 1209 extern char *pa; 1210 free(pretty_answer); 1211 if (pa) { 1212 free(pa); 1213 } 1214 } 1215 num_free(last_answer); 1216 lists_cleanup(); 1217 pthread_mutex_destroy(&displayLock); 1218 exit(EXIT_SUCCESS); 1219} 1220 1221@end 1222