Index: trunk/Cocoa/Pester/Source/English.lproj/MainMenu.nib/classes.nib
===================================================================
--- trunk/Cocoa/Pester/Source/English.lproj/MainMenu.nib/classes.nib	(revision 21)
+++ trunk/Cocoa/Pester/Source/English.lproj/MainMenu.nib/classes.nib	(revision 21)
@@ -0,0 +1,25 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {CLASS = NJRDateFormatter; LANGUAGE = ObjC; SUPERCLASS = NSDateFormatter; }, 
+        {CLASS = NJRIntegerFilter; LANGUAGE = ObjC; SUPERCLASS = NSNumberFormatter; }, 
+        {
+            ACTIONS = {dateCompleted = id; inAtChanged = id; setAlarm = id; update = id; }; 
+            CLASS = PSAlarmSetController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {
+                inAtMatrix = NSMatrix; 
+                messageField = NSTextField; 
+                setButton = NSButton; 
+                timeDate = NSTextField; 
+                timeDateCompletions = NSPopUpButton; 
+                timeInterval = NSTextField; 
+                timeIntervalUnits = NSPopUpButton; 
+                timeOfDay = NSTextField; 
+                timeSummary = NSTextField; 
+            }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: trunk/Cocoa/Pester/Source/English.lproj/MainMenu.nib/info.nib
===================================================================
--- trunk/Cocoa/Pester/Source/English.lproj/MainMenu.nib/info.nib	(revision 21)
+++ trunk/Cocoa/Pester/Source/English.lproj/MainMenu.nib/info.nib	(revision 21)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBDocumentLocation</key>
+	<string>67 8 356 240 0 0 1600 1178 </string>
+	<key>IBEditorPositions</key>
+	<dict>
+		<key>29</key>
+		<string>69 252 273 44 0 0 1600 1178 </string>
+	</dict>
+	<key>IBFramework Version</key>
+	<string>286.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>29</integer>
+		<integer>21</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6D52</string>
+</dict>
+</plist>
Index: trunk/Cocoa/Pester/Source/English.lproj/Notifier.nib/classes.nib
===================================================================
--- trunk/Cocoa/Pester/Source/English.lproj/Notifier.nib/classes.nib	(revision 21)
+++ trunk/Cocoa/Pester/Source/English.lproj/Notifier.nib/classes.nib	(revision 21)
@@ -0,0 +1,13 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {
+            ACTIONS = {close = id; }; 
+            CLASS = PSAlarmNotifierController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {dateField = NSTextField; messageField = NSTextField; }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: trunk/Cocoa/Pester/Source/English.lproj/Notifier.nib/info.nib
===================================================================
--- trunk/Cocoa/Pester/Source/English.lproj/Notifier.nib/info.nib	(revision 21)
+++ trunk/Cocoa/Pester/Source/English.lproj/Notifier.nib/info.nib	(revision 21)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBDocumentLocation</key>
+	<string>571 131 356 240 0 0 1600 1178 </string>
+	<key>IBFramework Version</key>
+	<string>286.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>5</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6D52</string>
+</dict>
+</plist>
Index: trunk/Cocoa/Pester/Source/NJRDateFormatter.h
===================================================================
--- trunk/Cocoa/Pester/Source/NJRDateFormatter.h	(revision 21)
+++ trunk/Cocoa/Pester/Source/NJRDateFormatter.h	(revision 21)
@@ -0,0 +1,16 @@
+//
+//  NJRDateFormatter.h
+//  Pester
+//
+//  Created by Nicholas Riley on Wed Oct 09 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NJRDateFormatter : NSDateFormatter {
+
+}
+
+@end
Index: trunk/Cocoa/Pester/Source/NJRDateFormatter.m
===================================================================
--- trunk/Cocoa/Pester/Source/NJRDateFormatter.m	(revision 21)
+++ trunk/Cocoa/Pester/Source/NJRDateFormatter.m	(revision 21)
@@ -0,0 +1,53 @@
+//
+//  NJRDateFormatter.m
+//  Pester
+//
+//  Created by Nicholas Riley on Wed Oct 09 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRDateFormatter.h"
+
+
+@implementation NJRDateFormatter
+
+// workaround for bug in Jaguar (and earlier?) NSCalendarDate dateWithNaturalLanguageString:
+NSString * stringByRemovingSurroundingWhitespace(NSString *string) {
+    static NSCharacterSet *nonWhitespace = nil;
+    NSRange firstValidCharacter, lastValidCharacter;
+
+    if (!nonWhitespace) {
+        nonWhitespace = [[[NSCharacterSet characterSetWithCharactersInString:
+            @" \t\r\n"] invertedSet] retain];
+    }
+
+    firstValidCharacter = [string rangeOfCharacterFromSet:nonWhitespace];
+    if (firstValidCharacter.length == 0)
+        return @"";
+    lastValidCharacter = [string rangeOfCharacterFromSet:nonWhitespace options:NSBackwardsSearch];
+
+    if (firstValidCharacter.location == 0 && lastValidCharacter.location == [string length] - 1)
+        return string;
+    else
+        return [string substringWithRange:NSUnionRange(firstValidCharacter, lastValidCharacter)];
+}
+
+
+- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
+{
+    NSCalendarDate *date;
+    if (![self allowsNaturalLanguage])
+        return [super getObjectValue: anObject forString: string errorDescription: error];
+    if (string == nil) return nil;
+    NS_DURING // dateWithNaturalLanguageString: can throw an exception
+        date = [NSCalendarDate dateWithNaturalLanguageString: stringByRemovingSurroundingWhitespace(string)];
+    NS_HANDLER
+        if (error != nil) *error = [localException reason];
+        NS_VALUERETURN(NO, BOOL);
+    NS_ENDHANDLER
+    if (date == nil) return [super getObjectValue: anObject forString: string errorDescription: error];
+    *anObject = date;
+    return YES;
+}
+
+@end
Index: trunk/Cocoa/Pester/Source/NJRIntegerFilter.h
===================================================================
--- trunk/Cocoa/Pester/Source/NJRIntegerFilter.h	(revision 21)
+++ trunk/Cocoa/Pester/Source/NJRIntegerFilter.h	(revision 21)
@@ -0,0 +1,16 @@
+//
+//  NJRIntegerFilter.h
+//  HostLauncher
+//
+//  Created by Nicholas Riley on Tue Dec 18 2001.
+//  Copyright (c) 2001 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJRIntegerFilter : NSNumberFormatter {
+
+}
+
+@end
Index: trunk/Cocoa/Pester/Source/NJRIntegerFilter.m
===================================================================
--- trunk/Cocoa/Pester/Source/NJRIntegerFilter.m	(revision 21)
+++ trunk/Cocoa/Pester/Source/NJRIntegerFilter.m	(revision 21)
@@ -0,0 +1,35 @@
+//
+//  NJRIntegerFilter.m
+//  HostLauncher
+//
+//  Created by Nicholas Riley on Tue Dec 18 2001.
+//  Copyright (c) 2001 Nicholas Riley. All rights reserved.
+//
+
+// based on MyIntegerFilter
+// Copyright © 2001 Bill Cheeseman. All rights reserved.
+
+#import "NJRIntegerFilter.h"
+
+@implementation NJRIntegerFilter
+
+// Input filter
+
+- (BOOL)isPartialStringValid:(NSString **)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString **)error {
+
+    // Override method to enable NSControl delegate method control:didFailToValidatePartialString:errorDescription: to
+    // reject invalid keypresses. Filters out keyboard input characters other than "1" .. "9".
+    if ([[*partialStringPtr substringWithRange:NSMakeRange(origSelRange.location, (*proposedSelRangePtr).location - origSelRange.location)] rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet] options:NSLiteralSearch].location != NSNotFound) {
+        *error = NSLocalizedString(@"Input is not an integer", @"Presented when user value not a numeric digit");
+        return NO; // Reject *partialStringPtr as typed, invoke delegate method
+    }
+
+    if ([*partialStringPtr length] == 0) {
+        // Work around NSFormatter issue in Mac OS X 10.0.
+        [[[NSApp keyWindow] fieldEditor:NO forObject:nil] setSelectedRange:*proposedSelRangePtr];
+    }
+
+    return YES; // Accept *partialStringPtr as typed
+}
+
+@end
Index: trunk/Cocoa/Pester/Source/PSAlarmNotifierController.h
===================================================================
--- trunk/Cocoa/Pester/Source/PSAlarmNotifierController.h	(revision 21)
+++ trunk/Cocoa/Pester/Source/PSAlarmNotifierController.h	(revision 21)
@@ -0,0 +1,19 @@
+//
+//  PSAlarmNotifierController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface PSAlarmNotifierController : NSWindowController {
+    IBOutlet NSTextField *messageField;
+    IBOutlet NSTextField *dateField;
+}
+
+- (IBAction)close:(NSButton *)sender;
+
+@end
Index: trunk/Cocoa/Pester/Source/PSAlarmNotifierController.m
===================================================================
--- trunk/Cocoa/Pester/Source/PSAlarmNotifierController.m	(revision 21)
+++ trunk/Cocoa/Pester/Source/PSAlarmNotifierController.m	(revision 21)
@@ -0,0 +1,37 @@
+//
+//  PSAlarmNotifierController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarmNotifierController.h"
+
+
+@implementation PSAlarmNotifierController
+
+- (id)initWithTimer:(NSTimer *)timer;
+{
+    if ([self initWithWindowNibName: @"Notifier"]) {
+        NSString *message = [timer userInfo];
+
+        [[self window] center];
+        if (message == nil || [message isEqualToString: @""])
+            message = @"Alarm!";
+        [messageField setStringValue: message];
+        [dateField setObjectValue: [timer fireDate]];
+        [NSApp activateIgnoringOtherApps: YES];
+        [[self window] makeKeyAndOrderFront: nil];
+        [[self window] orderFrontRegardless];
+        NSBeep();
+    }
+    return self;
+}
+
+- (IBAction)close:(id)sender;
+{
+    [self close];
+}
+
+@end
Index: trunk/Cocoa/Pester/Source/PSAlarmSetController.h
===================================================================
--- trunk/Cocoa/Pester/Source/PSAlarmSetController.h	(revision 21)
+++ trunk/Cocoa/Pester/Source/PSAlarmSetController.h	(revision 21)
@@ -0,0 +1,33 @@
+//
+//  PSAlarmSetController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface PSAlarmSetController : NSWindowController {
+    IBOutlet NSTextField *messageField;
+    IBOutlet NSMatrix *inAtMatrix;
+    IBOutlet NSTextField *timeInterval;
+    IBOutlet NSPopUpButton *timeIntervalUnits;
+    IBOutlet NSTextField *timeOfDay;
+    IBOutlet NSTextField *timeDate;
+    IBOutlet NSPopUpButton *timeDateCompletions; // XXX should go away when bug preventing both formatters and popup menus from existing is fixed
+    IBOutlet NSTextField *timeSummary;
+    IBOutlet NSButton *setButton;
+    NSString *status;
+    BOOL isIn;
+    NSCalendarDate *alarmDate;
+    NSTimeInterval alarmInterval;
+}
+
+- (IBAction)update:(id)sender;
+- (IBAction)dateCompleted:(NSPopUpButton *)sender;
+- (IBAction)inAtChanged:(id)sender;
+- (IBAction)setAlarm:(NSButton *)sender;
+
+@end
Index: trunk/Cocoa/Pester/Source/PSAlarmSetController.m
===================================================================
--- trunk/Cocoa/Pester/Source/PSAlarmSetController.m	(revision 21)
+++ trunk/Cocoa/Pester/Source/PSAlarmSetController.m	(revision 21)
@@ -0,0 +1,208 @@
+//
+//  PSAlarmSetController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarmSetController.h"
+#import "PSAlarmNotifierController.h"
+#import "NJRDateFormatter.h"
+
+// XXX Bugs to file:
+// XXX any trailing spaces: -> exception for +[NSCalendarDate dateWithNaturalLanguageString]:
+// > NSCalendarDate dateWithNaturalLanguageString: '12 '
+// format error: internal error
+
+// XXX NSDate natural language stuff in NSCalendarDate (why?), misspelled category name
+// XXX NSCalendarDate natural language stuff behaves differently from NSDateFormatter (AM/PM has no effect, shouldn't they share code?)
+// XXX NSDateFormatter doc class description gives two examples for natural language that are incorrect, no link to NSDate doc that describes exactly how natural language dates are parsed
+// XXX NSTimeFormatString does not include %p when it should, meaning that AM/PM is stripped yet 12-hour time is still used
+// XXX NSNextDayDesignations, NSNextNextDayDesignations are noted as 'a string' in NSUserDefaults docs, but maybe they are actually an array, or either an array or a string, given their names?
+// XXX "Setting the Format for Dates" does not document how to get 1:15 AM, the answer is %1I - strftime has no exact equivalent; the closest is %l.  strftime does not permit numeric prefixes.  It also refers to "NSCalendar" when no such class exists.
+// XXX none of many mentions of NSAMPMDesignation indicates that they include the leading spaces (" AM", " PM").  In "Setting the Format for Dates", needs to mention that the leading spaces are not included in %p with strftime.
+// XXX descriptions for %X and %x are reversed (time zone is in %X, not %x)
+// XXX too hard to implement date-only or time-only formatters
+// XXX should be able to specify that natural language favors date or time (10 = 10th of month, not 10am)
+// XXX please expose the iCal controls!
+
+
+@implementation PSAlarmSetController
+
+- (void)awakeFromNib;
+{
+    // NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [[self window] center];
+    // XXX bugs prevent these from working (sigh...)
+    // [timeOfDay setFormatter: [[NJRDateFormatter alloc] initWithDateFormat: [defaults objectForKey: NSTimeFormatString] allowNaturalLanguage: YES]];
+    // [timeDate setFormatter: [[NJRDateFormatter alloc] initWithDateFormat: [defaults objectForKey: NSShortDateFormatString] allowNaturalLanguage: YES]];
+    [self inAtChanged: nil];
+}
+
+- (void)setStatus:(NSString *)aString;
+{
+    if (aString != status) {
+        [status release]; status = nil;
+        status = [aString retain];
+        [timeSummary setStringValue: status];
+    }
+}
+
+- (id)objectValueForTextField:(NSTextField *)field whileEditing:(id)sender;
+{
+    if (sender == field) {
+        NSString *stringValue = [[[self window] fieldEditor: NO forObject: field] string];
+        id obj = nil;
+        [[field formatter] getObjectValue: &obj forString: stringValue errorDescription: NULL];
+        // NSLog(@"from field editor: %@", obj);
+        return obj;
+    } else {
+        // NSLog(@"from field: %@", [field objectValue]);
+        return [field objectValue];
+    }
+}
+
+- (void)setAlarmDateAndInterval:(id)sender;
+{
+    [alarmDate release];
+    alarmDate = nil;
+    alarmInterval = 0;
+    if (isIn) {
+        alarmInterval = [[self objectValueForTextField: timeInterval whileEditing: sender] intValue] * [timeIntervalUnits selectedTag];
+        if (alarmInterval == 0) {
+            [self setStatus: @"Please specify an alarm interval."]; return;
+        }
+        alarmDate = [NSCalendarDate dateWithTimeIntervalSinceNow: alarmInterval];
+        [alarmDate retain];
+    } else {
+        NSDate *time = [self objectValueForTextField: timeOfDay whileEditing: sender];
+        NSDate *date = [self objectValueForTextField: timeDate whileEditing: sender];
+        NSCalendarDate *calTime, *calDate;
+        if (time == nil && date == nil) {
+            [self setStatus: @"Please specify an alarm date and time."]; return;
+        }
+        if (time == nil) {
+            [self setStatus: @"Please specify an alarm time."]; return;
+        }
+        if (date == nil) {
+            [self setStatus: @"Please specify an alarm date."]; return;
+        }
+        // XXX if calTime's date is different from the default date, complain
+        calTime = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [time timeIntervalSinceReferenceDate]];
+        calDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [date timeIntervalSinceReferenceDate]];
+        if (time == nil || date == nil) {
+            [self setStatus: @"Please specify a reasonable date and time."];
+        }
+        alarmDate = [[NSCalendarDate alloc] initWithYear: [calDate yearOfCommonEra]
+                                                   month: [calDate monthOfYear]
+                                                     day: [calDate dayOfMonth]
+                                                    hour: [calTime hourOfDay]
+                                                  minute: [calTime minuteOfHour]
+                                                  second: [calTime secondOfMinute]
+                                                timeZone: nil];
+        alarmInterval = [alarmDate timeIntervalSinceNow];
+        if (alarmInterval <= 0) {
+            [self setStatus: @"Please specify an alarm time in the future."];
+            [alarmDate release];
+            alarmDate = nil;
+            return;
+        }
+    }
+}
+
+// XXX should set timer to update status every second while configuration is valid, application is in front, and isIn
+
+// XXX use OACalendar?
+
+// Be careful not to hook up any of the text fields' actions to update: because we handle them in controlTextDidChange: instead.  If we could get the active text field somehow via public API (guess we could use controlTextDidBegin/controlTextDidEndEditing) then we'd not need to overload the update sender for this purpose.  Or, I guess, we could use another method other than update.  It should not be this hard to implement what is essentially standard behavior.  Sigh.
+
+- (IBAction)update:(id)sender;
+{
+    // NSLog(@"update: %@", sender);
+    [self setAlarmDateAndInterval: sender];
+    if (alarmDate != nil) {
+        [self setStatus: [alarmDate descriptionWithCalendarFormat: @"Alarm will be set for %X on %x" timeZone: nil locale: nil]];
+        [setButton setEnabled: YES];
+    } else {
+        [setButton setEnabled: NO];
+    }
+}
+
+- (IBAction)inAtChanged:(id)sender;
+{
+    isIn = ([inAtMatrix selectedTag] == 0);
+    [timeInterval setEnabled: isIn];
+    [timeIntervalUnits setEnabled: isIn];
+    [timeOfDay setEnabled: !isIn];
+    [timeDate setEnabled: !isIn];
+    [timeDateCompletions setEnabled: !isIn];
+    if (sender != nil)
+        [[self window] makeFirstResponder: isIn ? timeInterval : timeOfDay];
+    // NSLog(@"UPDATING FROM inAtChanged");
+    [self update: nil];
+}
+
+- (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error;
+{
+    unichar c;
+    int tag;
+    unsigned length = [string length];
+    if (control != timeInterval || length == 0) return;
+    c = [string characterAtIndex: length - 1];
+    switch (c) {
+        case 's': case 'S': tag = 1; break;
+        case 'm': case 'M': tag = 60; break;
+        case 'h': case 'H': tag = 60 * 60; break;
+        default: return;
+    }
+    [timeIntervalUnits selectItemAtIndex:
+        [timeIntervalUnits indexOfItemWithTag: tag]];
+    // NSLog(@"UPDATING FROM validation");
+    [self update: timeInterval]; // make sure we still examine the field editor, otherwise if the existing numeric string is invalid, it'll be cleared
+}
+
+- (IBAction)dateCompleted:(NSPopUpButton *)sender;
+{
+    [timeDate setStringValue: [sender titleOfSelectedItem]];
+}
+
+// to ensure proper updating of interval, this should be the only method by which the window is shown (e.g. from the Alarm menu)
+- (IBAction)showWindow:(id)sender;
+{
+    if (![[self window] isVisible]) {
+        // NSLog(@"UPDATING FROM showWindow");
+        [self update: self];
+    }
+    [super showWindow: sender];
+    
+}
+
+- (IBAction)setAlarm:(NSButton *)sender;
+{
+    PSAlarmNotifierController *notifier = [PSAlarmNotifierController alloc];
+    NSTimer *timer;
+    [self setAlarmDateAndInterval: sender];
+    if (notifier == nil || alarmDate == nil) {
+        [self setStatus: @"Unable to set alarm (time just passed?)"];
+        return;
+    }
+    // XXX should use alarm object instead for userInfo
+    timer = [NSTimer scheduledTimerWithTimeInterval: alarmInterval
+                                             target: notifier
+                                           selector: @selector(initWithTimer:)
+                                           userInfo: [messageField stringValue]
+                                            repeats: NO];
+    [self setStatus: [alarmDate descriptionWithCalendarFormat: @"Alarm set for %x at %X" timeZone: nil locale: nil]];
+    [[self window] close];
+}
+
+// called because we're the delegate
+
+- (void)controlTextDidChange:(NSNotification *)notification;
+{
+    // NSLog(@"UPDATING FROM controlTextDidChange");
+    [self update: [notification object]];
+}
+
+@end
Index: trunk/Cocoa/Pester/Source/Pester.pbproj/nicholas.pbxuser
===================================================================
--- trunk/Cocoa/Pester/Source/Pester.pbproj/nicholas.pbxuser	(revision 21)
+++ trunk/Cocoa/Pester/Source/Pester.pbproj/nicholas.pbxuser	(revision 21)
@@ -0,0 +1,1306 @@
+// !$*UTF8*$!
+{
+	29B97313FDCFA39411CA2CEA = {
+		activeBuildStyle = 4A9504CDFFE6A4B311CA0CBA;
+		activeExecutable = F59B967103538BE201154278;
+		activeTarget = 29B97326FDCFA39411CA2CEA;
+		addToTargets = (
+			29B97326FDCFA39411CA2CEA,
+		);
+		breakpoints = (
+		);
+		executables = (
+			F59B967103538BE201154278,
+		);
+		perUserDictionary = {
+			PBXPerProjectTemplateStateSaveDate = 55845278;
+			"PBXTemplateGeometry-F5314676015831810DCA290F" = {
+				ContentSize = "{618, 257}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 23}, {618, 234}}";
+					Split0 = {
+						ActiveTab = 2;
+						Collapsed = YES;
+						Frame = "{{0, 0}, {618, 234}}";
+						Split0 = {
+							Frame = "{{1e+06, 1e+06}, {618, 0}}";
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Debugger = {
+								Collapsed = NO;
+								Frame = "{{0, 0}, {952, 321}}";
+								Split0 = {
+									Frame = "{{0, 24}, {952, 297}}";
+									Split0 = {
+										Frame = "{{0, 0}, {468, 297}}";
+									};
+									Split1 = {
+										DebugVariablesTableConfiguration = (
+											Name,
+											126.803,
+											Value,
+											150.074,
+											Summary,
+											172.123,
+										);
+										Frame = "{{477, 0}, {475, 297}}";
+									};
+									SplitCount = 2;
+								};
+								SplitCount = 1;
+								Tab0 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								Tab1 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								TabCount = 2;
+								TabsVisible = YES;
+							};
+							Frame = "{{0, 0}, {952, 321}}";
+							LauncherConfigVersion = 7;
+						};
+						Tab1 = {
+							Frame = "{{0, 0}, {781, 452}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {781, 452}}";
+							};
+						};
+						Tab2 = {
+							BuildMessageFrame = "{{0, 0}, {620, 123}}";
+							BuildTranscriptFrame = "{{0, 132}, {620, 98}}";
+							Frame = "{{0, 0}, {618, 228}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {612, 295}}";
+						};
+						TabCount = 4;
+						TabsVisible = NO;
+					};
+					SplitCount = 1;
+					Tab0 = {
+						Frame = "{{0, 0}, {300, 533}}";
+						GroupTreeTableConfiguration = (
+							TargetStatusColumn,
+							18,
+							MainColumn,
+							267,
+						);
+					};
+					Tab1 = {
+						ClassesFrame = "{{0, 0}, {280, 398}}";
+						ClassesTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXClassColumnIdentifier,
+							237,
+						);
+						Frame = "{{0, 0}, {278, 659}}";
+						MembersFrame = "{{0, 407}, {280, 252}}";
+						MembersTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXMethodColumnIdentifier,
+							236,
+						);
+					};
+					Tab2 = {
+						Frame = "{{0, 0}, {200, 100}}";
+					};
+					Tab3 = {
+						Frame = "{{0, 0}, {200, 100}}";
+						TargetTableConfiguration = (
+							ActiveObject,
+							16,
+							ObjectNames,
+							202.296,
+						);
+					};
+					Tab4 = {
+						BreakpointsTreeTableConfiguration = (
+							breakpointColumn,
+							197,
+							enabledColumn,
+							31,
+						);
+						Frame = "{{0, 0}, {250, 100}}";
+					};
+					TabCount = 5;
+					TabsVisible = NO;
+				};
+				StatusViewVisible = YES;
+				Template = F5314676015831810DCA290F;
+				ToolbarVisible = YES;
+				WindowLocation = "{601, 113}";
+			};
+			"PBXTemplateGeometry-F5534CB2020F3F8A0DCA290F" = {
+				ContentSize = "{594, 303}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 23}, {594, 280}}";
+					Split0 = {
+						ActiveTab = 1;
+						Collapsed = YES;
+						Frame = "{{0, 0}, {594, 280}}";
+						Split0 = {
+							Frame = "{{1e+06, 1e+06}, {594, 0}}";
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Debugger = {
+								Collapsed = NO;
+								Frame = "{{0, 0}, {804, 321}}";
+								Split0 = {
+									Frame = "{{0, 24}, {804, 297}}";
+									Split0 = {
+										Frame = "{{0, 0}, {394, 297}}";
+									};
+									Split1 = {
+										DebugVariablesTableConfiguration = (
+											Name,
+											123,
+											Value,
+											85,
+											Summary,
+											167.123,
+										);
+										Frame = "{{403, 0}, {401, 297}}";
+									};
+									SplitCount = 2;
+								};
+								SplitCount = 1;
+								Tab0 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								Tab1 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								TabCount = 2;
+								TabsVisible = YES;
+							};
+							Frame = "{{0, 0}, {804, 321}}";
+							LauncherConfigVersion = 7;
+						};
+						Tab1 = {
+							Frame = "{{0, 0}, {594, 274}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {594, 274}}";
+							};
+						};
+						Tab2 = {
+							BuildMessageFrame = "{{0, 0}, {806, 237}}";
+							BuildTranscriptFrame = "{{0, 246}, {806, 3}}";
+							Frame = "{{0, 0}, {804, 247}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {612, 295}}";
+						};
+						TabCount = 4;
+						TabsVisible = NO;
+					};
+					SplitCount = 1;
+					Tab0 = {
+						Frame = "{{0, 0}, {300, 533}}";
+						GroupTreeTableConfiguration = (
+							TargetStatusColumn,
+							18,
+							MainColumn,
+							267,
+						);
+					};
+					Tab1 = {
+						ClassesFrame = "{{0, 0}, {280, 398}}";
+						ClassesTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXClassColumnIdentifier,
+							237,
+						);
+						Frame = "{{0, 0}, {278, 659}}";
+						MembersFrame = "{{0, 407}, {280, 252}}";
+						MembersTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXMethodColumnIdentifier,
+							236,
+						);
+					};
+					Tab2 = {
+						Frame = "{{0, 0}, {200, 100}}";
+					};
+					Tab3 = {
+						Frame = "{{0, 0}, {200, 386}}";
+						TargetTableConfiguration = (
+							ActiveObject,
+							16,
+							ObjectNames,
+							202.296,
+						);
+					};
+					Tab4 = {
+						BreakpointsTreeTableConfiguration = (
+							breakpointColumn,
+							197,
+							enabledColumn,
+							31,
+						);
+						Frame = "{{0, 0}, {250, 386}}";
+					};
+					TabCount = 5;
+					TabsVisible = NO;
+				};
+				StatusViewVisible = YES;
+				Template = F5534CB2020F3F8A0DCA290F;
+				ToolbarVisible = YES;
+				WindowLocation = "{188, 218}";
+			};
+			"PBXTemplateGeometry-F5CA7EC8015C06940DCA290F" = {
+				ContentSize = "{705, 569}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 0}, {705, 569}}";
+					Split0 = {
+						Collapsed = NO;
+						Frame = "{{0, 0}, {705, 569}}";
+						Split0 = {
+							Frame = "{{0, 0}, {705, 569}}";
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Debugger = {
+								Collapsed = NO;
+								Frame = "{{0, 0}, {484, 208}}";
+								Split0 = {
+									Frame = "{{0, 24}, {484, 184}}";
+									Split0 = {
+										Frame = "{{0, 0}, {236, 184}}";
+									};
+									Split1 = {
+										DebugVariablesTableConfiguration = (
+											Name,
+											123,
+											Value,
+											85,
+											Summary,
+											62.123,
+										);
+										Frame = "{{245, 0}, {239, 184}}";
+									};
+									SplitCount = 2;
+								};
+								SplitCount = 1;
+								Tab0 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								Tab1 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								TabCount = 2;
+								TabsVisible = YES;
+							};
+							Frame = "{{0, 0}, {484, 208}}";
+							LauncherConfigVersion = 7;
+						};
+						Tab1 = {
+							Frame = "{{0, 0}, {522, 208}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {522, 208}}";
+							};
+						};
+						Tab2 = {
+							BuildMessageFrame = "{{0, 0}, {809, 410}}";
+							BuildTranscriptFrame = "{{0, 419}, {809, 119}}";
+							Frame = "{{0, 0}, {807, 536}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {612, 295}}";
+						};
+						TabCount = 4;
+						TabsVisible = NO;
+					};
+					SplitCount = 1;
+					Tab0 = {
+						Frame = "{{0, 0}, {300, 533}}";
+						GroupTreeTableConfiguration = (
+							TargetStatusColumn,
+							18,
+							MainColumn,
+							267,
+						);
+					};
+					Tab1 = {
+						ClassesFrame = "{{0, 0}, {280, 398}}";
+						ClassesTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXClassColumnIdentifier,
+							237,
+						);
+						Frame = "{{0, 0}, {278, 659}}";
+						MembersFrame = "{{0, 407}, {280, 252}}";
+						MembersTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXMethodColumnIdentifier,
+							236,
+						);
+					};
+					Tab2 = {
+						Frame = "{{0, 0}, {200, 100}}";
+					};
+					Tab3 = {
+						Frame = "{{0, 0}, {222, 536}}";
+						TargetTableConfiguration = (
+							ActiveObject,
+							16,
+							ObjectNames,
+							202.296,
+						);
+					};
+					Tab4 = {
+						BreakpointsTreeTableConfiguration = (
+							breakpointColumn,
+							197,
+							enabledColumn,
+							31,
+						);
+						Frame = "{{0, 0}, {250, 528}}";
+					};
+					TabCount = 5;
+					TabsVisible = NO;
+				};
+				StatusViewVisible = NO;
+				Template = F5CA7EC8015C06940DCA290F;
+				ToolbarVisible = YES;
+				WindowLocation = "{34, 330}";
+			};
+			"PBXTemplateGeometry-F5CA7EC9015C08ED0DCA290F" = {
+				ContentSize = "{665, 594}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 0}, {665, 594}}";
+					Split0 = {
+						ActiveTab = 3;
+						Collapsed = NO;
+						Frame = "{{0, 0}, {665, 594}}";
+						Split0 = {
+							Frame = "{{0, 304}, {665, 290}}";
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Debugger = {
+								Collapsed = NO;
+								Frame = "{{0, 0}, {484, 208}}";
+								Split0 = {
+									Frame = "{{0, 24}, {484, 184}}";
+									Split0 = {
+										Frame = "{{0, 0}, {236, 184}}";
+									};
+									Split1 = {
+										DebugVariablesTableConfiguration = (
+											Name,
+											123,
+											Value,
+											85,
+											Summary,
+											62.123,
+										);
+										Frame = "{{245, 0}, {239, 184}}";
+									};
+									SplitCount = 2;
+								};
+								SplitCount = 1;
+								Tab0 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								Tab1 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								TabCount = 2;
+								TabsVisible = YES;
+							};
+							Frame = "{{0, 0}, {484, 208}}";
+							LauncherConfigVersion = 7;
+						};
+						Tab1 = {
+							Frame = "{{0, 0}, {664, 208}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {664, 208}}";
+							};
+						};
+						Tab2 = {
+							BuildMessageFrame = "{{0, 0}, {666, 43}}";
+							BuildTranscriptFrame = "{{0, 52}, {666, 0}}";
+							Frame = "{{0, 0}, {664, 50}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {665, 298}}";
+						};
+						TabCount = 4;
+						TabsVisible = NO;
+					};
+					SplitCount = 1;
+					Tab0 = {
+						Frame = "{{0, 0}, {313, 531}}";
+						GroupTreeTableConfiguration = (
+							TargetStatusColumn,
+							18,
+							MainColumn,
+							280,
+						);
+					};
+					Tab1 = {
+						ClassesFrame = "{{0, 0}, {280, 398}}";
+						ClassesTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXClassColumnIdentifier,
+							237,
+						);
+						Frame = "{{0, 0}, {278, 659}}";
+						MembersFrame = "{{0, 407}, {280, 252}}";
+						MembersTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXMethodColumnIdentifier,
+							236,
+						);
+					};
+					Tab2 = {
+						Frame = "{{0, 0}, {200, 100}}";
+					};
+					Tab3 = {
+						Frame = "{{0, 0}, {200, 557}}";
+						TargetTableConfiguration = (
+							ActiveObject,
+							16,
+							ObjectNames,
+							202.296,
+						);
+					};
+					Tab4 = {
+						BreakpointsTreeTableConfiguration = (
+							breakpointColumn,
+							197,
+							enabledColumn,
+							31,
+						);
+						Frame = "{{0, 0}, {250, 100}}";
+					};
+					TabCount = 5;
+					TabsVisible = NO;
+				};
+				StatusViewVisible = NO;
+				Template = F5CA7EC9015C08ED0DCA290F;
+				ToolbarVisible = NO;
+				WindowLocation = "{69, 372}";
+			};
+			"PBXTemplateGeometry-F5CA7ECA015C09360DCA290F" = {
+				ContentSize = "{773, 818}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 0}, {773, 818}}";
+					Split0 = {
+						Collapsed = NO;
+						Frame = "{{0, 0}, {773, 818}}";
+						Split0 = {
+							Frame = "{{0, 0}, {773, 818}}";
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Debugger = {
+								Collapsed = NO;
+								Frame = "{{0, 0}, {484, 208}}";
+								Split0 = {
+									Frame = "{{0, 24}, {484, 184}}";
+									Split0 = {
+										Frame = "{{0, 0}, {236, 184}}";
+									};
+									Split1 = {
+										DebugVariablesTableConfiguration = (
+											Name,
+											123,
+											Value,
+											85,
+											Summary,
+											62.123,
+										);
+										Frame = "{{245, 0}, {239, 184}}";
+									};
+									SplitCount = 2;
+								};
+								SplitCount = 1;
+								Tab0 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								Tab1 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								TabCount = 2;
+								TabsVisible = YES;
+							};
+							Frame = "{{0, 0}, {484, 208}}";
+							LauncherConfigVersion = 7;
+						};
+						Tab1 = {
+							Frame = "{{0, 0}, {664, 208}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {664, 208}}";
+							};
+						};
+						Tab2 = {
+							BuildMessageFrame = "{{0, 0}, {666, 43}}";
+							BuildTranscriptFrame = "{{0, 52}, {666, 0}}";
+							Frame = "{{0, 0}, {664, 50}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {612, 295}}";
+						};
+						TabCount = 4;
+						TabsVisible = NO;
+					};
+					SplitCount = 1;
+					Tab0 = {
+						Frame = "{{0, 0}, {313, 531}}";
+						GroupTreeTableConfiguration = (
+							TargetStatusColumn,
+							18,
+							MainColumn,
+							280,
+						);
+					};
+					Tab1 = {
+						ClassesFrame = "{{0, 0}, {280, 398}}";
+						ClassesTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXClassColumnIdentifier,
+							237,
+						);
+						Frame = "{{0, 0}, {278, 659}}";
+						MembersFrame = "{{0, 407}, {280, 252}}";
+						MembersTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXMethodColumnIdentifier,
+							236,
+						);
+					};
+					Tab2 = {
+						Frame = "{{0, 0}, {200, 100}}";
+					};
+					Tab3 = {
+						Frame = "{{0, 0}, {200, 557}}";
+						TargetTableConfiguration = (
+							ActiveObject,
+							16,
+							ObjectNames,
+							202.296,
+						);
+					};
+					Tab4 = {
+						BreakpointsTreeTableConfiguration = (
+							breakpointColumn,
+							197,
+							enabledColumn,
+							31,
+						);
+						Frame = "{{0, 0}, {250, 100}}";
+					};
+					TabCount = 5;
+					TabsVisible = NO;
+				};
+				StatusViewVisible = NO;
+				Template = F5CA7ECA015C09360DCA290F;
+				ToolbarVisible = NO;
+				WindowLocation = "{724, 200}";
+			};
+			"PBXTemplateGeometry-F5CA7ECB015C094F0DCA290F" = {
+				ContentSize = "{668, 621}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 0}, {668, 621}}";
+					Split0 = {
+						Collapsed = NO;
+						Frame = "{{0, 0}, {668, 621}}";
+						Split0 = {
+							Frame = "{{0, 0}, {668, 621}}";
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Debugger = {
+								Collapsed = NO;
+								Frame = "{{0, 0}, {484, 208}}";
+								Split0 = {
+									Frame = "{{0, 24}, {484, 184}}";
+									Split0 = {
+										Frame = "{{0, 0}, {236, 184}}";
+									};
+									Split1 = {
+										DebugVariablesTableConfiguration = (
+											Name,
+											123,
+											Value,
+											85,
+											Summary,
+											62.123,
+										);
+										Frame = "{{245, 0}, {239, 184}}";
+									};
+									SplitCount = 2;
+								};
+								SplitCount = 1;
+								Tab0 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								Tab1 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								TabCount = 2;
+								TabsVisible = YES;
+							};
+							Frame = "{{0, 0}, {484, 208}}";
+							LauncherConfigVersion = 7;
+						};
+						Tab1 = {
+							Frame = "{{0, 0}, {664, 208}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {664, 208}}";
+							};
+						};
+						Tab2 = {
+							BuildMessageFrame = "{{0, 0}, {666, 43}}";
+							BuildTranscriptFrame = "{{0, 52}, {666, 0}}";
+							Frame = "{{0, 0}, {664, 50}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {612, 295}}";
+						};
+						TabCount = 4;
+						TabsVisible = NO;
+					};
+					SplitCount = 1;
+					Tab0 = {
+						Frame = "{{0, 0}, {313, 531}}";
+						GroupTreeTableConfiguration = (
+							TargetStatusColumn,
+							18,
+							MainColumn,
+							280,
+						);
+					};
+					Tab1 = {
+						ClassesFrame = "{{0, 0}, {280, 398}}";
+						ClassesTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXClassColumnIdentifier,
+							237,
+						);
+						Frame = "{{0, 0}, {278, 659}}";
+						MembersFrame = "{{0, 407}, {280, 252}}";
+						MembersTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXMethodColumnIdentifier,
+							236,
+						);
+					};
+					Tab2 = {
+						Frame = "{{0, 0}, {200, 100}}";
+					};
+					Tab3 = {
+						Frame = "{{0, 0}, {200, 557}}";
+						TargetTableConfiguration = (
+							ActiveObject,
+							16,
+							ObjectNames,
+							202.296,
+						);
+					};
+					Tab4 = {
+						BreakpointsTreeTableConfiguration = (
+							breakpointColumn,
+							197,
+							enabledColumn,
+							31,
+						);
+						Frame = "{{0, 0}, {250, 100}}";
+					};
+					TabCount = 5;
+					TabsVisible = NO;
+				};
+				StatusViewVisible = NO;
+				Template = F5CA7ECB015C094F0DCA290F;
+				ToolbarVisible = NO;
+				WindowLocation = "{382, 526}";
+			};
+			PBXWorkspaceContents = (
+				{
+					LeftSlideOut = {
+						Split0 = {
+							Split0 = {
+								NavCount = 1;
+								NavGeometry0 = {
+									Frame = "{{0, 0}, {150, 530}}";
+									NavBarVisible = YES;
+								};
+							};
+							SplitCount = 1;
+							Tab0 = {
+								Debugger = {
+									Split0 = {
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									TabCount = 2;
+								};
+								LauncherConfigVersion = 7;
+							};
+							Tab1 = {
+								LauncherConfigVersion = 3;
+								Runner = {
+								};
+							};
+							TabCount = 4;
+						};
+						SplitCount = 1;
+						Tab1 = {
+							OptionsSetName = "Hierarchy, all classes";
+						};
+						TabCount = 5;
+					};
+				},
+				{
+					LeftSlideOut = {
+						Split0 = {
+							Split0 = {
+								NavCount = 1;
+								NavGeometry0 = {
+									Frame = "{{0, 0}, {594, 150}}";
+									NavBarVisible = YES;
+								};
+							};
+							SplitCount = 1;
+							Tab0 = {
+								Debugger = {
+									Split0 = {
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									TabCount = 2;
+								};
+								LauncherConfigVersion = 7;
+							};
+							Tab1 = {
+								LauncherConfigVersion = 3;
+								Runner = {
+								};
+							};
+							TabCount = 4;
+						};
+						SplitCount = 1;
+						Tab1 = {
+							OptionsSetName = "Hierarchy, all classes";
+						};
+						TabCount = 5;
+					};
+				},
+				{
+					LeftSlideOut = {
+						Split0 = {
+							Split0 = {
+								NavCount = 1;
+								NavGeometry0 = {
+									Frame = "{{0, 0}, {618, 150}}";
+									NavBarVisible = YES;
+								};
+							};
+							SplitCount = 1;
+							Tab0 = {
+								Debugger = {
+									Split0 = {
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									TabCount = 2;
+								};
+								LauncherConfigVersion = 7;
+							};
+							Tab1 = {
+								LauncherConfigVersion = 3;
+								Runner = {
+								};
+							};
+							TabCount = 4;
+						};
+						SplitCount = 1;
+						Tab1 = {
+							OptionsSetName = "Hierarchy, all classes";
+						};
+						TabCount = 5;
+					};
+				},
+			);
+			PBXWorkspaceGeometries = (
+				{
+					ContentSize = "{352, 553}";
+					LeftSlideOut = {
+						ActiveTab = 0;
+						Collapsed = YES;
+						Frame = "{{0, 23}, {352, 530}}";
+						Split0 = {
+							Collapsed = NO;
+							Frame = "{{1e+06, 1e+06}, {0, 530}}";
+							Split0 = {
+								Frame = "{{0, 0}, {0, 530}}";
+							};
+							SplitCount = 1;
+							Tab0 = {
+								Debugger = {
+									Collapsed = NO;
+									Frame = "{{0, 0}, {484, 208}}";
+									Split0 = {
+										Frame = "{{0, 24}, {484, 184}}";
+										Split0 = {
+											Frame = "{{0, 0}, {236, 184}}";
+										};
+										Split1 = {
+											DebugVariablesTableConfiguration = (
+												Name,
+												123,
+												Value,
+												85,
+												Summary,
+												62.123,
+											);
+											Frame = "{{245, 0}, {239, 184}}";
+										};
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									Tab0 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									Tab1 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									TabCount = 2;
+									TabsVisible = YES;
+								};
+								Frame = "{{0, 0}, {484, 208}}";
+								LauncherConfigVersion = 7;
+							};
+							Tab1 = {
+								Frame = "{{0, 0}, {664, 208}}";
+								LauncherConfigVersion = 3;
+								Runner = {
+									Frame = "{{0, 0}, {664, 208}}";
+								};
+							};
+							Tab2 = {
+								BuildMessageFrame = "{{0, 0}, {666, 43}}";
+								BuildTranscriptFrame = "{{0, 52}, {666, 0}}";
+								Frame = "{{0, 0}, {664, 50}}";
+							};
+							Tab3 = {
+								Frame = "{{0, 0}, {612, 295}}";
+							};
+							TabCount = 4;
+							TabsVisible = NO;
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Frame = "{{0, 0}, {328, 530}}";
+							GroupTreeTableConfiguration = (
+								TargetStatusColumn,
+								18,
+								MainColumn,
+								295,
+							);
+						};
+						Tab1 = {
+							ClassesFrame = "{{0, 0}, {343, 348}}";
+							ClassesTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXClassColumnIdentifier,
+								300,
+							);
+							Frame = "{{0, 0}, {341, 578}}";
+							MembersFrame = "{{0, 357}, {343, 221}}";
+							MembersTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXMethodColumnIdentifier,
+								299,
+							);
+						};
+						Tab2 = {
+							Frame = "{{0, 0}, {328, 530}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {328, 530}}";
+							TargetTableConfiguration = (
+								ActiveObject,
+								16,
+								ObjectNames,
+								295.296,
+							);
+						};
+						Tab4 = {
+							BreakpointsTreeTableConfiguration = (
+								breakpointColumn,
+								275,
+								enabledColumn,
+								31,
+							);
+							Frame = "{{0, 0}, {328, 530}}";
+						};
+						TabCount = 5;
+						TabsVisible = YES;
+					};
+					StatusViewVisible = YES;
+					Template = F5E465990156DFB90DCA290F;
+					ToolbarVisible = YES;
+					WindowLocation = "{20, 553}";
+				},
+				{
+					ContentSize = "{594, 303}";
+					LeftSlideOut = {
+						Collapsed = NO;
+						Frame = "{{0, 23}, {594, 280}}";
+						Split0 = {
+							ActiveTab = 1;
+							Collapsed = YES;
+							Frame = "{{0, 0}, {594, 280}}";
+							Split0 = {
+								Frame = "{{1e+06, 1e+06}, {594, 0}}";
+							};
+							SplitCount = 1;
+							Tab0 = {
+								Debugger = {
+									Collapsed = NO;
+									Frame = "{{0, 0}, {804, 321}}";
+									Split0 = {
+										Frame = "{{0, 24}, {804, 297}}";
+										Split0 = {
+											Frame = "{{0, 0}, {394, 297}}";
+										};
+										Split1 = {
+											DebugVariablesTableConfiguration = (
+												Name,
+												123,
+												Value,
+												85,
+												Summary,
+												167.123,
+											);
+											Frame = "{{403, 0}, {401, 297}}";
+										};
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									Tab0 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									Tab1 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									TabCount = 2;
+									TabsVisible = YES;
+								};
+								Frame = "{{0, 0}, {804, 321}}";
+								LauncherConfigVersion = 7;
+							};
+							Tab1 = {
+								Frame = "{{0, 0}, {594, 274}}";
+								LauncherConfigVersion = 3;
+								Runner = {
+									Frame = "{{0, 0}, {594, 274}}";
+								};
+							};
+							Tab2 = {
+								BuildMessageFrame = "{{0, 0}, {806, 237}}";
+								BuildTranscriptFrame = "{{0, 246}, {806, 3}}";
+								Frame = "{{0, 0}, {804, 247}}";
+							};
+							Tab3 = {
+								Frame = "{{0, 0}, {612, 295}}";
+							};
+							TabCount = 4;
+							TabsVisible = NO;
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Frame = "{{0, 0}, {300, 533}}";
+							GroupTreeTableConfiguration = (
+								TargetStatusColumn,
+								18,
+								MainColumn,
+								267,
+							);
+						};
+						Tab1 = {
+							ClassesFrame = "{{0, 0}, {280, 398}}";
+							ClassesTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXClassColumnIdentifier,
+								237,
+							);
+							Frame = "{{0, 0}, {278, 659}}";
+							MembersFrame = "{{0, 407}, {280, 252}}";
+							MembersTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXMethodColumnIdentifier,
+								236,
+							);
+						};
+						Tab2 = {
+							Frame = "{{0, 0}, {200, 100}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {200, 386}}";
+							TargetTableConfiguration = (
+								ActiveObject,
+								16,
+								ObjectNames,
+								202.296,
+							);
+						};
+						Tab4 = {
+							BreakpointsTreeTableConfiguration = (
+								breakpointColumn,
+								197,
+								enabledColumn,
+								31,
+							);
+							Frame = "{{0, 0}, {250, 386}}";
+						};
+						TabCount = 5;
+						TabsVisible = NO;
+					};
+					StatusViewVisible = YES;
+					Template = F5534CB2020F3F8A0DCA290F;
+					ToolbarVisible = YES;
+					WindowLocation = "{188, 218}";
+				},
+				{
+					ContentSize = "{618, 257}";
+					LeftSlideOut = {
+						Collapsed = NO;
+						Frame = "{{0, 23}, {618, 234}}";
+						Split0 = {
+							ActiveTab = 2;
+							Collapsed = YES;
+							Frame = "{{0, 0}, {618, 234}}";
+							Split0 = {
+								Frame = "{{1e+06, 1e+06}, {618, 0}}";
+							};
+							SplitCount = 1;
+							Tab0 = {
+								Debugger = {
+									Collapsed = NO;
+									Frame = "{{0, 0}, {952, 321}}";
+									Split0 = {
+										Frame = "{{0, 24}, {952, 297}}";
+										Split0 = {
+											Frame = "{{0, 0}, {468, 297}}";
+										};
+										Split1 = {
+											DebugVariablesTableConfiguration = (
+												Name,
+												126.803,
+												Value,
+												150.074,
+												Summary,
+												172.123,
+											);
+											Frame = "{{477, 0}, {475, 297}}";
+										};
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									Tab0 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									Tab1 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									TabCount = 2;
+									TabsVisible = YES;
+								};
+								Frame = "{{0, 0}, {952, 321}}";
+								LauncherConfigVersion = 7;
+							};
+							Tab1 = {
+								Frame = "{{0, 0}, {781, 452}}";
+								LauncherConfigVersion = 3;
+								Runner = {
+									Frame = "{{0, 0}, {781, 452}}";
+								};
+							};
+							Tab2 = {
+								BuildMessageFrame = "{{0, 0}, {620, 123}}";
+								BuildTranscriptFrame = "{{0, 132}, {620, 98}}";
+								Frame = "{{0, 0}, {618, 228}}";
+							};
+							Tab3 = {
+								Frame = "{{0, 0}, {612, 295}}";
+							};
+							TabCount = 4;
+							TabsVisible = NO;
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Frame = "{{0, 0}, {300, 533}}";
+							GroupTreeTableConfiguration = (
+								TargetStatusColumn,
+								18,
+								MainColumn,
+								267,
+							);
+						};
+						Tab1 = {
+							ClassesFrame = "{{0, 0}, {280, 398}}";
+							ClassesTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXClassColumnIdentifier,
+								237,
+							);
+							Frame = "{{0, 0}, {278, 659}}";
+							MembersFrame = "{{0, 407}, {280, 252}}";
+							MembersTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXMethodColumnIdentifier,
+								236,
+							);
+						};
+						Tab2 = {
+							Frame = "{{0, 0}, {200, 100}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {200, 100}}";
+							TargetTableConfiguration = (
+								ActiveObject,
+								16,
+								ObjectNames,
+								202.296,
+							);
+						};
+						Tab4 = {
+							BreakpointsTreeTableConfiguration = (
+								breakpointColumn,
+								197,
+								enabledColumn,
+								31,
+							);
+							Frame = "{{0, 0}, {250, 100}}";
+						};
+						TabCount = 5;
+						TabsVisible = NO;
+					};
+					StatusViewVisible = YES;
+					Template = F5314676015831810DCA290F;
+					ToolbarVisible = YES;
+					WindowLocation = "{601, 113}";
+				},
+			);
+			PBXWorkspaceStateSaveDate = 55845278;
+		};
+		projectwideBuildSettings = {
+		};
+		userBookmarkGroup = F59DC6D20353C43201AEEDB1;
+		wantsIndex = 1;
+		wantsSCM = -1;
+	};
+	29B97326FDCFA39411CA2CEA = {
+		activeExec = 0;
+		executables = (
+			F59B967103538BE201154278,
+		);
+	};
+	F59B967103538BE201154278 = {
+		activeArgIndex = 2147483647;
+		argumentStrings = (
+		);
+		debuggerPlugin = GDBDebugging;
+		dylibVariantSuffix = "";
+		enableDebugStr = 1;
+		environmentEntries = (
+			{
+				active = YES;
+				name = NSZombieEnabled;
+				value = YES;
+			},
+		);
+		isa = PBXExecutable;
+		name = Pester;
+		shlibInfoDictList = (
+		);
+		sourceDirectories = (
+		);
+	};
+	F59DC6D20353C43201AEEDB1 = {
+		children = (
+			F59DC6D70353CA6401AEEDB1,
+			F59DC6D90353D35201AEEDB1,
+			F59DC6DA0353D72901AEEDB1,
+			F59DC6E20353E0EB01AEEDB1,
+		);
+		isa = PBXBookmarkGroup;
+		name = Root;
+	};
+	F59DC6D70353CA6401AEEDB1 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 16";
+		rLen = 0;
+		rLoc = 2511;
+		rType = 0;
+		vrLen = 291;
+		vrLoc = 0;
+	};
+	F59DC6D90353D35201AEEDB1 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: inAtChanged:";
+		rLen = 36;
+		rLoc = 6528;
+		rType = 0;
+		vrLen = 478;
+		vrLoc = 416;
+	};
+	F59DC6DA0353D72901AEEDB1 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 25";
+		rLen = 0;
+		rLoc = 799;
+		rType = 0;
+		vrLen = 758;
+		vrLoc = 0;
+	};
+	F59DC6E20353E0EB01AEEDB1 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 31";
+		rLen = 0;
+		rLoc = 959;
+		rType = 0;
+		vrLen = 826;
+		vrLoc = 0;
+	};
+}
Index: trunk/Cocoa/Pester/Source/Pester.pbproj/project.pbxproj
===================================================================
--- trunk/Cocoa/Pester/Source/Pester.pbproj/project.pbxproj	(revision 21)
+++ trunk/Cocoa/Pester/Source/Pester.pbproj/project.pbxproj	(revision 21)
@@ -0,0 +1,492 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 38;
+	objects = {
+		080E96DCFE201CFB7F000001 = {
+			fileRef = 29B97318FDCFA39411CA2CEA;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		080E96DDFE201D6D7F000001 = {
+			children = (
+				F59DC6D30353C9E601AEEDB1,
+				F59DC6D40353C9E601AEEDB1,
+				F59DC6DB0353DE5101AEEDB1,
+				F59DC6DC0353DE5101AEEDB1,
+				F59DC6E90353F58B01AEEDB1,
+				F59DC6E80353F58B01AEEDB1,
+				F59DC6FC0354188F01AEEDB1,
+				F59DC6FD0354188F01AEEDB1,
+			);
+			isa = PBXGroup;
+			name = Classes;
+			refType = 4;
+		};
+		089C165CFE840E0CC02AAC07 = {
+			children = (
+				089C165DFE840E0CC02AAC07,
+			);
+			isa = PBXVariantGroup;
+			name = InfoPlist.strings;
+			refType = 4;
+		};
+		089C165DFE840E0CC02AAC07 = {
+			fileEncoding = 10;
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/InfoPlist.strings;
+			refType = 4;
+		};
+		089C165EFE840E0CC02AAC07 = {
+			fileRef = 089C165CFE840E0CC02AAC07;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+//080
+//081
+//082
+//083
+//084
+//100
+//101
+//102
+//103
+//104
+		1058C7A0FEA54F0111CA2CBB = {
+			children = (
+				1058C7A1FEA54F0111CA2CBB,
+			);
+			isa = PBXGroup;
+			name = "Linked Frameworks";
+			refType = 4;
+		};
+		1058C7A1FEA54F0111CA2CBB = {
+			isa = PBXFrameworkReference;
+			name = Cocoa.framework;
+			path = /System/Library/Frameworks/Cocoa.framework;
+			refType = 0;
+		};
+		1058C7A2FEA54F0111CA2CBB = {
+			children = (
+				29B97325FDCFA39411CA2CEA,
+				29B97324FDCFA39411CA2CEA,
+			);
+			isa = PBXGroup;
+			name = "Other Frameworks";
+			refType = 4;
+		};
+		1058C7A3FEA54F0111CA2CBB = {
+			fileRef = 1058C7A1FEA54F0111CA2CBB;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+//100
+//101
+//102
+//103
+//104
+//170
+//171
+//172
+//173
+//174
+		17587328FF379C6511CA2CBB = {
+			isa = PBXApplicationReference;
+			path = Pester.app;
+			refType = 3;
+		};
+//170
+//171
+//172
+//173
+//174
+//190
+//191
+//192
+//193
+//194
+		19C28FACFE9D520D11CA2CBB = {
+			children = (
+				17587328FF379C6511CA2CBB,
+			);
+			isa = PBXGroup;
+			name = Products;
+			refType = 4;
+		};
+//190
+//191
+//192
+//193
+//194
+//290
+//291
+//292
+//293
+//294
+		29B97313FDCFA39411CA2CEA = {
+			buildStyles = (
+				4A9504CCFFE6A4B311CA0CBA,
+				4A9504CDFFE6A4B311CA0CBA,
+			);
+			isa = PBXProject;
+			mainGroup = 29B97314FDCFA39411CA2CEA;
+			projectDirPath = "";
+			targets = (
+				29B97326FDCFA39411CA2CEA,
+			);
+		};
+		29B97314FDCFA39411CA2CEA = {
+			children = (
+				080E96DDFE201D6D7F000001,
+				29B97315FDCFA39411CA2CEA,
+				29B97317FDCFA39411CA2CEA,
+				29B97323FDCFA39411CA2CEA,
+				19C28FACFE9D520D11CA2CBB,
+			);
+			isa = PBXGroup;
+			name = Pester;
+			path = "";
+			refType = 4;
+		};
+		29B97315FDCFA39411CA2CEA = {
+			children = (
+				29B97316FDCFA39411CA2CEA,
+			);
+			isa = PBXGroup;
+			name = "Other Sources";
+			path = "";
+			refType = 4;
+		};
+		29B97316FDCFA39411CA2CEA = {
+			isa = PBXFileReference;
+			path = main.m;
+			refType = 4;
+		};
+		29B97317FDCFA39411CA2CEA = {
+			children = (
+				29B97318FDCFA39411CA2CEA,
+				089C165CFE840E0CC02AAC07,
+				F59DC6E30353ED1201AEEDB1,
+				F59DC6DF0353DF5E01AEEDB1,
+			);
+			isa = PBXGroup;
+			name = Resources;
+			path = "";
+			refType = 4;
+		};
+		29B97318FDCFA39411CA2CEA = {
+			children = (
+				29B97319FDCFA39411CA2CEA,
+			);
+			isa = PBXVariantGroup;
+			name = MainMenu.nib;
+			path = "";
+			refType = 4;
+		};
+		29B97319FDCFA39411CA2CEA = {
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/MainMenu.nib;
+			refType = 4;
+		};
+		29B97323FDCFA39411CA2CEA = {
+			children = (
+				1058C7A0FEA54F0111CA2CBB,
+				1058C7A2FEA54F0111CA2CBB,
+			);
+			isa = PBXGroup;
+			name = Frameworks;
+			path = "";
+			refType = 4;
+		};
+		29B97324FDCFA39411CA2CEA = {
+			isa = PBXFrameworkReference;
+			name = AppKit.framework;
+			path = /System/Library/Frameworks/AppKit.framework;
+			refType = 0;
+		};
+		29B97325FDCFA39411CA2CEA = {
+			isa = PBXFrameworkReference;
+			name = Foundation.framework;
+			path = /System/Library/Frameworks/Foundation.framework;
+			refType = 0;
+		};
+		29B97326FDCFA39411CA2CEA = {
+			buildPhases = (
+				29B97327FDCFA39411CA2CEA,
+				29B97328FDCFA39411CA2CEA,
+				29B9732BFDCFA39411CA2CEA,
+				29B9732DFDCFA39411CA2CEA,
+			);
+			buildSettings = {
+				FRAMEWORK_SEARCH_PATHS = "";
+				HEADER_SEARCH_PATHS = "";
+				INSTALL_PATH = "$(HOME)/Applications";
+				LIBRARY_SEARCH_PATHS = "";
+				OTHER_CFLAGS = "";
+				OTHER_LDFLAGS = "";
+				PRODUCT_NAME = Pester;
+				SECTORDER_FLAGS = "";
+				WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+				WRAPPER_EXTENSION = app;
+			};
+			dependencies = (
+			);
+			isa = PBXApplicationTarget;
+			name = Pester;
+			productInstallPath = "$(HOME)/Applications";
+			productName = Pester;
+			productReference = 17587328FF379C6511CA2CBB;
+			productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>Pester</string>
+	<key>CFBundleGetInfoString</key>
+	<string>Pester 1.0d1, © 2002 Nicholas Riley</string>
+	<key>CFBundleIconFile</key>
+	<string>Application icon</string>
+	<key>CFBundleIdentifier</key>
+	<string>net.sabi.Pester</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>Pester</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0d1</string>
+	<key>CFBundleSignature</key>
+	<string>Pstr</string>
+	<key>CFBundleVersion</key>
+	<string>1.0d1</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
+";
+			shouldUseHeadermap = 1;
+		};
+		29B97327FDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				F59DC6D50353C9E601AEEDB1,
+				F59DC6DD0353DE5101AEEDB1,
+				F59DC6EB0353F58B01AEEDB1,
+				F59DC6FE0354188F01AEEDB1,
+			);
+			isa = PBXHeadersBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B97328FDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				080E96DCFE201CFB7F000001,
+				089C165EFE840E0CC02AAC07,
+				F59DC6E10353DF5E01AEEDB1,
+				F59DC6E40353ED1201AEEDB1,
+			);
+			isa = PBXResourcesBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B9732BFDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				29B9732CFDCFA39411CA2CEA,
+				F59DC6D60353C9E601AEEDB1,
+				F59DC6DE0353DE5101AEEDB1,
+				F59DC6EA0353F58B01AEEDB1,
+				F59DC6FF0354188F01AEEDB1,
+			);
+			isa = PBXSourcesBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B9732CFDCFA39411CA2CEA = {
+			fileRef = 29B97316FDCFA39411CA2CEA;
+			isa = PBXBuildFile;
+			settings = {
+				ATTRIBUTES = (
+				);
+			};
+		};
+		29B9732DFDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				1058C7A3FEA54F0111CA2CBB,
+			);
+			isa = PBXFrameworksBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+//290
+//291
+//292
+//293
+//294
+//4A0
+//4A1
+//4A2
+//4A3
+//4A4
+		4A9504CCFFE6A4B311CA0CBA = {
+			buildRules = (
+			);
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				OPTIMIZATION_CFLAGS = "-O0";
+			};
+			isa = PBXBuildStyle;
+			name = Development;
+		};
+		4A9504CDFFE6A4B311CA0CBA = {
+			buildRules = (
+			);
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+			};
+			isa = PBXBuildStyle;
+			name = Deployment;
+		};
+//4A0
+//4A1
+//4A2
+//4A3
+//4A4
+//F50
+//F51
+//F52
+//F53
+//F54
+		F59DC6D30353C9E601AEEDB1 = {
+			isa = PBXFileReference;
+			path = PSAlarmSetController.h;
+			refType = 4;
+		};
+		F59DC6D40353C9E601AEEDB1 = {
+			isa = PBXFileReference;
+			path = PSAlarmSetController.m;
+			refType = 4;
+		};
+		F59DC6D50353C9E601AEEDB1 = {
+			fileRef = F59DC6D30353C9E601AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6D60353C9E601AEEDB1 = {
+			fileRef = F59DC6D40353C9E601AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6DB0353DE5101AEEDB1 = {
+			isa = PBXFileReference;
+			path = PSAlarmNotifierController.h;
+			refType = 4;
+		};
+		F59DC6DC0353DE5101AEEDB1 = {
+			isa = PBXFileReference;
+			path = PSAlarmNotifierController.m;
+			refType = 4;
+		};
+		F59DC6DD0353DE5101AEEDB1 = {
+			fileRef = F59DC6DB0353DE5101AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6DE0353DE5101AEEDB1 = {
+			fileRef = F59DC6DC0353DE5101AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6DF0353DF5E01AEEDB1 = {
+			children = (
+				F59DC6E00353DF5E01AEEDB1,
+			);
+			isa = PBXVariantGroup;
+			name = Notifier.nib;
+			path = "";
+			refType = 4;
+		};
+		F59DC6E00353DF5E01AEEDB1 = {
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/Notifier.nib;
+			refType = 4;
+		};
+		F59DC6E10353DF5E01AEEDB1 = {
+			fileRef = F59DC6DF0353DF5E01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6E30353ED1201AEEDB1 = {
+			isa = PBXFileReference;
+			path = "Application icon.icns";
+			refType = 4;
+		};
+		F59DC6E40353ED1201AEEDB1 = {
+			fileRef = F59DC6E30353ED1201AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6E80353F58B01AEEDB1 = {
+			isa = PBXFileReference;
+			path = NJRIntegerFilter.m;
+			refType = 4;
+		};
+		F59DC6E90353F58B01AEEDB1 = {
+			isa = PBXFileReference;
+			path = NJRIntegerFilter.h;
+			refType = 4;
+		};
+		F59DC6EA0353F58B01AEEDB1 = {
+			fileRef = F59DC6E80353F58B01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6EB0353F58B01AEEDB1 = {
+			fileRef = F59DC6E90353F58B01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6FC0354188F01AEEDB1 = {
+			isa = PBXFileReference;
+			path = NJRDateFormatter.h;
+			refType = 4;
+		};
+		F59DC6FD0354188F01AEEDB1 = {
+			isa = PBXFileReference;
+			path = NJRDateFormatter.m;
+			refType = 4;
+		};
+		F59DC6FE0354188F01AEEDB1 = {
+			fileRef = F59DC6FC0354188F01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6FF0354188F01AEEDB1 = {
+			fileRef = F59DC6FD0354188F01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+	};
+	rootObject = 29B97313FDCFA39411CA2CEA;
+}
Index: trunk/Cocoa/Pester/Source/main.m
===================================================================
--- trunk/Cocoa/Pester/Source/main.m	(revision 21)
+++ trunk/Cocoa/Pester/Source/main.m	(revision 21)
@@ -0,0 +1,14 @@
+//
+//  main.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, const char *argv[])
+{
+    return NSApplicationMain(argc, argv);
+}
Index: trunk/Cocoa/Pester/package-Pester.sh
===================================================================
--- trunk/Cocoa/Pester/package-Pester.sh	(revision 21)
+++ trunk/Cocoa/Pester/package-Pester.sh	(revision 21)
@@ -0,0 +1,48 @@
+#!/bin/zsh
+
+# stuff to do:
+# hdiutil create DiskImage.dmg -megabytes <size> -layout NONE
+# hdid -nomount DiskImage.dmg
+# sudo /sbin/newfs_hfs -w -v VolumeName -b 4096 /dev/disk2
+# hdiutil eject /dev/disk2
+
+# also check out 'build' on mosxland.sf.net
+
+set -x -v
+
+PACKAGEDIR="$PWD"
+PRODUCT="Pester"
+
+cd "$PACKAGEDIR"/Source && \
+find . -name \*~\* -exec rm -r '{}' \; && \
+VERSION=`cat VERSION` && \
+DMG="$PRODUCT-$VERSION.dmg" VOL="$PRODUCT $VERSION" MOUNTPOINT="/Volumes/$VOL" && \
+DSTROOT="$PACKAGEDIR/$VOL" && \
+sudo rm -fr "$DSTROOT" && \
+rm -rf build/ && \
+pbxbuild install "DSTROOT=$DSTROOT" && \
+ditto -rsrc "$PACKAGEDIR"/Source "$DSTROOT"/Source && \
+ditto -rsrc "${PACKAGEDIR}/Read Me" "$DSTROOT" && \
+rm -rf "$DSTROOT"/Source/build "${DSTROOT}/Source/Read Me.rtfd" && \
+#breaks in 10.2 and later, sigh.
+#mkdir "$DSTROOT/Read Me.rtfd" && \
+#cd "$DSTROOT/Read Me.rtfd" && \
+#for i in "../Pester.app/Contents/Resources/Read Me.rtfd"/*; do ln -s "$i"; done && \
+find "$DSTROOT" -name ".svn" -exec sudo /bin/rm -rf "{}" \; ; \
+cd "$PACKAGEDIR" && \
+rm -f "$DMG" && \
+hdiutil create "$DMG" -megabytes 5 -ov -type UDIF && \
+DISK=`hdid -nomount "$DMG" | sed -ne ' /Apple_partition_scheme/ s|^/dev/\([^ ]*\).*$|\1|p'` && \
+newfs_hfs -v "$VOL" "/dev/r${DISK}s2" && \
+hdiutil eject "$DISK" && \
+hdid "$DMG" && \
+ditto -rsrc "$DSTROOT" "$MOUNTPOINT" && \
+chmod -R a+rX,u+w "$MOUNTPOINT" && \
+openUp "$MOUNTPOINT" && \
+# sleep 2 && \
+hdiutil eject $DISK && \
+# osascript -e "tell application \"Finder\" to eject disk \"$VOL\"" && \
+hdiutil convert "$DMG" -format UDZO -imagekey zlib-level=9 -o "z$DMG" && \
+mv "z$DMG" "$DMG" && \
+#scp "$DMG" ainaz:web/nriley/software/ && \
+:
