Index: releases/Pester/1.1b1/Source/BDAlias.h
===================================================================
--- releases/Pester/1.1b1/Source/BDAlias.h	(revision 62)
+++ releases/Pester/1.1b1/Source/BDAlias.h	(revision 62)
@@ -0,0 +1,77 @@
+/*
+    Copyright (c) 2001, bDistributed.com, Inc.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    *   Redistributions of source code must retain the above
+        copyright notice, this list of conditions and the following
+        disclaimer.
+    
+    *   Redistributions in binary form must reproduce the above
+        copyright notice, this list of conditions and the following
+        disclaimer in the documentation and/or other materials
+        provided with the distribution.
+    
+    *   Neither the name of bDistributed.com, Inc. nor the names of
+        its contributors may be used to endorse or promote products
+        derived from this software without specific prior written
+        permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+    OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+    OF SUCH DAMAGE.
+*/
+
+#import <Foundation/Foundation.h>
+#import <CoreServices/CoreServices.h>
+
+@interface BDAlias : NSObject
+{
+	AliasHandle _alias;
+}
+
+- (id)initWithAliasHandle:(AliasHandle)alias; // designated initializer
+- (id)initWithData:(NSData *)data;
+- (id)initWithPath:(NSString *)fullPath;
+- (id)initWithPath:(NSString *)path relativeToPath:(NSString *)relPath;
+- (id)initWithFSRef:(FSRef *)ref;
+- (id)initWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef;
+
+- (void)dealloc;
+
+- (AliasHandle)alias;
+- (void)setAlias:(AliasHandle)newAlias;
+
+- (NSData *)aliasData;
+- (void)setAliasData:(NSData *)newAliasData;
+
+- (BOOL)aliasIsEqual:(AliasHandle)otherAlias;
+- (BOOL)aliasDataIsEqual:(NSData *)data;
+- (BOOL)isEqual:(id)object;
+
+- (NSString *)displayNameWithKindString:(NSString **)outKindString;
+
+- (NSString *)fullPath;
+- (NSString *)fullPathRelativeToPath:(NSString *)relPath;
+
++ (BDAlias *)aliasWithAliasHandle:(AliasHandle)alias;
++ (BDAlias *)aliasWithData:(NSData *)data;
++ (BDAlias *)aliasWithPath:(NSString *)fullPath;
++ (BDAlias *)aliasWithPath:(NSString *)path relativeToPath:(NSString *)relPath;
++ (BDAlias *)aliasWithFSRef:(FSRef *)ref;
++ (BDAlias *)aliasWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef;
+
+@end
Index: releases/Pester/1.1b1/Source/BDAlias.m
===================================================================
--- releases/Pester/1.1b1/Source/BDAlias.m	(revision 62)
+++ releases/Pester/1.1b1/Source/BDAlias.m	(revision 62)
@@ -0,0 +1,368 @@
+/*
+    Copyright (c) 2001, bDistributed.com, Inc.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    *   Redistributions of source code must retain the above
+        copyright notice, this list of conditions and the following
+        disclaimer.
+    
+    *   Redistributions in binary form must reproduce the above
+        copyright notice, this list of conditions and the following
+        disclaimer in the documentation and/or other materials
+        provided with the distribution.
+    
+    *   Neither the name of bDistributed.com, Inc. nor the names of
+        its contributors may be used to endorse or promote products
+        derived from this software without specific prior written
+        permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+    OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+    OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+
+#import "BDAlias.h"
+
+
+static Handle DataToHandle(CFDataRef inData);
+static CFDataRef HandleToData(Handle inHandle);
+
+static OSStatus PathToFSRef(CFStringRef inPath, FSRef *outRef);
+static CFStringRef FSRefToPathCopy(const FSRef *inRef);
+
+
+static Handle DataToHandle(CFDataRef inData)
+{
+    CFIndex	len;
+    Handle	handle = NULL;
+    
+    if (inData == NULL) {
+        return NULL;
+    }
+    
+    len = CFDataGetLength(inData);
+    
+    handle = NewHandle(len);
+    
+    if ((handle != NULL) && (len > 0)) {
+        HLock(handle);
+        BlockMoveData(CFDataGetBytePtr(inData), *handle, len);
+        HUnlock(handle);
+    }
+    
+    return handle;
+}
+
+static CFDataRef HandleToData(Handle inHandle)
+{
+    CFDataRef	data = NULL;
+    CFIndex	len;
+    SInt8	handleState;
+    
+    if (inHandle == NULL) {
+        return NULL;
+    }
+    
+    len = GetHandleSize(inHandle);
+    
+    handleState = HGetState(inHandle);
+    
+    HLock(inHandle);
+    
+    data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *) *inHandle, len);
+    
+    HSetState(inHandle, handleState);
+    
+    return data;
+}
+
+static OSStatus PathToFSRef(CFStringRef inPath, FSRef *outRef)
+{
+    CFURLRef	tempURL = NULL;
+    Boolean	gotRef = false;
+    
+    tempURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, inPath,
+                                            kCFURLPOSIXPathStyle, false);
+    
+    if (tempURL == NULL) {
+        return fnfErr;
+    }
+    
+    gotRef = CFURLGetFSRef(tempURL, outRef);
+    
+    if (gotRef == false) {
+        return fnfErr;
+    }
+    
+    return noErr;
+}
+
+static CFStringRef FSRefToPathCopy(const FSRef *inRef)
+{
+    CFURLRef	tempURL = NULL;
+    CFStringRef	result = NULL;
+    
+    if (inRef != NULL) {
+        tempURL = CFURLCreateFromFSRef(kCFAllocatorDefault, inRef);
+        
+        if (tempURL == NULL) {
+            return NULL;
+        }
+        
+        result = CFURLCopyFileSystemPath(tempURL, kCFURLPOSIXPathStyle);
+        
+        CFRelease(tempURL);
+    }
+    
+    return result;
+}
+
+
+@implementation BDAlias
+
+- (id)initWithAliasHandle:(AliasHandle)alias
+{
+    id ret = [super init];
+    
+    if (ret != nil) {
+        _alias = alias;
+    }
+    
+    return ret;
+}
+
+- (id)initWithData:(NSData *)data
+{
+    return [self initWithAliasHandle:(AliasHandle)DataToHandle((CFDataRef) data)];
+}
+
+- (id)initWithPath:(NSString *)fullPath
+{
+    OSStatus	anErr = noErr;
+    FSRef		ref;
+    
+    anErr = PathToFSRef((CFStringRef) fullPath, &ref);
+    
+    if (anErr != noErr) {
+        return nil;
+    }
+    
+    return [self initWithFSRef:&ref];;
+}
+
+- (id)initWithPath:(NSString *)path relativeToPath:(NSString *)relPath
+{
+    OSStatus	anErr = noErr;
+    FSRef		ref, relRef;
+    
+    anErr = PathToFSRef((CFStringRef) [relPath stringByAppendingPathComponent:path],
+                        &ref);
+    
+    if (anErr != noErr) {
+        return nil;
+    }
+    
+    anErr = PathToFSRef((CFStringRef) relPath, &relRef);
+    
+    if (anErr != noErr) {
+        return nil;
+    }
+    
+    return [self initWithFSRef:&ref relativeToFSRef:&relRef];
+}
+
+- (id)initWithFSRef:(FSRef *)ref
+{
+    return [self initWithFSRef:ref relativeToFSRef:NULL];
+}
+
+- (id)initWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef
+{
+    OSStatus	anErr = noErr;
+    AliasHandle	alias = NULL;
+    
+    anErr = FSNewAlias(relRef, ref, &alias);
+    
+    if (anErr != noErr) {
+        return nil;
+    }
+    
+    return [self initWithAliasHandle:alias];
+}
+
+- (void)dealloc
+{
+    if (_alias != NULL) {
+        DisposeHandle((Handle) _alias);
+        _alias = NULL;
+    }
+    
+    [super dealloc];
+}
+
+- (AliasHandle)alias
+{
+    return _alias;
+}
+
+- (void)setAlias:(AliasHandle)newAlias
+{
+    if (_alias != NULL) {
+        DisposeHandle((Handle) _alias);
+    }
+    
+    _alias = newAlias;
+}
+
+- (NSData *)aliasData
+{
+    NSData *result;
+    
+    result = (NSData *)HandleToData((Handle) _alias);
+    
+    return [result autorelease];
+}
+
+- (void)setAliasData:(NSData *)newAliasData
+{
+    [self setAlias:(AliasHandle) DataToHandle((CFDataRef) newAliasData)];
+}
+
+- (NSString *)displayNameWithKindString:(NSString **)outKindString;
+{
+    AliasHandle alias = [self alias];
+    FSRef ref;
+    Boolean wasChanged;
+    CFStringRef name;
+
+    if (alias == NULL) return nil;
+    if (FSResolveAlias(NULL, alias, &ref, &wasChanged) != noErr) return nil;
+
+    if (LSCopyDisplayNameForRef(&ref, &name) != noErr) return nil;
+    [(NSString *)name autorelease];
+
+    if (outKindString != NULL) {
+        if (LSCopyKindStringForRef(&ref, (CFStringRef *)outKindString) != noErr) return nil;
+        [*outKindString autorelease];
+    }
+
+    return (NSString *)name;
+}
+
+- (NSString *)fullPath
+{
+    return [self fullPathRelativeToPath:nil];
+}
+
+- (NSString *)fullPathRelativeToPath:(NSString *)relPath
+{
+    OSStatus	anErr = noErr;
+    FSRef	relPathRef;
+    FSRef	tempRef;
+    NSString	*result = nil;
+    Boolean	wasChanged;
+    
+    if (_alias != NULL) {
+        if (relPath != nil) {
+            anErr = PathToFSRef((CFStringRef)relPath, &relPathRef);
+            
+            if (anErr != noErr) {
+                return NULL;
+            }
+            
+            anErr = FSResolveAlias(&relPathRef, _alias, &tempRef, &wasChanged);
+        } else {
+            anErr = FSResolveAlias(NULL, _alias, &tempRef, &wasChanged);
+        }
+        
+        if (anErr != noErr) {
+            return NULL;
+        }
+        
+        result = (NSString *)FSRefToPathCopy(&tempRef);
+    }
+    
+    return [result autorelease];
+}
+
+- (BOOL)aliasIsEqual:(AliasHandle)otherAlias;
+{
+    AliasHandle alias = [self alias];
+    FSRef ref, otherRef;
+    Boolean wasChanged;
+
+    if (alias == otherAlias) return YES;
+    if (alias == NULL || otherAlias == NULL) return NO;
+    if (FSResolveAlias(NULL, alias, &ref, &wasChanged) != noErr) return NO;
+    if (FSResolveAlias(NULL, otherAlias, &otherRef, &wasChanged) != noErr) return NO;
+    return (FSCompareFSRefs(&ref, &otherRef) == noErr);
+}
+
+- (BOOL)aliasDataIsEqual:(NSData *)data;
+{
+    AliasHandle otherAlias;
+    const UInt8 *aliasPtr = CFDataGetBytePtr((CFDataRef)data);
+    BOOL result;
+    if (aliasPtr == NULL) {
+        otherAlias = (AliasHandle)DataToHandle((CFDataRef)data);
+    } else {
+        otherAlias = (AliasHandle)&aliasPtr;
+    }
+    result = [self aliasIsEqual: otherAlias];
+    if (aliasPtr == NULL) DisposeHandle((Handle)otherAlias);
+    return result;
+}
+
+- (BOOL)isEqual:(id)object;
+{
+    if (![object isKindOfClass: [BDAlias class]]) return NO;
+    return [self aliasIsEqual: [object alias]];
+}
+
++ (BDAlias *)aliasWithAliasHandle:(AliasHandle)alias
+{
+    return [[[BDAlias alloc] initWithAliasHandle:alias] autorelease];
+}
+
++ (BDAlias *)aliasWithData:(NSData *)data
+{
+    return [[[BDAlias alloc] initWithData:data] autorelease];
+}
+
++ (BDAlias *)aliasWithPath:(NSString *)fullPath
+{
+    return [[[BDAlias alloc] initWithPath:fullPath] autorelease];
+}
+
++ (BDAlias *)aliasWithPath:(NSString *)path relativeToPath:(NSString *)relPath
+{
+    return [[[BDAlias alloc] initWithPath:path relativeToPath:relPath] autorelease];
+}
+
++ (BDAlias *)aliasWithFSRef:(FSRef *)ref
+{
+    return [[[BDAlias alloc] initWithFSRef:ref] autorelease];
+}
+
++ (BDAlias *)aliasWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef
+{
+    return [[[BDAlias alloc] initWithFSRef:ref relativeToFSRef:relRef] autorelease];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/English.lproj/Alarms.nib/classes.nib
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/Alarms.nib/classes.nib	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/Alarms.nib/classes.nib	(revision 62)
@@ -0,0 +1,27 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {CLASS = NJRScrollView; LANGUAGE = ObjC; SUPERCLASS = NSScrollView; }, 
+        {
+            CLASS = NJRTableDelegate; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {tableView = NSTableView; }; 
+            SUPERCLASS = NSObject; 
+        }, 
+        {
+            CLASS = NJRTableView; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {typeSelectDisplay = id; }; 
+            SUPERCLASS = NSTableView; 
+        }, 
+        {CLASS = NSObject; LANGUAGE = ObjC; }, 
+        {
+            ACTIONS = {remove = id; }; 
+            CLASS = PSAlarmsController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {removeButton = NSButton; tableView = NSTableView; }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b1/Source/English.lproj/Alarms.nib/info.nib
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/Alarms.nib/info.nib	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/Alarms.nib/info.nib	(revision 62)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>IBDocumentLocation</key>
+	<string>322 50 356 240 0 0 1280 832 </string>
+	<key>IBFramework Version</key>
+	<string>263.2</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>8</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>5S66</string>
+</dict>
+</plist>
Index: releases/Pester/1.1b1/Source/English.lproj/Credits.html
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/Credits.html	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/Credits.html	(revision 62)
@@ -0,0 +1,2 @@
+<font face="Lucida Grande" size="-1"><b>Icon by</b> <a href="mailto:excellence@global.co.za">Diederik Vemer</a>.</font><br>
+<font face="Lucida Grande" size="-1"><b>Thanks to</b> <a href="mailto:ryanwilcox@mac.com">Ryan Wilcox</a> and <a href="mailto:bhines@alumni.ucsd.edu">Ben Hines</a>.</font>
Index: releases/Pester/1.1b1/Source/English.lproj/MainMenu.nib/classes.nib
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/MainMenu.nib/classes.nib	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/MainMenu.nib/classes.nib	(revision 62)
@@ -0,0 +1,101 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {CLASS = NJRDateFormatter; LANGUAGE = ObjC; SUPERCLASS = NSDateFormatter; }, 
+        {
+            ACTIONS = {select = id; }; 
+            CLASS = NJRFSObjectSelector; 
+            LANGUAGE = ObjC; 
+            SUPERCLASS = NSButton; 
+        }, 
+        {
+            ACTIONS = {clearAllEntries = id; removeEntry = id; }; 
+            CLASS = NJRHistoryTrackingComboBox; 
+            LANGUAGE = ObjC; 
+            SUPERCLASS = NSComboBox; 
+        }, 
+        {CLASS = NJRIntegerFilter; LANGUAGE = ObjC; SUPERCLASS = NSNumberFormatter; }, 
+        {
+            CLASS = NJRIntervalField; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {intervalUnits = NSPopUpButton; }; 
+            SUPERCLASS = NSTextField; 
+        }, 
+        {
+            ACTIONS = {stopSoundPreview = id; }; 
+            CLASS = NJRQTMediaPopUpButton; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {preview = NSMovieView; }; 
+            SUPERCLASS = NSPopUpButton; 
+        }, 
+        {CLASS = NJRUnfocusableMovieView; LANGUAGE = ObjC; SUPERCLASS = NSMovieView; }, 
+        {
+            ACTIONS = {stopVoicePreview = id; }; 
+            CLASS = NJRVoicePopUpButton; 
+            LANGUAGE = ObjC; 
+            SUPERCLASS = NSPopUpButton; 
+        }, 
+        {CLASS = NSDisclosureButtonCell; LANGUAGE = ObjC; SUPERCLASS = NSButtonCell; }, 
+        {CLASS = NSObject; LANGUAGE = ObjC; }, 
+        {
+            ACTIONS = {
+                dateCompleted = id; 
+                doScriptChanged = id; 
+                doSpeakChanged = id; 
+                editAlertChanged = id; 
+                inAtChanged = id; 
+                playSoundChanged = id; 
+                setAlarm = id; 
+                setSoundRepetitionCount = id; 
+                silence = id; 
+                update = id; 
+            }; 
+            CLASS = PSAlarmSetController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {
+                alertTabs = NSTabView; 
+                alertView = NSTextField; 
+                bounceDockIcon = NSButton; 
+                cancelButton = NSButton; 
+                displayMessage = NSButtonCell; 
+                doScript = NSButtonCell; 
+                doSpeak = NSButtonCell; 
+                editAlert = NSButtonCell; 
+                inAtMatrix = NSMatrix; 
+                messageField = NSTextField; 
+                playSound = NSButtonCell; 
+                script = NJRFSObjectSelector; 
+                scriptSelectButton = NSButton; 
+                setButton = NSButton; 
+                sound = NJRQTMediaPopUpButton; 
+                soundRepetitionStepper = NSStepper; 
+                soundRepetitions = NSTextField; 
+                soundRepetitionsLabel = NSTextField; 
+                timeDate = NSTextField; 
+                timeDateCompletions = NSPopUpButton; 
+                timeInterval = NSTextField; 
+                timeIntervalRepeats = NSButton; 
+                timeIntervalUnits = NSPopUpButton; 
+                timeOfDay = NSTextField; 
+                timeSummary = NSTextField; 
+                voice = NJRVoicePopUpButton; 
+                wakeUp = NSButtonCell; 
+            }; 
+            SUPERCLASS = NSWindowController; 
+        }, 
+        {
+            CLASS = PSAlarmsController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {tableView = NSTableView; }; 
+            SUPERCLASS = NSWindowController; 
+        }, 
+        {
+            ACTIONS = {orderFrontAlarmsPanel = id; orderFrontSetAlarmPanel = id; stopAlerts = id; }; 
+            CLASS = PSApplication; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {alarmSetController = PSAlarmSetController; }; 
+            SUPERCLASS = NSApplication; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b1/Source/English.lproj/MainMenu.nib/info.nib
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/MainMenu.nib/info.nib	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/MainMenu.nib/info.nib	(revision 62)
@@ -0,0 +1,41 @@
+<?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>63 2 356 240 0 0 1280 832 </string>
+	<key>IBEditorPositions</key>
+	<dict>
+		<key>29</key>
+		<string>130 241 273 44 0 0 1280 832 </string>
+	</dict>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>29</integer>
+		<integer>21</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6G30</string>
+	<key>IBUserGuides</key>
+	<dict>
+		<key>21</key>
+		<dict>
+			<key>guideLocations</key>
+			<array>
+				<string>Horizontal:122.000000</string>
+				<string>Horizontal:178.000000</string>
+				<string>Horizontal:192.000000</string>
+				<string>Vertical:36.000000</string>
+				<string>Vertical:16.000000</string>
+				<string>Vertical:85.000000</string>
+				<string>Vertical:422.000000</string>
+				<string>Horizontal:151.000000</string>
+			</array>
+			<key>guidesLocked</key>
+			<false/>
+		</dict>
+	</dict>
+</dict>
+</plist>
Index: releases/Pester/1.1b1/Source/English.lproj/Movie alert.nib/classes.nib
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/Movie alert.nib/classes.nib	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/Movie alert.nib/classes.nib	(revision 62)
@@ -0,0 +1,15 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {CLASS = NJRCenteringMovieView; LANGUAGE = ObjC; SUPERCLASS = NSMovieView; }, 
+        {
+            ACTIONS = {close = id; }; 
+            CLASS = PSMovieAlertController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {movieView = NSMovieView; }; 
+            SUPERCLASS = NSWindowController; 
+        }, 
+        {CLASS = "java.lang.Object"; LANGUAGE = Java; }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b1/Source/English.lproj/Movie alert.nib/info.nib
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/Movie alert.nib/info.nib	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/Movie alert.nib/info.nib	(revision 62)
@@ -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>36 16 356 240 0 0 1280 832 </string>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>10</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6G30</string>
+</dict>
+</plist>
Index: releases/Pester/1.1b1/Source/English.lproj/Notifier.nib/classes.nib
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/Notifier.nib/classes.nib	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/Notifier.nib/classes.nib	(revision 62)
@@ -0,0 +1,28 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {CLASS = NJRIntegerFilter; LANGUAGE = ObjC; SUPERCLASS = NSNumberFormatter; }, 
+        {
+            CLASS = NJRIntervalField; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {intervalUnits = NSPopUpButton; }; 
+            SUPERCLASS = NSTextField; 
+        }, 
+        {
+            ACTIONS = {close = id; snooze = id; stopRepeating = id; }; 
+            CLASS = PSAlarmNotifierController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {
+                dateField = NSTextField; 
+                intervalField = NSTextField; 
+                messageField = NSTextField; 
+                nextDateField = NSTextField; 
+                okButton = NSButton; 
+                snoozeButton = NSButton; 
+                snoozeIntervalField = NJRIntervalField; 
+            }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b1/Source/English.lproj/Notifier.nib/info.nib
===================================================================
--- releases/Pester/1.1b1/Source/English.lproj/Notifier.nib/info.nib	(revision 62)
+++ releases/Pester/1.1b1/Source/English.lproj/Notifier.nib/info.nib	(revision 62)
@@ -0,0 +1,32 @@
+<?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>122 13 356 240 0 0 1280 832 </string>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>5</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6G30</string>
+	<key>IBUserGuides</key>
+	<dict>
+		<key>5</key>
+		<dict>
+			<key>guideLocations</key>
+			<array>
+				<string>Horizontal:87.000000</string>
+				<string>Horizontal:108.000000</string>
+				<string>Horizontal:66.000000</string>
+				<string>Vertical:92.000000</string>
+				<string>Horizontal:133.000000</string>
+			</array>
+			<key>guidesLocked</key>
+			<false/>
+		</dict>
+	</dict>
+</dict>
+</plist>
Index: releases/Pester/1.1b1/Source/NJRCenteringMovieView.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRCenteringMovieView.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRCenteringMovieView.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  NJRCenteringMovieView.h
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Jan 03 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJRCenteringMovieView : NSMovieView {
+
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRCenteringMovieView.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRCenteringMovieView.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRCenteringMovieView.m	(revision 62)
@@ -0,0 +1,57 @@
+//
+//  NJRCenteringMovieView.m
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Jan 03 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRCenteringMovieView.h"
+#import <QuickTime/Movies.h>
+
+@implementation NJRCenteringMovieView
+
+// from _MacTech_ December 2002, p. 76
+
+- (NSRect)movieRect;
+{
+    NSRect viewRect = [super movieRect];
+    Movie qtMovie = [[self movie] QTMovie];
+    Rect movieRect = {0, 0, 0, 0};
+
+    GetMovieNaturalBoundsRect(qtMovie, &movieRect);
+
+    float movieWidth = movieRect.right - movieRect.left;
+    float movieHeight = movieRect.bottom - movieRect.top;
+
+    if ( (movieWidth <= viewRect.size.width) &&
+         (movieHeight <= viewRect.size.height) ) {
+        // Movie is smaller than or equal to the view size; just center the movie
+        viewRect.origin.y += (int)((viewRect.size.height - movieHeight) / 2.);
+        viewRect.size.height = movieHeight;
+
+        viewRect.origin.x += (int)((viewRect.size.width - movieWidth) / 2.);
+        viewRect.size.width = movieWidth;
+    } else {
+        // We need to scale down movie, centering horizontally and vertically
+        float movieRatio = movieWidth / (float)movieHeight;
+        float viewRatio = viewRect.size.width / viewRect.size.height;
+
+        if (movieRatio > viewRatio) {
+            // Movie is wider than will fit; rescale.
+            float newHeight = viewRect.size.width / movieRatio;
+
+            viewRect.origin.y += (int)((viewRect.size.height - newHeight) / 2.);
+            viewRect.size.height = newHeight;
+        } else {
+            // Movie is taller than will fit (or has the ideal aspect ratio); rescale.
+            float newWidth = viewRect.size.height * movieRatio;
+
+            viewRect.origin.x += (int) ((viewRect.size.width - newWidth) / 2.);
+            viewRect.size.width = newWidth;
+        }
+    }
+    return viewRect;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRDateFormatter.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRDateFormatter.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRDateFormatter.h	(revision 62)
@@ -0,0 +1,21 @@
+//
+//  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 {
+    NSDictionary *alteredLocale;
+}
+
++ (NSString *)format:(NSString *)format withoutComponent:(unichar)component;
++ (NSString *)localizedDateFormatIncludingWeekday:(BOOL)weekday;
++ (NSString *)localizedShortDateFormatIncludingWeekday:(BOOL)weekday;
++ (NSString *)localizedTimeFormatIncludingSeconds:(BOOL)seconds;
+
+@end
Index: releases/Pester/1.1b1/Source/NJRDateFormatter.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRDateFormatter.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRDateFormatter.m	(revision 62)
@@ -0,0 +1,181 @@
+//
+//  NJRDateFormatter.m
+//  Pester
+//
+//  Created by Nicholas Riley on Wed Oct 09 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRDateFormatter.h"
+
+NSUserDefaults *locale;
+
+@implementation NJRDateFormatter
+
++ (void)initialize;
+{
+    locale = [[NSUserDefaults standardUserDefaults] retain];
+}
+
++ (NSString *)format:(NSString *)format withoutComponent:(unichar)component;
+{
+    NSScanner *scanner = [NSScanner scannerWithString: format];
+    int formatLength = [format length];
+    NSRange range;
+    [scanner setCharactersToBeSkipped: [NSCharacterSet characterSetWithCharactersInString: @""]];
+    // NSLog(@"format:withoutComponent: trying to excise %c from %@", component, format);
+    while ([scanner scanUpToString: @"%" intoString: nil] || ![scanner isAtEnd]) {
+        range.location = [scanner scanLocation];
+        // NSLog(@"location: %d/%d, remaining: %@%@", range.location, formatLength, [format substringFromIndex: range.location], [scanner isAtEnd] ? @", isAtEnd" : @"");
+        // XXX works fine without keeping track of length in 10.1.5; in 10.2, [scanner scanUptoString:intoString:] still returns YES even when scanner is at end and thereÕs nothing left to scan, and if you start accessing the string past the end... *boom*
+        if (range.location >= formatLength) break;
+        [scanner scanUpToCharactersFromSet: [NSCharacterSet letterCharacterSet] intoString: nil];
+        if ([format characterAtIndex: [scanner scanLocation]] == component) {
+            if ([scanner scanUpToString: @"%" intoString: nil] && ![scanner isAtEnd]) {
+                NSMutableString *mutableFormat = [format mutableCopy];
+                if (range.location != 0 && [[NSCharacterSet punctuationCharacterSet] characterIsMember: [format characterAtIndex: range.location - 1]]) {
+                    range.location--; // "%I:%M:%S%p" -> "%I:%M%p"
+                }
+                range.length = [scanner scanLocation] - range.location;
+                [mutableFormat deleteCharactersInRange: range];
+                format = [mutableFormat copy];
+                [mutableFormat release];
+                return [format autorelease];
+            } else {
+                range = [format rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet] options: NSBackwardsSearch range: NSMakeRange(0, range.location)];
+                return [format substringToIndex: NSMaxRange(range)];
+            }
+        }
+    }
+    return format;
+}
+
++ (NSString *)localizedDateFormatIncludingWeekday:(BOOL)weekday;
+{
+    NSString *format = [locale stringForKey: NSDateFormatString];
+    if (weekday) return format;
+    return [self format: format withoutComponent: (unichar)'A'];
+}
+
++ (NSString *)localizedShortDateFormatIncludingWeekday:(BOOL)weekday;
+{
+    NSString *format = [locale stringForKey: NSShortDateFormatString];
+    if (weekday) return format;
+    return [self format: format withoutComponent: (unichar)'A'];
+}
+
+NSString *stringByInsertingStringAtLocation(NSString *string, NSString *insert, int location) {
+    return [NSString stringWithFormat: @"%@%@%@", [string substringToIndex: location], insert,
+        [string substringFromIndex: location]];
+}
+
++ (NSString *)localizedTimeFormatIncludingSeconds:(BOOL)seconds;
+{
+    NSString *format = [locale stringForKey: NSTimeFormatString];
+    NSArray *ampm = [locale arrayForKey: NSAMPMDesignation];
+    NSString *am = [ampm objectAtIndex: 0], *pm = [ampm objectAtIndex: 1];
+    // work around bug with inconsistent AM/PM and time format
+    if ([am isEqualToString: @""] && [pm isEqualToString: @""])
+        format = [self format: format withoutComponent: 'p'];
+    else {
+        NSRange ampmComponentRange = [format rangeOfString: @"%p"];
+        NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
+        BOOL needSpaceInFormatString = ![whitespace characterIsMember: [am characterAtIndex: 0]];
+        if (ampmComponentRange.location == NSNotFound) // "%1I:%M:%S" -> "%1I:%M:%S%p", "%1I:%M:%S %p"
+            format = [format stringByAppendingString: (needSpaceInFormatString ? @" %p" : @"%p")];
+        else {
+            NSRange whitespaceRange = [format rangeOfCharacterFromSet: whitespace options: NSBackwardsSearch range: NSMakeRange(0, ampmComponentRange.location)];
+            if (whitespaceRange.location == NSNotFound) {
+                if (needSpaceInFormatString) // "%1I:%M:%S%p" -> "%1I:%M:%S %p"
+                    format = stringByInsertingStringAtLocation(format, @" ", ampmComponentRange.location);
+                // else "%1I:%M:%S%p" -> no change
+            } else {
+                if (NSMaxRange(whitespaceRange) == ampmComponentRange.location) { 
+                    if (!needSpaceInFormatString) // "%1I:%M:%S %p" -> "%1I:%M:%S%p"
+                        format = [[format substringToIndex: whitespaceRange.location] stringByAppendingString: [format substringFromIndex: ampmComponentRange.location]];
+                    // else "%1I:%M:%S %p" -> no change
+                } else {
+                    if (needSpaceInFormatString)
+                        format = stringByInsertingStringAtLocation(format, @" ", ampmComponentRange.location);
+                    // else "%1I %M:%S%p" -> no change
+                }
+            }
+        }
+    }
+    if (seconds) return format;
+    return [self format: format withoutComponent: 'S'];
+}
+
+// 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)];
+}
+
+- (id)initWithDateFormat:(NSString *)format allowNaturalLanguage:(BOOL)flag;
+{
+    if ( (self = [super initWithDateFormat: format allowNaturalLanguage: flag]) != nil) {
+        NSRange ampmRange = [format rangeOfString: @"%p"];
+        NSArray *ampm = [locale arrayForKey: NSAMPMDesignation];
+        NSString *am = [ampm objectAtIndex: 0], *pm = [ampm objectAtIndex: 1];
+        if (flag && ampmRange.location != NSNotFound &&
+            [[locale stringForKey: NSTimeFormatString] rangeOfString: @"%p"].location == NSNotFound && ![am isEqualToString: pm]) {
+            // workaround for bug in NSCalendarDate dateWithNaturalLanguageString: discarding AM/PM value when AM/PM designations have spaces in them (of which the use thereof is a workaround for NSDateFormatter discarding the AM/PM value)
+            NSMutableString *paddedFormat = [format mutableCopy];
+            [paddedFormat replaceCharactersInRange: ampmRange withString: @" %p"];
+            alteredLocale = [[locale dictionaryRepresentation] mutableCopy];
+            [(NSMutableDictionary *)alteredLocale setObject: paddedFormat forKey: NSTimeFormatString];
+            [(NSMutableDictionary *)alteredLocale setObject:
+                [NSArray arrayWithObjects: stringByRemovingSurroundingWhitespace(am),
+                    stringByRemovingSurroundingWhitespace(pm), nil]
+                                                     forKey: NSAMPMDesignation];
+            [paddedFormat release];
+        } else {
+            alteredLocale = [(NSDictionary *)locale retain];
+        }
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [alteredLocale release];
+    [super dealloc];
+}
+
+- (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) locale: alteredLocale];
+        // NSLog(@"%@: natural language date is %@", string, date);
+    NS_HANDLER
+        if (error != nil) *error = [localException reason];
+        NS_VALUERETURN(NO, BOOL);
+    NS_ENDHANDLER
+    // [super getObjectValue: anObject forString: string errorDescription: error];
+    // NSLog(@"%@: formatter date is %@", string, anObject == nil ? @"(null)" : *anObject);
+    if (date == nil) return [super getObjectValue: anObject forString: string errorDescription: error];
+    *anObject = date;
+    return YES;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRFSObjectSelector.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRFSObjectSelector.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRFSObjectSelector.h	(revision 62)
@@ -0,0 +1,27 @@
+/* NJRFSObjectSelector */
+
+#import <Cocoa/Cocoa.h>
+#import "BDAlias.h"
+
+@interface NJRFSObjectSelector : NSButton
+{
+    BDAlias *selectedAlias;
+    NSArray *fileTypes;
+    BOOL canChooseDirectories;
+    BOOL canChooseFiles;
+    BOOL dragAccepted;
+    BOOL isEnabled;
+}
+- (IBAction)select:(id)sender;
+- (void)setAlias:(BDAlias *)alias;
+- (BDAlias *)alias;
+- (BOOL)acceptsPath:(NSString *)path;
+- (void)setPath:(NSString *)path; // does not validate
+- (BOOL)canChooseDirectories;
+- (BOOL)canChooseFiles;
+- (void)setCanChooseDirectories:(BOOL)flag;
+- (void)setCanChooseFiles:(BOOL)flag;
+- (NSArray *)fileTypes;
+- (void)setFileTypes:(NSArray *)types;
+
+@end
Index: releases/Pester/1.1b1/Source/NJRFSObjectSelector.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRFSObjectSelector.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRFSObjectSelector.m	(revision 62)
@@ -0,0 +1,317 @@
+#import "NJRFSObjectSelector.h"
+#import "NSImage-NJRExtensions.h"
+#import "NSString-NJRExtensions.h"
+#include <Carbon/Carbon.h>
+
+static NSImage *PopupTriangleImage = nil;
+static NSSize PopupTriangleSize;
+
+@implementation NJRFSObjectSelector
+
+- (void)_initSelector;
+{
+    if (PopupTriangleImage == nil) {
+        PopupTriangleImage = [[NSImage imageNamed: @"Popup triangle"] retain];
+        PopupTriangleSize = [PopupTriangleImage size];
+    }
+    canChooseFiles = YES; canChooseDirectories = NO;
+    [self setAlias: nil];
+    [[self cell] setHighlightsBy: NSChangeBackgroundCell];
+    [[self cell] setGradientType: NSGradientNone];
+    [self registerForDraggedTypes:
+        [NSArray arrayWithObjects: NSFilenamesPboardType, NSURLPboardType, nil]];
+}
+
+- (void)dealloc;
+{
+    [selectedAlias release];
+    [fileTypes release];
+    [super dealloc];
+}
+
+- (id)initWithCoder:(NSCoder *)coder;
+{
+    if ( (self = [super initWithCoder: coder]) != nil) {
+        [self _initSelector];
+    }
+    return self;
+}
+
+- (id)initWithFrame:(NSRect)frame;
+{
+    if ( (self = [super initWithFrame: frame]) != nil) {
+        [self _initSelector];
+    }
+    return self;
+}
+
+- (void)drawRect:(NSRect)rect;
+{
+    NSRect boundsRect = [self bounds];
+    [super drawRect: rect];
+    if (dragAccepted) {
+        [[NSColor selectedControlColor] set];
+        [NSBezierPath setDefaultLineWidth: 2];
+        [NSBezierPath strokeRect: NSInsetRect(boundsRect, 2, 2)];
+    } else if (selectedAlias != nil && [self isEnabled]) {
+        // equivalent to popup triangle location for large bezel in Carbon
+        [PopupTriangleImage compositeToPoint: NSMakePoint(NSMaxX(boundsRect) - PopupTriangleSize.width - 5, NSMaxY(boundsRect) - 5) operation: NSCompositeSourceOver];
+    }
+}
+
+- (BOOL)acceptsPath:(NSString *)path;
+{
+    NSFileManager *fm = [NSFileManager defaultManager];
+    BOOL isDir;
+
+    if (![fm fileExistsAtPath: path isDirectory: &isDir]) return NO;
+
+    if (isDir) return canChooseDirectories;
+    if (canChooseFiles) {
+        NSEnumerator *e = [fileTypes objectEnumerator];
+        NSString *extension = [path pathExtension];
+        NSString *hfsType = NSHFSTypeOfFile(path);
+        NSString *fileType;
+        
+        while ( (fileType = [e nextObject]) != nil) {
+            if ([fileType isEqualToString: extension] || [fileType isEqualToString: hfsType])
+                return YES;
+        }
+    }
+    return NO;
+}
+
+- (void)setImage:(NSImage *)image;
+{
+    [super setImage: [image bestFitImageForSize: [[self cell] cellSize]]];
+}
+
+- (IBAction)select:(id)sender;
+{
+    NSOpenPanel *openPanel = [NSOpenPanel openPanel];
+    NSString *path = [selectedAlias fullPath];
+    [openPanel setAllowsMultipleSelection: NO];
+    [openPanel setCanChooseDirectories: canChooseDirectories];
+    [openPanel setCanChooseFiles: canChooseFiles];
+    [openPanel beginSheetForDirectory: [path stringByDeletingLastPathComponent]
+                                 file: [path lastPathComponent]
+                                types: fileTypes
+                       modalForWindow: [self window]
+                        modalDelegate: self
+                       didEndSelector: @selector(openPanelDidEnd:returnCode:contextInfo:)
+                          contextInfo: nil];
+}
+
+- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
+{
+    [sheet close];
+
+    if (returnCode == NSOKButton) {
+        NSArray *files = [sheet filenames];
+        NSAssert1([files count] == 1, @"%d items returned, only one expected", [files count]);
+        [self setPath: [files objectAtIndex: 0]];
+        [[self target] tryToPerform: [self action] with: self];
+    }
+}
+
+- (void)revealInFinder:(id<NSMenuItem>)sender;
+{
+    NSString *path = [sender representedObject];
+    if (path == nil) return;
+    [[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath: @""];
+}
+
+- (void)setAlias:(BDAlias *)alias;
+{
+    if (selectedAlias != alias) {
+        [selectedAlias release];
+        selectedAlias = [alias retain];
+    }
+
+    if (alias != nil) { // alias is set
+        NSString *path = [alias fullPath];
+        NSString *revealPath = nil;
+        NSMenu *menu = [[NSMenu alloc] initWithTitle: @""];
+        NSFileManager *fmgr = [NSFileManager defaultManager];
+        NSMenuItem *item;
+        if (path != nil) { // can resolve alias
+            [self setImage: [[NSWorkspace sharedWorkspace] iconForFile: path]];
+            {	// set image first so titleRectForBounds: returns the correct value
+                NSMutableString *title = [[fmgr displayNameAtPath: path] mutableCopy];
+                NSDictionary *fontAttributes = [[self attributedTitle] fontAttributesInRange: NSMakeRange(0, 0)];
+                [title truncateToWidth: [[self cell] titleRectForBounds: [self bounds]].size.width - PopupTriangleSize.width by: NSLineBreakByTruncatingMiddle withAttributes: fontAttributes];
+                [self setTitle: title];
+                [title release];
+            }
+            do {
+                item = [menu addItemWithTitle: [fmgr displayNameAtPath: path]
+                                       action: @selector(revealInFinder:)
+                                keyEquivalent: @""];
+                [item setTarget: self];
+                [item setRepresentedObject: revealPath];
+                [item setImage:
+                    [[[NSWorkspace sharedWorkspace] iconForFile: path] bestFitImageForSize: NSMakeSize(16, 16)]];
+                revealPath = path;
+                path = [path stringByDeletingLastPathComponent];
+                NSAssert1(![path isEqualToString: revealPath], @"Stuck on path |%@|", [alias fullPath]);
+            } while (![revealPath isEqualToString: @"/"] && ![path isEqualToString: @"/Volumes"]);
+            [[self cell] setMenu: menu];
+        } else {
+            [self setImage: nil];
+            [self setTitle: @"(not available)"];
+            [[self cell] setMenu: nil];
+        }
+    } else {
+        [self setImage: nil];
+        [self setTitle: @"(none selected)"];
+        [[self cell] setMenu: nil];
+    }
+    [self setEnabled: isEnabled];
+}
+
+- (BOOL)isEnabled;
+{
+    return isEnabled;
+}
+
+- (void)setEnabled:(BOOL)enabled;
+{
+    isEnabled = enabled;
+    [super setEnabled: enabled ? selectedAlias != nil : NO];
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent;
+{
+    [self mouseDown: theEvent];
+}
+
+- (void)otherMouseDown:(NSEvent *)theEvent;
+{
+    [self mouseDown: theEvent];
+}
+
+extern MenuRef _NSGetCarbonMenu(NSMenu *menu);
+
+- (void)mouseDown:(NSEvent *)theEvent;
+{
+    NSMenu *menu = [[self cell] menu];
+    MenuRef mRef = _NSGetCarbonMenu(menu);
+
+    if (mRef == NULL) {
+        NSMenu *appMenu = [[[NSApp mainMenu] itemWithTitle: @""] submenu];
+        if (appMenu != nil) {
+            NSMenuItem *item = [appMenu addItemWithTitle: @"" action: NULL keyEquivalent: @""];
+            [appMenu setSubmenu: menu forItem: item];
+            [appMenu removeItem: item];
+        }
+        mRef = _NSGetCarbonMenu(menu);
+    }
+
+    ChangeMenuAttributes(mRef, kMenuAttrExcludesMarkColumn, 0);
+    theEvent = [NSEvent mouseEventWithType: [theEvent type]
+                                  location: [self convertPoint: NSMakePoint(-1, 1) toView: nil]
+                             modifierFlags: [theEvent modifierFlags]
+                                 timestamp: [theEvent timestamp]
+                              windowNumber: [theEvent windowNumber]
+                                   context: [theEvent context]
+                               eventNumber: [theEvent eventNumber]
+                                clickCount: [theEvent clickCount]
+                                  pressure: [theEvent pressure]];
+
+    // this undocumented API does not work any better; contextual menu items are still added:
+    // [menu _popUpMenuWithEvent: theEvent forView: self];
+    [NSMenu popUpContextMenu: menu withEvent: theEvent forView: self];
+}
+
+- (BDAlias *)alias;
+{
+    return selectedAlias;
+}
+
+- (void)setPath:(NSString *)path;
+{
+    [self setAlias: [BDAlias aliasWithPath: path]];
+}
+
+- (BOOL)canChooseDirectories;
+{
+    return canChooseDirectories;
+}
+
+- (BOOL)canChooseFiles;
+{
+    return canChooseFiles;
+}
+
+- (void)setCanChooseDirectories:(BOOL)flag;
+{
+    canChooseDirectories = flag;
+}
+
+- (void)setCanChooseFiles:(BOOL)flag;
+{
+    canChooseFiles = flag;
+}
+
+- (NSArray *)fileTypes;
+{
+    return fileTypes;
+}
+
+- (void)setFileTypes:(NSArray *)types;
+{
+    if (fileTypes == types) return;
+    
+    [fileTypes release];
+    fileTypes = [types retain];
+}
+
+@end
+
+
+@implementation NJRFSObjectSelector (NSDraggingDestination)
+
+- (BOOL)acceptsDragFrom:(id <NSDraggingInfo>)sender;
+{
+    NSURL *url = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
+
+    if (url == nil || ![url isFileURL]) return NO;
+    return [self acceptsPath: [url path]];
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender;
+{
+    if ([self acceptsDragFrom: sender] && [sender draggingSourceOperationMask] &
+        (NSDragOperationCopy | NSDragOperationLink)) {
+        dragAccepted = YES;
+        [self setNeedsDisplay: YES];
+        return NSDragOperationLink;
+    }
+    return NSDragOperationNone;
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)sender;
+{
+    dragAccepted = NO;
+    [self setNeedsDisplay: YES];
+}
+
+- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender;
+{
+    dragAccepted = NO;
+    [self setNeedsDisplay: YES];
+    return [self acceptsDragFrom: sender];
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
+{
+    if ([sender draggingSource] != self) {
+        NSURL *url = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
+        if (url == nil) return NO;
+        [self setPath: [url path]];
+        [[self target] tryToPerform: [self action] with: self];
+    }
+    return YES;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRHistoryTrackingComboBox.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRHistoryTrackingComboBox.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRHistoryTrackingComboBox.h	(revision 62)
@@ -0,0 +1,19 @@
+//
+//  NJRHistoryTrackingComboBox.h
+//  DockCam
+//
+//  Created by Nicholas Riley on Fri Jun 28 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface NJRHistoryTrackingComboBox : NSComboBox {
+
+}
+
+- (IBAction)removeEntry:(id)sender;
+- (IBAction)clearAllEntries:(id)sender;
+
+@end
Index: releases/Pester/1.1b1/Source/NJRHistoryTrackingComboBox.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRHistoryTrackingComboBox.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRHistoryTrackingComboBox.m	(revision 62)
@@ -0,0 +1,75 @@
+//
+//  NJRHistoryTrackingComboBox.m
+//  DockCam
+//
+//  Created by Nicholas Riley on Fri Jun 28 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRHistoryTrackingComboBox.h"
+
+#define NJRHistoryTrackingComboBoxMaxItems 10
+
+@implementation NJRHistoryTrackingComboBox
+
+- (NSString *)_defaultKey;
+{
+    NSAssert([self tag] != 0, @"CanÕt track history for combo box with tag 0: please set a tag");
+    return [NSString stringWithFormat: @"NJRHistoryTrackingComboBox tag %d", [self tag]];
+}
+
+- (void)awakeFromNib;
+{
+    [[NSNotificationCenter defaultCenter] addObserver: self
+                                             selector: @selector(textDidEndEditing:)
+                                                 name: NSTextDidEndEditingNotification
+                                               object: self];
+    [self removeAllItems];
+    [self addItemsWithObjectValues: [[NSUserDefaults standardUserDefaults] stringArrayForKey: [self _defaultKey]]];
+    [self setItemHeight: [self itemHeight] + 2];
+}
+
+- (void)_writeHistory;
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [defaults setObject: [self objectValues] forKey: [self _defaultKey]];
+    [defaults synchronize];
+}
+
+- (IBAction)removeEntry:(id)sender;
+{
+    int idx = [self indexOfSelectedItem];
+    if (idx == -1) {
+        [self selectItemWithObjectValue: [self stringValue]];
+        idx = [self indexOfSelectedItem];
+    }
+    if (idx != -1) [self removeItemAtIndex: idx];
+    [self setStringValue: @""];
+    [self _writeHistory];
+}
+
+- (IBAction)clearAllEntries:(id)sender;
+{
+    [self removeAllItems];
+    [self setStringValue: @""];
+    [self _writeHistory];
+}
+
+- (BOOL)textShouldEndEditing:(NSText *)textObject;
+{
+    NSString *newValue = [self stringValue];
+    int oldIndex = [self indexOfItemWithObjectValue: newValue];
+    if ([newValue length] == 0) return YES; // donÕt save empty entries
+    [self removeItemWithObjectValue: newValue];
+    [self insertItemWithObjectValue: newValue atIndex: 0];
+    if (oldIndex == NSNotFound) {
+        int numItems = [self numberOfItems];
+        while (numItems-- > NJRHistoryTrackingComboBoxMaxItems) {
+            [self removeItemAtIndex: numItems - 1];
+        }
+    }
+    [self _writeHistory];
+    return YES;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRIntegerFilter.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRIntegerFilter.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRIntegerFilter.h	(revision 62)
@@ -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 <Foundation/Foundation.h>
+
+
+@interface NJRIntegerFilter : NSNumberFormatter {
+
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRIntegerFilter.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRIntegerFilter.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRIntegerFilter.m	(revision 62)
@@ -0,0 +1,29 @@
+//
+//  NJRIntegerFilter.m
+//  HostLauncher
+//
+//  Created by Nicholas Riley on Tue Dec 18 2001.
+//  Copyright (c) 2001 Nicholas Riley. All rights reserved.
+//
+
+// based on MyIntegerFilter, later VRIntegerNumberFilter
+// Copyright © 2001-2002 Bill Cheeseman. All rights reserved.
+
+#import "NJRIntegerFilter.h"
+
+@implementation NJRIntegerFilter
+
+// Input validation
+
+- (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 0..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 for error handling
+    }
+    *error = nil;
+    return YES; // Accept *partialStringPtr as typed
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRIntervalField.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRIntervalField.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRIntervalField.h	(revision 62)
@@ -0,0 +1,21 @@
+//
+//  NJRIntervalField.h
+//  Pester
+//
+//  Created by Nicholas Riley on Wed Dec 25 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJRIntervalField : NSTextField {
+    IBOutlet NSPopUpButton *intervalUnits;
+}
+
+- (NSTimeInterval)interval;
+- (BOOL)setInterval:(NSTimeInterval)interval; // returns false if out of range
+
+- (void)handleDidFailToFormatString:(NSString *)string errorDescription:(NSString *)error label:(NSString *)label;
+
+@end
Index: releases/Pester/1.1b1/Source/NJRIntervalField.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRIntervalField.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRIntervalField.m	(revision 62)
@@ -0,0 +1,154 @@
+//
+//  NJRIntervalField.m
+//  Pester
+//
+//  Created by Nicholas Riley on Wed Dec 25 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRIntervalField.h"
+
+// XXX much implementation borrowed from DockCam, then factored; should replace DockCam interval selector with a NJRIntervalField at some point
+
+@implementation NJRIntervalField
+
+- (NSTimeInterval)interval;
+{
+    NSText *editor = [self currentEditor];
+    id obj = nil;
+    
+    if (editor != nil) {
+        NSString *stringValue = [editor string];
+        if (![[self formatter] getObjectValue: &obj forString: stringValue errorDescription: NULL])
+            return 0;
+    } else {
+        obj = self;
+    }
+    
+    return [obj intValue] * [[intervalUnits selectedItem] tag];
+}
+
+- (BOOL)setInterval:(NSTimeInterval)interval;
+{
+    // we assume that the tags are in ascending order in the array
+    NSEnumerator *e = [[intervalUnits itemArray] reverseObjectEnumerator];
+    NSMenuItem *i;
+    int multiplierTag;
+
+    while ( (i = [e nextObject]) != nil) {
+        multiplierTag = [i tag];
+        if (((int)interval % multiplierTag) == 0) {
+            NSFormatter *formatter = [self formatter];
+            int intervalValue = interval / multiplierTag;
+            if (formatter != nil) {
+                id ignored;
+                if (![formatter getObjectValue: &ignored forString: [formatter stringForObjectValue: [NSNumber numberWithInt: intervalValue]] errorDescription: NULL]) return NO;
+            }
+            [self setIntValue: intervalValue];
+            [intervalUnits selectItem: i];
+            return YES;
+        }
+    }
+    return NO;
+}
+
+- (BOOL)textView:(NSTextView *)textView shouldChangeTextInRange:(NSRange)range replacementString:(NSString *)string;
+{
+    unsigned length = [string length];
+    if (length != 0) {
+        unichar c;
+        int tag = -1;
+        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: break;
+        }
+        if (tag != -1) [intervalUnits selectItemAtIndex: [intervalUnits indexOfItemWithTag: tag]];
+    }
+    return [super textView: textView shouldChangeTextInRange: range replacementString: string];
+}
+
+- (void)handleDidFailToFormatString:(NSString *)string errorDescription:(NSString *)error label:(NSString *)label;
+{
+    NSString *alertMessage;
+    NSString *alternateButtonString;
+    NSDecimalNumber *proposedValue;
+    NSDictionary *contextInfo;
+
+    NSString *alertInformation = [NSString localizedStringWithFormat:
+        NSLocalizedString(@"The %@ field must be set to a value between %@ and %@.",
+                          @"Informative text for alert posed by text field when invalid value entered"),
+        label, [[self formatter] minimum], [[self formatter] maximum]];
+    NSString *defaultButtonString = NSLocalizedString(@"Edit", @"Name of Edit button");
+    NSString *otherButtonString = NSLocalizedString(@"Cancel", @"Name of Cancel button");
+
+    if ([error isEqualToString:
+        NSLocalizedStringFromTableInBundle(@"Fell short of minimum", @"Formatter",
+                                           [NSBundle bundleForClass:[NSFormatter class]],
+                                           @"Presented when user value smaller than minimum")]) {
+        proposedValue = [[self formatter] minimum];
+        alertMessage = [NSString stringWithFormat:
+            NSLocalizedString(@"Ò%@Ó is too small for the %@ field.",
+                              @"Message text for alert posed by numeric field when too-small value entered"),
+            string, label];
+        alternateButtonString = [NSString localizedStringWithFormat:
+            NSLocalizedString(@"Set to %@",
+                              @"Name of alternate button for alert posed by numeric field when too-small value entered"),
+            proposedValue];
+    } else if ([error isEqualToString:
+        NSLocalizedStringFromTableInBundle(@"Maximum exceeded", @"Formatter",
+                                           [NSBundle bundleForClass:[NSFormatter class]],
+                                           @"Presented when user value larger than maximum")]) {
+        proposedValue = [[self formatter] maximum];
+        alertMessage = [NSString stringWithFormat:
+            NSLocalizedString(@"Ò%@Ó is too large for the %@ field.",
+                              @"Message text for alert posed by numeric field when too-large value entered"),
+            string, label];
+        alternateButtonString = [NSString localizedStringWithFormat:
+            NSLocalizedString(@"Set to %@",
+                              @"Name of alternate button for alert posed by numeric field when too-large value entered"),
+            proposedValue];
+    } else if ([error isEqualToString:
+        NSLocalizedStringFromTableInBundle(@"Invalid number", @"Formatter",
+                                           [NSBundle bundleForClass:[NSFormatter class]],
+                                           @"Presented when user typed illegal characters: no valid object")]) {
+        alertMessage = [NSString stringWithFormat:
+            NSLocalizedString(@"Ò%@Ó is not a valid entry for the %@ field.",
+                              @"Message text for alert posed by text field when invalid value entered"),
+            string, label];
+        alternateButtonString = nil;
+    }
+
+    contextInfo = [NSDictionary dictionaryWithObject: proposedValue forKey: @"proposedValue"];
+    [contextInfo retain];
+    NSBeep();
+    NSBeginAlertSheet(alertMessage, defaultButtonString, alternateButtonString, otherButtonString, [self window],
+                      self, @selector(validationFailedSheetDidEnd:returnCode:contextInfo:), NULL, contextInfo,
+                      alertInformation);
+}
+
+- (void)_propagateValidationChange;
+{
+    NSText *fieldEditor = [self currentEditor];
+    NSDictionary *userInfo = nil;
+    if (fieldEditor != nil) userInfo = [NSDictionary dictionaryWithObject: fieldEditor forKey: @"NSFieldEditor"];
+    [[NSNotificationCenter defaultCenter] postNotificationName: NSControlTextDidChangeNotification object: self userInfo: userInfo];
+    [self selectText: self];
+}
+
+- (void)validationFailedSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
+    // modal delegate callback method for NSBeginAlertSheet() function; called in the above method
+    if (returnCode == NSAlertOtherReturn) { // cancel
+        [self abortEditing]; // abort edit session and reinstate original value
+        [self _propagateValidationChange];
+    } else if (returnCode == NSAlertAlternateReturn) { // set to min/max/default value
+        [self setObjectValue: [(NSDictionary *)contextInfo objectForKey: @"proposedValue"]];
+        [self validateEditing];
+        [self _propagateValidationChange];
+    }
+    [(NSDictionary *)contextInfo release];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRQTMediaPopUpButton.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRQTMediaPopUpButton.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRQTMediaPopUpButton.h	(revision 62)
@@ -0,0 +1,30 @@
+//
+//  NJRQTMediaPopUpButton.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "BDAlias.h"
+
+extern NSString * const NJRQTMediaPopUpButtonMovieChangedNotification;
+
+@interface NJRQTMediaPopUpButton : NSPopUpButton {
+    IBOutlet NSMovieView *preview;
+    BOOL movieCanRepeat;
+    NSMenuItem *otherItem;
+    BDAlias *selectedAlias, *previousAlias;
+    NSMutableArray *recentMediaAliasData;
+    BOOL dragAccepted;
+}
+
+- (BDAlias *)selectedAlias;
+- (void)setAlias:(BDAlias *)alias;
+
+- (BOOL)canRepeat;
+
+- (IBAction)stopSoundPreview:(id)sender;
+
+@end
Index: releases/Pester/1.1b1/Source/NJRQTMediaPopUpButton.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRQTMediaPopUpButton.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRQTMediaPopUpButton.m	(revision 62)
@@ -0,0 +1,531 @@
+//
+//  NJRQTMediaPopUpButton.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRQTMediaPopUpButton.h"
+#import "SoundFileManager.h"
+#import "NSMovie-NJRExtensions.h"
+#import "NSImage-NJRExtensions.h"
+#import <QuickTime/Movies.h>
+
+// XXX workaround for SoundFileManager log message in 10.2.3 and earlier
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+// XXX end workaround
+
+static const int NJRQTMediaPopUpButtonMaxRecentItems = 10;
+
+NSString * const NJRQTMediaPopUpButtonMovieChangedNotification = @"NJRQTMediaPopUpButtonMovieChangedNotification";
+
+@interface NJRQTMediaPopUpButton (Private)
+- (void)_setPath:(NSString *)path;
+- (NSMenuItem *)_itemForAlias:(BDAlias *)alias;
+- (BOOL)_validateWithPreview:(BOOL)doPreview;
+@end
+
+@implementation NJRQTMediaPopUpButton
+
+// XXX handle refreshing sound list on resume
+// XXX don't add icons on Puma, they look like ass
+// XXX launch preview on a separate thread (if movies take too long to load, they inhibit the interface responsiveness)
+
+// Recent media layout:
+// Most recent media are at TOP of menu (smaller item numbers, starting at [self indexOfItem: otherItem] + 1)
+// Most recent media are at END of array (larger indices)
+
+#pragma mark recently selected media tracking
+
+- (NSString *)_defaultKey;
+{
+    NSAssert([self tag] != 0, @"CanÕt track recently selected media for popup with tag 0: please set a tag");
+    return [NSString stringWithFormat: @"NJRQTMediaPopUpButtonMaxRecentItems tag %d", [self tag]];
+}
+
+- (void)_writeRecentMedia;
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [defaults setObject: recentMediaAliasData forKey: [self _defaultKey]];
+    [defaults synchronize];
+}
+
+- (NSMenuItem *)_addRecentMediaAtPath:(NSString *)path withAlias:(BDAlias *)alias;
+{
+    NSString *title = [[NSFileManager defaultManager] displayNameAtPath: path];
+    NSMenu *menu = [self menu];
+    NSMenuItem *item;
+    if (title == nil || path == nil) return nil;
+    item = [menu insertItemWithTitle: title action: @selector(_aliasSelected:) keyEquivalent: @"" atIndex: [menu indexOfItem: otherItem] + 1];
+    [item setTarget: self];
+    [item setRepresentedObject: alias];
+    [item setImage: [[[NSWorkspace sharedWorkspace] iconForFile: path] bestFitImageForSize: NSMakeSize(16, 16)]];
+    [recentMediaAliasData addObject: [alias aliasData]];
+    if ([recentMediaAliasData count] > NJRQTMediaPopUpButtonMaxRecentItems) {
+        [menu removeItemAtIndex: [menu numberOfItems] - 1];
+        [recentMediaAliasData removeObjectAtIndex: 0];
+    }
+    return item;
+}
+
+- (void)_addRecentMediaFromAliasesData:(NSArray *)aliasesData;
+{
+    NSEnumerator *e = [aliasesData objectEnumerator];
+    NSData *aliasData;
+    BDAlias *alias;
+    while ( (aliasData = [e nextObject]) != nil) {
+        if ( (alias = [[BDAlias alloc] initWithData: aliasData]) != nil) {
+            [self _addRecentMediaAtPath: [alias fullPath] withAlias: alias];
+            [alias release];
+        }
+    }
+}
+
+- (void)_validateRecentMedia;
+{
+    NSEnumerator *e = [recentMediaAliasData reverseObjectEnumerator];
+    NSData *aliasData;
+    NSMenuItem *item;
+    BDAlias *itemAlias;
+    int otherIndex = [self indexOfItem: otherItem];
+    int aliasDataCount = [recentMediaAliasData count];
+    int lastItemIndex = [self numberOfItems] - 1;
+    int recentItemCount = lastItemIndex - otherIndex;
+    int recentItemIndex = otherIndex;
+    NSAssert2(recentItemCount == aliasDataCount, @"Counted %d recent menu items, %d of alias data", recentItemCount, aliasDataCount);
+    while ( (aliasData = [e nextObject]) != nil) { // go BACKWARD through array while going DOWN menu
+        recentItemIndex++;
+        item = [self itemAtIndex: recentItemIndex];
+        itemAlias = [item representedObject];
+        if ([itemAlias aliasDataIsEqual: aliasData])
+            NSLog(@"item %d %@: %@", recentItemIndex, [item title], [itemAlias fullPath]);
+        else
+            NSLog(@"ITEM %d %@: %@ != aliasData %@", recentItemIndex, [item title], [itemAlias fullPath], [[BDAlias aliasWithData: aliasData] fullPath]);
+    }
+}
+
+#pragma mark initialize-release
+
+- (void)_setUp;
+{
+    NSMenu *menu;
+    NSMenuItem *item;
+    SoundFileManager *sfm = [SoundFileManager sharedSoundFileManager];
+    int soundCount = [sfm count];
+
+    [self removeAllItems];
+    menu = [self menu];
+    item = [menu addItemWithTitle: @"Alert sound" action: @selector(_beepSelected:) keyEquivalent: @""];
+    [item setTarget: self];
+    [menu addItem: [NSMenuItem separatorItem]];
+    if (soundCount == 0) {
+        item = [menu addItemWithTitle: @"CanÕt locate alert sounds" action: nil keyEquivalent: @""];
+        [item setEnabled: NO];
+    } else {
+        SoundFile *sf;
+        int i;
+        [sfm sortByName];
+        for (i = 0 ; i < soundCount ; i++) {
+            sf = [sfm soundFileAtIndex: i];
+            item = [menu addItemWithTitle: [sf name] action: @selector(_soundFileSelected:) keyEquivalent: @""];
+            [item setTarget: self];
+            [item setRepresentedObject: sf];
+            [item setImage: [[[NSWorkspace sharedWorkspace] iconForFile: [sf path]] bestFitImageForSize: NSMakeSize(16, 16)]];
+        }
+    }
+    [menu addItem: [NSMenuItem separatorItem]];
+    item = [menu addItemWithTitle: @"OtherÉ" action: @selector(select:) keyEquivalent: @""];
+    [item setTarget: self];
+    otherItem = [item retain];
+
+    [self _validateWithPreview: NO];
+
+    recentMediaAliasData = [[NSMutableArray alloc] initWithCapacity: NJRQTMediaPopUpButtonMaxRecentItems + 1];
+    [self _addRecentMediaFromAliasesData: [[NSUserDefaults standardUserDefaults] arrayForKey: [self _defaultKey]]];
+    // [self _validateRecentMedia];
+
+    [self registerForDraggedTypes:
+        [NSArray arrayWithObjects: NSFilenamesPboardType, NSURLPboardType, nil]];
+}
+
+- (id)initWithFrame:(NSRect)frame;
+{
+    if ( (self = [super initWithFrame: frame]) != nil) {
+        [self _setUp];
+    }
+    return self;
+}
+
+- (id)initWithCoder:(NSCoder *)coder;
+{
+    if ( (self = [super initWithCoder: coder]) != nil) {
+        [self _setUp];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [recentMediaAliasData release]; recentMediaAliasData = nil;
+    [otherItem release];
+    [selectedAlias release]; [previousAlias release];
+    [super dealloc];
+}
+
+#pragma mark accessing
+
+- (BDAlias *)selectedAlias;
+{
+    return selectedAlias;
+}
+
+- (void)_setAlias:(BDAlias *)alias;
+{
+    BDAlias *oldAlias = [selectedAlias retain];
+    [previousAlias release];
+    previousAlias = oldAlias;
+    if (selectedAlias != alias) {
+        [selectedAlias release];
+        selectedAlias = [alias retain];
+    }
+}
+
+- (void)setAlias:(BDAlias *)alias;
+{
+    [self _setAlias: alias];
+    if ([self _validateWithPreview: NO]) {
+        [self selectItem: [self _itemForAlias: selectedAlias]];
+    }
+}
+
+- (void)_setPath:(NSString *)path;
+{
+    [self _setAlias: [BDAlias aliasWithPath: path]];
+}
+
+- (NSMenuItem *)_itemForAlias:(BDAlias *)alias;
+{
+    NSString *path;
+    SoundFile *sf;
+    if (alias == nil) {
+        return [self itemAtIndex: 0];
+    }
+
+    // [self _validateRecentMedia];
+    path = [alias fullPath];
+    {   // XXX suppress log message from Apple's code:
+        // 2002-12-14 14:09:58.740 Pester[26529] Could not find sound type for directory /Users/nicholas/Desktop
+        int errfd = dup(STDERR_FILENO), nullfd = open("/dev/null", O_WRONLY, 0);
+        // need to have something open in STDERR_FILENO because if it isn't,
+        // NSLog will log to /dev/console
+        dup2(nullfd, STDERR_FILENO);
+        close(nullfd);
+        sf = [[SoundFileManager sharedSoundFileManager] soundFileFromPath: path];
+        dup2(errfd, STDERR_FILENO);
+        close(errfd);
+    }
+    // NSLog(@"_itemForAlias: %@", path);
+
+    // selected a system sound?
+    if (sf != nil) {
+        // NSLog(@"_itemForAlias: selected system sound");
+        return [self itemAtIndex: [self indexOfItemWithRepresentedObject: sf]];
+    } else {
+        NSEnumerator *e = [recentMediaAliasData reverseObjectEnumerator];
+        NSData *aliasData;
+        NSMenuItem *item;
+        int recentIndex = 1;
+
+        while ( (aliasData = [e nextObject]) != nil) {
+            // selected a recently selected, non-system sound?
+            if ([alias aliasDataIsEqual: aliasData]) {
+                int otherIndex = [self indexOfItem: otherItem];
+                int menuIndex = recentIndex + otherIndex;
+                if (menuIndex == otherIndex + 1) return [self itemAtIndex: menuIndex]; // already at top
+                // remove item, add (at top) later
+                // NSLog(@"_itemForAlias removing item: idx %d + otherItemIdx %d + 1 = %d [%@]", recentIndex, otherIndex, menuIndex, [self itemAtIndex: menuIndex]);
+                [self removeItemAtIndex: menuIndex];
+                [recentMediaAliasData removeObjectAtIndex: [recentMediaAliasData count] - recentIndex];
+                break;
+            }
+            recentIndex++;
+        }
+
+        // create the item
+        item = [self _addRecentMediaAtPath: path withAlias: alias];
+        [self _writeRecentMedia];
+        return item;
+    }
+}
+
+- (BOOL)canRepeat;
+{
+    return movieCanRepeat;
+}
+
+#pragma mark selected media validation
+
+- (void)_invalidateSelection;
+{
+    [self _setAlias: previousAlias];
+    [self selectItem: [self _itemForAlias: [self selectedAlias]]];
+    [[NSNotificationCenter defaultCenter] postNotificationName: NJRQTMediaPopUpButtonMovieChangedNotification object: self];
+}
+
+void
+MovieStoppedCB(QTCallBack cb, long refCon)
+{
+    NSMovieView *preview = (NSMovieView *)refCon;
+    // if we donÕt do this after the runloop has finished, then we crash in MCIdle because itÕs expecting a movie and doesnÕt have one any more
+    [preview performSelector: @selector(setMovie:) withObject: nil afterDelay: 0]; // otherwise we get an extra runloop timer which uses a lot of CPU from +[NSMovieView _idleMovies]
+    DisposeCallBack(cb);
+}
+
+- (BOOL)_validateWithPreview:(BOOL)doPreview;
+{
+    [preview stop: self];
+    if (selectedAlias == nil) {
+        [preview setMovie: nil];
+        movieCanRepeat = YES;
+        if (doPreview) NSBeep();
+    } else {
+        NSMovie *movie = [[NSMovie alloc] initWithURL: [NSURL fileURLWithPath: [selectedAlias fullPath]] byReference: YES];
+        movieCanRepeat = ![movie isStatic];
+        if ([movie hasAudio]) {
+            [preview setMovie: doPreview ? movie : nil];
+        } else {
+            [preview setMovie: nil];
+            if (movie == nil) {
+                NSBeginAlertSheet(@"Format not recognized", nil, nil, nil, [self window], nil, nil, nil, nil, @"The item you selected isnÕt a sound or movie recognized by QuickTime.  Please select a different item.");
+                [self _invalidateSelection];
+                return NO;
+            }
+            if (![movie hasAudio] && ![movie hasVideo]) {
+                NSBeginAlertSheet(@"No video or audio", nil, nil, nil, [self window], nil, nil, nil, nil, @"Ò%@Ó contains neither audio nor video content playable by QuickTime.  Please select a different item.", [[NSFileManager defaultManager] displayNameAtPath: [selectedAlias fullPath]]);
+                [self _invalidateSelection];
+                [movie release];
+                return NO;
+            }
+        }
+        if (doPreview) {
+            Movie qtMovie = [movie QTMovie];
+            QTCallBack cbStop = NewCallBack(GetMovieTimeBase(qtMovie), callBackAtExtremes);
+            QTCallBackUPP cbStopUPP = NewQTCallBackUPP(MovieStoppedCB);
+            OSErr err = CallMeWhen(cbStop, cbStopUPP, (long)preview, triggerAtStop, 0, 0);
+            if (err != noErr) {
+                NSLog(@"CanÕt register QuickTime stop timebase callback for preview: %ld", err);
+                DisposeCallBack(cbStop);
+            }
+            [preview start: self];
+        }
+        [movie release];
+    }
+    [[NSNotificationCenter defaultCenter] postNotificationName: NJRQTMediaPopUpButtonMovieChangedNotification object: self];
+    return YES;
+}
+
+#pragma mark actions
+
+- (IBAction)stopSoundPreview:(id)sender;
+{
+    [preview stop: self];
+    [preview setMovie: nil]; // otherwise we get an extra runloop timer which uses a lot of CPU from +[NSMovieView _idleMovies]
+}
+
+- (void)_beepSelected:(NSMenuItem *)sender;
+{
+    [self _setAlias: nil];
+    [self _validateWithPreview: YES];
+}
+
+- (void)_soundFileSelected:(NSMenuItem *)sender;
+{
+    [self _setPath: [(SoundFile *)[sender representedObject] path]];
+    if (![self _validateWithPreview: YES]) {
+        [[self menu] removeItem: sender];
+    }
+}
+
+- (void)_aliasSelected:(NSMenuItem *)sender;
+{
+    BDAlias *alias = [sender representedObject];
+    int index = [self indexOfItem: sender], otherIndex = [self indexOfItem: otherItem];
+    [self _setAlias: alias];
+    if (![self _validateWithPreview: YES]) {
+        [[self menu] removeItem: sender];
+    } else if (index > otherIndex + 1) { // move "other" item to top of list
+        int recentIndex = [recentMediaAliasData count] - index + otherIndex;
+        NSMenuItem *item = [[self itemAtIndex: index] retain];
+        NSData *data = [[recentMediaAliasData objectAtIndex: recentIndex] retain];
+        // [self _validateRecentMedia];
+        [self removeItemAtIndex: index];
+        [[self menu] insertItem: item atIndex: otherIndex + 1];
+        [self selectItem: item];
+        [item release];
+        NSAssert(recentIndex >= 0, @"Recent media index invalid");
+        // NSLog(@"_aliasSelected removing item %d - %d + %d = %d of recentMediaAliasData", [recentMediaAliasData count], index, otherIndex, recentIndex);
+        [recentMediaAliasData removeObjectAtIndex: recentIndex];
+        [recentMediaAliasData addObject: data];
+        [self _validateRecentMedia];
+        [data release];
+    } // else NSLog(@"_aliasSelected ...already at top");
+}
+
+- (IBAction)select:(id)sender;
+{
+    NSOpenPanel *openPanel = [NSOpenPanel openPanel];
+    NSString *path = [selectedAlias fullPath];
+    [openPanel setAllowsMultipleSelection: NO];
+    [openPanel setCanChooseDirectories: NO];
+    [openPanel setCanChooseFiles: YES];
+    [openPanel beginSheetForDirectory: [path stringByDeletingLastPathComponent]
+                                 file: [path lastPathComponent]
+                                types: nil // XXX fix for QuickTime!
+                       modalForWindow: [self window]
+                        modalDelegate: self
+                       didEndSelector: @selector(openPanelDidEnd:returnCode:contextInfo:)
+                          contextInfo: nil];
+}
+
+- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
+{
+    [sheet close];
+
+    if (returnCode == NSOKButton) {
+        NSArray *files = [sheet filenames];
+        NSAssert1([files count] == 1, @"%d items returned, only one expected", [files count]);
+        [self _setPath: [files objectAtIndex: 0]];
+        if ([self _validateWithPreview: YES]) {
+            [self selectItem: [self _itemForAlias: selectedAlias]];
+        }
+    } else {
+        // "Other..." item is still selected, revert to previously selected item
+        // XXX issue with cancelling, top item in recent menu is sometimes duplicated!?
+        [self selectItem: [self _itemForAlias: selectedAlias]];
+    }
+    // [self _validateRecentMedia];
+}
+
+- (void)setEnabled:(BOOL)flag;
+{
+    [super setEnabled: flag];
+    if (flag) ; // XXX [self startSoundPreview: self]; // need to prohibit at startup
+    else [self stopSoundPreview: self];
+}
+
+#pragma mark drag feedback
+
+- (void)drawRect:(NSRect)rect;
+{
+    if (dragAccepted) {
+        NSWindow *window = [self window];
+        NSRect boundsRect = [self bounds];
+        BOOL isFirstResponder = ([window firstResponder] == self);
+        // focus ring and drag feedback interfere with one another
+        if (isFirstResponder) [window makeFirstResponder: window];
+        [super drawRect: rect];
+        [[NSColor selectedControlColor] set];
+        NSFrameRectWithWidthUsingOperation(NSInsetRect(boundsRect, 2, 2), 3, NSCompositeSourceIn);
+        if (isFirstResponder) [window makeFirstResponder: self];
+    } else {
+        [super drawRect: rect];
+    }
+}
+
+@end
+
+@implementation NJRQTMediaPopUpButton (NSDraggingDestination)
+
+- (BOOL)acceptsDragFrom:(id <NSDraggingInfo>)sender;
+{
+    NSURL *url = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
+    NSFileManager *fm = [NSFileManager defaultManager];
+    BOOL isDir;
+
+    if (url == nil || ![url isFileURL]) return NO;
+
+    if (![fm fileExistsAtPath: [url path] isDirectory: &isDir]) return NO;
+
+    if (isDir) return NO;
+    
+    return YES;
+}
+
+- (NSString *)_descriptionForDraggingInfo:(id <NSDraggingInfo>)sender;
+{
+    NSDragOperation mask = [sender draggingSourceOperationMask];
+    NSMutableString *s = [NSMutableString stringWithFormat: @"Drag seq %d source: %@",
+        [sender draggingSequenceNumber], [sender draggingSource]];
+    NSPasteboard *draggingPasteboard = [sender draggingPasteboard];
+    NSArray *types = [draggingPasteboard types];
+    NSEnumerator *e = [types objectEnumerator];
+    NSString *type;
+    [s appendString: @"\nDrag operations:"];
+    if (mask & NSDragOperationCopy) [s appendString: @" copy"];
+    if (mask & NSDragOperationLink) [s appendString: @" link"];
+    if (mask & NSDragOperationGeneric) [s appendString: @" generic"];
+    if (mask & NSDragOperationPrivate) [s appendString: @" private"];
+    if (mask & NSDragOperationMove) [s appendString: @" move"];
+    if (mask & NSDragOperationDelete) [s appendString: @" delete"];
+    if (mask & NSDragOperationEvery) [s appendString: @" every"];
+    if (mask & NSDragOperationNone) [s appendString: @" none"];
+    [s appendFormat: @"\nImage: %@ at %@", [sender draggedImage],
+        NSStringFromPoint([sender draggedImageLocation])];
+    [s appendFormat: @"\nDestination: %@ at %@", [sender draggingDestinationWindow],
+        NSStringFromPoint([sender draggingLocation])];
+    [s appendFormat: @"\nPasteboard: %@ types:", draggingPasteboard];
+    while ( (type = [e nextObject]) != nil) {
+        if ([type hasPrefix: @"CorePasteboardFlavorType 0x"]) {
+            const char *osTypeHex = [[type substringFromIndex: [type rangeOfString: @"0x" options: NSBackwardsSearch].location] lossyCString];
+            OSType osType;
+            sscanf(osTypeHex, "%lx", &osType);
+            [s appendFormat: @" '%4s'", &osType];
+        } else {
+            [s appendFormat: @" \"%@\"", type];
+        }
+    }
+    return s;
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender;
+{
+    if ([self acceptsDragFrom: sender] && [sender draggingSourceOperationMask] &
+        (NSDragOperationCopy | NSDragOperationLink)) {
+        dragAccepted = YES;
+        [self setNeedsDisplay: YES];
+        // NSLog(@"draggingEntered accept:\n%@", [self _descriptionForDraggingInfo: sender]);
+        return NSDragOperationLink;
+    }
+    return NSDragOperationNone;
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)sender;
+{
+    dragAccepted = NO;
+    [self setNeedsDisplay: YES];
+}
+
+- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender;
+{
+    dragAccepted = NO;
+    [self setNeedsDisplay: YES];
+    return [self acceptsDragFrom: sender];
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
+{
+    if ([sender draggingSource] != self) {
+        NSURL *url = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
+        if (url == nil) return NO;
+        [self _setPath: [url path]];
+        if ([self _validateWithPreview: YES]) {
+            [self selectItem: [self _itemForAlias: selectedAlias]];
+        }
+    }
+    return YES;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRScrollView.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRScrollView.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRScrollView.h	(revision 62)
@@ -0,0 +1,17 @@
+//
+//  NJRScrollView.h
+//  HostLauncher
+//
+//  Created by nicholas on Tue Oct 30 2001.
+//  Copyright (c) 2001 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJRScrollView : NSScrollView {
+    BOOL shouldDrawFocusRing;
+    NSResponder *lastResp;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRScrollView.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRScrollView.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRScrollView.m	(revision 62)
@@ -0,0 +1,38 @@
+//
+//  NJRScrollView.m
+//  HostLauncher
+//
+//  Created by nicholas on Tue Oct 30 2001.
+//  Copyright (c) 2001 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRScrollView.h"
+
+
+@implementation NJRScrollView
+
+- (BOOL)needsDisplay;
+{
+    NSResponder *resp = nil;
+    if ([[self window] isKeyWindow]) {
+        resp = [[self window] firstResponder];
+        if (resp == lastResp) return [super needsDisplay];
+    } else if (lastResp == nil) {
+        return [super needsDisplay];
+    }
+    shouldDrawFocusRing = (resp != nil && [resp isKindOfClass: [NSView class]] &&
+                           [(NSView *)resp isDescendantOf: self]); // [sic]
+    lastResp = resp;
+    [self setKeyboardFocusRingNeedsDisplayInRect: [self bounds]];
+    return YES;
+}
+
+- (void)drawRect:(NSRect)rect {
+    [super drawRect: rect];
+    if (shouldDrawFocusRing) {
+        NSSetFocusRingStyle(NSFocusRingOnly);
+        NSRectFill([self bounds]);
+    }
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRTableDelegate.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRTableDelegate.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRTableDelegate.h	(revision 62)
@@ -0,0 +1,27 @@
+//
+//  NJRTableDelegate.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Oct 27 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "NJRTableView.h"
+
+
+@interface NJRTableDelegate : NSObject {
+    IBOutlet NJRTableView *tableView;
+    NSTableColumn *sortingColumn;
+    NSString *sortingKey;
+    BOOL sortDescending;
+
+    NSMutableArray *reorderedData;
+}
+
+- (NSMutableArray *)reorderedDataForData:(NSArray *)data;
+
+- (NSSet *)selectedItems;
+- (void)selectItems:(NSSet *)inSelectedItems;
+
+@end
Index: releases/Pester/1.1b1/Source/NJRTableDelegate.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRTableDelegate.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRTableDelegate.m	(revision 62)
@@ -0,0 +1,272 @@
+//
+//  NJRTableDelegate.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Oct 27 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRTableDelegate.h"
+#import "NSTableView-NJRExtensions.h"
+
+#pragma mark sorting support
+
+typedef struct { NSString *key; BOOL descending; } SortContext;
+
+// Sort array of itemNums, by looking up the itemNum in the dictionary of objects.
+// based on code of Ondra Cada <ocs@ocs.cz> on cocoa-dev list
+
+int ORDER_BY_CONTEXT(id left, id right, void *ctxt) {
+    SortContext *context = (SortContext *)ctxt;
+    int order = 0;
+    id key = context->key;
+    if (0 != key) {
+        id first, second;	// the actual objects to compare
+
+        if (context->descending) {
+            first  = [right valueForKey: key];
+            second = [left  valueForKey: key];
+        } else {
+            first  = [left  valueForKey: key];
+            second = [right valueForKey: key];
+        }
+
+        if ([first respondsToSelector: @selector(caseInsensitiveCompare:)]) {
+            order = [first caseInsensitiveCompare:second];
+        } else { // sort numbers or dates
+            order = [(NSNumber *)first compare:second];
+        }
+    }
+    return order;
+}
+
+@interface NJRTableDelegate (Private)
+
+- (void)_positionTypeSelectDisplay;
+- (void)_sortByColumn:(NSTableColumn *)inTableColumn;
+
+@end
+
+@implementation NJRTableDelegate
+
+#pragma mark initialize-release
+
+- (void)awakeFromNib;
+{
+    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_positionTypeSelectDisplay) name: NSViewFrameDidChangeNotification object: tableView];
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+    [sortingColumn release];
+    [sortingKey release];
+    [reorderedData release];
+    [super dealloc];
+}
+
+#pragma mark accessing
+
+- (void)setSortingColumn:(NSTableColumn *)inNewValue;
+{
+    [inNewValue retain];
+    [sortingColumn release];
+    sortingColumn = inNewValue;
+}
+
+- (void)setSortingKey:(NSString *)inNewValue;
+{
+    [inNewValue retain];
+    [sortingKey release];
+    sortingKey = inNewValue;
+}
+
+#pragma mark sorting
+
+- (NSString *)_sortContextDefaultKey;
+{
+    NSString *autosaveName = [tableView autosaveName];
+    if (autosaveName != nil)
+        return [NSString stringWithFormat: @"NJRTableDelegate SortContext %@", autosaveName];
+    else
+        return nil;
+}
+
+- (void)_sortData;
+{
+    SortContext ctxt = { sortingKey, sortDescending };
+    NSString *sortContextKey = [self _sortContextDefaultKey];
+
+    if (sortContextKey != nil) {
+        [[NSUserDefaults standardUserDefaults] setObject:
+            [NSDictionary dictionaryWithObjectsAndKeys: sortingKey, @"sortingKey", [NSNumber numberWithBool: sortDescending], @"sortDescending", nil]
+                                                    forKey: [self _sortContextDefaultKey]];
+    }
+    
+    // sort the NSMutableArray
+    [reorderedData sortUsingFunction: ORDER_BY_CONTEXT context: &ctxt];
+    [tableView reloadData];
+}
+
+- (void)_sortByColumn:(NSTableColumn *)inTableColumn;
+{
+    NSSet *oldSelection = [self selectedItems];
+    if (sortingColumn == inTableColumn) {
+        // User clicked same column, change sort order
+        sortDescending = !sortDescending;
+        // Possible optimization: Don't actually re-sort if you just change the sorting direction; instead, just display either the nth item or the (count-1-n)th item depending on ascending/descending.)
+    } else {
+        // User clicked new column, change old/new column headers, save new sorting column, and re-sort the array.
+        if (sortingColumn != nil) {
+            [tableView setIndicatorImage: nil inTableColumn: sortingColumn];
+            sortDescending = NO; // on initial sort, preserve previous sort order
+        }
+        [self setSortingKey: [inTableColumn identifier]];
+        [self setSortingColumn: inTableColumn];
+        [tableView setHighlightedTableColumn: inTableColumn];
+    }
+    [tableView setIndicatorImage: (sortDescending ? [NSTableView descendingSortIndicator] : [NSTableView ascendingSortIndicator]) inTableColumn: inTableColumn];
+    [self _positionTypeSelectDisplay];
+    // Actually sort the data
+    [self _sortData];
+    [self selectItems: oldSelection];
+}
+
+- (void)_initialSortData;
+{
+    NSString *sortContextKey = [self _sortContextDefaultKey];
+    NSDictionary *sortContext;
+    NSString *key;
+    NSTableColumn *column;
+
+    if (sortContextKey == nil) goto noContext;
+    if ( (sortContext = [[NSUserDefaults standardUserDefaults] dictionaryForKey: sortContextKey]) == nil) goto noContext;
+    if ( (key = [sortContext objectForKey: @"sortingKey"]) == nil) goto noContext;
+    if ( (column = [tableView tableColumnWithIdentifier: key]) == nil) goto noContext;
+    sortDescending = [[sortContext objectForKey: @"sortDescending"] boolValue];
+    [self _sortByColumn: column];
+    return;
+    
+noContext:
+    sortDescending = NO;
+    [self _sortByColumn: [[tableView tableColumns] objectAtIndex: 0]];
+}
+
+- (NSMutableArray *)reorderedDataForData:(NSArray *)data;
+{
+    if (reorderedData == nil) {
+        reorderedData = [data mutableCopy];
+        [self _initialSortData];
+    } else {
+        NSSet *oldSelection = [self selectedItems];
+        [reorderedData release]; reorderedData = nil;
+        reorderedData = [data mutableCopy];
+        [self _sortData];
+        [self selectItems: oldSelection];
+    }
+    return reorderedData;
+}
+
+#pragma mark type selection
+
+- (void)_positionTypeSelectDisplay;
+{
+    [tableView resetTypeSelect]; // avoid extraneous matching
+    if ([tableView typeSelectDisplay] != nil && sortingColumn != nil) {
+        NSControl *typeSelectControl = [tableView typeSelectDisplay];
+        if ([typeSelectControl isKindOfClass: [NSControl class]]) {
+            NSView *superview = [typeSelectControl superview];
+            NSRect columnRect = [superview convertRect: [tableView rectOfColumn: [tableView columnWithIdentifier: sortingKey]] fromView: tableView];
+            // XXX support horizontal scroll bar/clipping (not for Pester, but eventually)
+            // NSRect tableScrollFrame = [[tableView enclosingScrollView] frame];
+            NSRect selectFrame = [typeSelectControl frame];
+            [superview setNeedsDisplayInRect: selectFrame]; // fix artifacts caused by moving view
+            selectFrame.origin.x = columnRect.origin.x;
+            selectFrame.size.width = columnRect.size.width;
+            [typeSelectControl setAlignment: [[sortingColumn dataCell] alignment]];
+            [typeSelectControl setFrame: selectFrame];
+        }
+    }
+}
+
+#pragma mark saving/restoring selection
+
+- (NSSet *)selectedItems;
+{
+    NSMutableSet *result = [NSMutableSet set];
+    NSEnumerator *e = [tableView selectedRowEnumerator];
+    NSNumber *rowNum;
+
+    while ( (rowNum = [e nextObject]) != nil) {
+        id item = [reorderedData objectAtIndex: [rowNum intValue]];
+        [result addObject: item];
+    }
+    return result;
+}
+
+- (void)selectItems:(NSSet *)inSelectedItems;
+{
+    NSEnumerator *e = [inSelectedItems objectEnumerator];
+    id item;
+    int savedLastRow = 0;
+
+    [tableView deselectAll: nil];
+
+    while ( (item = [e nextObject]) != nil ) {
+        int row = [reorderedData indexOfObjectIdenticalTo: item];
+        if (row != NSNotFound) {
+            [tableView selectRow: row byExtendingSelection: YES];
+            savedLastRow = row;
+        }
+    }
+    [tableView scrollRowToVisible: savedLastRow];
+}
+
+@end
+
+@implementation NJRTableDelegate (NJRTableViewDelegate)
+
+- (void)tableView:(NSTableView *)aTableView didClickTableColumn:(NSTableColumn *)inTableColumn
+{
+    [[tableView window] makeFirstResponder: aTableView];
+    [self _sortByColumn: inTableColumn];
+}
+
+- (void)tableViewColumnDidResize:(NSNotification *)notification;
+{
+    [self _positionTypeSelectDisplay];
+}
+
+- (void)tableViewColumnDidMove:(NSNotification *)notification;
+{
+    [self _positionTypeSelectDisplay];
+}
+
+- (void)tableView:(NSTableView *)aTableView selectRowMatchingString:(NSString *)matchString;
+{
+    // Look for a highlighted column, presuming we are sorted by that column, and search its values.
+    NSTableColumn *col = [aTableView highlightedTableColumn];
+    id dataSource = [aTableView dataSource];
+    int i, rowCount = [reorderedData count];
+    if (nil == col) return;
+    if (sortDescending) {
+        for ( i = rowCount - 1 ; i >= 0 ; i-- ) {
+            NSComparisonResult order = [matchString caseInsensitiveCompare:
+                [dataSource tableView: aTableView objectValueForTableColumn: col row: i]];
+            if (order != NSOrderedDescending) break;
+        }
+        if (i < 0) i = 0;
+    } else {
+        for ( i = 0 ; i < rowCount ; i++ ) {
+            NSComparisonResult order = [matchString caseInsensitiveCompare:
+                [dataSource tableView: aTableView objectValueForTableColumn: col row: i]];
+            if (order != NSOrderedDescending) break;
+        }
+        if (i >= rowCount) i = rowCount - 1;
+    }
+    // Now select row i -- either the one we found, or the first/last row if not found.
+    [aTableView selectRow: i byExtendingSelection: NO];
+    [aTableView scrollRowToVisible: i];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRTableView.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRTableView.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRTableView.h	(revision 62)
@@ -0,0 +1,34 @@
+//
+//  NJRTableView.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Nov 17 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJRTableView : NSTableView {
+    NSMutableDictionary *toolTipRegionList;
+    NSMutableString *typed;
+    IBOutlet id typeSelectDisplay;
+}
+
+- (id)typeSelectDisplay;
+- (void)resetTypeSelect;
+
+@end
+
+@interface NSObject (NJRTableViewDelegate)
+
+- (void)tableView:(NSTableView *)aTableView selectRowMatchingString:(NSString *)matchString;
+
+@end
+
+@interface NSObject (NJRTableViewDataSource)
+
+- (void)removeSelectedRowsFromTableView:(NSTableView *)tableView;
+- (NSString *)tableView:(NSTableView *)aTableView toolTipForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex;
+
+@end
Index: releases/Pester/1.1b1/Source/NJRTableView.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRTableView.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRTableView.m	(revision 62)
@@ -0,0 +1,207 @@
+//
+//  NJRTableView.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Nov 17 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRTableView.h"
+#import "NSTableView-NJRExtensions.h"
+#import "NSCharacterSet-NJRExtensions.h"
+
+/* only defined in 10.2, but we want to be able to compile without warnings on 10.1.x */
+@interface NSColor (JaguarExtras)
++ (NSColor *)alternateSelectedControlColor;
+@end
+
+@implementation NJRTableView
+
+- (id)initWithCoder:(NSCoder *)aDecoder;
+{
+    if ( (self = [super initWithCoder: aDecoder]) != nil) {
+        toolTipRegionList = [[NSMutableDictionary alloc] initWithCapacity: 20];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [toolTipRegionList release];
+    [super dealloc];
+}
+
+#pragma mark tool tips
+
+- (void)reloadData;
+{
+    [toolTipRegionList removeAllObjects];
+    [self removeAllToolTips];
+    [super reloadData];
+}
+
+- (void)noteNumberOfRowsChanged;
+{
+    [toolTipRegionList removeAllObjects];
+    [self removeAllToolTips];
+    [super noteNumberOfRowsChanged];
+}
+
+- (NSString *)_keyForColumn:(int)columnIndex row:(int)rowIndex;
+{
+    return [NSString stringWithFormat:@"%d,%d", rowIndex, columnIndex];
+}
+
+- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)data;
+{
+    // ask our data source for the tool tip
+    if ([[self dataSource] respondsToSelector: @selector(tableView:toolTipForTableColumn:row:)]) {
+        if ([self rowAtPoint: point] >= 0) return [[self dataSource] tableView: self toolTipForTableColumn: [[self tableColumns] objectAtIndex: [self columnAtPoint: point]] row: [self rowAtPoint: point]];
+    }
+    return nil;
+}
+
+- (NSRect)frameOfCellAtColumn:(int)columnIndex row:(int)rowIndex;
+{
+    // this cell is apparently displayed, so we need to add a region for it
+    NSNumber *toolTipTag;
+    NSRect result = [super frameOfCellAtColumn: columnIndex row: rowIndex];
+    // check if cell is already in the list
+    NSString *cellKey = [self _keyForColumn: columnIndex row: rowIndex];
+    // remove old region
+    if (toolTipTag = [toolTipRegionList objectForKey: cellKey])
+        [self removeToolTip: [toolTipTag intValue]];
+    // add new region
+    [toolTipRegionList setObject: [NSNumber numberWithInt: [self addToolTipRect: result owner: self userData: cellKey]] forKey: cellKey];
+    return [super frameOfCellAtColumn: columnIndex row: rowIndex];
+}
+
+#pragma mark type selection
+
+- (id)typeSelectDisplay;
+{
+    return typeSelectDisplay;
+}
+
+- (void)moveToEndOfDocument:(id)sender {
+    [self scrollRowToVisible: [self numberOfRows] - 1];
+}
+
+- (void)moveToBeginningOfDocument:(id)sender {
+    [self scrollRowToVisible: 0];
+}
+
+- (void)keyDown:(NSEvent *)theEvent;
+{
+    NSString *characters;
+    unichar firstCharacter;
+    characters = [theEvent characters];
+    firstCharacter = [characters characterAtIndex: 0];
+    switch (firstCharacter) {
+        case 0177: // delete key
+        case NSDeleteFunctionKey:
+        case NSDeleteCharFunctionKey:
+            if ([self selectedRow] >= 0 && [[self dataSource] respondsToSelector: @selector(removeSelectedRowsFromTableView:)]) {
+                [[self dataSource] removeSelectedRowsFromTableView: self];
+            }
+            return;
+        case NSHomeFunctionKey:
+            [self moveToBeginningOfDocument: nil];
+            return;
+        case NSEndFunctionKey:
+            [self moveToEndOfDocument: nil];
+            return;
+    }
+    if ([[NSCharacterSet typeSelectSet] characterIsMember: firstCharacter]) {
+        // invoking -[NSResponder interpretKeyEvents:] will cause insertText: to be invoked, and allows function keys to still work.
+        [self interpretKeyEvents: [NSArray arrayWithObject: theEvent]];
+    } else {
+        [super keyDown: theEvent];
+    }
+}
+
+- (void)insertText:(id)inString;
+{
+    if (![[self delegate] respondsToSelector:@selector(selectString:inTableView:)]) {
+        // For consistency with List Manager as documented, reset the typeahead buffer after twice the delay until key repeat (in ticks).
+        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+        int keyRepeatTicks = [defaults integerForKey: @"InitialKeyRepeat"];
+        NSTimeInterval resetDelay;
+
+        if (keyRepeatTicks == 0) keyRepeatTicks = 35; // default may be missing; if so, set default
+
+        resetDelay = MIN(2.0 / 60.0 * keyRepeatTicks, 2.0);
+
+        if (typed == nil) typed = [[NSMutableString alloc] init];
+        [typed appendString: inString];
+
+        // Cancel any previously queued future invocations of _resetTypeSelect
+        [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(_resetTypeSelect) object: nil];
+
+        // queue an invocation of clearAccumulatingTypeahead for the near future.
+        [self performSelector: @selector(_resetTypeSelect) withObject: nil afterDelay: resetDelay];
+
+        // Use stringWithString to make an autoreleased copy, since we may clear out the original string below before it can be used.
+        [[self delegate] tableView: self selectRowMatchingString: [NSString stringWithString: typed]];
+
+        // Show the current typeahead string in the optional display field, like CodeWarrior does (well, not really, CW is much more elegant because it doesn't select anything until you stop typing)
+        [typeSelectDisplay setObjectValue: typed];
+    }
+}
+
+- (void)_resetTypeSelect;
+{
+    [typed setString: @""];
+    [typeSelectDisplay setObjectValue: nil];
+}
+
+- (void)resetTypeSelect;
+{
+    [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(_resetTypeSelect) object: nil];
+    [self _resetTypeSelect];
+}
+
+#pragma mark row coloring
+
+- (void)drawGridInClipRect:(NSRect)rect;
+{
+    NSRange columnRange = [self columnsInRect: rect];
+    int i;
+    // match iTunesÕ grid color
+    [[[NSColor gridColor] blendedColorWithFraction: 0.70 ofColor: [NSColor whiteColor]] set];
+    for (i = columnRange.location ; i < NSMaxRange(columnRange) ; i++) {
+        NSRect colRect = [self rectOfColumn:i];
+        int rightEdge = (int) 0.5 + colRect.origin.x + colRect.size.width;
+        [NSBezierPath strokeLineFromPoint: NSMakePoint(-0.5 + rightEdge, -0.5 + rect.origin.y)
+                                  toPoint: NSMakePoint(-0.5 + rightEdge, -0.5 + rect.origin.y + rect.size.height)];
+    }
+}
+
+- (void)highlightSelectionInClipRect:(NSRect)clipRect;
+{
+    NSColor *evenColor, *oddColor = [self backgroundColor];
+    float cellHeight = [self cellHeight];
+    NSRect visibleRect = [self visibleRect];
+    NSRect highlightRect;
+    
+    if ([NSColor respondsToSelector: @selector(alternateSelectedControlColor)])
+        evenColor = [[NSColor alternateSelectedControlColor] highlightWithLevel:0.90];
+    else // match iTunesÕ row background color
+        evenColor = [NSColor colorWithCalibratedRed: 0.929 green: 0.953 blue: 0.996 alpha:1.0];
+
+    highlightRect.origin = NSMakePoint(NSMinX(visibleRect), (int)(NSMinY(clipRect) / cellHeight) * cellHeight);
+    highlightRect.size = NSMakeSize(NSWidth(visibleRect), cellHeight);
+
+    while (NSMinY(highlightRect) < NSMaxY(clipRect)) {
+        NSRect clippedHighlightRect = NSIntersectionRect(highlightRect, clipRect);
+        int row = (int)((NSMinY(highlightRect) + cellHeight / 2.0) / cellHeight);
+        NSColor *rowColor = (row % 2 == 0) ? evenColor : oddColor;
+        [rowColor set];
+        NSRectFill(clippedHighlightRect);
+        highlightRect.origin.y += cellHeight;
+    }
+
+    [super highlightSelectionInClipRect: clipRect];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRUnfocusableMovieView.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRUnfocusableMovieView.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRUnfocusableMovieView.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  NJRUnfocusableMovieView.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Dec 15 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJRUnfocusableMovieView : NSMovieView {
+
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRUnfocusableMovieView.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRUnfocusableMovieView.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRUnfocusableMovieView.m	(revision 62)
@@ -0,0 +1,19 @@
+//
+//  NJRUnfocusableMovieView.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Dec 15 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRUnfocusableMovieView.h"
+
+
+@implementation NJRUnfocusableMovieView
+
+- (BOOL)acceptsFirstResponder;
+{
+    return NO;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NJRVoicePopUpButton.h
===================================================================
--- releases/Pester/1.1b1/Source/NJRVoicePopUpButton.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRVoicePopUpButton.h	(revision 62)
@@ -0,0 +1,30 @@
+//
+//  NJRVoicePopUpButton.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "SUSpeaker.h"
+
+@interface NJRVoicePopUpButton : NSPopUpButton {
+    id _delegate;
+    SUSpeaker *_speaker;
+}
+
+- (void)setVoice:(NSString *)voice;
+
+- (id)delegate;
+- (void)setDelegate:(id)delegate;
+
+- (IBAction)stopVoicePreview:(id)sender;
+
+@end
+
+@interface NSObject (NJRVoicePopUpButtonDelegate)
+
+- (NSString *)voicePopUpButton:(NJRVoicePopUpButton *)sender previewStringForVoice:(NSString *)voice;
+
+@end
Index: releases/Pester/1.1b1/Source/NJRVoicePopUpButton.m
===================================================================
--- releases/Pester/1.1b1/Source/NJRVoicePopUpButton.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NJRVoicePopUpButton.m	(revision 62)
@@ -0,0 +1,141 @@
+//
+//  NJRVoicePopUpButton.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRVoicePopUpButton.h"
+
+@implementation NJRVoicePopUpButton
+
+- (void)_refreshVoiceList;
+{
+    NSMenu *menu;
+    NSMenuItem *item;
+    NSArray *voiceNames = [SUSpeaker voiceNames];
+
+    [self removeAllItems];
+    menu = [self menu];
+    [menu setAutoenablesItems: NO];
+    // XXX would be more elegant with surrogate support like my font popup menu
+    item = [menu addItemWithTitle: @"ÇunknownÈ" action: nil keyEquivalent: @""];
+    [item setEnabled: NO];
+    [menu addItem: [NSMenuItem separatorItem]];
+    if (voiceNames == nil || [voiceNames count] == 0) {
+        item = [menu addItemWithTitle: @"CanÕt locate voices" action: nil keyEquivalent: @""];
+        [item setEnabled: NO];
+    } else {
+        NSEnumerator *e = [voiceNames objectEnumerator];
+        NSString *voiceName;
+        while ( (voiceName = [e nextObject]) != nil) {
+            item = [menu addItemWithTitle: voiceName action: @selector(_previewVoice) keyEquivalent: @""];
+            [item setTarget: self];
+        }
+    }
+    if (_speaker == nil) [self selectItemWithTitle: [SUSpeaker defaultVoice]];
+}
+
+- (id)initWithFrame:(NSRect)frame;
+{
+    if ( (self = [super initWithFrame: frame]) != nil) {
+        [self _refreshVoiceList];
+    }
+    return self;
+}
+
+- (id)initWithCoder:(NSCoder *)coder;
+{
+    if ( (self = [super initWithCoder: coder]) != nil) {
+        [self _refreshVoiceList];
+    }
+    return self;
+}
+
+- (SUSpeaker *)_speaker;
+{
+    if (_speaker == nil) _speaker = [[SUSpeaker alloc] init];
+    return _speaker;
+}
+
+- (void)_invalidateVoiceSelection;
+{
+    [self _refreshVoiceList];
+    [self selectItemAtIndex: 0];
+}
+
+- (void)setVoice:(NSString *)voice;
+{
+    int voiceIdx = [self indexOfItemWithTitle: voice];
+    if (voiceIdx == -1) {
+        [self _invalidateVoiceSelection];
+    } else {
+        [self selectItemAtIndex: voiceIdx];
+    }
+}
+
+- (void)_previewVoice;
+{
+    NSString *voiceName = [self titleOfSelectedItem];
+    NSString *previewString = nil;
+    VoiceSpec voice;
+    OSStatus err = noErr;
+    VoiceDescription info;
+    short voiceIndex = [[SUSpeaker voiceNames] indexOfObject: voiceName] + 1;
+
+    [_speaker stopSpeaking];
+
+    if ( (err = GetIndVoice(voiceIndex, &voice)) != noErr) {
+        NSBeginAlertSheet(@"Voice not available", nil, nil, nil, [self window], nil, nil, nil, nil, @"The voice Ò%@Ó you selected could not be used.  An error of type %ld occurred while attempting to retrieve voice information.", voiceName, err);
+        [self _invalidateVoiceSelection];
+        return;
+    }
+
+    if (_delegate != nil && [_delegate respondsToSelector: @selector(voicePopUpButton:previewStringForVoice:)]) {
+        previewString = [_delegate voicePopUpButton: self previewStringForVoice: voiceName];
+    }
+
+    if (previewString == nil) {
+        err = GetVoiceDescription(&voice, &info, sizeof(info));
+        if (err != noErr || info.comment[0] == 0)
+            previewString = voiceName;
+        else {
+            previewString = (NSString *)CFStringCreateWithPascalString(NULL, info.comment, kCFStringEncodingMacRoman);
+            [previewString autorelease];
+        }
+    }
+
+    [[self _speaker] setVoice: voiceIndex];
+    [_speaker speakText: previewString];
+}
+
+- (void)dealloc;
+{
+    [_speaker release];
+    [super dealloc];
+}
+
+- (IBAction)stopVoicePreview:(id)sender;
+{
+    [_speaker stopSpeaking];
+}
+
+- (void)setEnabled:(BOOL)flag;
+{
+    [super setEnabled: flag];
+    if (flag) ; // XXX [self stopVoicePreview: self]; // need to prohibit at startup
+    else [self stopVoicePreview: self];
+}
+
+- (void)setDelegate:(id)delegate;
+{
+    _delegate = delegate;
+}
+
+- (id)delegate;
+{
+    return _delegate;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NSAttributedString-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b1/Source/NSAttributedString-NJRExtensions.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSAttributedString-NJRExtensions.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  NSAttributedString-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Dec 16 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NSAttributedString (NJRExtensions)
+
+- (float)heightWrappedToWidth:(float)width;
+
+@end
Index: releases/Pester/1.1b1/Source/NSAttributedString-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b1/Source/NSAttributedString-NJRExtensions.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NSAttributedString-NJRExtensions.m	(revision 62)
@@ -0,0 +1,30 @@
+//
+//  NSAttributedString-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Dec 16 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NSAttributedString-NJRExtensions.h"
+
+@implementation NSAttributedString (NJRExtensions)
+
+- (float)heightWrappedToWidth:(float)width;
+{
+    float height = 0;
+    NSTextStorage *storage = [[NSTextStorage alloc] initWithAttributedString: self];
+    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
+    NSTextContainer *container = [[NSTextContainer alloc]
+        initWithContainerSize: NSMakeSize(width, MAXFLOAT)];
+    [layoutManager addTextContainer: container];
+    [storage addLayoutManager: layoutManager];
+    (void) [layoutManager glyphRangeForTextContainer: container]; // force layout
+    height = [layoutManager usedRectForTextContainer: container].size.height;
+    [layoutManager release];
+    [container release];
+    [storage release];
+    return height;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NSCalendarDate-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b1/Source/NSCalendarDate-NJRExtensions.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSCalendarDate-NJRExtensions.h	(revision 62)
@@ -0,0 +1,17 @@
+//
+//  NSCalendarDate-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Dec 22 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NSCalendarDate (NJRExtensions)
+
++ (NSCalendarDate *)dateForDay:(NSDate *)date;
++ (NSCalendarDate *)dateWithDate:(NSDate *)date atTime:(NSDate *)time;
+
+@end
Index: releases/Pester/1.1b1/Source/NSCalendarDate-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b1/Source/NSCalendarDate-NJRExtensions.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NSCalendarDate-NJRExtensions.m	(revision 62)
@@ -0,0 +1,49 @@
+//
+//  NSCalendarDate-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Dec 22 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NSCalendarDate-NJRExtensions.h"
+
+
+@interface NSCalendarDate (Private)
+
+// implemented in Foundation, but not declared in NSDate.h
++ (NSCalendarDate *)dateWithDate:(NSDate *)date;
+
+@end
+
+@implementation NSCalendarDate (NJRExtensions)
+
++ (NSCalendarDate *)dateForDay:(NSDate *)date;
+{
+    NSCalendarDate *calDate = [NSCalendarDate dateWithDate: date];
+    return [NSCalendarDate dateWithYear: [calDate yearOfCommonEra]
+                                  month: [calDate monthOfYear]
+                                    day: [calDate dayOfMonth]
+                                   hour: 0
+                                 minute: 0
+                                 second: 0
+                               timeZone: nil];
+}
+
++ (NSCalendarDate *)dateWithDate:(NSDate *)date atTime:(NSDate *)time;
+{
+    NSCalendarDate *calTime, *calDate;
+    if (time == nil || date == nil) return nil;
+    calTime = [NSCalendarDate dateWithDate: time];
+    calDate = [NSCalendarDate dateWithDate: date];
+    if (calTime == nil || calDate == nil) return nil;
+    return [NSCalendarDate dateWithYear: [calDate yearOfCommonEra]
+                                  month: [calDate monthOfYear]
+                                    day: [calDate dayOfMonth]
+                                   hour: [calTime hourOfDay]
+                                 minute: [calTime minuteOfHour]
+                                 second: [calTime secondOfMinute]
+                               timeZone: nil];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NSCharacterSet-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b1/Source/NSCharacterSet-NJRExtensions.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSCharacterSet-NJRExtensions.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  NSCharacterSet-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Nov 17 2002.
+//  Copyright (c) 2002 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NSCharacterSet (NJRExtensions)
+
++ (NSCharacterSet *)typeSelectSet;
+
+@end
Index: releases/Pester/1.1b1/Source/NSCharacterSet-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b1/Source/NSCharacterSet-NJRExtensions.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NSCharacterSet-NJRExtensions.m	(revision 62)
@@ -0,0 +1,28 @@
+//
+//  NSCharacterSet-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Nov 17 2002.
+//  Copyright (c) 2002 __MyCompanyName__. All rights reserved.
+//
+
+#import "NSCharacterSet-NJRExtensions.h"
+
+
+@implementation NSCharacterSet (NJRExtensions)
+
+static NSCharacterSet *_typeSelectSet = nil;
+
++ (NSCharacterSet *)typeSelectSet {
+    if (_typeSelectSet == nil) {
+        NSMutableCharacterSet *set;
+        set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
+        [set formUnionWithCharacterSet: [NSCharacterSet punctuationCharacterSet]];
+        [set formUnionWithCharacterSet: [NSCharacterSet whitespaceCharacterSet]];
+        _typeSelectSet = [set copy]; // make immutable again - for efficiency
+        [set release];
+    }
+    return _typeSelectSet;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NSDictionary-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b1/Source/NSDictionary-NJRExtensions.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSDictionary-NJRExtensions.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  NSDictionary-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Nov 19 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NSDictionary (NJRExtensions)
+
+- (id)objectForRequiredKey:(NSString *)key;
+
+@end
Index: releases/Pester/1.1b1/Source/NSDictionary-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b1/Source/NSDictionary-NJRExtensions.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NSDictionary-NJRExtensions.m	(revision 62)
@@ -0,0 +1,21 @@
+//
+//  NSDictionary-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Nov 19 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NSDictionary-NJRExtensions.h"
+
+
+@implementation NSDictionary (NJRExtensions)
+
+- (id)objectForRequiredKey:(NSString *)key;
+{
+    id obj = [self objectForKey: key];
+    NSAssert1(obj != nil, @"Dictionary does not contain object for required key Ò%@Ó", key);
+    return obj;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NSDisclosureButtonCell.h
===================================================================
--- releases/Pester/1.1b1/Source/NSDisclosureButtonCell.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSDisclosureButtonCell.h	(revision 62)
@@ -0,0 +1,18 @@
+/*
+ *     Generated by class-dump (version 2.1.5).
+ *
+ *     class-dump is Copyright (C) 1997, 1999, 2000, 2001 by Steve Nygard.
+ */
+/*
+ * File: /System/Library/Frameworks/AppKit.framework/AppKit
+ */
+
+#import <AppKit/AppKit.h>
+
+@interface NSDisclosureButtonCell : NSButtonCell
+{
+}
+
+- (void)initWithCell:(NSCell *)cell;
+
+@end
Index: releases/Pester/1.1b1/Source/NSImage-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b1/Source/NSImage-NJRExtensions.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSImage-NJRExtensions.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  NSImage-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Oct 28 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NSImage (NJRExtensions)
+
+- (NSImage *)bestFitImageForSize:(NSSize)imageSize;
+
+@end
Index: releases/Pester/1.1b1/Source/NSImage-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b1/Source/NSImage-NJRExtensions.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NSImage-NJRExtensions.m	(revision 62)
@@ -0,0 +1,62 @@
+//
+//  NSImage-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Oct 28 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NSImage-NJRExtensions.h"
+
+
+@implementation NSImage (NJRExtensions)
+
+- (NSImage *)bestFitImageForSize:(NSSize)imageSize;
+{
+    NSSize repSize;
+    NSArray *imageReps;
+    int i, repCount;
+    NSImageRep *preferredRep, *rep;
+    imageReps = [self representations];
+    repCount = [imageReps count];
+    preferredRep = [imageReps objectAtIndex: 0];
+    for (i = 1 ; i < repCount ; i++) {
+        rep = [imageReps objectAtIndex: i];
+        repSize = [rep size];
+        if (repSize.width == imageSize.width && repSize.height == imageSize.height) {
+            preferredRep = rep;
+            break;
+        }
+        if (repSize.width >= imageSize.width || repSize.height >= imageSize.height) {
+            // pick the smallest of the larger representations
+            if (repSize.width <= [preferredRep size].width ||
+                repSize.height <= [preferredRep size].height) preferredRep = rep;
+        } else {
+            // or the largest of the smaller representations
+            if (([preferredRep size].width > imageSize.width ||
+                    [preferredRep size].height > imageSize.height) ||
+                // (assuming that the previous preferred rep was smaller, too)
+                // XXX fix this in HostLauncher too - or is the FSA code better?
+                (repSize.width >= [preferredRep size].width ||
+                    repSize.height >= [preferredRep size].height)) preferredRep = rep;
+        }
+    }
+    // Begin workaround code for bug in OS X 10.1 (removeRepresentation: has no effect)
+    if ([preferredRep size].width > imageSize.width || [preferredRep size].height > imageSize.height) {
+        NSImage *scaledImage = [[NSImage alloc] initWithSize: imageSize];
+        NSRect rect = { NSZeroPoint, imageSize };
+        [scaledImage setFlipped: [self isFlipped]]; // XXX this works, but is correct?
+        [scaledImage lockFocus];
+        [preferredRep drawInRect: rect];
+        [scaledImage unlockFocus];
+        return scaledImage;
+    } else if (repCount > 1) {
+        NSImage *sizedImage = [[NSImage alloc] initWithSize: [preferredRep size]];
+        [sizedImage addRepresentation: preferredRep];
+        return sizedImage;
+    } else {
+        return self;
+    }
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NSMovie-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b1/Source/NSMovie-NJRExtensions.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSMovie-NJRExtensions.h	(revision 62)
@@ -0,0 +1,18 @@
+//
+//  NSMovie-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NSMovie (NJRExtensions)
+
+- (BOOL)hasAudio;
+- (BOOL)hasVideo;
+- (BOOL)isStatic;
+
+@end
Index: releases/Pester/1.1b1/Source/NSMovie-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b1/Source/NSMovie-NJRExtensions.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NSMovie-NJRExtensions.m	(revision 62)
@@ -0,0 +1,41 @@
+//
+//  NSMovie-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NSMovie-NJRExtensions.h"
+#import <QuickTime/Movies.h>
+
+@implementation NSMovie (NJRExtensions)
+
+- (BOOL)hasAudio;
+{
+    return (NULL != GetMovieIndTrackType((Movie)[self QTMovie], 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly));
+}
+
+- (BOOL)hasVideo;
+{
+    return (NULL != GetMovieIndTrackType((Movie)[self QTMovie], 1, VisualMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly));
+}
+
+- (BOOL)isStatic;
+{
+    Movie movie = (Movie)[self QTMovie];
+    long trackCount = (long)GetMovieTrackCount(movie);
+    long trackIdx = 0;
+    Track track;
+    Media media;
+    for (trackIdx = 1 ; trackIdx <= trackCount ; trackIdx++) {
+        track = GetMovieIndTrack(movie, trackIdx);
+        if (track == nil) continue;
+        media = GetTrackMedia(track);
+        if (media == nil) continue;
+        if (GetMediaSampleCount(media) > 1) return NO;
+    }
+    return YES;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NSString-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b1/Source/NSString-NJRExtensions.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSString-NJRExtensions.h	(revision 62)
@@ -0,0 +1,28 @@
+//
+//  NSString-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Dec 16 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NSString (NJRExtensions)
+
+- (NSAttributedString *)small;
+- (NSAttributedString *)smallBold;
+- (NSAttributedString *)underlined;
+
++ (NSString *)ellipsisString;
+
+
+@end
+
+@interface NSMutableString (NJRExtensions)
+
+- (void)truncateToLength:(unsigned)maxLength by:(NSLineBreakMode)method;
+- (void)truncateToWidth:(float)maxWidth by:(NSLineBreakMode)method withAttributes:(NSDictionary *)attributes;
+
+@end
Index: releases/Pester/1.1b1/Source/NSString-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b1/Source/NSString-NJRExtensions.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NSString-NJRExtensions.m	(revision 62)
@@ -0,0 +1,94 @@
+//
+//  NSString-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Dec 16 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NSString-NJRExtensions.h"
+
+@implementation NSString (NJRExtensions)
+
+- (NSAttributedString *)attributedStringWithFont:(NSFont *)font;
+{
+    return [[[NSAttributedString alloc] initWithString: self attributes: [NSDictionary dictionaryWithObject: font forKey: NSFontAttributeName]] autorelease];
+}
+
+- (NSAttributedString *)underlined;
+{
+    return [[[NSAttributedString alloc] initWithString: self attributes: [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: NSSingleUnderlineStyle] forKey: NSUnderlineStyleAttributeName]] autorelease];
+}
+
+- (NSAttributedString *)small;
+{
+    return [self attributedStringWithFont: [NSFont systemFontOfSize: [NSFont smallSystemFontSize]]];
+}
+
+- (NSAttributedString *)smallBold;
+{
+    return [self attributedStringWithFont: [NSFont boldSystemFontOfSize: [NSFont smallSystemFontSize]]];
+}
+
++ (NSString *)ellipsisString;
+{
+    static NSString *ellipsis = nil;
+    if (ellipsis == nil) {
+        const unichar ellipsisChar = 0x2026;
+        ellipsis = [[NSString alloc] initWithCharacters: &ellipsisChar length: 1];
+    }
+    return ellipsis;
+}
+
+@end
+
+@implementation NSMutableString (NJRExtensions)
+
+- (void)truncateToLength:(unsigned)maxLength by:(NSLineBreakMode)method;
+{
+    if ([self length] > maxLength) {
+        NSRange range = {0, [self length] - maxLength};
+        switch (method) {
+            case NSLineBreakByTruncatingHead:
+                range.location = 0;
+                break;
+            case NSLineBreakByTruncatingMiddle:
+                range.location = maxLength / 2;
+                break;
+            case NSLineBreakByTruncatingTail:
+                range.location = maxLength;
+                break;
+            default:
+                range.location = maxLength;
+                break;
+        }
+        [self replaceCharactersInRange: range withString: [NSString ellipsisString]];
+    }
+}
+
+- (void)truncateToWidth:(float)maxWidth by:(NSLineBreakMode)method withAttributes:(NSDictionary *)attributes;
+{
+    if ([self sizeWithAttributes: attributes].width > maxWidth) {
+        float width;
+        int min = 0, max = [self length], avg;
+        NSMutableString *original = [self mutableCopy];
+        while (max >= min) {
+            avg = (max + min) / 2;
+            [self truncateToLength: avg by: method];
+            width = [self sizeWithAttributes: attributes].width;
+            if (width > maxWidth) {
+                max = avg - 1; // too wide
+            } else if (width == maxWidth) {
+                break;
+            } else {
+                min = avg + 1; // too narrow
+                [self setString: original];
+            }
+        }
+        if (width != maxWidth)
+            [self truncateToLength: max by: method];
+        [original release];
+    }
+}
+
+@end
Index: releases/Pester/1.1b1/Source/NSTableView-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b1/Source/NSTableView-NJRExtensions.h	(revision 62)
+++ releases/Pester/1.1b1/Source/NSTableView-NJRExtensions.h	(revision 62)
@@ -0,0 +1,19 @@
+//
+//  NSTableView-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Oct 27 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NSTableView (NJRExtensions)
+
++ (NSImage *)ascendingSortIndicator;
++ (NSImage *)descendingSortIndicator;
+
+- (float)cellHeight;
+
+@end
Index: releases/Pester/1.1b1/Source/NSTableView-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b1/Source/NSTableView-NJRExtensions.m	(revision 62)
+++ releases/Pester/1.1b1/Source/NSTableView-NJRExtensions.m	(revision 62)
@@ -0,0 +1,47 @@
+//
+//  NSTableView-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Oct 27 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "NSTableView-NJRExtensions.h"
+
+
+@interface NSTableView (PumaPrivate)
+// Declarations of 10.1 private methods, just to make the compiler happy.
++ (id) _defaultTableHeaderReverseSortImage;
++ (id) _defaultTableHeaderSortImage;
+@end
+
+@implementation NSTableView (NJRExtensions)
+
++ (NSImage *)ascendingSortIndicator;
+{
+    NSImage *result = [NSImage imageNamed: @"NSAscendingSortIndicator"];
+    if (result == nil && [[NSTableView class] respondsToSelector: @selector(_defaultTableHeaderSortImage)])
+        result = [NSTableView _defaultTableHeaderSortImage];
+    return result;
+}
+
++ (NSImage *)descendingSortIndicator;
+{
+    NSImage *result = [NSImage imageNamed: @"NSDescendingSortIndicator"];
+    if (result == nil && [[NSTableView class] respondsToSelector: @selector(_defaultTableHeaderReverseSortImage)])
+        result = [NSTableView _defaultTableHeaderReverseSortImage];
+    return result;
+}
+
+- (float)cellHeight;
+{
+    return [self rowHeight] + [self intercellSpacing].height;
+}
+
+// causes NSTableView to get keyboard focus (with thanks to Pierre-Olivier Latour)
+- (BOOL)needsPanelToBecomeKey
+{
+    return YES;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarm.h
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarm.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarm.h	(revision 62)
@@ -0,0 +1,81 @@
+//
+//  PSAlarm.h
+//  Pester
+//
+//  Created by Nicholas Riley on Wed Oct 09 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "PSPropertyListSerialization.h"
+
+typedef enum {
+    PSAlarmInvalid, // incorrectly specified
+    PSAlarmInterval, // interval specified (possibly repeating)
+    PSAlarmDate, // date specified
+    PSAlarmSet, // pending, timer set
+    PSAlarmSnooze, // expired alarm with snooze interval set (possibly repeating)
+    PSAlarmExpired // expired alarm (possibly repeating)
+} PSAlarmType;
+
+extern NSString * const PSAlarmTimerSetNotification;
+extern NSString * const PSAlarmTimerExpiredNotification;
+extern NSString * const PSAlarmDiedNotification;
+
+@class PSAlert, PSAlerts, PSTimer;
+
+@interface PSAlarm : NSObject <NSCoding, PSPropertyListSerialization> {
+    PSAlarmType alarmType; // changes during lifetime of alarm; more like a state
+    NSCalendarDate *alarmDate;
+    NSTimeInterval alarmInterval;
+    NSTimeInterval snoozeInterval;
+    NSTimeInterval timeRemaining;
+    NSString *alarmMessage;
+    NSString *invalidMessage;
+    PSTimer *timer;
+    PSAlerts *alerts;
+    BOOL repeating;
+}
+
+- (void)setInterval:(NSTimeInterval)anInterval;
+- (void)setForDateAtTime:(NSCalendarDate *)dateTime;
+- (void)setForDate:(NSDate *)date atTime:(NSDate *)time;
+- (void)setMessage:(NSString *)aMessage;
+- (void)setAlerts:(PSAlerts *)theAlerts;
+- (void)setRepeating:(BOOL)isRepeating;
+- (void)setSnoozeInterval:(NSTimeInterval)anInterval;
+- (void)setWakeUp:(BOOL)doWake;
+
+- (NSCalendarDate *)date;
+- (NSCalendarDate *)time;
+- (NSTimeInterval)interval;
+- (NSTimeInterval)timeRemaining;
+- (NSString *)message;
+- (PSAlerts *)alerts;
+- (BOOL)isRepeating;
+- (NSTimeInterval)snoozeInterval; // most recent interval (nonzero return does not indicate alarm is snoozing or set to snooze)
+
+- (NSString *)dateString;
+- (NSString *)shortDateString;
+- (NSString *)timeString;
+- (NSString *)dateTimeString; // current or next alarm time
+- (NSString *)nextDateTimeString; // next alarm time
+- (NSString *)intervalString;
+- (NSString *)timeRemainingString;
+
+- (BOOL)isValid;
+- (NSString *)invalidMessage;
+
+- (NSAttributedString *)prettyDescription;
+
+- (NSComparisonResult)compareDate:(PSAlarm *)otherAlarm;
+- (NSComparisonResult)compareMessage:(PSAlarm *)otherAlarm;
+
+- (BOOL)setTimer; // or die, if expired and no snooze/repeat
+- (void)cancelTimer;
+
+// 1.1 only, going away when we move to keyed archiving
+- (NSDictionary *)propertyListRepresentation;
+- (id)initWithPropertyList:(NSDictionary *)dict;
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarm.m
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarm.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarm.m	(revision 62)
@@ -0,0 +1,552 @@
+//
+//  PSAlarm.m
+//  Pester
+//
+//  Created by Nicholas Riley on Wed Oct 09 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarm.h"
+#import "PSAlert.h"
+#import "PSAlerts.h"
+#import "PSTimer.h"
+#import "NJRDateFormatter.h"
+#import "NSCalendarDate-NJRExtensions.h"
+#import "NSDictionary-NJRExtensions.h"
+#import "NSString-NJRExtensions.h"
+
+NSString * const PSAlarmTimerSetNotification = @"PSAlarmTimerSetNotification";
+NSString * const PSAlarmTimerExpiredNotification = @"PSAlarmTimerExpiredNotification";
+NSString * const PSAlarmDiedNotification = @"PSAlarmDiedNotification";
+
+// property list keys
+static NSString * const PLAlarmType = @"type"; // NSString
+static NSString * const PLAlarmDate = @"date"; // NSNumber
+static NSString * const PLAlarmInterval = @"interval"; // NSNumber
+static NSString * const PLAlarmSnoozeInterval = @"snooze interval"; // NSNumber
+static NSString * const PLAlarmMessage = @"message"; // NSString
+static NSString * const PLAlarmAlerts = @"alerts"; // NSDictionary
+static NSString * const PLAlarmRepeating = @"repeating"; // NSNumber
+
+static NSString *dateFormat, *shortDateFormat, *timeFormat;
+static NSDictionary *locale;
+
+// XXX need to reset pending alarms after sleep, they "freeze" and never expire.
+
+@implementation PSAlarm
+
+#pragma mark initialize-release
+
++ (void)initialize; // XXX change on locale modification, subscribe to NSNotifications
+{
+    dateFormat = [[NJRDateFormatter localizedDateFormatIncludingWeekday: YES] retain];
+    shortDateFormat = [[NJRDateFormatter localizedShortDateFormatIncludingWeekday: NO] retain];
+    timeFormat = [[NJRDateFormatter localizedTimeFormatIncludingSeconds: YES] retain];
+    locale = [[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] retain];
+}
+
+- (void)dealloc;
+{
+    // NSLog(@"DEALLOC %@", self);
+    alarmType = PSAlarmInvalid;
+    [alarmDate release]; alarmDate = nil;
+    [alarmMessage release]; alarmMessage = nil;
+    [invalidMessage release]; invalidMessage = nil;
+    [timer invalidate]; [timer release]; timer = nil;
+    [alerts release]; alerts = nil;
+    [super dealloc];
+}
+
+#pragma mark private
+
+- (void)_setAlarmDate:(NSCalendarDate *)aDate;
+{
+    if (alarmDate != aDate) {
+        [alarmDate release];
+        alarmDate = nil;
+        alarmDate = [aDate retain];
+    }
+}
+
+- (void)_beInvalid:(NSString *)aMessage;
+{
+    alarmType = PSAlarmInvalid;
+    if (aMessage != invalidMessage) {
+        [invalidMessage release];
+        invalidMessage = nil;
+        [self _setAlarmDate: nil];
+        alarmInterval = 0;
+        invalidMessage = [aMessage retain];
+    }
+}
+
+- (void)_beValidWithType:(PSAlarmType)type;
+{
+    if (alarmType == PSAlarmSet) return; // already valid
+    [invalidMessage release];
+    invalidMessage = nil;
+    alarmType = type;
+    if (type != PSAlarmInterval) [self setRepeating: NO];
+}
+
+- (void)_setDateFromInterval;
+{
+    [self _setAlarmDate: [NSCalendarDate dateWithTimeIntervalSinceNow: alarmInterval]];
+    [self _beValidWithType: PSAlarmInterval];
+}
+
+- (void)_setIntervalFromDate;
+{
+    alarmInterval = [alarmDate timeIntervalSinceNow];
+    if (alarmInterval <= 0) {
+        [self _beInvalid: @"Please specify an alarm time in the future."];
+        return;
+    }
+    [self _beValidWithType: PSAlarmDate];
+}
+
+- (PSAlarmType)_alarmTypeForString:(NSString *)string;
+{
+    if ([string isEqualToString: @"PSAlarmDate"]) return PSAlarmDate;
+    if ([string isEqualToString: @"PSAlarmInterval"]) return PSAlarmInterval;
+    if ([string isEqualToString: @"PSAlarmSet"]) return PSAlarmSet;
+    if ([string isEqualToString: @"PSAlarmInvalid"]) return PSAlarmInvalid;
+    if ([string isEqualToString: @"PSAlarmSnooze"]) return PSAlarmSnooze;
+    if ([string isEqualToString: @"PSAlarmExpired"]) return PSAlarmExpired;
+    NSLog(@"unknown alarm type string: %@", string);
+    return nil;
+}
+
+- (NSString *)_alarmTypeString;
+{
+    switch (alarmType) {
+        case PSAlarmDate: return @"PSAlarmDate";
+        case PSAlarmInterval: return @"PSAlarmInterval";
+        case PSAlarmSet: return @"PSAlarmSet";
+        case PSAlarmInvalid: return @"PSAlarmInvalid";
+        case PSAlarmSnooze: return @"PSAlarmSnooze";
+        case PSAlarmExpired: return @"PSAlarmExpired";
+        default: return [NSString stringWithFormat: @"<unknown: %u>", alarmType];
+    }
+}
+
+- (NSString *)_stringForInterval:(unsigned long long)interval;
+{
+    const unsigned long long minute = 60, hour = minute * 60, day = hour * 24, year = day * 365.26;
+    // +[NSString stringWithFormat:] in 10.1 does not support long longs: work around it by converting to unsigned ints or longs for display
+    if (interval == 0) return nil;
+    if (interval < minute) return [NSString stringWithFormat: @"%us", (unsigned)interval];
+    if (interval < day) return [NSString stringWithFormat: @"%uh %um", (unsigned)(interval / hour), (unsigned)((interval % hour) / minute)];
+    if (interval < 2 * day) return @"One day";
+    if (interval < year) return [NSString stringWithFormat: @"%u days", (unsigned)(interval / day)];
+    if (interval < 2 * year) return @"One year";
+    return [NSString stringWithFormat: @"%lu years", (unsigned long)(interval / year)];
+}
+
+- (void)_timerExpired:(PSTimer *)aTimer;
+{
+    NSLog(@"expired: %@; now %@", [[aTimer fireDate] description], [[NSDate date] description]);
+    alarmType = PSAlarmExpired;
+    [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmTimerExpiredNotification object: self];
+    [timer release]; timer = nil;
+}
+
+#pragma mark alarm setting
+
+- (void)setInterval:(NSTimeInterval)anInterval;
+{
+    alarmInterval = anInterval;
+    if (alarmInterval <= 0) {
+        [self _beInvalid: @"Please specify an alarm interval."]; return;
+    }
+    [self _setDateFromInterval];
+}
+
+- (void)setForDateAtTime:(NSCalendarDate *)dateTime;
+{
+    [self _setAlarmDate: dateTime];
+    [self _setIntervalFromDate];
+}
+
+- (void)setForDate:(NSDate *)date atTime:(NSDate *)time;
+{
+    NSCalendarDate *dateTime;
+    if (time == nil && date == nil) {
+        [self _beInvalid: @"Please specify an alarm date and time."]; return;
+    }
+    if (time == nil) {
+        [self _beInvalid: @"Please specify an alarm time."]; return;
+    }
+    if (date == nil) {
+        [self _beInvalid: @"Please specify an alarm date."]; return;
+    }
+    // XXX if calTime's date is different from the default date, complain
+    dateTime = [NSCalendarDate dateWithDate: date atTime: time];
+    if (dateTime == nil) {
+        [self _beInvalid: @"Please specify a reasonable date and time."];
+    }
+    [self setForDateAtTime: dateTime];
+}
+
+- (void)setRepeating:(BOOL)isRepeating;
+{
+    repeating = isRepeating;
+}
+
+- (void)setSnoozeInterval:(NSTimeInterval)anInterval;
+{
+    snoozeInterval = anInterval;
+    NSAssert(alarmType == PSAlarmExpired, @"CanÕt snooze an alarm that hasnÕt expired");
+    alarmType = PSAlarmSnooze;
+}
+
+- (void)setWakeUp:(BOOL)doWake;
+{
+    [timer setWakeUp: doWake];
+}
+
+#pragma mark accessing
+
+- (NSString *)message;
+{
+    if (alarmMessage == nil || [alarmMessage isEqualToString: @""])
+        return @"Alarm!";
+    return alarmMessage;
+}
+
+- (void)setMessage:(NSString *)aMessage;
+{
+    if (aMessage != alarmMessage) {
+        [alarmMessage release];
+        alarmMessage = nil;
+        alarmMessage = [aMessage retain];
+    }
+}
+
+- (BOOL)isValid;
+{
+    if (alarmType == PSAlarmDate) [self _setIntervalFromDate];
+    if (alarmType == PSAlarmInvalid ||
+        (alarmType == PSAlarmExpired && ![self isRepeating])) return NO;
+    return YES;
+}
+
+- (NSString *)invalidMessage;
+{
+    if (invalidMessage == nil) return @"";
+    return invalidMessage;
+}
+
+- (NSCalendarDate *)date;
+{
+    if (alarmType == PSAlarmInterval) [self _setDateFromInterval];
+    return alarmDate;
+}
+
+- (NSCalendarDate *)time;
+{
+    if (alarmType == PSAlarmInterval) [self _setDateFromInterval];
+    return [[NSCalendarDate alloc] initWithYear: 0
+                                          month: 1
+                                            day: 1
+                                           hour: [alarmDate hourOfDay]
+                                         minute: [alarmDate minuteOfHour]
+                                         second: [alarmDate secondOfMinute]
+                                       timeZone: nil];
+}
+
+- (NSTimeInterval)interval;
+{
+    if (alarmType == PSAlarmDate) [self _setIntervalFromDate];
+    return alarmInterval;
+}
+
+- (NSTimeInterval)snoozeInterval;
+{
+    return snoozeInterval;
+}
+
+- (NSTimeInterval)timeRemaining;
+{
+    NSAssert1(alarmType == PSAlarmSet, @"CanÕt get time remaining on alarm with no timer set: %@", self);
+    return -[[NSDate date] timeIntervalSinceDate: alarmDate];
+}
+
+- (void)setAlerts:(PSAlerts *)theAlerts;
+{
+    [alerts release]; alerts = nil;
+    alerts = [theAlerts retain];
+}
+
+- (PSAlerts *)alerts;
+{
+    if (alerts == nil) alerts = [[PSAlerts alloc] init];
+    return alerts;
+}
+
+- (BOOL)isRepeating;
+{
+    return repeating;
+}
+
+- (NSString *)dateString;
+{
+    return [[self date] descriptionWithCalendarFormat: dateFormat locale: locale];
+}
+
+- (NSString *)shortDateString;
+{
+    return [[self date] descriptionWithCalendarFormat: shortDateFormat locale: locale];
+}
+
+- (NSString *)timeString;
+{
+    return [[self date] descriptionWithCalendarFormat: timeFormat locale: locale];
+}
+
+- (NSString *)dateTimeString;
+{
+    return [NSString stringWithFormat: @"%@ at %@", [self dateString], [self timeString]];
+}
+
+- (NSString *)nextDateTimeString;
+{
+    if (![self isRepeating]) {
+        return nil;
+    } else {
+        NSCalendarDate *date = [[NSCalendarDate alloc] initWithTimeIntervalSinceNow: [self interval]];
+        NSString *nextDateTimeString = [NSString stringWithFormat: @"%@ at %@",
+            [date descriptionWithCalendarFormat: dateFormat locale: locale],
+            [date descriptionWithCalendarFormat: timeFormat locale: locale]];
+        [date release];
+        return nextDateTimeString;
+    }
+}
+
+- (NSString *)intervalString;
+{
+    const unsigned long long mval = 99, minute = 60, hour = minute * 60;
+    unsigned long long interval = [self interval];
+    if (interval == 0) return nil;
+    if (interval == 1) return @"One second";
+    if (interval == minute) return @"One minute";
+    if (interval % minute == 0) return [NSString stringWithFormat: @"%u minutes", (unsigned)(interval / minute)];
+    if (interval <= mval) return [NSString stringWithFormat: @"%u seconds", (unsigned)interval];
+    if (interval == hour) return @"One hour";
+    if (interval % hour == 0) return [NSString stringWithFormat: @"%u hours", (unsigned)(interval / hour)];
+    if (interval <= mval * minute) return [NSString stringWithFormat: @"%u minutes", (unsigned)(interval / minute)];
+    if (interval <= mval * hour) return [NSString stringWithFormat: @"%u hours", (unsigned)(interval / hour)];
+    return [self _stringForInterval: interval];
+}
+
+- (NSString *)timeRemainingString;
+{
+    NSString *timeRemainingString = [self _stringForInterval: llround([self timeRemaining])];
+    
+    if (timeRemainingString == nil) return @"ÇexpiredÈ";
+    return timeRemainingString;
+}
+
+- (NSAttributedString *)prettyDescription;
+{
+    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] init];
+    NSAttributedString *alertList = [alerts prettyList];
+
+    [string appendAttributedString:
+        [[NSString stringWithFormat: @"At alarm time for Ò%@Ó:\n", [self message]] small]];
+    if (alertList != nil) {
+        [string appendAttributedString: alertList];
+    } else {
+        [string appendAttributedString: [@"Do nothing." small]];
+    }
+    if ([self isRepeating]) {
+        [string appendAttributedString:
+            [[NSString stringWithFormat: @"\nAlarm repeats every %@.", [[self intervalString] lowercaseString]] small]];
+    }
+    return [string autorelease];
+}
+
+#pragma mark actions
+
+- (BOOL)setTimer;
+{
+    if (alarmType == PSAlarmExpired) {
+        if ([self isRepeating]) {
+            [self _setDateFromInterval];
+        } else {
+            [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmDiedNotification object: self];
+            return NO;
+        }
+    } else if (alarmType == PSAlarmDate) {
+        if (![self isValid]) return NO;
+    } else if (alarmType == PSAlarmSnooze) {
+        [self _setAlarmDate: [NSCalendarDate dateWithTimeIntervalSinceNow: snoozeInterval]];
+    } else if (alarmType != PSAlarmInterval) {
+        return NO;
+    }
+    timer = [PSTimer scheduledTimerWithTimeInterval: (alarmType == PSAlarmSnooze ? snoozeInterval : alarmInterval) target: self selector: @selector(_timerExpired:) userInfo: nil repeats: NO];
+    if (timer == nil) return NO;
+    [timer retain];
+    alarmType = PSAlarmSet;
+    [alerts prepareForAlarm: self];
+
+    [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmTimerSetNotification object: self];
+    // NSLog(@"set: %@; now %@; remaining %@", [[timer fireDate] description], [[NSDate date] description], [self timeRemainingString]);
+    return YES;
+}
+
+- (void)cancelTimer;
+{
+    [timer invalidate]; [timer release]; timer = nil;
+    [self setRepeating: NO];
+}
+
+#pragma mark comparing
+
+- (NSComparisonResult)compareDate:(PSAlarm *)otherAlarm;
+{
+    return [[self date] compare: [otherAlarm date]];
+}
+
+- (NSComparisonResult)compareMessage:(PSAlarm *)otherAlarm;
+{
+    return [[self message] caseInsensitiveCompare: [otherAlarm message]];
+}
+
+#pragma mark printing
+
+- (NSString *)description;
+{
+    return [NSString stringWithFormat: @"%@: type %@ date %@ interval %.1f%@",
+        [super description], [self _alarmTypeString], alarmDate, alarmInterval,
+        (alarmType == PSAlarmInvalid ?
+         [NSString stringWithFormat: @"\ninvalid message: %@", invalidMessage]
+        : (alarmType == PSAlarmSet ?
+           [NSString stringWithFormat: @"\ntimer: %@", timer] : @""))];
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity: 5];
+    if (![self isValid]) return nil;
+    [dict setObject: [self _alarmTypeString] forKey: PLAlarmType];
+    switch (alarmType) {
+        case PSAlarmDate:
+        case PSAlarmSet:
+            [dict setObject: [NSNumber numberWithDouble: [alarmDate timeIntervalSinceReferenceDate]] forKey: PLAlarmDate];
+            break;
+        case PSAlarmSnooze:
+        case PSAlarmInterval:
+        case PSAlarmExpired:
+            [dict setObject: [NSNumber numberWithDouble: alarmInterval] forKey: PLAlarmInterval];
+            [dict setObject: [NSNumber numberWithBool: repeating] forKey: PLAlarmRepeating];
+            break;
+        default:
+            NSAssert1(NO, @"CanÕt save alarm type %@", [self _alarmTypeString]);
+            break;
+    }
+    if (snoozeInterval != 0)
+        [dict setObject: [NSNumber numberWithDouble: snoozeInterval] forKey: PLAlarmSnoozeInterval];
+    [dict setObject: alarmMessage forKey: PLAlarmMessage];
+    if (alerts != nil) {
+        [dict setObject: [alerts propertyListRepresentation] forKey: PLAlarmAlerts];
+    }
+    return dict;
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    if ( (self = [self init]) != nil) {
+        PSAlerts *alarmAlerts;
+        alarmType = [self _alarmTypeForString: [dict objectForRequiredKey: PLAlarmType]];
+        switch (alarmType) {
+            case PSAlarmDate:
+            case PSAlarmSet:
+               { NSCalendarDate *date = [[NSCalendarDate alloc] initWithTimeIntervalSinceReferenceDate: [[dict objectForRequiredKey: PLAlarmDate] doubleValue]];
+                [self _setAlarmDate: date];
+                [date release];
+               }
+                break;
+            case PSAlarmSnooze: // snooze interval set but not confirmed; ignore
+                alarmType = PSAlarmExpired;
+            case PSAlarmInterval:
+            case PSAlarmExpired:
+                alarmInterval = [[dict objectForRequiredKey: PLAlarmInterval] doubleValue];
+                repeating = [[dict objectForRequiredKey: PLAlarmRepeating] boolValue];
+                break;
+            default:
+                NSAssert1(NO, @"CanÕt load alarm type %@", [self _alarmTypeString]);
+                break;
+        }
+        snoozeInterval = [[dict objectForKey: PLAlarmSnoozeInterval] doubleValue];
+        [self setMessage: [dict objectForRequiredKey: PLAlarmMessage]];
+        alarmAlerts = [[PSAlerts alloc] initWithPropertyList: [dict objectForRequiredKey: PLAlarmAlerts]];
+        [self setAlerts: alarmAlerts];
+        [alarmAlerts release];
+        if (alarmType == PSAlarmSet) {
+            alarmType = PSAlarmDate;
+            [self setTimer];
+        }
+        if (alarmType == PSAlarmExpired) {
+            [self setTimer];
+            if (alarmType == PSAlarmExpired) { // failed to restart
+                [self release];
+                self = nil;
+            }
+        }
+    }
+    return self;
+}
+
+#pragma mark archiving (Pester 1.0)
+
+- (void)encodeWithCoder:(NSCoder *)coder;
+{
+    if (![self isValid]) return;
+    [coder encodeValueOfObjCType: @encode(PSAlarmType) at: &alarmType];
+    switch (alarmType) {
+        case PSAlarmDate:
+        case PSAlarmSet:
+            [coder encodeObject: alarmDate];
+            break;
+        case PSAlarmInterval:
+            [coder encodeValueOfObjCType: @encode(NSTimeInterval) at: &alarmInterval];
+            break;
+        default:
+            break;
+    }
+    [coder encodeObject: alarmMessage];
+    // NSLog(@"encoded: %@", self); // XXX happening twice, gdb refuses to show proper backtrace, grr
+    return;
+}
+
+- (id)initWithCoder:(NSCoder *)coder;
+{
+    if ( (self = [self init]) != nil) {
+        PSAlerts *legacyAlerts = [[PSAlerts alloc] initWithPesterVersion1Alerts];
+        [self setAlerts: legacyAlerts];
+        [legacyAlerts release];
+        [coder decodeValueOfObjCType: @encode(PSAlarmType) at: &alarmType];
+        switch (alarmType) {
+            case PSAlarmDate:
+            case PSAlarmSet:
+                [self _setAlarmDate: [coder decodeObject]];
+                break;
+            case PSAlarmInterval:
+                [coder decodeValueOfObjCType: @encode(NSTimeInterval) at: &alarmInterval];
+                break;
+            default:
+                break;
+        }
+        [self setMessage: [coder decodeObject]];
+        if (alarmType == PSAlarmSet) {
+            alarmType = PSAlarmDate;
+            [self setTimer];
+        }
+    }
+    return self;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarmAlertController.h
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarmAlertController.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarmAlertController.h	(revision 62)
@@ -0,0 +1,26 @@
+//
+//  PSAlarmAlertController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "PSAlarm.h"
+
+extern NSString * const PSAlarmAlertStopNotification;
+
+@interface PSAlarmAlertController : NSObject {
+    NSMutableSet *pendingAlerts;
+    ProcessSerialNumber frontmostApp;
+    BOOL appWasHidden;
+}
+
++ (PSAlarmAlertController *)controllerWithTimerExpiredNotification:(NSNotification *)notification;
+
++ (IBAction)stopAlerts:(id)sender;
+
+- (id)initWithAlarm:(PSAlarm *)alarm;
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarmAlertController.m
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarmAlertController.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarmAlertController.m	(revision 62)
@@ -0,0 +1,85 @@
+//
+//  PSAlarmAlertController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarmAlertController.h"
+#import "PSAlert.h"
+#import "PSAlerts.h"
+
+NSString * const PSAlarmAlertStopNotification = @"PSAlarmAlertStopNotification";
+
+@implementation PSAlarmAlertController
+
++ (PSAlarmAlertController *)controllerWithTimerExpiredNotification:(NSNotification *)notification;
+{
+    return [[[self alloc] initWithAlarm: [notification object]] autorelease];
+}
+
++ (IBAction)stopAlerts:(id)sender;
+{
+    [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmAlertStopNotification object: nil];
+}
+
+- (void)_resumeAlarm:(PSAlarm *)alarm;
+{
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+    [alarm setTimer]; // if snooze not set and not repeating, alarm will die
+    if (frontmostApp.highLongOfPSN != 0 || frontmostApp.lowLongOfPSN != 0) {
+        SetFrontProcess(&frontmostApp);
+        if (appWasHidden)
+            [NSApp hide: self];
+    }
+}
+
+- (void)_alertCompleted:(NSNotification *)notification;
+{
+    PSAlert *alert = [[notification userInfo] objectForKey: @"alert"];
+    unsigned count = [pendingAlerts count];
+    [pendingAlerts removeObject: alert];
+    // NSLog(@"removed: %@; still pending: %@", alert, [pendingAlerts description]);
+    // NSLog(@"alarm: %@ retainCount %d", [notification object], [[notification object] retainCount]);
+    NSAssert2([pendingAlerts count] == count - 1, @"alert not in set: %@\n%@", alert, notification);
+    if ([pendingAlerts count] == 0) {
+        [self _resumeAlarm: [notification object]];
+        [self release];
+    }
+}
+
+- (id)initWithAlarm:(PSAlarm *)alarm;
+{
+    if ( (self = [super init]) != nil) {
+        PSAlerts *alerts = [alarm alerts];
+        NSArray *allAlerts = [alerts allAlerts];
+        if ([allAlerts count] == 0) {
+            [self _resumeAlarm: alarm];
+        } else {
+            pendingAlerts = [[NSMutableSet alloc] init];
+            [pendingAlerts addObjectsFromArray: allAlerts];
+            [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_alertCompleted:)
+                                                         name: PSAlarmAlertCompletedNotification object: alarm];
+            [self retain]; // release in _alertCompleted:
+        }
+        [alerts triggerForAlarm: alarm];
+        if ([alerts requirePesterFrontmost] && ![NSApp isActive]) { // restore frontmost process afterward
+            NSDictionary *activeProcessInfo = [[NSWorkspace sharedWorkspace] activeApplication];
+            frontmostApp.highLongOfPSN = [[activeProcessInfo objectForKey: @"NSApplicationProcessSerialNumberHigh"] longValue];
+            frontmostApp.lowLongOfPSN = [[activeProcessInfo objectForKey: @"NSApplicationProcessSerialNumberLow"] longValue];
+            appWasHidden = [NSApp isHidden];
+            [NSApp activateIgnoringOtherApps: YES];
+        }
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    NSLog(@"%@ dealloc", self);
+    [pendingAlerts release];
+    [super dealloc];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarmNotifierController.h
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarmNotifierController.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarmNotifierController.h	(revision 62)
@@ -0,0 +1,33 @@
+//
+//  PSAlarmNotifierController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+@class NJRIntervalField;
+@class PSAlarm;
+
+@interface PSAlarmNotifierController : NSWindowController {
+    IBOutlet NSTextField *messageField;
+    IBOutlet NSTextField *dateField;
+    IBOutlet NSTextField *intervalField;
+    IBOutlet NSTextField *nextDateField;
+    IBOutlet NJRIntervalField *snoozeIntervalField;
+    IBOutlet NSButton *okButton;
+    IBOutlet NSButton *snoozeButton;
+    NSTimer *updateTimer;
+    PSAlarm *alarm;
+    BOOL canSnooze;
+}
+
+- (id)initWithAlarm:(PSAlarm *)anAlarm;
+
+- (IBAction)close:(id)sender;
+- (IBAction)snooze:(NSButton *)sender;
+- (IBAction)stopRepeating:(NSButton *)sender;
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarmNotifierController.m
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarmNotifierController.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarmNotifierController.m	(revision 62)
@@ -0,0 +1,166 @@
+//
+//  PSAlarmNotifierController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarmNotifierController.h"
+#import "PSAlarmAlertController.h"
+#import "PSAlarm.h"
+#import "PSNotifierAlert.h"
+#import "NJRIntervalField.h"
+
+static NSString * const PSAlarmSnoozeInterval = @"Pester alarm snooze interval"; // NSUserDefaults key
+
+@interface PSAlarmNotifierController (Private)
+
+- (void)update:(id)sender;
+- (void)updateNextDateDisplay:(id)sender;
+
+@end
+
+@implementation PSAlarmNotifierController
+
+// XXX should use NSNonactivatingPanelMask on 10.2
+
+- (id)initWithAlarm:(PSAlarm *)anAlarm;
+{
+    if ([self initWithWindowNibName: @"Notifier"]) {
+        NSWindow *window = [self window];
+        NSRect frameRect = [window frame];
+        alarm = [anAlarm retain];
+        [messageField setStringValue: [alarm message]];
+        [dateField setStringValue: [alarm dateTimeString]];
+        if (![snoozeIntervalField setInterval: [alarm snoozeInterval]] &&
+            ![snoozeIntervalField setInterval: [[[NSUserDefaults standardUserDefaults] objectForKey: PSAlarmSnoozeInterval] doubleValue]])
+            [snoozeIntervalField setInterval: 15 * 60]; // 15 minutes
+        if ([alarm isRepeating]) {
+            [intervalField setStringValue:
+                [NSString stringWithFormat: @"every %@", [[alarm intervalString] lowercaseString]]];
+            [self updateNextDateDisplay: nil];
+            updateTimer = [NSTimer scheduledTimerWithTimeInterval: 1 target: self selector: @selector(updateNextDateDisplay:) userInfo: nil repeats: YES];
+            frameRect.size = [window maxSize];
+        } else {
+            frameRect.size = [window minSize];
+        }
+        [window setFrame: frameRect display: NO];
+        [window center];
+        [window makeKeyAndOrderFront: nil];
+        [window orderFrontRegardless];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [alarm release];
+    [updateTimer invalidate]; updateTimer = nil;
+    [super dealloc];
+}
+
+- (void)updateNextDateDisplay:(id)sender;
+{
+    if (!canSnooze) {
+        NSString *nextDateTimeString = [alarm nextDateTimeString];
+        if (nextDateTimeString == nil) { // no longer repeating
+            [updateTimer invalidate]; updateTimer = nil;
+        } else {
+            [nextDateField setStringValue: nextDateTimeString];
+        }
+    }
+}
+
+- (void)update:(id)sender;
+{
+    canSnooze = [snoozeIntervalField interval] != 0;
+    if (canSnooze) [nextDateField setStringValue: @"after snooze"];
+    [snoozeButton setEnabled: canSnooze];
+    [canSnooze ? snoozeButton : okButton setKeyEquivalent: @"\r"];
+    [canSnooze ? okButton : snoozeButton setKeyEquivalent: @""];
+}
+
+- (IBAction)close:(id)sender;
+{
+    [PSAlarmAlertController stopAlerts: sender];
+    [self close];
+    [[PSNotifierAlert alert] completedForAlarm: alarm];
+}
+
+- (IBAction)snooze:(NSButton *)sender;
+{
+    NSTimeInterval snoozeInterval = [snoozeIntervalField interval];
+    [alarm setSnoozeInterval: snoozeInterval];
+    [[NSUserDefaults standardUserDefaults] setObject: [NSNumber numberWithDouble: snoozeInterval] forKey: PSAlarmSnoozeInterval];
+    [self close: sender];
+}
+
+- (IBAction)stopRepeating:(NSButton *)sender;
+{
+    NSWindow *window = [self window];
+    NSRect frameRect = [window frame];
+    NSSize newSize = [window minSize];
+    
+    [alarm setRepeating: NO];
+    [sender setEnabled: NO];
+    frameRect.origin.y += frameRect.size.height - newSize.height;
+    frameRect.size = newSize;
+    [window setFrame: frameRect display: YES animate: YES];
+}
+
+@end
+
+@implementation PSAlarmNotifierController (NSControlSubclassDelegate)
+
+- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error;
+{
+    if (control == snoozeIntervalField)
+        [snoozeIntervalField handleDidFailToFormatString: string errorDescription: error label: @"snooze interval"];
+    return NO;
+}
+
+- (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error;
+{
+    // NSLog(@"UPDATING FROM validation");
+    [self update: control]; // switch to snooze if someone types something weird...
+}
+
+- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector;
+{
+    // NSLog(@"UPDATING from textView: %@", NSStringFromSelector(commandSelector));
+    if (commandSelector == @selector(cancel:)) {
+        // if someone just wants the stupid thing to go away and presses escape, donÕt hinder them
+        [self close: control];
+        return YES;
+    }
+    // if someone invokes the default button or switches fields, donÕt override it
+    if (commandSelector == @selector(insertNewline:) ||
+        commandSelector == @selector(insertTab:) ||
+        commandSelector == @selector(insertBacktab:)) return NO;
+    [self update: control]; // ...or if they type a navigation key...
+    return NO; // we donÕt handle it
+}
+
+@end
+
+@implementation PSAlarmNotifierController (NSControlSubclassNotifications)
+
+- (void)controlTextDidChange:(NSNotification *)notification;
+{
+    // NSLog(@"UPDATING FROM controlTextDidChange: %@", [notification object]);
+    [self update: [notification object]]; // ...or if they modify the snooze interval
+}
+
+@end
+
+@implementation PSAlarmNotifierController (NSWindowNotifications)
+
+- (void)windowWillClose:(NSNotification *)notification;
+{
+    // canÕt rely on dealloc to invalidate the timer, because it retains this object
+    [updateTimer invalidate]; updateTimer = nil;
+    [self release]; // in non-document-based apps, this is needed; see docs
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarmSetController.h
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarmSetController.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarmSetController.h	(revision 62)
@@ -0,0 +1,63 @@
+//
+//  PSAlarmSetController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "PSAlarm.h"
+
+@class NJRFSObjectSelector;
+@class NJRIntervalField;
+@class NJRQTMediaPopUpButton;
+@class NJRVoicePopUpButton;
+
+@interface PSAlarmSetController : NSWindowController {
+    IBOutlet NSTextField *messageField;
+    IBOutlet NSMatrix *inAtMatrix;
+    IBOutlet NJRIntervalField *timeInterval;
+    IBOutlet NSPopUpButton *timeIntervalUnits;
+    IBOutlet NSButton *timeIntervalRepeats;
+    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 NSButtonCell *editAlert;
+    IBOutlet NSTextField *alertView;
+    IBOutlet NSTabView *alertTabs;
+    IBOutlet NSButtonCell *displayMessage;
+    IBOutlet NSButton *bounceDockIcon;
+    IBOutlet NSButtonCell *playSound;
+    IBOutlet NJRQTMediaPopUpButton *sound;
+    IBOutlet NSTextField *soundRepetitions;
+    IBOutlet NSStepper *soundRepetitionStepper;
+    IBOutlet NSTextField *soundRepetitionsLabel;
+    IBOutlet NSButtonCell *doScript;
+    IBOutlet NJRFSObjectSelector *script;
+    IBOutlet NSButtonCell *doSpeak;
+    IBOutlet NJRVoicePopUpButton *voice;
+    IBOutlet NSButton *scriptSelectButton;
+    IBOutlet NSButtonCell *wakeUp;
+    IBOutlet NSTextField *timeSummary;
+    IBOutlet NSButton *cancelButton;
+    IBOutlet NSButton *setButton;
+    NSString *status;
+    NSTimer *updateTimer;
+    PSAlarm *alarm;
+    BOOL isInterval;
+}
+
+- (IBAction)update:(id)sender;
+- (IBAction)dateCompleted:(NSPopUpButton *)sender;
+- (IBAction)inAtChanged:(id)sender;
+- (IBAction)editAlertChanged:(id)sender;
+- (IBAction)playSoundChanged:(id)sender;
+- (IBAction)doScriptChanged:(id)sender;
+- (IBAction)doSpeakChanged:(id)sender;
+- (IBAction)setAlarm:(NSButton *)sender;
+- (IBAction)setSoundRepetitionCount:(id)sender;
+
+- (IBAction)silence:(id)sender;
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarmSetController.m
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarmSetController.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarmSetController.m	(revision 62)
@@ -0,0 +1,554 @@
+//
+//  PSAlarmSetController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Oct 08 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarmSetController.h"
+#import "PSAlarmAlertController.h"
+#import "PSPowerManager.h"
+#import "NJRDateFormatter.h"
+#import "NJRFSObjectSelector.h"
+#import "NJRIntervalField.h"
+#import "NJRQTMediaPopUpButton.h"
+#import "NJRVoicePopUpButton.h"
+#import "NSString-NJRExtensions.h"
+#import "NSAttributedString-NJRExtensions.h"
+#import "NSCalendarDate-NJRExtensions.h"
+#import <Carbon/Carbon.h>
+
+#import "PSAlerts.h"
+#import "PSDockBounceAlert.h"
+#import "PSScriptAlert.h"
+#import "PSNotifierAlert.h"
+#import "PSBeepAlert.h"
+#import "PSMovieAlert.h"
+#import "PSSpeechAlert.h"
+#import "PSWakeAlert.h"
+
+/* Bugs to file:
+
+¥ any trailing spaces: -> exception for +[NSCalendarDate dateWithNaturalLanguageString]:
+ > NSCalendarDate dateWithNaturalLanguageString: '12 '
+  format error: internal error
+
+¥ NSDate natural language stuff in NSCalendarDate (why?), misspelled category name
+¥ NSCalendarDate natural language stuff behaves differently from NSDateFormatter (AM/PM has no effect, shouldn't they share code?)
+¥ descriptionWithCalendarFormat:, dateWithNaturalLanguageString: does not default to current locale, instead it defaults to US unless you tell it otherwise
+¥ 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
+¥ NSTimeFormatString does not include %p when it should, meaning that AM/PM is stripped yet 12-hour time is still used
+¥ 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?
+¥ "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.
+¥ 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.  But if you use the NSCalendarDate stuff, it appears %p doesn't include the space (because it doesn't use the locale dictionary).
+¥ If you feed NSCalendarDate dateWithNaturalLanguageString: an " AM"/" PM" locale, it doesn't accept that date format.
+¥ descriptions for %X and %x are reversed (time zone is in %X, not %x)
+¥ NSComboBox data source issues, canÕt have it appear as ÒtodayÓ because the formatter doesnÕt like that.  Should be able to enter text into the data source and have the formatter process it without altering it.
+¥ too hard to implement date-only or time-only formatters
+¥ should be able to specify that natural language favors date or time (10 = 10th of month, not 10am)
+¥ please expose the iCal controls!
+
+*/
+
+static NSString * const PSAlertsSelected = @"Pester alerts selected"; // NSUserDefaults key
+static NSString * const PSAlertsEditing = @"Pester alerts editing"; // NSUserDefaults key
+
+@interface PSAlarmSetController (Private)
+
+- (void)_readAlerts:(PSAlerts *)alerts;
+- (BOOL)_setAlerts;
+- (void)_stopUpdateTimer;
+
+@end
+
+@implementation PSAlarmSetController
+
+- (void)awakeFromNib;
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+    alarm = [[PSAlarm alloc] init];
+    [[self window] center];
+    // XXX excessive retention of formatters?  check later...
+    [timeOfDay setFormatter: [[NJRDateFormatter alloc] initWithDateFormat: [NJRDateFormatter localizedTimeFormatIncludingSeconds: NO] allowNaturalLanguage: YES]];
+    [timeDate setFormatter: [[NJRDateFormatter alloc] initWithDateFormat: [NJRDateFormatter localizedDateFormatIncludingWeekday: NO] allowNaturalLanguage: YES]];
+    {
+        NSArray *dayNames = [defaults arrayForKey:
+            NSWeekDayNameArray];
+        NSArray *completions = [timeDateCompletions itemTitles];
+        NSEnumerator *e = [completions objectEnumerator];
+        NSString *title;
+        int itemIndex = 0;
+        NSRange matchingRange;
+        while ( (title = [e nextObject]) != nil) {
+            matchingRange = [title rangeOfString: @"ÇdayÈ"];
+            if (matchingRange.location != NSNotFound) {
+                NSMutableString *format = [title mutableCopy];
+                NSEnumerator *we = [dayNames objectEnumerator];
+                NSString *dayName;
+                [format deleteCharactersInRange: matchingRange];
+                [format insertString: @"%@" atIndex: matchingRange.location];
+                [timeDateCompletions removeItemAtIndex: itemIndex];
+                while ( (dayName = [we nextObject]) != nil) {
+                    [timeDateCompletions insertItemWithTitle: [NSString stringWithFormat: format, dayName] atIndex: itemIndex];
+                    itemIndex++;
+                }
+            } else itemIndex++;
+        }
+    }
+    [editAlert setIntValue: [defaults boolForKey: PSAlertsEditing]];
+    {
+        NSDictionary *plAlerts = [defaults dictionaryForKey: PSAlertsSelected];
+        PSAlerts *alerts;
+        if (plAlerts == nil) {
+            alerts = [[PSAlerts alloc] initWithPesterVersion1Alerts];
+        } else {
+            NS_DURING
+                alerts = [[PSAlerts alloc] initWithPropertyList: plAlerts];
+            NS_HANDLER
+                NSRunAlertPanel(@"Unable to restore alerts", @"Pester could not restore recent alert information for one or more alerts in the Set Alarm window.  The default set of alerts will be used instead.\n\n%@", nil, nil, nil, [localException reason]);
+                alerts = [[PSAlerts alloc] initWithPesterVersion1Alerts];
+            NS_ENDHANDLER
+        }
+        [self _readAlerts: alerts];
+    }
+    [timeDate setObjectValue: [NSDate date]];
+    [self inAtChanged: nil]; // by convention, if sender is nil, we're initializing
+    [self playSoundChanged: nil];
+    [self doScriptChanged: nil];
+    [self doSpeakChanged: nil];
+    [self editAlertChanged: nil];
+    [script setFileTypes: [NSArray arrayWithObjects: @"applescript", @"script", NSFileTypeForHFSTypeCode(kOSAFileType), NSFileTypeForHFSTypeCode('TEXT'), nil]];
+    [notificationCenter addObserver: self selector: @selector(silence:) name: PSAlarmAlertStopNotification object: nil];
+    [notificationCenter addObserver: self selector: @selector(playSoundChanged:) name: NJRQTMediaPopUpButtonMovieChangedNotification object: sound];
+    [notificationCenter addObserver: self selector: @selector(applicationWillHide:) name: NSApplicationWillHideNotification object: NSApp];
+    [notificationCenter addObserver: self selector: @selector(applicationDidUnhide:) name: NSApplicationDidUnhideNotification object: NSApp];
+    [notificationCenter addObserver: self selector: @selector(applicationWillTerminate:) name: NSApplicationWillTerminateNotification object: NSApp];
+    [voice setDelegate: self]; // XXX why don't we do this in IB?  It should use the accessor...
+    [wakeUp setEnabled: [PSPowerManager autoWakeSupported]];
+    // XXX workaround for 10.1.x and 10.2.x bug which sets the first responder to the wrong field alternately, but it works if I set the initial first responder to nil... go figure.
+    [[self window] setInitialFirstResponder: nil];
+    [[self window] makeKeyAndOrderFront: nil];
+}
+
+- (void)setStatus:(NSString *)aString;
+{
+    // NSLog(@"%@", alarm);
+    if (aString != status) {
+        [status release]; status = nil;
+        status = [aString retain];
+        [timeSummary setStringValue: status];
+    }
+}
+
+// XXX with -[NSControl currentEditor] don't need to compare?  Also check -[NSControl validateEditing]
+- (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];
+    }
+}
+
+#pragma mark date/interval setting
+
+- (void)setAlarmDateAndInterval:(id)sender;
+{
+    if (isInterval) {
+        [alarm setInterval: [timeInterval interval]];
+    } else {
+        [alarm setForDate: [self objectValueForTextField: timeDate whileEditing: sender]
+                   atTime: [self objectValueForTextField: timeOfDay whileEditing: sender]];
+    }
+}
+
+- (void)_stopUpdateTimer;
+{
+    [updateTimer invalidate]; [updateTimer release]; updateTimer = nil;
+}
+
+// XXX use OACalendar in popup like Palm Desktop?
+
+- (IBAction)updateDateDisplay:(id)sender;
+{
+    // NSLog(@"updateDateDisplay: %@", sender);
+    if ([alarm isValid]) {
+        [self setStatus: [NSString stringWithFormat: @"Alarm will be set for %@ on %@", [alarm timeString], [alarm dateString]]];
+        [setButton setEnabled: YES];
+        if (updateTimer == nil || ![updateTimer isValid]) {
+            // XXX this logic (and the timer) should really go into PSAlarm, to send notifications for status updates instead.  Timer starts when people are watching, stops when people aren't.
+            // NSLog(@"setting timer");
+            if (isInterval) {
+                updateTimer = [NSTimer scheduledTimerWithTimeInterval: 1 target: self selector: @selector(updateDateDisplay:) userInfo: nil repeats: YES];
+            } else {
+                updateTimer = [NSTimer scheduledTimerWithTimeInterval: [alarm interval] target: self selector: @selector(updateDateDisplay:) userInfo: nil repeats: NO];
+            }
+            [updateTimer retain];
+        }
+    } else {
+        [setButton setEnabled: NO];
+        [self setStatus: [alarm invalidMessage]];
+        [self _stopUpdateTimer];
+    }
+}
+
+// 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.
+// Note: finding out whether a given control is editing is easier.  See: <http://cocoa.mamasam.com/COCOADEV/2002/03/2/28501.php>.
+
+- (IBAction)update:(id)sender;
+{
+    // NSLog(@"update: %@", sender);
+    [self setAlarmDateAndInterval: sender];
+    [self updateDateDisplay: sender];
+}
+
+- (IBAction)inAtChanged:(id)sender;
+{
+    NSButtonCell *new = [inAtMatrix selectedCell], *old;
+    isInterval = ([inAtMatrix selectedTag] == 0);
+    old = [inAtMatrix cellWithTag: isInterval];
+    NSAssert(new != old, @"in and at buttons should be distinct!");
+    [old setKeyEquivalent: [new keyEquivalent]];
+    [old setKeyEquivalentModifierMask: [new keyEquivalentModifierMask]];
+    [new setKeyEquivalent: @""];
+    [new setKeyEquivalentModifierMask: 0];
+    [timeInterval setEnabled: isInterval];
+    [timeIntervalUnits setEnabled: isInterval];
+    [timeIntervalRepeats setEnabled: isInterval];
+    [timeOfDay setEnabled: !isInterval];
+    [timeDate setEnabled: !isInterval];
+    [timeDateCompletions setEnabled: !isInterval];
+    if (sender != nil)
+        [[self window] makeFirstResponder: isInterval ? (NSTextField *)timeInterval : timeOfDay];
+    // NSLog(@"UPDATING FROM inAtChanged");
+    [self update: nil];
+}
+
+- (IBAction)dateCompleted:(NSPopUpButton *)sender;
+{
+    [timeDate setStringValue: [sender titleOfSelectedItem]];
+    [self update: sender];
+}
+
+#pragma mark alert editing
+
+- (IBAction)editAlertChanged:(id)sender;
+{
+    BOOL editAlertSelected = [editAlert intValue];
+    NSView *editAlertControl = [editAlert controlView];
+    NSWindow *window = [self window];
+    NSRect frame = [window frame];
+    if (editAlertSelected) {
+        NSSize editWinSize = [window maxSize];
+        [editAlertControl setNextKeyView: [displayMessage controlView]];
+        frame.origin.y += frame.size.height - editWinSize.height;
+        frame.size = editWinSize;
+        [window setFrame: frame display: (sender != nil) animate: (sender != nil)];
+        [self updateDateDisplay: sender];
+        [alertTabs selectTabViewItemWithIdentifier: @"edit"];
+    } else {
+        NSSize viewWinSize = [window minSize];
+        NSRect textFrame = [alertView frame];
+        float textHeight;
+        if (![self _setAlerts]) {
+            [alertView setStringValue: [NSString stringWithFormat: @"CouldnÕt process alert information.\n%@", status]];
+        } else {
+            NSAttributedString *string = [[alarm alerts] prettyList];
+            if (string == nil) {
+                [alertView setStringValue: @"Do nothing. Click the button labeled ÒEditÓ to add an alert."];
+            } else {
+                [alertView setAttributedStringValue: string];
+                [self updateDateDisplay: sender];
+            }
+        }
+        if (sender != nil) { // nil == we're initializing, don't mess with focus
+            NSResponder *oldResponder = [window firstResponder];
+            // make sure focus doesn't get stuck in the edit tab: it is confusing and leaves behind artifacts
+            if (oldResponder == editAlertControl || [oldResponder isKindOfClass: [NSView class]] && [(NSView *)oldResponder isDescendantOf: alertTabs])
+                [window makeFirstResponder: messageField]; // would use editAlertControl, but can't get it to display anomaly-free.
+            [self silence: sender];
+        }
+        // allow height to expand, though not arbitrarily (should still fit on an 800x600 screen)
+        textHeight = [[alertView cell] cellSizeForBounds: NSMakeRect(0, 0, textFrame.size.width, 400)].height;
+        textFrame.origin.y += textFrame.size.height - textHeight;
+        textFrame.size.height = textHeight;
+        [alertView setFrame: textFrame];
+        viewWinSize.height += textHeight;
+        [alertTabs selectTabViewItemWithIdentifier: @"view"];
+        frame.origin.y += frame.size.height - viewWinSize.height;
+        frame.size = viewWinSize;
+        [window setFrame: frame display: (sender != nil) animate: (sender != nil)];
+        [editAlertControl setNextKeyView: cancelButton];
+    }
+    if (sender != nil) {
+        [[NSUserDefaults standardUserDefaults] setBool: editAlertSelected forKey: PSAlertsEditing];
+    }
+}
+
+
+- (IBAction)playSoundChanged:(id)sender;
+{
+    BOOL playSoundSelected = [playSound intValue];
+    BOOL canRepeat = playSoundSelected ? [sound canRepeat] : NO;
+    [sound setEnabled: playSoundSelected];
+    [soundRepetitions setEnabled: canRepeat];
+    [soundRepetitionStepper setEnabled: canRepeat];
+    [soundRepetitionsLabel setTextColor: canRepeat ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]];
+    if (playSoundSelected && sender == playSound) {
+        [[self window] makeFirstResponder: sound];
+    }
+}
+
+- (IBAction)setSoundRepetitionCount:(id)sender;
+{
+    NSTextView *fieldEditor = (NSTextView *)[soundRepetitions currentEditor];
+    BOOL isEditing = (fieldEditor != nil);
+    int newReps = [sender intValue], oldReps;
+    if (isEditing) {
+        // XXX work around bug where if you ask soundRepetitions for its intValue too often while it's editing, the field begins to flash
+        oldReps = [[[fieldEditor textStorage] string] intValue];
+    } else oldReps = [soundRepetitions intValue];
+    if (newReps != oldReps) {
+        [soundRepetitions setIntValue: newReps];
+        // NSLog(@"updating: new value %d, old value %d%@", newReps, oldReps, isEditing ? @", is editing" : @"");
+        // XXX work around 10.1 bug, otherwise field only displays every second value
+        if (isEditing) [soundRepetitions selectText: self];
+    }
+}
+
+// XXX should check the 'Do script:' button when someone drops a script on the button
+
+- (IBAction)doScriptChanged:(id)sender;
+{
+    BOOL doScriptSelected = [doScript intValue];
+    [script setEnabled: doScriptSelected];
+    [scriptSelectButton setEnabled: doScriptSelected];
+    if (doScriptSelected && sender != nil) {
+        [[self window] makeFirstResponder: scriptSelectButton];
+        if ([script alias] == nil) [scriptSelectButton performClick: sender];
+    }
+}
+
+- (IBAction)doSpeakChanged:(id)sender;
+{
+    BOOL doSpeakSelected = [doSpeak state] == NSOnState;
+    [voice setEnabled: doSpeakSelected];
+    if (doSpeakSelected && sender != nil)
+        [[self window] makeFirstResponder: voice];
+}
+
+- (void)_readAlerts:(PSAlerts *)alerts;
+{
+    NSEnumerator *e = [alerts alertEnumerator];
+    PSAlert *alert;
+    
+    [alarm setAlerts: alerts];
+
+    // turn off all alerts
+    [bounceDockIcon setState: NSOffState];
+    [doScript setIntValue: NO];
+    [displayMessage setIntValue: NO];
+    [playSound setIntValue: NO];
+    [doSpeak setIntValue: NO];
+
+    while ( (alert = [e nextObject]) != nil) {
+        if ([alert isKindOfClass: [PSDockBounceAlert class]]) {
+            [bounceDockIcon setState: NSOnState];
+        } else if ([alert isKindOfClass: [PSScriptAlert class]]) {
+            [doScript setIntValue: YES];
+            [script setAlias: [(PSScriptAlert *)alert scriptFileAlias]];
+        } else if ([alert isKindOfClass: [PSNotifierAlert class]]) {
+            [displayMessage setIntValue: YES];
+        } else if ([alert isKindOfClass: [PSBeepAlert class]]) {
+            unsigned int repetitions = [(PSBeepAlert *)alert repetitions];
+            [playSound setIntValue: YES];
+            [sound setAlias: nil];
+            [soundRepetitions setIntValue: repetitions];
+            [soundRepetitionStepper setIntValue: repetitions];
+        } else if ([alert isKindOfClass: [PSMovieAlert class]]) {
+            unsigned int repetitions = [(PSMovieAlert *)alert repetitions];
+            [playSound setIntValue: YES];
+            [sound setAlias: [(PSMovieAlert *)alert movieFileAlias]];
+            [soundRepetitions setIntValue: repetitions];
+            [soundRepetitionStepper setIntValue: repetitions];
+        } else if ([alert isKindOfClass: [PSSpeechAlert class]]) {
+            [doSpeak setIntValue: YES];
+            [voice setVoice: [(PSSpeechAlert *)alert voice]];
+        } else if ([alert isKindOfClass: [PSWakeAlert class]]) {
+            [wakeUp setIntValue: YES];
+        }
+}
+}
+
+- (BOOL)_setAlerts;
+{
+    PSAlerts *alerts = [alarm alerts];
+    
+    [alerts removeAlerts];
+    NS_DURING
+        // dock bounce alert
+        if ([bounceDockIcon state] == NSOnState)
+            [alerts addAlert: [PSDockBounceAlert alert]];
+        // script alert
+        if ([doScript intValue]) {
+            BDAlias *scriptFileAlias = [script alias];
+            if (scriptFileAlias == nil) {
+                [self setStatus: @"Unable to set script alert (no script specified?)"];
+                return NO;
+            }
+            [alerts addAlert: [PSScriptAlert alertWithScriptFileAlias: scriptFileAlias]];
+        }
+        // notifier alert
+        if ([displayMessage intValue])
+            [alerts addAlert: [PSNotifierAlert alert]];
+        // sound alerts
+        if ([playSound intValue]) {
+            BDAlias *soundAlias = [sound selectedAlias];
+            unsigned short numReps = [soundRepetitions intValue];
+            if (soundAlias == nil) // beep alert
+                [alerts addAlert: [PSBeepAlert alertWithRepetitions: numReps]];
+            else // movie alert
+                [alerts addAlert: [PSMovieAlert alertWithMovieFileAlias: soundAlias repetitions: numReps]];
+        }
+        // speech alert
+        if ([doSpeak intValue])
+            [alerts addAlert: [PSSpeechAlert alertWithVoice: [voice titleOfSelectedItem]]];
+        // wake alert
+        if ([wakeUp intValue])
+            [alerts addAlert: [PSWakeAlert alert]];
+        [[NSUserDefaults standardUserDefaults] setObject: [alerts propertyListRepresentation] forKey: PSAlertsSelected];
+    NS_HANDLER
+        [self setStatus: [localException reason]];
+        NS_VALUERETURN(NO, BOOL);
+    NS_ENDHANDLER
+    return YES;
+}
+
+#pragma mark actions
+
+// 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]) {
+        NSDate *today = [NSCalendarDate dateForDay: [NSDate date]];
+        if ([(NSDate *)[timeDate objectValue] compare: today] == NSOrderedAscending) {
+            [timeDate setObjectValue: today];
+        }
+        [self update: self];
+        // XXX bug workaround - otherwise, first responder appears to alternate every time the window is shown.  And if you set the initial first responder, you can't tab in the window. :(
+        [[self window] makeFirstResponder: [[self window] initialFirstResponder]];
+    }
+    [super showWindow: sender];
+}
+
+- (IBAction)setAlarm:(NSButton *)sender;
+{
+    // set alerts before setting alarm...
+    if (![self _setAlerts]) return;
+
+    // set alarm
+    [self setAlarmDateAndInterval: sender];
+    [alarm setRepeating: [timeIntervalRepeats state] == NSOnState];
+    [alarm setMessage: [messageField stringValue]];
+    if (![alarm setTimer]) {
+        [self setStatus: [@"Unable to set alarm.  " stringByAppendingString: [alarm invalidMessage]]];
+        return;
+    }
+    
+    [self setStatus: [[alarm date] descriptionWithCalendarFormat: @"Alarm set for %x at %X" timeZone: nil locale: nil]];
+    [[self window] close];
+    [alarm release];
+    alarm = [[PSAlarm alloc] init];
+}
+
+- (IBAction)silence:(id)sender;
+{
+    [sound stopSoundPreview: self];
+    [voice stopVoicePreview: self];
+}
+
+@end
+
+@implementation PSAlarmSetController (NSControlSubclassDelegate)
+
+- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error;
+{
+    if (control == timeInterval)
+        [timeInterval handleDidFailToFormatString: string errorDescription: error label: @"alarm interval"];
+    return NO;
+}
+
+- (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error;
+{
+    // NSLog(@"UPDATING FROM validation");
+    if (control == timeInterval) [self update: timeInterval]; // make sure we still examine the field editor, otherwise if the existing numeric string is invalid, it'll be cleared
+}
+
+@end
+
+@implementation PSAlarmSetController (NSWindowNotifications)
+
+- (void)windowWillClose:(NSNotification *)notification;
+{
+    // NSLog(@"stopping update timer");
+    [self silence: nil];
+    [self _stopUpdateTimer];
+    [self _setAlerts];
+}
+
+@end
+
+@implementation PSAlarmSetController (NSControlSubclassNotifications)
+
+// called because we're the delegate
+
+- (void)controlTextDidChange:(NSNotification *)notification;
+{
+    // NSLog(@"UPDATING FROM controlTextDidChange: %@", [notification object]);
+    [self update: [notification object]];
+}
+
+@end
+
+@implementation PSAlarmSetController (NJRVoicePopUpButtonDelegate)
+
+- (NSString *)voicePopUpButton:(NJRVoicePopUpButton *)sender previewStringForVoice:(NSString *)voice;
+{
+    NSString *message = [messageField stringValue];
+    if (message == nil || [message length] == 0)
+        message = [alarm message];
+    return message;
+}
+
+@end
+
+@implementation PSAlarmSetController (NSApplicationNotifications)
+
+- (void)applicationWillTerminate:(NSNotification *)notification;
+{
+    [self _setAlerts];
+}
+
+- (void)applicationWillHide:(NSNotification *)notification;
+{
+    if ([[self window] isVisible]) {
+        [self silence: nil];
+        [self _stopUpdateTimer];
+    }
+}
+
+- (void)applicationDidUnhide:(NSNotification *)notification;
+{
+    if ([[self window] isVisible]) {
+        [self update: self];
+    }
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarms.h
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarms.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarms.h	(revision 62)
@@ -0,0 +1,41 @@
+//
+//  PSAlarms.h
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Oct 11 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "PSPropertyListSerialization.h"
+
+extern NSString * const PSAlarmsDidChangeNotification;
+extern NSString * const PSAlarmsNextAlarmDidChangeNotification;
+
+@class PSAlarm;
+
+@interface PSAlarms : NSObject <PSPropertyListSerialization> {
+    NSMutableArray *alarms;
+    NSMutableSet *expiredAlarms;
+    PSAlarm *nextAlarm;
+}
+
++ (void)setUp;
++ (PSAlarms *)allAlarms;
+
+- (unsigned)countOfVersion1Alarms;
+- (void)importVersion1Alarms;
+- (void)discardVersion1Alarms;
+
+- (NSArray *)alarms;
+
+- (PSAlarm *)nextAlarm;
+- (int)alarmCount;
+- (PSAlarm *)alarmAtIndex:(int)index;
+- (void)removeAlarmAtIndex:(int)index;
+- (void)removeAlarmsAtIndices:(NSArray *)indices;
+- (void)removeAlarms:(NSSet *)alarmsToRemove;
+
+- (BOOL)alarmsExpiring;
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarms.m
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarms.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarms.m	(revision 62)
@@ -0,0 +1,309 @@
+//
+//  PSAlarms.m
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Oct 11 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarms.h"
+#import "PSAlarm.h"
+#import "PSTimer.h"
+#import "NSDictionary-NJRExtensions.h"
+
+NSString * const PSAlarmImportException = @"PSAlarmImportException";
+
+NSString * const PSAlarmsDidChangeNotification = @"PSAlarmsDidChangeNotification";
+NSString * const PSAlarmsNextAlarmDidChangeNotification = @"PSAlarmsNextAlarmDidChangeNotification";
+
+// NSUserDefaults key
+static NSString * const PSPendingAlarms = @"Pester pending alarms"; // 1.0 Ð 1.1a3
+static NSString * const PSAllAlarms = @"Pester alarms"; // 1.1a4 Ð 
+
+// property list keys
+static NSString * const PLAlarmsPending = @"pending";
+static NSString * const PLAlarmsExpired = @"expired";
+
+static PSAlarms *PSAlarmsAllAlarms = nil;
+
+@interface PSAlarms (Private)
+
+- (void)_updateNextAlarm;
+
+@end
+
+@implementation PSAlarms
+
++ (void)setUp;
+{
+    if (PSAlarmsAllAlarms == nil) {
+        NSDictionary *plAlarms = [[NSUserDefaults standardUserDefaults] objectForKey: PSAllAlarms];
+        if (plAlarms == nil) {
+            PSAlarmsAllAlarms = [[self alloc] init];
+        } else {
+            PSAlarmsAllAlarms = [[self alloc] initWithPropertyList: plAlarms];
+        }
+        [PSAlarmsAllAlarms _updateNextAlarm]; // only generate notifications after singleton established
+        [PSTimer setUp];
+    }
+}
+
++ (PSAlarms *)allAlarms;
+{
+    NSAssert(PSAlarmsAllAlarms != nil, @"Attempt to use +[PSAlarms allAlarms] before setup complete");
+    return PSAlarmsAllAlarms;
+}
+
+#pragma mark private
+
+- (void)_changed;
+{
+    NSMutableArray *alarmsData = [[NSMutableArray alloc] init];
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [self _updateNextAlarm];
+    // NSLog(@"PSAlarms _changed:\n%@", alarms);
+    [defaults setObject: [self propertyListRepresentation] forKey: PSAllAlarms];
+    [defaults synchronize];
+    [alarmsData release];
+    [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmsDidChangeNotification object: self];
+}
+
+- (void)_alarmTimerExpired:(NSNotification *)notification;
+{
+    PSAlarm *alarm = [notification object];
+    // NSLog(@"timer expired: %@ retainCount %d", alarm, [alarm retainCount]);
+    [expiredAlarms addObject: alarm];
+    // NSLog(@"expired alarms: %@", [expiredAlarms description]);
+    [alarms removeObject: alarm];
+    [self _changed];
+}
+
+- (void)_alarmTimerSet:(NSNotification *)notification;
+{
+    PSAlarm *alarm = [notification object];
+    // NSLog(@"timer set: %@ retainCount %d", alarm, [alarm retainCount]);
+    [alarms addObject: alarm];
+    [expiredAlarms removeObject: alarm];
+    [self _changed];
+}
+
+- (void)_alarmDied:(NSNotification *)notification;
+{
+    PSAlarm *alarm = [notification object];
+    // NSLog(@"alarm died: %@ retainCount %d", alarm, [alarm retainCount]);
+    [alarms removeObject: alarm];
+    [expiredAlarms removeObject: alarm];
+    [self _changed];
+}
+
+- (void)_updateNextAlarm;
+{
+    NSEnumerator *e;
+    PSAlarm *alarm, *oldNextAlarm = nextAlarm;
+    [nextAlarm release];
+    nextAlarm = nil;
+    // sort alarms so earliest is first
+    [alarms sortUsingSelector: @selector(compareDate:)];
+    // find first un-expired alarm
+    e = [alarms objectEnumerator];
+    while ( (alarm = [e nextObject]) != nil) {
+        if ([alarm isValid]) {
+            nextAlarm = [alarm retain];
+            break;
+        }
+    }
+    if (oldNextAlarm != nextAlarm)
+        [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmsNextAlarmDidChangeNotification object: nextAlarm];
+}
+
+- (void)_setUpNotifications;
+{
+    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_alarmTimerSet:) name: PSAlarmTimerSetNotification object: nil];
+    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_alarmTimerExpired:) name: PSAlarmTimerExpiredNotification object: nil];
+    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_alarmDied:) name: PSAlarmDiedNotification object: nil];
+}
+
+#pragma mark initialize-release
+
+- (id)init;
+{
+    if ( (self = [super init]) != nil) {
+        alarms = [[NSMutableArray alloc] init];
+        expiredAlarms = [[NSMutableSet alloc] init];
+        [self _setUpNotifications];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [alarms release];
+    [expiredAlarms release];
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+    [super dealloc];
+}
+
+#pragma mark accessing
+
+- (NSArray *)alarms;
+{
+    return alarms;
+}
+
+- (PSAlarm *)nextAlarm;
+{
+    return nextAlarm;
+}
+
+- (int)alarmCount;
+{
+    return [alarms count];
+}
+
+- (PSAlarm *)alarmAtIndex:(int)index;
+{
+    return [alarms objectAtIndex: index];
+}
+
+- (void)removeAlarmAtIndex:(int)index;
+{
+    [(PSAlarm *)[alarms objectAtIndex: index] cancelTimer];
+    [alarms removeObjectAtIndex: index];
+}
+
+- (void)removeAlarmsAtIndices:(NSArray *)indices;
+{
+    NSEnumerator *e = [indices objectEnumerator];
+    NSNumber *n;
+    int indexCount = [indices count], i = 0, alarmIndex;
+    int *indexArray = (int *)malloc(indexCount * sizeof(int));
+    NS_DURING
+        while ( (n = [e nextObject]) != nil) {
+            alarmIndex = [n intValue];
+            [(PSAlarm *)[alarms objectAtIndex: alarmIndex] cancelTimer];
+            indexArray[i] = alarmIndex;
+            i++;
+        }
+        [alarms removeObjectsFromIndices: indexArray numIndices: indexCount];
+        free(indexArray); indexArray = NULL;
+        [self _changed];
+    NS_HANDLER
+        free(indexArray);
+        [self _changed];
+        [localException raise];
+    NS_ENDHANDLER
+}
+
+- (void)removeAlarms:(NSSet *)alarmsToRemove;
+{
+    NSEnumerator *e = [alarms objectEnumerator];
+    PSAlarm *alarm;
+    NSMutableArray *indices = [NSMutableArray arrayWithCapacity: [alarmsToRemove count]];
+    int alarmIndex = 0;
+
+    while ( (alarm = [e nextObject]) != nil) {
+        if ([alarmsToRemove containsObject: alarm])
+            [indices addObject: [NSNumber numberWithInt: alarmIndex]];
+        alarmIndex++;
+    }
+    [self removeAlarmsAtIndices: indices];
+}
+
+- (BOOL)alarmsExpiring;
+{
+    return [expiredAlarms count] != 0;
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    NSMutableArray *plPendingAlarms = [[NSMutableArray alloc] initWithCapacity: [alarms count]];
+    NSMutableArray *plExpiredAlarms = [[NSMutableArray alloc] initWithCapacity: [expiredAlarms count]];
+    NSDictionary *plAllAlarms, *plAlarm;
+    NSEnumerator *e;
+    PSAlarm *alarm;
+
+    e = [alarms objectEnumerator];
+    while ( (alarm = [e nextObject]) != nil) {
+        plAlarm = [alarm propertyListRepresentation];
+        if (plAlarm != nil)
+            [plPendingAlarms addObject: plAlarm];
+    }
+
+    e = [expiredAlarms objectEnumerator];
+    while ( (alarm = [e nextObject]) != nil) {
+        plAlarm = [alarm propertyListRepresentation];
+        if (plAlarm != nil)
+            [plExpiredAlarms addObject: plAlarm];
+    }
+    
+    plAllAlarms = [NSDictionary dictionaryWithObjectsAndKeys:
+        plPendingAlarms, PLAlarmsPending, plExpiredAlarms, PLAlarmsExpired, nil];
+    [plPendingAlarms release];
+    [plExpiredAlarms release];
+    
+    return plAllAlarms;
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    if ( (self = [super init]) != nil) {
+        NSArray *plPendingAlarms = [dict objectForRequiredKey: PLAlarmsPending];
+        NSArray *plExpiredAlarms = [dict objectForRequiredKey: PLAlarmsExpired];
+        NSEnumerator *e;
+        NSDictionary *plAlarm;
+        PSAlarm *alarm;
+
+        alarms = [[NSMutableArray alloc] initWithCapacity: [plPendingAlarms count]];
+        e = [plPendingAlarms objectEnumerator];
+        while ( (plAlarm = [e nextObject]) != nil) {
+            [alarms addObject: [[PSAlarm alloc] initWithPropertyList: plAlarm]];
+        }
+
+        e = [plExpiredAlarms objectEnumerator];
+        while ( (plAlarm = [e nextObject]) != nil) {
+            // expired alarms may be just that, or they may have outstanding repeats - if the latter, PSAlarm will reschedule the alarm.
+            if ( (alarm = [[PSAlarm alloc] initWithPropertyList: plAlarm]) != nil)
+                [alarms addObject: alarm];
+        }
+        expiredAlarms = [[NSMutableSet alloc] init];
+        
+        [self _setUpNotifications];
+    }
+    return self;
+}
+
+#pragma mark archiving (Pester 1.0)
+
+- (unsigned)countOfVersion1Alarms;
+{
+    return [[[NSUserDefaults standardUserDefaults] objectForKey: PSPendingAlarms] count];
+}
+
+- (void)discardVersion1Alarms;
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [defaults removeObjectForKey: PSPendingAlarms];
+    [defaults synchronize];
+}
+
+- (void)importVersion1Alarms;
+{
+    NSArray *alarmsData = [[NSUserDefaults standardUserDefaults] arrayForKey: PSPendingAlarms];
+    NSEnumerator *e = [alarmsData objectEnumerator];
+    NSData *alarmData;
+    PSAlarm *alarm;
+    while ( (alarmData = [e nextObject]) != nil) {
+        NS_DURING
+            alarm = [NSUnarchiver unarchiveObjectWithData: alarmData];
+        NS_HANDLER
+            alarm = nil;
+            // XXX
+        NS_ENDHANDLER
+        if (alarm != nil)
+            [alarms addObject: alarm];
+    }
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarmsController.h
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarmsController.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarmsController.h	(revision 62)
@@ -0,0 +1,21 @@
+//
+//  PSAlarmsController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Oct 11 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "PSAlarms.h"
+
+@interface PSAlarmsController : NSWindowController {
+    IBOutlet NSTableView *tableView;
+    IBOutlet NSButton *removeButton;
+    PSAlarms *alarms;
+    NSArray *reorderedAlarms;
+}
+
+- (IBAction)remove:(id)sender;
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlarmsController.m
===================================================================
--- releases/Pester/1.1b1/Source/PSAlarmsController.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlarmsController.m	(revision 62)
@@ -0,0 +1,143 @@
+//
+//  PSAlarmsController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Oct 11 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarmsController.h"
+#import "PSAlarm.h"
+#import "PSAlerts.h"
+#import "NSTableView-NJRExtensions.h"
+#import "NJRTableView.h"
+#import "NJRTableDelegate.h"
+
+@implementation PSAlarmsController
+
+- (void)alarmsChanged;
+{
+    reorderedAlarms = [[tableView delegate] reorderedDataForData: [alarms alarms]];
+}
+
+- (id)init;
+{
+    if ( (self = [super initWithWindowNibName: @"Alarms"]) != nil) {
+        alarms = [PSAlarms allAlarms];
+        // XXX workaround for bug in 10.2.1, 10.1.5: autosave name set in IB doesn't show up
+        [self setWindowFrameAutosaveName: @"Pester alarm list"];
+        // Apple documents the NSUserDefaults key, so we can rely on it hopefully.
+        if (nil == [[NSUserDefaults standardUserDefaults] objectForKey:
+            [@"NSWindow Frame " stringByAppendingString: [[self window] frameAutosaveName]]])
+           {
+            [[self window] center];
+           }
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(alarmsChanged) name: PSAlarmsDidChangeNotification object: alarms];
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(tableViewSelectionDidChange:) name: NSTableViewSelectionDidChangeNotification object: tableView];
+        [tableView setAutosaveName: @"Alarm list"];
+        [tableView setAutosaveTableColumns: YES];
+        [self alarmsChanged];
+        [[self window] makeFirstResponder: tableView];
+        [[self window] setResizeIncrements: NSMakeSize(1, [tableView cellHeight])];
+    }
+    return self;
+}
+
+
+- (IBAction)remove:(id)sender;
+{
+    [alarms removeAlarms: [[tableView delegate] selectedItems]];
+}
+
+@end
+
+@implementation PSAlarmsController (NSTableDataSource)
+
+- (int)numberOfRowsInTableView:(NSTableView *)tableView;
+{
+    return [alarms alarmCount];
+}
+
+- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row;
+{
+    PSAlarm *alarm = [reorderedAlarms objectAtIndex: row];
+
+    if ([[tableColumn identifier] isEqualToString: @"message"]) return [alarm message];
+    else {
+        NSCalendarDate *date = [alarm date];
+        if ([[tableColumn identifier] isEqualToString: @"date"]) return [alarm shortDateString];
+        if ([[tableColumn identifier] isEqualToString: @"time"]) {
+            if (date == nil) return @"ÇexpiredÈ";
+            return [alarm timeString];
+        }
+    }
+    return nil;
+}
+@end
+
+@implementation PSAlarmsController (NJRTableViewDataSource)
+
+- (void)removeSelectedRowsFromTableView:(NSTableView *)aTableView;
+{
+    [self remove: aTableView];
+}
+
+- (NSString *)tableView:(NSTableView *)aTableView toolTipForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex;
+{
+    PSAlarm *alarm = [reorderedAlarms objectAtIndex: rowIndex];
+
+    return [[alarm prettyDescription] string];
+}
+
+@end
+
+@implementation PSAlarmsController (NSTableViewNotifications)
+
+- (void)tableViewSelectionDidChange:(NSNotification *)aNotification;
+{
+    [removeButton setEnabled: ([tableView numberOfSelectedRows] != 0)];
+}
+
+@end
+
+@implementation PSAlarmsController (NSWindowDelegate)
+
+// XXX workaround for bug in 10.1.5, 10.2.1 (and earlier?): no autosave on window move
+- (void)windowDidMove:(NSNotification *)aNotification
+{
+    NSString *autosaveName = [[self window] frameAutosaveName];
+    // on initial display, we get a notification inside -[NSWindow setFrameAutosaveName]!
+    if (autosaveName != nil) {
+        [[self window] saveFrameUsingName: autosaveName];
+    }
+}
+
+- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)defaultFrame;
+{
+    NSWindow *window = [tableView window];
+    NSRect frame = [window frame];
+    NSScrollView *scrollView = [tableView enclosingScrollView];
+    float displayedHeight = [[scrollView contentView] bounds].size.height;
+    float heightChange = [[scrollView documentView] bounds].size.height - displayedHeight;
+    float heightExcess;
+
+    if (heightChange >= 0 && heightChange <= 1) {
+        // either the window is already optimal size, or it's too big
+        float rowHeight = [tableView cellHeight];
+        heightChange = (rowHeight * [tableView numberOfRows]) - displayedHeight;
+    }
+
+    frame.size.height += heightChange;
+
+    if ( (heightExcess = [window minSize].height - frame.size.height) > 1 ||
+         (heightExcess = [window maxSize].height - frame.size.height) < 1) {
+        heightChange += heightExcess;
+        frame.size.height += heightExcess;
+    }
+
+    frame.origin.y -= heightChange;
+
+    return frame;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlert.h
===================================================================
--- releases/Pester/1.1b1/Source/PSAlert.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlert.h	(revision 62)
@@ -0,0 +1,33 @@
+//
+//  PSAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "PSAlarm.h"
+#import "PSPropertyListSerialization.h"
+#import "NSString-NJRExtensions.h"
+
+extern NSString * const PSAlertCreationException;
+
+extern NSString * const PSAlarmAlertCompletedNotification; // userInfo key: "alert" -> PSAlert
+
+@interface PSAlert : NSObject <PSPropertyListSerialization> {
+    
+}
+
+// subclasses should implement these methods
++ (PSAlert *)alert;
+- (void)prepareForAlarm:(PSAlarm *)alarm;
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+- (BOOL)requiresPesterFrontmost;
+
+- (NSAttributedString *)actionDescription;
+
+// after alert completes, invoke method of superclass
+- (void)completedForAlarm:(PSAlarm *)alarm;
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlert.m
===================================================================
--- releases/Pester/1.1b1/Source/PSAlert.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlert.m	(revision 62)
@@ -0,0 +1,78 @@
+//
+//  PSAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlert.h"
+#import "NSDictionary-NJRExtensions.h"
+
+NSString * const PSAlertCreationException = @"PSAlertCreationException";
+
+NSString * const PSAlarmAlertCompletedNotification = @"PSAlarmAlertCompletedNotification";
+
+// property list keys
+static NSString * const PLAlertClass = @"class"; // NSString
+
+@implementation PSAlert
+
++ (PSAlert *)alert;
+{
+    NSAssert(NO, @"Class is abstract");
+    return nil;
+}
+
+- (void)prepareForAlarm:(PSAlarm *)alarm;
+{
+    return;
+}
+
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+{
+    NSAssert(NO, @"Class is abstract");
+}
+
+- (BOOL)requiresPesterFrontmost;
+{
+    return NO;
+}
+
+- (void)completedForAlarm:(PSAlarm *)alarm;
+{
+    [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmAlertCompletedNotification object: alarm userInfo: [NSDictionary dictionaryWithObject: self forKey: @"alert"]];
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    NSAssert(NO, @"Class is abstract");
+    return nil;
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    return [NSDictionary dictionaryWithObject: NSStringFromClass([self class]) forKey: PLAlertClass];
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    if ( (self = [self init]) != nil) {
+        IMP myImp = [self methodForSelector: _cmd];
+        NSString *clsString = [dict objectForRequiredKey: PLAlertClass];
+        Class cls = NSClassFromString(clsString);
+        NSAssert1(cls != nil, @"Alert class %@ is not available", clsString);
+        [super release];
+        self = [cls alloc];
+        if (self != nil) {
+            IMP subImp = [self methodForSelector: @selector(initWithPropertyList:)];
+            NSAssert1(subImp != myImp, @"No implementation of initWithPropertyList: for alert class %@", clsString);
+            self = [self initWithPropertyList: dict];
+        }
+    }
+    return self;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlerts.h
===================================================================
--- releases/Pester/1.1b1/Source/PSAlerts.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlerts.h	(revision 62)
@@ -0,0 +1,35 @@
+//
+//  PSAlerts.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Dec 21 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "PSPropertyListSerialization.h"
+
+@class PSAlert, PSAlarm;
+
+@interface PSAlerts : NSObject <PSPropertyListSerialization>
+{
+    NSMutableArray *alerts;
+    BOOL requirePesterFrontmost;
+}
+
+- (id)init;
+- (id)initWithPesterVersion1Alerts;
+
+- (void)addAlert:(PSAlert *)alert;
+- (void)removeAlerts;
+
+- (NSArray *)allAlerts;
+- (NSEnumerator *)alertEnumerator;
+- (BOOL)requirePesterFrontmost; // do any alerts require Pester be in front?
+
+- (void)prepareForAlarm:(PSAlarm *)alarm;
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+
+- (NSAttributedString *)prettyList;
+
+@end
Index: releases/Pester/1.1b1/Source/PSAlerts.m
===================================================================
--- releases/Pester/1.1b1/Source/PSAlerts.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSAlerts.m	(revision 62)
@@ -0,0 +1,139 @@
+//
+//  PSAlerts.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Dec 21 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlerts.h"
+#import "PSAlert.h"
+#import "PSDockBounceAlert.h"
+#import "PSNotifierAlert.h"
+#import "PSBeepAlert.h"
+
+// property list keys
+static NSString * const PLAlerts = @"alerts"; // NSString
+
+@implementation PSAlerts
+
+#pragma mark initialize-release
+
+- (id)init;
+{
+    if ( (self = [super init]) != nil) {
+        alerts = [[NSMutableArray alloc] initWithCapacity: 4];
+    }
+    return self;
+}
+
+- (id)initWithPesterVersion1Alerts;
+{
+    if ( (self = [self init]) != nil) {
+        [self addAlert: [PSDockBounceAlert alert]];
+        [self addAlert: [PSNotifierAlert alert]];
+        [self addAlert: [PSBeepAlert alertWithRepetitions: 1]];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [alerts release]; alerts = nil;
+}
+
+#pragma mark accessing
+
+- (void)addAlert:(PSAlert *)alert;
+{
+    [alerts addObject: alert];
+    if ([alert requiresPesterFrontmost])
+        requirePesterFrontmost = YES;
+}
+
+- (void)removeAlerts;
+{
+    [alerts removeAllObjects];
+    requirePesterFrontmost = NO;
+}
+
+- (NSEnumerator *)alertEnumerator;
+{
+    return [alerts objectEnumerator];
+}
+
+- (NSArray *)allAlerts;
+{
+    return [[alerts copy] autorelease];
+}
+
+- (BOOL)requirePesterFrontmost;
+{
+    return requirePesterFrontmost;
+}
+
+#pragma mark actions
+
+- (void)prepareForAlarm:(PSAlarm *)alarm;
+{
+    [alerts makeObjectsPerformSelector: @selector(prepareForAlarm:) withObject: alarm];
+}
+
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+{
+    [alerts makeObjectsPerformSelector: @selector(triggerForAlarm:) withObject: alarm];
+}
+
+#pragma mark printing
+
+- (NSAttributedString *)prettyList;
+{
+    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] init];
+    NSEnumerator *e = [self alertEnumerator];
+    PSAlert *alert;
+    unsigned int length;
+    while ( (alert = [e nextObject]) != nil) {
+        [string appendAttributedString: [@"¥ " small]];
+        [string appendAttributedString: [alert actionDescription]];
+        [string appendAttributedString: [@"\n" small]];
+    }
+    if ( (length = [string length]) == 0) {
+        [string release];
+        return nil;
+    } else {
+        NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
+        [string deleteCharactersInRange: NSMakeRange(length - 1, 1)]; // remove trailing newline
+        [paraStyle setHeadIndent: [[string attribute: NSFontAttributeName atIndex: 0 effectiveRange: NULL] widthOfString: @"¥ "]];
+        [string addAttribute: NSParagraphStyleAttributeName value: paraStyle range: NSMakeRange(0, length - 1)];
+        [paraStyle release]; paraStyle = nil;
+        return [string autorelease];
+    }
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    NSMutableArray *plAlerts = [[NSMutableArray alloc] initWithCapacity: [alerts count]];
+    NSEnumerator *e = [self alertEnumerator];
+    PSAlert *alert;
+    while ( (alert = [e nextObject]) != nil) {
+        [plAlerts addObject: [alert propertyListRepresentation]];
+    }
+    return [NSDictionary dictionaryWithObject: plAlerts forKey: PLAlerts];
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    if ( (self = [self init]) != nil) {
+        NSArray *plAlerts = [dict objectForKey: PLAlerts];
+        NSEnumerator *e = [plAlerts objectEnumerator];
+        NSDictionary *alertDict;
+        while ( (alertDict = [e nextObject]) != nil) {
+            [self addAlert: [[PSAlert alloc] initWithPropertyList: alertDict]];
+        }
+    }
+    return self;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSApplication.h
===================================================================
--- releases/Pester/1.1b1/Source/PSApplication.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSApplication.h	(revision 62)
@@ -0,0 +1,27 @@
+//
+//  PSApplication.h
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Oct 11 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+@class PSAlarmsController;
+@class PSAlarmSetController;
+@class PSTimer;
+
+@interface PSApplication : NSApplication {
+    PSAlarmsController *alarmsController;
+    IBOutlet PSAlarmSetController *alarmSetController;
+    PSTimer *dockUpdateTimer;
+    NSTimeInterval dockUpdateInterval;
+    NSImage *appIconImage;
+}
+
+- (IBAction)orderFrontSetAlarmPanel:(id)sender;
+- (IBAction)orderFrontAlarmsPanel:(id)sender;
+- (IBAction)stopAlerts:(id)sender;
+
+@end
Index: releases/Pester/1.1b1/Source/PSApplication.m
===================================================================
--- releases/Pester/1.1b1/Source/PSApplication.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSApplication.m	(revision 62)
@@ -0,0 +1,217 @@
+//
+//  PSApplication.m
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Oct 11 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSApplication.h"
+#import "PSAlarmSetController.h"
+#import "PSAlarmAlertController.h"
+#import "PSAlarmsController.h"
+#import "PSAlarm.h"
+#import "PSAlarms.h"
+#import "PSTimer.h"
+
+@implementation PSApplication
+
+- (void)finishLaunching;
+{
+    appIconImage = [[NSImage imageNamed: @"NSApplicationIcon"] retain];
+    [[NSNotificationCenter defaultCenter] addObserver: [PSAlarmAlertController class] selector: @selector(controllerWithTimerExpiredNotification:) name: PSAlarmTimerExpiredNotification object: nil];
+    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(nextAlarmDidChange:) name: PSAlarmsNextAlarmDidChangeNotification object: nil];
+    // XXX exception handling
+    [PSAlarms setUp];
+    [self setDelegate: self];
+    [super finishLaunching];
+}
+
+- (IBAction)showHelp:(id)sender;
+{
+    [[NSWorkspace sharedWorkspace] openFile: [[NSBundle mainBundle] pathForResource: @"Read Me" ofType: @"rtfd"]];
+}
+
+- (IBAction)stopAlerts:(id)sender;
+{
+    [PSAlarmAlertController stopAlerts: sender];
+}	
+
+- (IBAction)orderFrontSetAlarmPanel:(id)sender;
+{
+    [NSApp activateIgnoringOtherApps: YES];
+    [alarmSetController showWindow: self];
+}
+
+- (IBAction)orderFrontAlarmsPanel:(id)sender;
+{
+    [NSApp activateIgnoringOtherApps: YES];
+    if (alarmsController == nil) {
+        alarmsController = [[PSAlarmsController alloc] init];
+    }
+    [alarmsController showWindow: self];
+}
+
+- (void)_resetUpdateTimer;
+{
+    if (dockUpdateTimer != nil) {
+        [dockUpdateTimer invalidate];
+        [dockUpdateTimer release];
+        dockUpdateInterval = 0;
+        dockUpdateTimer = nil;
+    }
+}
+
+- (void)_setUpdateTimerForInterval:(NSTimeInterval)interval alarm:(PSAlarm *)alarm repeats:(BOOL)repeats;
+{
+    dockUpdateTimer = [PSTimer scheduledTimerWithTimeInterval: interval target: self selector: @selector(_updateDockTile:) userInfo: alarm repeats: repeats];
+    [dockUpdateTimer retain];
+    dockUpdateInterval = interval; // because [timer timeInterval] always returns 0 once set
+}
+
+- (void)_updateDockTile:(PSTimer *)timer;
+{
+    PSAlarm *alarm = [timer userInfo];
+    NSTimeInterval timeRemaining;
+    NSString *tileString;
+    if (timer == nil) alarm = [[PSAlarms allAlarms] nextAlarm];
+    if (alarm == nil) return;
+    tileString = [alarm timeRemainingString];
+    timeRemaining = [alarm timeRemaining]; // want to err on the side of timeRemaining being smaller, otherwise ÇexpiredÈ can appear
+    {
+        NSMutableDictionary *atts = [NSMutableDictionary dictionary];
+        NSSize imageSize = [appIconImage size];
+        NSImage *tile = [[NSImage alloc] initWithSize: imageSize];
+        NSSize textSize;
+        NSPoint textOrigin;
+        NSRect frameRect;
+        float fontSize = 37;
+        
+        do {
+            fontSize -= 1;
+            [atts setObject: [NSFont boldSystemFontOfSize: fontSize] forKey: NSFontAttributeName];
+            textSize = [tileString sizeWithAttributes: atts];
+        } while (textSize.width > imageSize.width - 8);
+
+        textOrigin = NSMakePoint(imageSize.width / 2 - textSize.width / 2,
+                                 imageSize.height / 2 - textSize.height / 2);
+        frameRect = NSInsetRect(NSMakeRect(textOrigin.x, textOrigin.y, textSize.width, textSize.height),
+                                -4, -2);
+        
+        [tile lockFocus];
+        // draw the grayed-out app icon
+        [appIconImage dissolveToPoint: NSZeroPoint fraction: 0.5];
+        // draw the frame
+        [[NSColor colorWithCalibratedWhite: 0.1 alpha: 0.5] set];
+        NSRectFill(frameRect);
+        // draw a gray two-pixel text shadow
+        [atts setObject: [NSColor grayColor] forKey: NSForegroundColorAttributeName];
+        textOrigin.x++; textOrigin.y--;
+        [tileString drawAtPoint: textOrigin withAttributes: atts];
+        textOrigin.x++; textOrigin.y--;
+        [tileString drawAtPoint: textOrigin withAttributes: atts];
+        // draw white text
+        textOrigin.x -= 2; textOrigin.y += 2;
+        [atts setObject: [NSColor whiteColor] forKey: NSForegroundColorAttributeName];
+        [tileString drawAtPoint: textOrigin withAttributes: atts];
+        
+        [tile unlockFocus];
+        [NSApp setApplicationIconImage: tile];
+        [tile release];
+    }
+    // NSLog(@"_updateDockTile > time remaining %@ (%.6lf), last time interval %.6lf", tileString, timeRemaining, dockUpdateInterval);
+    if (timeRemaining > 61) {
+        NSTimeInterval nextUpdate = ((unsigned long long)timeRemaining) % 60;
+        if (nextUpdate <= 1) nextUpdate = 60;
+        [self _resetUpdateTimer];
+        [self _setUpdateTimerForInterval: nextUpdate alarm: alarm repeats: NO];
+        // NSLog(@"_updateDockTile > set timer for %.0lf seconds", nextUpdate);
+    } else if (timer == nil || dockUpdateInterval > 1) {
+        [self _resetUpdateTimer]; 
+        [self _setUpdateTimerForInterval: 1 alarm: alarm repeats: YES];
+        // NSLog(@"_updateDockTile > set timer for 1 second");
+    } else if (timeRemaining <= 1) {
+        [self _resetUpdateTimer];
+    }
+}
+
+- (void)nextAlarmDidChange:(NSNotification *)notification;
+{
+    PSAlarm *nextAlarm = [notification object];
+    // NSLog(@"nextAlarmDidChange: %@", nextAlarm);
+    [self _resetUpdateTimer];
+    if (nextAlarm == nil) {
+        [NSApp setApplicationIconImage: appIconImage];
+    } else {
+        [self _updateDockTile: nil];
+    }
+}
+
+@end
+
+@implementation PSApplication (NSApplicationDelegate)
+
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag;
+{
+    if (!flag && ![[PSAlarms allAlarms] alarmsExpiring]) [alarmSetController showWindow: self];
+    return YES;
+}
+
+- (NSMenu *)applicationDockMenu:(NSApplication *)sender;
+{
+    NSMenu *dockMenu = [[NSMenu alloc] initWithTitle: @""];
+    PSAlarms *alarms = [PSAlarms allAlarms];
+    PSAlarm *nextAlarm = [alarms nextAlarm];
+    NSMenuItem *item;
+    if (nextAlarm == nil) {
+        [dockMenu addItemWithTitle: @"No Pending Alarms" action: nil keyEquivalent: @""];
+    } else {
+        [dockMenu addItemWithTitle: @"Next Alarm" action: nil keyEquivalent: @""];
+        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   %@", [nextAlarm message]] action: nil keyEquivalent: @""];
+        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   %@ %@", [nextAlarm shortDateString], [nextAlarm timeString]] action: nil keyEquivalent: @""];
+        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   Remaining: %@", [nextAlarm timeRemainingString]] action: nil keyEquivalent: @""];
+    }
+    [dockMenu addItem: [NSMenuItem separatorItem]];
+    item = [dockMenu addItemWithTitle: @"Set AlarmÉ" action: @selector(orderFrontSetAlarmPanel:) keyEquivalent: @""];
+    [item setTarget: self];
+    item = [dockMenu addItemWithTitle: [NSString stringWithFormat: @"All Alarms (%d)É", [alarms alarmCount]] action: @selector(orderFrontAlarmsPanel:) keyEquivalent: @""];
+    [item setTarget: self];
+    return [dockMenu autorelease];
+}
+
+@end
+
+@implementation PSApplication (NSApplicationNotifications)
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification;
+{
+    // XXX import panel will not be frontmost window if you switch to another app while Pester is launching; Mac OS X bug?
+    PSAlarms *allAlarms = [PSAlarms allAlarms];
+    unsigned version1AlarmCount = [allAlarms countOfVersion1Alarms];
+    if (version1AlarmCount > 0) {
+        int answer = NSRunAlertPanel(@"Import alarms from older Pester version?", @"Pester found %u alarm%@ created with an older version. These alarms must be converted for use with this version of Pester, and will be unavailable in previous versions after conversion. New alarms created with this version of Pester will not appear in Pester version 1.1a3 or earlier.",
+                                     @"Import", @"Discard", @"DonÕt Import",
+                                     version1AlarmCount, version1AlarmCount == 1 ? @"" : @"s");
+        switch (answer) {
+            case NSAlertDefaultReturn:
+                NS_DURING
+                    [allAlarms importVersion1Alarms];
+                NS_HANDLER
+                    NSRunAlertPanel(@"Error occurred importing alarms", @"Pester was unable to convert some alarms created with an older version. Those alarms which could be read have been converted. The previous-format alarms have been retained; try using an older version of Pester to read them.\n\n%@", nil, nil, nil, [localException reason]);
+                    NS_VOIDRETURN;
+                NS_ENDHANDLER
+            case NSAlertAlternateReturn:
+                [allAlarms discardVersion1Alarms];
+                break;
+            case NSAlertOtherReturn:
+                break;
+        }
+    }
+}
+
+- (void)applicationWillTerminate:(NSNotification *)notification;
+{
+    [NSApp setApplicationIconImage: appIconImage];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSBeepAlert.h
===================================================================
--- releases/Pester/1.1b1/Source/PSBeepAlert.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSBeepAlert.h	(revision 62)
@@ -0,0 +1,22 @@
+//
+//  PSBeepAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlert.h"
+
+@interface PSBeepAlert : PSAlert {
+    PSAlarm *alarm;
+    unsigned short repetitions;
+    unsigned short repetitionsRemaining;
+}
+
++ (PSBeepAlert *)alertWithRepetitions:(unsigned short)numReps;
+- (id)initWithRepetitions:(unsigned short)numReps;
+
+- (unsigned short)repetitions;
+
+@end
Index: releases/Pester/1.1b1/Source/PSBeepAlert.m
===================================================================
--- releases/Pester/1.1b1/Source/PSBeepAlert.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSBeepAlert.m	(revision 62)
@@ -0,0 +1,89 @@
+//
+//  PSBeepAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "PSBeepAlert.h"
+#import "PSAlarmAlertController.h"
+#import "NSDictionary-NJRExtensions.h"
+
+// property list keys
+static NSString * const PLAlertRepetitions = @"times"; // NSNumber
+
+@implementation PSBeepAlert
+
++ (PSBeepAlert *)alertWithRepetitions:(unsigned short)numReps;
+{
+    return [[self alloc] initWithRepetitions: numReps];
+}
+
+- (id)initWithRepetitions:(unsigned short)numReps;
+{
+    if ( (self = [super init]) != nil) {
+        repetitions = numReps;
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+    [super dealloc];
+}
+
+- (unsigned short)repetitions;
+{
+    return repetitions;
+}
+
+- (void)beep;
+{
+    NSBeep();
+    repetitionsRemaining--;
+    if (repetitionsRemaining == 0) {
+        [self completedForAlarm: alarm];
+        [self release];
+        return;
+    }
+    [self performSelector: @selector(beep) withObject: nil afterDelay: 0.15 inModes: [NSArray arrayWithObject: NSDefaultRunLoopMode]];
+}
+
+- (void)_stopBeeping:(NSNotification *)notification;
+{
+    repetitionsRemaining = 1;
+}
+
+- (void)triggerForAlarm:(PSAlarm *)anAlarm;
+{
+    alarm = anAlarm;
+    repetitionsRemaining = repetitions;
+    [self retain];
+    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_stopBeeping:) name: PSAlarmAlertStopNotification object: nil];
+    [self beep];
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    return [[@"Play the system alert sound" stringByAppendingString:
+                                            repetitions == 1 ? @"" : [NSString stringWithFormat: @" %hu times", repetitions]] small];
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    NSMutableDictionary *plAlert = [[super propertyListRepresentation] mutableCopy];
+    [plAlert setObject: [NSNumber numberWithUnsignedShort: repetitions] forKey: PLAlertRepetitions];
+    return [plAlert autorelease];
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    return [self initWithRepetitions: [[dict objectForRequiredKey: PLAlertRepetitions] unsignedShortValue]];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSDockBounceAlert.h
===================================================================
--- releases/Pester/1.1b1/Source/PSDockBounceAlert.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSDockBounceAlert.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  PSDockBounceAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlert.h"
+
+
+@interface PSDockBounceAlert : PSAlert {
+
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSDockBounceAlert.m
===================================================================
--- releases/Pester/1.1b1/Source/PSDockBounceAlert.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSDockBounceAlert.m	(revision 62)
@@ -0,0 +1,48 @@
+//
+//  PSDockBounceAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "PSDockBounceAlert.h"
+
+static PSDockBounceAlert *PSDockBounceAlertShared;
+
+@implementation PSDockBounceAlert
+
++ (PSAlert *)alert;
+{
+    if (PSDockBounceAlertShared == nil)
+        PSDockBounceAlertShared = [[PSDockBounceAlert alloc] init];
+    return PSDockBounceAlertShared;
+}
+
++ (void)stopBouncing;
+{
+    [NSApp cancelUserAttentionRequest: NSInformationalRequest];
+}
+
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+{
+    [NSApp requestUserAttention: NSInformationalRequest];
+    [[self class] performSelector: @selector(stopBouncing) withObject: nil afterDelay: 1 inModes: [NSArray arrayWithObject: NSDefaultRunLoopMode]];
+    [self completedForAlarm: alarm];
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    return [@"Bounce dock icon" small];
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    [self release];
+    return [[PSDockBounceAlert alert] retain];
+}
+        
+@end
Index: releases/Pester/1.1b1/Source/PSError.h
===================================================================
--- releases/Pester/1.1b1/Source/PSError.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSError.h	(revision 62)
@@ -0,0 +1,24 @@
+//
+//  PSError.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Dec 29 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface PSError : NSObject {
+    NSCountedSet *reasons;
+    NSString *operation;
+    unsigned count;
+}
+
+// create an error object
++ (PSError *)error;
+
+// raise exception, invalidates error object
+- (void)raiseIfNeededForOperation:(NSString *)anOperation count:(unsigned)aCount;
+
+@end
Index: releases/Pester/1.1b1/Source/PSError.m
===================================================================
--- releases/Pester/1.1b1/Source/PSError.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSError.m	(revision 62)
@@ -0,0 +1,60 @@
+//
+//  PSError.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Dec 29 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSError.h"
+
+static NSString * const PSErrorException = @"PSErrorException";
+
+@implementation PSError
+
++ (PSError *)error;
+{
+    return [[self alloc] init];
+}
+
+- (void)dealloc;
+{
+    [reasons release]; reasons = nil;
+    [operation release]; operation = nil;
+    [super dealloc];
+}
+
+- (NSCountedSet *)reasons;
+{
+    if (reasons == nil)
+        reasons = [[NSCountedSet alloc] initWithCapacity: 2];
+    return reasons;
+}
+
+- (void)addException:(NSException *)exception;
+{
+
+}
+
+- (void)raiseIfNeededForOperation:(NSString *)anOperation count:(unsigned)aCount;
+{
+    if (reasons != nil && [reasons count] > 0) {
+        // NSMutableString *
+        [self autorelease];
+        [NSException raise: PSErrorException
+                    format: @"Pester encountered errors while %@ %@."];
+    } else {
+        [self release];
+    }
+}
+
+@end
+
+/* Use cases:
+   - PSAlerts => can't restore one or more alerts, keep the rest
+   - 
+
+   Need to add error to initWithPropertyList: protocol, otherwise we can't get back partially-formed objects.
+   - (id)initWithPropertyList:(NSDictionary *)dict error:(PSException **)exception;
+
+ */
Index: releases/Pester/1.1b1/Source/PSMovieAlert.h
===================================================================
--- releases/Pester/1.1b1/Source/PSMovieAlert.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSMovieAlert.h	(revision 62)
@@ -0,0 +1,31 @@
+//
+//  PSMovieAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "PSAlert.h"
+
+@class BDAlias;
+
+@interface PSMovieAlert : PSAlert {
+    BDAlias *alias;
+    NSMovie *movie;
+    unsigned short repetitions;
+    BOOL hasAudio;
+    BOOL hasVideo;
+}
+
++ (PSMovieAlert *)alertWithMovieFileAlias:(BDAlias *)anAlias repetitions:(unsigned short)numReps;
+
+- (id)initWithMovieFileAlias:(BDAlias *)anAlias repetitions:(unsigned int) numReps;
+
+- (BOOL)hasVideo;
+- (NSMovie *)movie;
+- (BDAlias *)movieFileAlias;
+- (unsigned short)repetitions;
+
+@end
Index: releases/Pester/1.1b1/Source/PSMovieAlert.m
===================================================================
--- releases/Pester/1.1b1/Source/PSMovieAlert.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSMovieAlert.m	(revision 62)
@@ -0,0 +1,127 @@
+//
+//  PSMovieAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <QuickTime/Movies.h>
+#import "PSMovieAlert.h"
+#import "PSMovieAlertController.h"
+#import "NSDictionary-NJRExtensions.h"
+#import "NSMovie-NJRExtensions.h"
+#import "BDAlias.h"
+
+// property list keys
+static NSString * const PLAlertRepetitions = @"times"; // NSString
+static NSString * const PLAlertAlias = @"alias"; // NSData
+
+@implementation PSMovieAlert
+
++ (PSMovieAlert *)alertWithMovieFileAlias:(BDAlias *)anAlias repetitions:(unsigned short)numReps;
+{
+    return [[[self alloc] initWithMovieFileAlias: anAlias repetitions: numReps] autorelease];
+}
+
+- (id)initWithMovieFileAlias:(BDAlias *)anAlias repetitions:(unsigned int) numReps;
+{
+    if ( (self = [super init]) != nil) {
+        NSString *path = [anAlias fullPath];
+        if (path == nil) {
+            [self release];
+            [NSException raise: PSAlertCreationException format: @"CanÕt locate media to play as alert."];
+        }
+        alias = [anAlias retain];
+        repetitions = numReps;
+        // XXX if we support remote movie URLs, need to call EnterMovies() ourselves at least in Jaguar (_MacTech_ December 2002, p. 64); also should do async movie loading (p. 73Ð74).
+        movie = [[NSMovie alloc] initWithURL: [NSURL fileURLWithPath: path] byReference: YES];
+        if (movie == nil) {
+            [self release];
+            self = nil;
+        } else {
+            hasAudio = [movie hasAudio];
+            hasVideo = [movie hasVideo];
+            
+            if (!hasAudio && !hasVideo) {
+                [self release]; self = nil;
+            }
+        }
+    }
+    
+    return self;
+}
+
+- (BOOL)hasVideo;
+{
+    return hasVideo;
+}
+
+- (BOOL)requiresPesterFrontmost;
+{
+    return hasVideo;
+}
+
+- (NSMovie *)movie;
+{
+    return movie;
+}
+
+- (BDAlias *)movieFileAlias;
+{
+    return alias;
+}
+
+- (unsigned short)repetitions;
+{
+    return repetitions;
+}
+
+- (void)dealloc;
+{
+    [alias release];
+    [movie release];
+    [super dealloc];
+}
+
+- (NSString *)description;
+{
+    return [NSString stringWithFormat: @"PSMovieAlert (%@%@): %@, repeats %hu times", hasAudio ? @"A" : @"", hasVideo ? @"V" : @"", [alias fullPath], repetitions];
+}
+
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+{
+    [PSMovieAlertController controllerWithAlarm: alarm movieAlert: self];
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    BOOL isStatic = [movie isStatic];
+    NSMutableAttributedString *string = [[(isStatic ? @"Show " : @"Play ") small] mutableCopy];
+    NSString *kindString = nil, *name = [alias displayNameWithKindString: &kindString];
+    if (name == nil) name = @"ÇcanÕt locate media fileÈ";
+    else [string appendAttributedString: [[NSString stringWithFormat: @"%@ ", kindString] small]];
+    [string appendAttributedString: [name underlined]];
+    if (repetitions > 1 && !isStatic) {
+        [string appendAttributedString: [[NSString stringWithFormat: @" %hu times", repetitions] small]];
+    }
+    return [string autorelease];
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    NSMutableDictionary *plAlert = [[super propertyListRepresentation] mutableCopy];
+    [plAlert setObject: [NSNumber numberWithUnsignedShort: repetitions] forKey: PLAlertRepetitions];
+    [plAlert setObject: [alias aliasData] forKey: PLAlertAlias];
+    return [plAlert autorelease];
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    return [self initWithMovieFileAlias: [BDAlias aliasWithData: [dict objectForRequiredKey: PLAlertAlias]]
+                            repetitions: [[dict objectForRequiredKey: PLAlertRepetitions] unsignedShortValue]];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSMovieAlertController.h
===================================================================
--- releases/Pester/1.1b1/Source/PSMovieAlertController.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSMovieAlertController.h	(revision 62)
@@ -0,0 +1,27 @@
+//
+//  PSMovieAlertController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+@class PSAlarm;
+@class PSMovieAlert;
+
+@interface PSMovieAlertController : NSWindowController {
+    PSAlarm *alarm;
+    PSMovieAlert *alert;
+    IBOutlet NSMovieView *movieView;
+    void *theMovie; /* Movie */
+    unsigned short repetitions;
+    unsigned short repetitionsRemaining;    
+}
+
++ (PSMovieAlertController *)controllerWithAlarm:(PSAlarm *)anAlarm movieAlert:(PSMovieAlert *)anAlert;
+
+- (id)initWithAlarm:(PSAlarm *)anAlarm movieAlert:(PSMovieAlert *)anAlert;
+
+@end
Index: releases/Pester/1.1b1/Source/PSMovieAlertController.m
===================================================================
--- releases/Pester/1.1b1/Source/PSMovieAlertController.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSMovieAlertController.m	(revision 62)
@@ -0,0 +1,113 @@
+//
+//  PSMovieAlertController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarmAlertController.h"
+#import "PSMovieAlertController.h"
+#import "PSMovieAlert.h"
+#import "NSMovie-NJRExtensions.h"
+#import <QuickTime/Movies.h>
+
+@implementation PSMovieAlertController
+
++ (PSMovieAlertController *)controllerWithAlarm:(PSAlarm *)anAlarm movieAlert:(PSMovieAlert *)anAlert;
+{
+    return [[self alloc] initWithAlarm: anAlarm movieAlert: anAlert];
+}
+
+- (void)play;
+{
+    NSTimeInterval delay;
+    if (repetitions == 0) return;
+    if (IsMovieDone((Movie)theMovie) || repetitionsRemaining == repetitions) {
+        if (repetitionsRemaining == 0) {
+            [self close];
+            return;
+        }
+        repetitionsRemaining--;
+        [movieView gotoBeginning: self];
+        [movieView start: self];
+    }
+    delay = (GetMovieDuration((Movie)theMovie) - GetMovieTime((Movie)theMovie, NULL)) / (double)GetMovieTimeScale((Movie)theMovie);
+    // XXX should use a timebase callback for this instead (see NJRQTMediaPopUpButton); also, use QuickTimeÕs built-in loop functionality instead of rolling our own?
+    [self performSelector: @selector(play) withObject: nil afterDelay: delay inModes: [NSArray arrayWithObject: NSDefaultRunLoopMode]];
+}
+
+- (id)initWithAlarm:(PSAlarm *)anAlarm movieAlert:(PSMovieAlert *)anAlert;
+{
+    if ([self initWithWindowNibName: @"Movie alert"]) {
+        NSMovie *movie = [anAlert movie];
+        NSWindow *window = [self window]; // connect outlets
+        alarm = anAlarm;
+        alert = anAlert;
+        [movieView setMovie: movie];
+        theMovie = [movie QTMovie];
+        if ([alert hasVideo]) {
+            NSRect screenRect = [[window screen] visibleFrame];
+            float magnification = 1.0;
+            NSSize movieSize;
+            NSSize minSize = [window minSize];
+            float windowFrameHeight = [window frame].size.height - [[window contentView] frame].size.height;
+            NSRect frame;
+            screenRect.size.height -= windowFrameHeight;
+            minSize.height -= windowFrameHeight;
+            while (1) {
+                movieSize = [movieView sizeForMagnification: magnification];
+                movieSize.height -= 16; // controller is hidden, but its size is included (documented, ergh)
+                if (movieSize.width > screenRect.size.width || movieSize.height > screenRect.size.height)
+                    magnification /= 2;
+                else
+                    break;
+            }
+            if (movieSize.width < minSize.width) movieSize.width = minSize.width;
+            if (movieSize.height < minSize.height) movieSize.width = minSize.height;
+            [window setContentSize: movieSize];
+            [window center];
+            frame = [window frame];
+            frame.origin.y -= 400; // appear below notifier window - XXX this is very inaccurate, fix
+            if (frame.origin.y < screenRect.origin.y) frame.origin.y = screenRect.origin.y;
+            [window setFrame: frame display: NO];
+            [window setTitle: [alarm message]];
+            {	// XXX workaround for (IMO) ugly appearance of Cocoa utility windows
+                NSView *miniButton = [window standardWindowButton: NSWindowMiniaturizeButton],
+                *zoomButton = [window standardWindowButton: NSWindowZoomButton];
+                // NOTE: this will not work if the window is resizable: when the frame is reset, the standard buttons reappear
+                [miniButton setFrameOrigin: NSMakePoint(-100, -100)];
+                [zoomButton setFrameOrigin: NSMakePoint(-100, -100)];
+                [[miniButton superview] setNeedsDisplay: YES];
+                [[zoomButton superview] setNeedsDisplay: YES];
+            }
+            [[self window] orderFrontRegardless];
+        }
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(close) name: PSAlarmAlertStopNotification object: nil];
+        repetitions = [alert repetitions];
+        repetitionsRemaining = repetitions;
+        if (![movie isStatic]) [self play]; // if it's an image, don't close the window automatically
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+    [super dealloc];
+}
+
+@end
+
+@implementation PSMovieAlertController (NSWindowNotifications)
+
+- (void)windowWillClose:(NSNotification *)notification;
+{
+    repetitions = 0;
+    [movieView stop: self];
+    [alert completedForAlarm: alarm];
+    [self autorelease];
+    // note: there may still be a retained copy of this object until the runloop timer has let go of us at the end of the current movie playback cycle; donÕt worry about it.
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSNotifierAlert.h
===================================================================
--- releases/Pester/1.1b1/Source/PSNotifierAlert.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSNotifierAlert.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  PSNotifierAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlert.h"
+
+
+@interface PSNotifierAlert : PSAlert {
+
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSNotifierAlert.m
===================================================================
--- releases/Pester/1.1b1/Source/PSNotifierAlert.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSNotifierAlert.m	(revision 62)
@@ -0,0 +1,46 @@
+//
+//  PSNotifierAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSNotifierAlert.h"
+#import "PSAlarmNotifierController.h"
+
+static PSNotifierAlert *PSNotifierAlertShared;
+
+@implementation PSNotifierAlert
+
++ (PSAlert *)alert;
+{
+    if (PSNotifierAlertShared == nil)
+        PSNotifierAlertShared = [[PSNotifierAlert alloc] init];
+    return PSNotifierAlertShared;
+}
+
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+{
+    [[PSAlarmNotifierController alloc] initWithAlarm: alarm];
+}
+
+- (BOOL)requiresPesterFrontmost;
+{
+    return YES;
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    return [@"Display message and time" small];
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    [self release];
+    return [[PSNotifierAlert alert] retain];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSPowerManager.h
===================================================================
--- releases/Pester/1.1b1/Source/PSPowerManager.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSPowerManager.h	(revision 62)
@@ -0,0 +1,33 @@
+//
+//  PSPowerManager.h
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Dec 23 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <IOKit/IOKitLib.h>
+
+@interface PSPowerManager : NSObject {
+    id delegate;
+    io_connect_t root_port;
+    io_object_t notifier;
+}
+
+- (id)initWithDelegate:(id)aDelegate;
+
++ (BOOL)autoWakeSupported;
++ (NSDate *)wakeTime;
++ (void)setWakeTime:(NSDate *)time;
++ (void)clearWakeTime;
+
+@end
+
+@interface NSObject (PSPowerManagerDelegate)
+
+- (void)powerManagerWillDemandSleep:(PSPowerManager *)powerManager;
+- (BOOL)powerManagerShouldIdleSleep:(PSPowerManager *)powerManager;
+- (void)powerManagerDidWake:(PSPowerManager *)powerManager;
+
+@end
Index: releases/Pester/1.1b1/Source/PSPowerManager.m
===================================================================
--- releases/Pester/1.1b1/Source/PSPowerManager.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSPowerManager.m	(revision 62)
@@ -0,0 +1,270 @@
+//
+//  PSPowerManager.m
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Dec 23 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSPowerManager.h"
+
+#import <IOKit/pwr_mgt/IOPMLib.h>
+#import <IOKit/IOMessage.h>
+#import <CoreFoundation/CoreFoundation.h>
+
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/* Sample code to set an automatic wakeup timer to wake machines from sleep.
+
+When a machine is asleep, most hardware (including the processor) is
+powered off. The PMU chip is one of the few things left powered on, and it's
+able to generate a wakeup event on a timer.
+This code shows how to set the wakeup timer within the PMU.
+*/
+
+// From autowake.cpp:
+
+// #define kAppleVIAUserClientMagicCookie 0x101face // or 0x101beef -- for PMU
+// #define kAppleVIAUserClientMagicCookie 0x101beef // or 0x101face  -- for PMU
+
+// The difference is 101beef is only for superusers and 101face works for
+// non-privileged users.  I have not determined which calls are only available
+// for superusers
+
+#define PMU_MAGIC_PASSWORD	0x0101FACE // BEEF
+
+/* ==========================================
+* Close a device user client
+* =========================================== */
+static kern_return_t
+closeDevice(io_connect_t con)
+{
+    kern_return_t ret = IOServiceClose(con);
+
+    NSCAssert1(ret == kIOReturnSuccess, @"closeDevice: IOServiceClose returned an error of type %08lx", (unsigned long)ret);
+
+    return ret;
+}
+
+/* ==========================================
+* Open an IORegistry device user client
+* =========================================== */
+static void
+openDevice(io_object_t obj, unsigned int type, io_connect_t * con)
+{
+    kern_return_t ret = IOServiceOpen(obj, mach_task_self(), type, con);
+
+    NSCAssert1(ret == kIOReturnSuccess, @"openDevice: IOServiceOpen returned an error of type %08lx", (unsigned long)ret);
+}
+
+/* ===========================================
+* Changes the string for a registry
+* property.
+* ===========================================  */
+void
+writeDataProperty(io_object_t handle, CFStringRef name,
+                  unsigned char * bytes, unsigned int size)
+{
+    kern_return_t kr = kIOReturnNoMemory;
+    CFDataRef data;
+    CFMutableDictionaryRef dict = 0;
+
+    data = CFDataCreate(kCFAllocatorDefault, bytes, size);
+    NSCAssert(data != NULL, @"writeDataProperty: CFDataCreate failed");
+    [(NSData *)data autorelease];
+
+    dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    NSCAssert(data != NULL, @"writeDataProperty: CFDictionaryCreateMutable failed");
+    [(NSMutableDictionary *)dict autorelease];
+
+    CFDictionarySetValue(dict, name, data);
+    kr = IOConnectSetCFProperties(handle, dict);
+    NSCAssert1(kr == KERN_SUCCESS, @"writeDataProperty: IOConnectSetCFProperties returned an error of type %08lx", (unsigned long)kr);
+}
+
+/* ==========================================
+* Write a data property to the PMU driver
+* Arguments
+*     pmuReference - the IORegistry device to write to
+*     propertyName - Name of the property to write to
+*     data - Data to write
+*     dataSize - Data size
+* =========================================== */
+void
+writePMUProperty(io_object_t pmuReference, CFStringRef propertyName, void *data, size_t dataSize)
+{
+    io_connect_t conObj;
+    openDevice(pmuReference, PMU_MAGIC_PASSWORD, &conObj);
+    writeDataProperty(conObj, propertyName, (unsigned char *)data, dataSize);
+    closeDevice(conObj);
+}
+
+
+/* ==========================================
+* Look through the registry and search for an
+* IONetworkInterface objects with the given
+* name.
+* If a match is found, the object is returned.
+* =========================================== */
+
+io_service_t
+getInterfaceWithName(mach_port_t masterPort, char *className)
+{
+    io_service_t obj;
+
+    obj = IOServiceGetMatchingService(masterPort, IOServiceMatching(className));
+
+    NSCAssert(obj != NULL, @"getInterfaceWithName: IOServiceGetMatchingService returned NULL");
+
+    return obj;
+}
+
+/* ==========================================
+* Find the PMU in the IORegistry
+* =========================================== */
+io_service_t
+openPMUComPort(void)
+{
+    static mach_port_t masterPort;
+    kern_return_t kr;
+
+    // Get a master port to talk with the mach_kernel
+    kr = IOMasterPort(bootstrap_port, &masterPort);
+    NSCAssert1(kr == KERN_SUCCESS, @"openPMUComPort: IOMasterPort returned an error of type %08lx", (unsigned long)kr);
+
+    return getInterfaceWithName(masterPort, "ApplePMU");
+}
+
+
+/* ==========================================
+* Release our reference to the PMU in the IORegistry
+* =========================================== */
+void
+closePMUComPort(io_object_t pmuRef)
+{
+    IOObjectRelease(pmuRef);
+}
+
+@implementation PSPowerManager
+
++ (BOOL)autoWakeSupported;
+{
+    io_service_t pmuReference = openPMUComPort();
+    if (pmuReference == NULL) return NO;
+    closePMUComPort(pmuReference);
+    return YES;
+}
+
++ (NSDate *)wakeTime;
+{
+    io_service_t pmuReference = openPMUComPort();
+    NSNumber *autoWakeTime;
+    unsigned long long rawWakeTime;
+    
+    NSAssert(pmuReference != NULL, @"Couldn’t find PMU in IORegistry. This computer may not support automatic wake from sleep.");
+    autoWakeTime = (NSNumber *)IORegistryEntryCreateCFProperty(pmuReference, CFSTR("AutoWake"), NULL, 0);
+    closePMUComPort(pmuReference);
+
+    if (autoWakeTime == nil) return nil;
+    rawWakeTime = [autoWakeTime unsignedLongLongValue];
+    if (rawWakeTime == 0) return nil;
+    // XXX no idea what the epoch is supposed to be, but this works...
+    return [NSDate dateWithTimeIntervalSinceReferenceDate: rawWakeTime - 18446744072475718320LLU];
+}
+
++ (void)setWakeTime:(NSDate *)time;
+{
+    unsigned long wakeTime;
+    io_service_t pmuReference = openPMUComPort();
+    NSAssert(pmuReference != NULL, @"Couldn’t find PMU in IORegistry. This computer may not support automatic wake from sleep.");
+
+    if (time == nil) wakeTime = 0;
+    else {
+        wakeTime = [time timeIntervalSinceNow];
+        if (wakeTime == 0) wakeTime++; // 0 will disable
+    }
+    writePMUProperty(pmuReference, CFSTR("AutoWake"), (unsigned long *)&wakeTime, sizeof(wakeTime));
+    
+    closePMUComPort(pmuReference);
+}
+
++ (void)clearWakeTime;
+{
+    [self setWakeTime: nil];
+}
+
+// modified from RegisterForSleep sample code
+
+- (void)_messageReceived:(natural_t)messageType withArgument:(void *)messageArgument;
+{
+    switch (messageType) {
+        case kIOMessageSystemWillSleep:
+            if ([delegate respondsToSelector: @selector(powerManagerWillDemandSleep:)]) {
+                [delegate powerManagerWillDemandSleep: self];
+                IOAllowPowerChange(root_port, (long)messageArgument);
+            }
+            break;
+        case kIOMessageCanSystemSleep:
+            if ([delegate respondsToSelector: @selector(powerManagerShouldIdleSleep:)]) {
+                if ([delegate powerManagerShouldIdleSleep: self]) {
+                    IOAllowPowerChange(root_port, (long)messageArgument);
+                } else {
+                    IOCancelPowerChange(root_port, (long)messageArgument);
+                }
+            }
+            break;
+        case kIOMessageSystemHasPoweredOn:
+            if ([delegate respondsToSelector: @selector(powerManagerDidWake:)])
+                [delegate powerManagerDidWake: self];
+            break;
+    }
+}
+
+void
+powerCallback(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
+{
+    [(PSPowerManager *)refCon _messageReceived: messageType withArgument: messageArgument];
+}
+
+- (id)initWithDelegate:(id)aDelegate;
+{
+    if ( (self = [super init]) != nil) {
+        IONotificationPortRef notificationPort;
+
+        delegate = [aDelegate retain];
+        root_port = IORegisterForSystemPower(self, &notificationPort, powerCallback, &notifier);
+        NSAssert(root_port != NULL, @"IORegisterForSystemPower failed");
+
+        CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode);
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    IODeregisterForSystemPower(&notifier);
+    [delegate release];
+    [super dealloc];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSPropertyListSerialization.h
===================================================================
--- releases/Pester/1.1b1/Source/PSPropertyListSerialization.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSPropertyListSerialization.h	(revision 62)
@@ -0,0 +1,19 @@
+//
+//  PSPropertyListSerialization.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Dec 21 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@protocol PSPropertyListSerialization
+
+// 1.1 only, deprecated when we move to keyed archiving
+- (NSDictionary *)propertyListRepresentation;
+// subclasses should NOT call [super initWithPropertyList:] - infinite recursion will result!
+- (id)initWithPropertyList:(NSDictionary *)dict;
+
+@end
Index: releases/Pester/1.1b1/Source/PSScriptAlert.h
===================================================================
--- releases/Pester/1.1b1/Source/PSScriptAlert.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSScriptAlert.h	(revision 62)
@@ -0,0 +1,22 @@
+//
+//  PSScriptAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlert.h"
+
+@class BDAlias;
+
+@interface PSScriptAlert : PSAlert {
+    BDAlias *alias;
+}
+
++ (PSScriptAlert *)alertWithScriptFileAlias:(BDAlias *)anAlias;
+- (id)initWithScriptFileAlias:(BDAlias *)anAlias;
+
+- (BDAlias *)scriptFileAlias;
+
+@end
Index: releases/Pester/1.1b1/Source/PSScriptAlert.m
===================================================================
--- releases/Pester/1.1b1/Source/PSScriptAlert.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSScriptAlert.m	(revision 62)
@@ -0,0 +1,99 @@
+//
+//  PSScriptAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSScriptAlert.h"
+#import "BDAlias.h"
+#import "NSDictionary-NJRExtensions.h"
+
+// property list keys
+static NSString * const PLAlertAlias = @"alias"; // NSData
+
+@implementation PSScriptAlert
+
++ (PSScriptAlert *)alertWithScriptFileAlias:(BDAlias *)anAlias;
+{
+    return [[[self alloc] initWithScriptFileAlias: anAlias] autorelease];
+}
+
+- (id)initWithScriptFileAlias:(BDAlias *)anAlias;
+{
+    if ( (self = [super init]) != nil) {
+        alias = [anAlias retain];
+    }
+    return self;
+}
+
+- (BDAlias *)scriptFileAlias;
+{
+    return alias;
+}
+
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+{
+    NSString *scriptPath = [alias fullPath];
+
+    if (scriptPath == nil) {
+        NSRunAlertPanel(@"CanÕt find script", @"Pester couldnÕt find the script for the alarm Ò%@Ó.",
+                        nil, nil, nil, [alarm message]);
+    } else {
+        NSDictionary *errorInfo;
+        NSAppleScript *script = [[NSAppleScript alloc] initWithContentsOfURL: [NSURL fileURLWithPath: scriptPath] error: &errorInfo];
+        if (script == nil) {
+            NSString *errorMessage = [errorInfo objectForKey: NSAppleScriptErrorMessage];
+            NSNumber *errorNumber = [errorInfo objectForKey: NSAppleScriptErrorNumber];
+            NSString *appName = [errorInfo objectForKey: NSAppleScriptErrorAppName];
+            if (errorMessage == nil) errorMessage = [errorInfo objectForKey: NSAppleScriptErrorBriefMessage];
+            NSRunAlertPanel(@"Script loading error",
+                            @"Pester encountered an error while attempting to load Ò%@Ó%@ %@",
+                            nil, nil, nil,
+                            [[NSFileManager defaultManager] displayNameAtPath: scriptPath],
+                            errorMessage == nil ? @"" : [NSString stringWithFormat: @":\n\n%@%@", appName == nil ? @"" : @"Ò%@Ó reported an error: ", errorMessage],
+                            errorNumber == nil ? @"" : [NSString stringWithFormat: @"(%@)", errorNumber]);
+        } else {
+            NSAppleEventDescriptor *scriptResult = [script executeAndReturnError: &errorInfo];
+            if (scriptResult == nil) {
+                NSString *errorMessage = [errorInfo objectForKey: NSAppleScriptErrorMessage];
+                NSNumber *errorNumber = [errorInfo objectForKey: NSAppleScriptErrorNumber];
+                NSString *appName = [errorInfo objectForKey: NSAppleScriptErrorAppName];
+                if (errorMessage == nil) errorMessage = [errorInfo objectForKey: NSAppleScriptErrorBriefMessage];
+                NSRunAlertPanel(@"Script execution error",
+                                @"Pester encountered an error while attempting to execute the script Ò%@Ó%@ %@",
+                                nil, nil, nil,
+                                [[NSFileManager defaultManager] displayNameAtPath: scriptPath],
+                                errorMessage == nil ? @"" : [NSString stringWithFormat: @":\n\n%@%@", appName == nil ? @"" : @"Ò%@Ó reported an error: ", errorMessage],
+                                errorNumber == nil ? @"" : [NSString stringWithFormat: @"(%@)", errorNumber]);
+            }
+        }
+    }
+    [self completedForAlarm: alarm];
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    NSMutableAttributedString *string = [[@"Do script " small] mutableCopy];
+    NSString *scriptName = [alias displayNameWithKindString: NULL];
+    if (scriptName == nil) scriptName = @"ÇcanÕt locate scriptÈ";
+    [string appendAttributedString: [scriptName underlined]];
+    return [string autorelease];
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    NSMutableDictionary *plAlert = [[super propertyListRepresentation] mutableCopy];
+    [plAlert setObject: [alias aliasData] forKey: PLAlertAlias];
+    return [plAlert autorelease];
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    return [self initWithScriptFileAlias: [BDAlias aliasWithData: [dict objectForRequiredKey: PLAlertAlias]]];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSSpeechAlert.h
===================================================================
--- releases/Pester/1.1b1/Source/PSSpeechAlert.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSSpeechAlert.h	(revision 62)
@@ -0,0 +1,25 @@
+//
+//  PSSpeechAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlert.h"
+
+@class SUSpeaker;
+
+@interface PSSpeechAlert : PSAlert {
+    SUSpeaker *speaker;
+    NSString *voice;
+    PSAlarm *alarm;
+}
+
++ (PSSpeechAlert *)alertWithVoice:(NSString *)aVoice;
+
+- (id)initWithVoice:(NSString *)aVoice;
+
+- (NSString *)voice;
+
+@end
Index: releases/Pester/1.1b1/Source/PSSpeechAlert.m
===================================================================
--- releases/Pester/1.1b1/Source/PSSpeechAlert.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSSpeechAlert.m	(revision 62)
@@ -0,0 +1,95 @@
+//
+//  PSSpeechAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSSpeechAlert.h"
+#import "PSAlarmAlertController.h"
+#import "NSDictionary-NJRExtensions.h"
+#import "SUSpeaker.h"
+
+// property list keys
+static NSString * const PLAlertVoice = @"voice"; // NSString
+
+@implementation PSSpeechAlert
+
++ (PSSpeechAlert *)alertWithVoice:(NSString *)aVoice;
+{
+    return [[[self alloc] initWithVoice: aVoice] autorelease];
+}
+
+- (id)initWithVoice:(NSString *)aVoice;
+{
+    if ( (self = [super init]) != nil) {
+        voice = [aVoice retain];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+    [speaker release]; speaker = nil;
+    [voice release]; voice = nil;
+    [super dealloc];
+}
+
+- (NSString *)voice;
+{
+    return voice;
+}
+
+- (void)_stopSpeaking:(NSNotification *)notification;
+{
+    [speaker stopSpeaking]; // triggers didFinishSpeaking:
+}
+
+- (void)triggerForAlarm:(PSAlarm *)anAlarm;
+{
+    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_stopSpeaking:) name: PSAlarmAlertStopNotification object: nil];
+    
+    if ( (speaker = [[SUSpeaker alloc] init]) == nil) return;
+    alarm = anAlarm;
+    [speaker setDelegate: self];
+    [speaker setVoice: [[SUSpeaker voiceNames] indexOfObject: voice] + 1];
+    [speaker speakText: [alarm message]];
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    NSMutableAttributedString *string = [[@"Speak message with voice " small] mutableCopy];
+    [string appendAttributedString: [voice underlined]];
+    return [string autorelease];
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    NSMutableDictionary *plAlert = [[super propertyListRepresentation] mutableCopy];
+    [plAlert setObject: voice forKey: PLAlertVoice];
+    return [plAlert autorelease];
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    if ( (self = [self init]) != nil) {
+        voice = [dict objectForRequiredKey: PLAlertVoice];
+    }
+    return self;
+}
+
+@end
+
+@implementation PSSpeechAlert (SUSpeakerDelegate)
+
+- (void)didFinishSpeaking:(SUSpeaker *)aSpeaker;
+{
+    [self completedForAlarm: alarm];
+    [speaker release]; speaker = nil;
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSTimer.h
===================================================================
--- releases/Pester/1.1b1/Source/PSTimer.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSTimer.h	(revision 62)
@@ -0,0 +1,49 @@
+//
+//  PSTimer.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Jan 05 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface PSTimer : NSObject {
+    BOOL isValid;
+    BOOL repeats;
+    BOOL isWakeUp;
+    NSDate *fireDate;
+    NSTimeInterval timeInterval;
+    NSInvocation *invocation;
+    id userInfo;
+}
+
++ (void)setUp;
+
+// partial emulation of Mac OS X 10.1 NSTimer interface
+// + (PSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+// + (PSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+
+// + (PSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
++ (PSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
+
+// - (void)fire;
+
+- (NSDate *)fireDate;
+
+// - (NSTimeInterval)timeInterval; // NSTimer’s version returns 0 once timer is scheduled
+
+- (void)invalidate;
+- (BOOL)isValid;
+
+- (id)userInfo;
+
+// other methods
+
+- (BOOL)isWakeUp;
+- (void)setWakeUp:(BOOL)doWake;
+
+- (NSComparisonResult)compare:(PSTimer *)other;
+
+@end
Index: releases/Pester/1.1b1/Source/PSTimer.m
===================================================================
--- releases/Pester/1.1b1/Source/PSTimer.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSTimer.m	(revision 62)
@@ -0,0 +1,246 @@
+//
+//  PSTimer.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Jan 05 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSTimer.h"
+#import "PSAlarm.h"
+#import "PSPowerManager.h"
+
+NSTimer *PSTimerCurrent = nil;
+PSTimer *PSTimerOnWake = nil;
+NSMutableArray *PSTimerAllTimers = nil;
+
+@interface PSTimer (Private)
++ (void)_schedule;
+@end
+
+@implementation PSTimer
+
++ (void)setUp;
+{
+    static PSPowerManager *powerManager;
+
+    if (powerManager == nil) {
+        powerManager = [[PSPowerManager alloc] initWithDelegate: self];
+        PSTimerAllTimers = [[NSMutableArray alloc] init];
+    }
+}
+
++ (void)_schedule;
+{
+    NSDate *aboutNow = [NSDate dateWithTimeIntervalSinceNow: 0.1];
+    [PSTimerCurrent invalidate]; [PSTimerCurrent release]; PSTimerCurrent = nil;
+    PSTimerOnWake = nil;
+    if ([PSTimerAllTimers count] > 0) {
+        PSTimer *timer = nil;
+        NSEnumerator *e;
+        [PSTimerAllTimers sortUsingSelector: @selector(compare:)];
+        // NSLog(@"_schedule: timers %@", [PSTimerAllTimers description]);
+        e = [PSTimerAllTimers objectEnumerator];
+        while ( (timer = [e nextObject]) != nil) {
+            if ([timer isWakeUp]) {
+                PSTimerOnWake = timer;
+                // NSLog(@"scheduling wake timer %@", timer);
+                break;
+            }
+        }
+        e = [PSTimerAllTimers objectEnumerator];
+        while ( (timer = [e nextObject]) != nil) {
+            if ([[timer fireDate] compare: aboutNow] != NSOrderedDescending) {
+                [timer performSelector: @selector(_timerExpired) withObject: nil afterDelay: 0];
+                return;
+            } else {
+                NSTimeInterval ti = [[timer fireDate] timeIntervalSinceNow];
+                if (ti > 0.1) {
+                    PSTimerCurrent = [[NSTimer scheduledTimerWithTimeInterval: ti target: timer selector: @selector(_timerExpired) userInfo: nil repeats: NO] retain];
+                    // NSLog(@"setting timer: %@", PSTimerCurrent);
+                } else {
+                    // NSLog(@"timer would have been too fast, setting: %@", timer);
+                    [timer performSelector: @selector(_timerExpired) withObject: nil afterDelay: 0];
+                }
+                return;
+            }
+        }
+        NSAssert(NO, @"shouldn’t get here");
+    } else {
+        // NSLog(@"_schedule: no timers");
+    }
+}
+
++ (void)_timerAdded:(PSTimer *)timer;
+{
+    NSAssert1([PSTimerAllTimers indexOfObject: timer] == NSNotFound, @"PSTimerAllTimers already contains %@", timer);
+    [PSTimerAllTimers addObject: timer];
+    [self _schedule];
+}
+
++ (void)_timerDeleted:(PSTimer *)timer;
+{
+    NSAssert1([PSTimerAllTimers indexOfObject: timer] != NSNotFound, @"PSTimerAllTimers does not contain %@", timer);
+    [PSTimerAllTimers removeObject: timer];
+    [self _schedule];
+}
+
+#pragma mark private
+
+- (void)_setFireDate:(NSDate *)date;
+{
+    if (fireDate != date) {
+        [fireDate release];
+        fireDate = [date retain];
+        if (fireDate != nil) {
+            isValid = YES;
+        }
+    }
+}
+
+- (void)_setFireDateFromInterval;
+{
+    [self _setFireDate: [NSDate dateWithTimeIntervalSinceNow: timeInterval]];
+}
+
+- (void)_invalidate;
+{
+    isValid = NO;
+    [[self class] _timerDeleted: self];
+}
+
+- (void)_timerExpired;
+{
+    if (!isValid) return; // in case the timer went off after we were invalidated
+    [self retain]; // make sure we’re still accessible during the invocation
+    // NSLog(@"timer expired: %@", self);
+    if (repeats) {
+        [invocation invoke];
+        if (isValid) {
+            [self _setFireDateFromInterval];
+            [[self class] _schedule];
+            // NSLog(@"timer repeats: %@", self);
+        }
+    } else {
+        [self _invalidate];
+        [invocation invoke];
+    }
+    [self release];
+}
+
+#pragma mark initialize-release
+
+- (id)initWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)anObject repeats:(BOOL)yesOrNo;
+{
+    if ( (self = [self init]) != nil) {
+        invocation = [[NSInvocation invocationWithMethodSignature:
+            [aTarget methodSignatureForSelector: aSelector]] retain];
+        [invocation setSelector: aSelector];
+        [invocation setTarget: aTarget];
+        [invocation setArgument: &self atIndex: 2];
+        userInfo = [anObject retain];
+        repeats = yesOrNo;
+        timeInterval = ti;
+        [invocation retainArguments]; // mimics retain behavior
+        [self _setFireDateFromInterval];
+        [[self class] _timerAdded: self]; // mimics runloop retention behavior
+    }
+    return self;
+}
+
++ (PSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)anObject repeats:(BOOL)yesOrNo;
+{
+    PSTimer *timer = [[self alloc] initWithTimeInterval: ti target: aTarget selector: aSelector userInfo: anObject repeats: yesOrNo];
+    [timer release];
+    return timer;
+}
+
+- (void)dealloc;
+{
+    // NSLog(@"DEALLOC %@", self);
+    isValid = NO;
+    [fireDate release]; fireDate = nil;
+    [invocation release]; invocation = nil;
+    [userInfo release]; userInfo = nil;
+    [super dealloc];
+}
+
+#pragma mark accessing
+
+- (NSDate *)fireDate;
+{
+    return fireDate;
+}
+
+- (void)invalidate;
+{
+    repeats = NO;
+    [self _invalidate];
+}
+
+- (BOOL)isValid;
+{
+    return isValid;
+}
+
+- (id)userInfo;
+{
+    return userInfo;
+}
+
+- (BOOL)isWakeUp;
+{
+    return isWakeUp;
+}
+
+- (void)setWakeUp:(BOOL)doWake;
+{
+    isWakeUp = doWake;
+}
+
+- (NSComparisonResult)compare:(PSTimer *)other;
+{
+    return [fireDate compare: [other fireDate]];
+}
+
+- (NSString *)description;
+{
+    return [NSString stringWithFormat: @"%@: at %@ do %@ on %@", [super description], [self fireDate], NSStringFromSelector([invocation selector]), [[invocation target] class]];
+}
+
+@end
+
+@implementation PSTimer (PSPowerManagerDelegate)
+
++ (BOOL)powerManagerShouldIdleSleep:(PSPowerManager *)powerManager;
+{
+    [PSTimerCurrent invalidate];
+    if (PSTimerOnWake != nil) {
+        NSDate *date = [PSTimerOnWake fireDate];
+        NSLog(@"%lf sec remain until alarm", [date timeIntervalSinceNow]);
+        if ([date timeIntervalSinceNow] > 30) {
+            NSLog(@"going to sleep, setting timer %@", PSTimerOnWake);
+            [PSPowerManager setWakeTime: [[PSTimerOnWake fireDate] addTimeInterval: -15]];
+            return YES;
+        } else {
+            NSLog(@"not setting timer, will attempt to prevent idle sleep");
+            return NO;
+        }
+    }
+    return YES;
+}
+
++ (void)powerManagerWillDemandSleep:(PSPowerManager *)powerManager;
+{
+    [self powerManagerShouldIdleSleep: powerManager];
+    return;
+}
+
++ (void)powerManagerDidWake:(PSPowerManager *)powerManager;
+{
+    if (PSTimerCurrent != nil) {
+        [self _schedule];
+    }
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSWakeAlert.h
===================================================================
--- releases/Pester/1.1b1/Source/PSWakeAlert.h	(revision 62)
+++ releases/Pester/1.1b1/Source/PSWakeAlert.h	(revision 62)
@@ -0,0 +1,16 @@
+//
+//  PSWakeAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Jan 06 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlert.h"
+
+
+@interface PSWakeAlert : PSAlert {
+
+}
+
+@end
Index: releases/Pester/1.1b1/Source/PSWakeAlert.m
===================================================================
--- releases/Pester/1.1b1/Source/PSWakeAlert.m	(revision 62)
+++ releases/Pester/1.1b1/Source/PSWakeAlert.m	(revision 62)
@@ -0,0 +1,45 @@
+//
+//  PSWakeAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Jan 06 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSWakeAlert.h"
+
+static PSWakeAlert *PSWakeAlertShared;
+
+@implementation PSWakeAlert
+
++ (PSAlert *)alert;
+{
+    if (PSWakeAlertShared == nil)
+        PSWakeAlertShared = [[PSWakeAlert alloc] init];
+    return PSWakeAlertShared;
+}
+
+- (void)prepareForAlarm:(PSAlarm *)alarm;
+{
+    [alarm setWakeUp: YES];
+}
+
+- (void)triggerForAlarm:(PSAlarm *)alarm;
+{
+    [self completedForAlarm: alarm];
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    return [@"Wake up computer if asleep" small];
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    [self release];
+    return [[PSWakeAlert alert] retain];
+}
+
+@end
Index: releases/Pester/1.1b1/Source/Pester.pbproj/nicholas.pbxuser
===================================================================
--- releases/Pester/1.1b1/Source/Pester.pbproj/nicholas.pbxuser	(revision 62)
+++ releases/Pester/1.1b1/Source/Pester.pbproj/nicholas.pbxuser	(revision 62)
@@ -0,0 +1,6490 @@
+// !$*UTF8*$!
+{
+	29B97313FDCFA39411CA2CEA = {
+		activeBuildStyle = 4A9504CCFFE6A4B311CA0CBA;
+		activeExecutable = F59B967103538BE201154278;
+		activeTarget = 29B97326FDCFA39411CA2CEA;
+		addToTargets = (
+			29B97326FDCFA39411CA2CEA,
+		);
+		breakpoints = (
+			F596730D0355CFA301407038,
+			F500E5370359719B01AEEDB1,
+			F5B15F74037E42EB01AEEDB1,
+			E1A9DEE703BF3C110089E8B2,
+			E17AED7003C0F4D600B89ACF,
+			E1156BFA03C148E2006717DC,
+			E1156C2C03C394D6006717DC,
+			E117A4AB03C3E2FD00E10BA2,
+		);
+		executables = (
+			F59B967103538BE201154278,
+		);
+		perUserDictionary = {
+			PBXPerProjectTemplateStateSaveDate = 63549866;
+			"PBXTemplateGeometry-F5314676015831810DCA290F" = {
+				ContentSize = "{769, 299}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 23}, {769, 276}}";
+					Split0 = {
+						ActiveTab = 2;
+						ActiveTabName = PBXBuildResultsModule;
+						Collapsed = NO;
+						Frame = "{{0, 0}, {769, 276}}";
+						Split0 = {
+							Frame = "{{0, 129}, {769, 147}}";
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Frame = "{{0, 0}, {952, 321}}";
+						};
+						Tab1 = {
+							Debugger = {
+								Collapsed = NO;
+								Frame = "{{0, 0}, {781, 452}}";
+								Split0 = {
+									Frame = "{{0, 24}, {781, 428}}";
+									Split0 = {
+										Frame = "{{0, 0}, {383, 428}}";
+									};
+									Split1 = {
+										DebugVariablesTableConfiguration = (
+											Name,
+											123,
+											Value,
+											85,
+											Summary,
+											155.123,
+										);
+										Frame = "{{392, 0}, {389, 428}}";
+									};
+									SplitCount = 2;
+								};
+								SplitCount = 1;
+								Tab0 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								Tab1 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								TabCount = 2;
+								TabsVisible = YES;
+							};
+							Frame = "{{0, 0}, {781, 452}}";
+							LauncherConfigVersion = 7;
+						};
+						Tab2 = {
+							Frame = "{{0, 0}, {685, 215}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {685, 215}}";
+							};
+						};
+						Tab3 = {
+							BuildMessageFrame = "{{0, 0}, {771, 92}}";
+							BuildTranscriptFrame = "{{0, 101}, {771, 0}}";
+							BuildTranscriptFrameExpanded = YES;
+							Frame = "{{0, 0}, {769, 123}}";
+						};
+						Tab4 = {
+							Frame = "{{0, 0}, {612, 295}}";
+						};
+						TabCount = 5;
+						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;
+				};
+				NavBarShownByDefault = YES;
+				StatusViewVisible = YES;
+				Template = F5314676015831810DCA290F;
+				ToolbarVisible = YES;
+				WindowLocation = "{509, 0}";
+			};
+			PBXWorkspaceContents = (
+				{
+					LeftSlideOut = {
+						Split0 = {
+							Split0 = {
+								NavContent0 = {
+									bookmark = E1F4C96603C9B1E6001509F3;
+									history = (
+										E1D2937503BD418200F9204E,
+										E1D2937B03BD418200F9204E,
+										E1D2937C03BD418200F9204E,
+										E1D2937E03BD418200F9204E,
+										E1D2938303BD418200F9204E,
+										E1D2938403BD418200F9204E,
+										E1D2938503BD418200F9204E,
+										E1D2938603BD418200F9204E,
+										E195A26403BE251F00186F9B,
+										E195A26503BE251F00186F9B,
+										E195A26603BE251F00186F9B,
+										E195A26703BE251F00186F9B,
+										E195A26803BE251F00186F9B,
+										E195A26C03BE251F00186F9B,
+										E195A26D03BE251F00186F9B,
+										E195A26E03BE251F00186F9B,
+										E195A26F03BE251F00186F9B,
+										E195A27603BE251F00186F9B,
+										E195A27A03BE251F00186F9B,
+										E195A27B03BE251F00186F9B,
+										E195A27D03BE251F00186F9B,
+										E195A27E03BE251F00186F9B,
+										E195A28003BE251F00186F9B,
+										E195A28F03BE251F00186F9B,
+										E19DCB7803BE4A0A00B934BF,
+										E19DCB8203BE4A0A00B934BF,
+										E19DCB8303BE4A0A00B934BF,
+										E19DCC8703BE900300B934BF,
+										E19DCC8903BE900300B934BF,
+										E19DCC8A03BE900300B934BF,
+										E19DCC8E03BE900300B934BF,
+										E19DCC8F03BE900300B934BF,
+										E19DCC9203BE900300B934BF,
+										E19DCC9603BE900300B934BF,
+										E19DCC9C03BE900300B934BF,
+										E19DCC9E03BE900300B934BF,
+										E1A9DEEB03BF480F0089E8B2,
+										E1A9DEEE03BF480F0089E8B2,
+										E1A9DEF003BF480F0089E8B2,
+										E1A9DEF103BF480F0089E8B2,
+										E1A9DEF203BF480F0089E8B2,
+										E11CD2D003BF9B3300C49BEF,
+										E11CD2D103BF9B3300C49BEF,
+										E11CD2D203BF9B3300C49BEF,
+										E11CD2D303BF9B3300C49BEF,
+										E11CD2D403BF9B3300C49BEF,
+										E11CD2D503BF9B3300C49BEF,
+										E11CD2D603BF9B3300C49BEF,
+										E11CD2D803BF9B3300C49BEF,
+										E11CD2E003BF9B3300C49BEF,
+										E17AED7303C0F5D300B89ACF,
+										E17AED7403C0F5D300B89ACF,
+										E17AED7503C0F5D300B89ACF,
+										E17AED7603C0F5D300B89ACF,
+										E17AED7703C0F5D300B89ACF,
+										E17AED7803C0F5D300B89ACF,
+										E17AED7903C0F5D300B89ACF,
+										E17AED7A03C0F5D300B89ACF,
+										E17AED7B03C0F5D300B89ACF,
+										E17AED7D03C0F5D300B89ACF,
+										E17AED8003C0F5D300B89ACF,
+										E17AED8403C0F5D300B89ACF,
+										E17AED8703C0F5D300B89ACF,
+										E17AED8803C0F5D300B89ACF,
+										E117A4AC03C3E9C600E10BA2,
+										E117A4AD03C3E9C600E10BA2,
+										E117A4AE03C3E9C600E10BA2,
+										E117A4AF03C3E9C600E10BA2,
+										E117A4B003C3E9C600E10BA2,
+										E1BF6E9A03C95F4E00050002,
+										E1BF6E9D03C95F4E00050002,
+										E1BF6E9E03C95F4E00050002,
+										E1BF6E9F03C95F4E00050002,
+										E1BF6EA003C95F4E00050002,
+										E1BF6EA103C95F4E00050002,
+										E1BF6EA203C95F4E00050002,
+										E1BF6EA903C95F4E00050002,
+										E1FCECFD03C972CF001509F3,
+										E19FD3A203C9985C001509F3,
+										E1AFB0D103C9A59C001509F3,
+										E1AFB0D203C9A59C001509F3,
+										E1AFB0D303C9A59C001509F3,
+										E1AFB0D403C9A59C001509F3,
+										E1AFB0D503C9A59C001509F3,
+										E1AFB0D603C9A59C001509F3,
+										E1AFB0D703C9A59C001509F3,
+										E1AFB0D803C9A59C001509F3,
+										E1AFB0D903C9A59C001509F3,
+										E1AFB0DA03C9A59C001509F3,
+										E1AFB0DB03C9A59C001509F3,
+										E1AFB0DE03C9A59C001509F3,
+										E1C6414303C9AC4B001509F3,
+										E1C6414403C9AC4B001509F3,
+										E1C6414503C9AC4B001509F3,
+										E1F4C96203C9B1E6001509F3,
+										E1F4C96303C9B1E6001509F3,
+										E1AFB0CE03C9A59C001509F3,
+									);
+									prevStack = (
+										E1D2939103BD418200F9204E,
+										E1D2939203BD418200F9204E,
+										E1D2939503BD418200F9204E,
+										E1D2939703BD418200F9204E,
+										E1D293B003BD418200F9204E,
+										E1D293B403BD418200F9204E,
+										E1D293B503BD418200F9204E,
+										E1D293B703BD418200F9204E,
+										E1D293B903BD418200F9204E,
+										E1D293BA03BD418200F9204E,
+										E1D293BB03BD418200F9204E,
+										E1D293BC03BD418200F9204E,
+										E1D293BD03BD418200F9204E,
+										E1D293BE03BD418200F9204E,
+										E1D293BF03BD418200F9204E,
+										E1D293C003BD418200F9204E,
+										E1D293C103BD418200F9204E,
+										E1D293C203BD418200F9204E,
+										E1D293C403BD418200F9204E,
+										E1D293C503BD418200F9204E,
+										E1D293C603BD418200F9204E,
+										E1D293C703BD418200F9204E,
+										E1D293C803BD418200F9204E,
+										E1D293C903BD418200F9204E,
+										E1D293CA03BD418200F9204E,
+										E1D293CB03BD418200F9204E,
+										E1D293CC03BD418200F9204E,
+										E1D293CD03BD418200F9204E,
+										E1D293CE03BD418200F9204E,
+										E1D293CF03BD418200F9204E,
+										E1D293D003BD418200F9204E,
+										E1D293D103BD418200F9204E,
+										E1D293D203BD418200F9204E,
+										E1D293D303BD418200F9204E,
+										E1D293D403BD418200F9204E,
+										E1D293D503BD418200F9204E,
+										E1D293D603BD418200F9204E,
+										E1D293D703BD418200F9204E,
+										E1D293D803BD418200F9204E,
+										E1D293D903BD418200F9204E,
+										E1D293DA03BD418200F9204E,
+										E1D293DB03BD418200F9204E,
+										E1D293DC03BD418200F9204E,
+										E1D293DD03BD418200F9204E,
+										E1D293DE03BD418200F9204E,
+										E1D293DF03BD418200F9204E,
+										E1D293E003BD418200F9204E,
+										E1D293E103BD418200F9204E,
+										E1D293E203BD418200F9204E,
+										E1D293E303BD418200F9204E,
+										E1D293E403BD418200F9204E,
+										E1D293E503BD418200F9204E,
+										E1D293E603BD418200F9204E,
+										E1D293E703BD418200F9204E,
+										E1D293E803BD418200F9204E,
+										E1D293E903BD418200F9204E,
+										E1D293EA03BD418200F9204E,
+										E1D293EB03BD418200F9204E,
+										E1D293EC03BD418200F9204E,
+										E1D293F103BD418200F9204E,
+										E1D293F203BD418200F9204E,
+										E1D293F303BD418200F9204E,
+										E1D293F403BD418200F9204E,
+										E1D293F503BD418200F9204E,
+										E1D293F703BD418200F9204E,
+										E1D293F803BD418200F9204E,
+										E1D293F903BD418200F9204E,
+										E1D293FC03BD418200F9204E,
+										E1D293FD03BD418200F9204E,
+										E1D293FE03BD418200F9204E,
+										E1D293FF03BD418200F9204E,
+										E1D2940003BD418200F9204E,
+										E1D2940103BD418200F9204E,
+										E1D2940203BD418200F9204E,
+										E1D2940303BD418200F9204E,
+										E1D2940403BD418200F9204E,
+										E1D2940503BD418200F9204E,
+										E1D2940603BD418200F9204E,
+										E1D2940703BD418200F9204E,
+										E1D2940803BD418200F9204E,
+										E1D2942C03BD418200F9204E,
+										E1D2942D03BD418200F9204E,
+										E1D2942E03BD418200F9204E,
+										E1D2942F03BD418200F9204E,
+										E1D2943103BD418200F9204E,
+										E1D2943903BD418200F9204E,
+										E195A29203BE251F00186F9B,
+										E195A29503BE251F00186F9B,
+										E195A29603BE251F00186F9B,
+										E195A29703BE251F00186F9B,
+										E195A29803BE251F00186F9B,
+										E195A29903BE251F00186F9B,
+										E195A2AC03BE251F00186F9B,
+										E195A2AD03BE251F00186F9B,
+										E195A2AE03BE251F00186F9B,
+										E195A2B003BE251F00186F9B,
+										E195A2B103BE251F00186F9B,
+										E195A2B403BE251F00186F9B,
+										E195A2B503BE251F00186F9B,
+										E195A2B603BE251F00186F9B,
+										E195A2B703BE251F00186F9B,
+										E195A2B803BE251F00186F9B,
+										E195A2B903BE251F00186F9B,
+										E195A2BA03BE251F00186F9B,
+										E195A2BB03BE251F00186F9B,
+										E195A2BC03BE251F00186F9B,
+										E195A2BD03BE251F00186F9B,
+										E195A2BE03BE251F00186F9B,
+										E195A2C103BE251F00186F9B,
+										E195A2C203BE251F00186F9B,
+										E195A2C303BE251F00186F9B,
+										E195A2C403BE251F00186F9B,
+										E195A2C503BE251F00186F9B,
+										E195A2C603BE251F00186F9B,
+										E195A2C703BE251F00186F9B,
+										E195A2C803BE251F00186F9B,
+										E195A2C903BE251F00186F9B,
+										E195A2CA03BE251F00186F9B,
+										E195A2CB03BE251F00186F9B,
+										E195A2CD03BE251F00186F9B,
+										E195A2E003BE251F00186F9B,
+										E195A2E103BE251F00186F9B,
+										E195A2E203BE251F00186F9B,
+										E195A2E803BE251F00186F9B,
+										E195A2E903BE251F00186F9B,
+										E195A2EA03BE251F00186F9B,
+										E195A2EB03BE251F00186F9B,
+										E195A2EC03BE251F00186F9B,
+										E195A2ED03BE251F00186F9B,
+										E195A2F003BE251F00186F9B,
+										E195A2F103BE251F00186F9B,
+										E195A2F303BE251F00186F9B,
+										E195A2F503BE251F00186F9B,
+										E195A2F703BE251F00186F9B,
+										E195A2F903BE251F00186F9B,
+										E195A2FC03BE251F00186F9B,
+										E195A2FE03BE251F00186F9B,
+										E19DCB8503BE4A0A00B934BF,
+										E19DCB8903BE4A0A00B934BF,
+										E19DCB8B03BE4A0A00B934BF,
+										E19DCB8C03BE4A0A00B934BF,
+										E19DCB8E03BE4A0A00B934BF,
+										E19DCB9003BE4A0A00B934BF,
+										E19DCB9103BE4A0A00B934BF,
+										E19DCB9303BE4A0A00B934BF,
+										E19DCB9403BE4A0A00B934BF,
+										E19DCB9503BE4A0A00B934BF,
+										E19DCB9603BE4A0A00B934BF,
+										E19DCB9703BE4A0A00B934BF,
+										E19DCB9803BE4A0A00B934BF,
+										E19DCB9903BE4A0A00B934BF,
+										E19DCB9A03BE4A0A00B934BF,
+										E19DCB9B03BE4A0A00B934BF,
+										E19DCB9C03BE4A0A00B934BF,
+										E19DCB9D03BE4A0A00B934BF,
+										E19DCB9E03BE4A0A00B934BF,
+										E19DCB9F03BE4A0A00B934BF,
+										E19DCBA103BE4A0A00B934BF,
+										E19DCBA203BE4A0A00B934BF,
+										E19DCBA803BE4A0A00B934BF,
+										E19DCBA903BE4A0A00B934BF,
+										E19DCBAA03BE4A0A00B934BF,
+										E19DCBAB03BE4A0A00B934BF,
+										E19DCBAC03BE4A0A00B934BF,
+										E19DCBAD03BE4A0A00B934BF,
+										E19DCBAE03BE4A0A00B934BF,
+										E19DCBB203BE4A0A00B934BF,
+										E19DCBB603BE4A0A00B934BF,
+										E19DCBBC03BE4A0A00B934BF,
+										E19DCBBD03BE4A0A00B934BF,
+										E19DCCA203BE900300B934BF,
+										E19DCCA303BE900300B934BF,
+										E19DCCA403BE900300B934BF,
+										E19DCCA603BE900300B934BF,
+										E19DCCA703BE900300B934BF,
+										E19DCCA903BE900300B934BF,
+										E19DCCAC03BE900300B934BF,
+										E19DCCAE03BE900300B934BF,
+										E19DCCB203BE900300B934BF,
+										E19DCCB303BE900300B934BF,
+										E19DCCB403BE900300B934BF,
+										E19DCCB503BE900300B934BF,
+										E19DCCB603BE900300B934BF,
+										E19DCCB703BE900300B934BF,
+										E19DCCB903BE900300B934BF,
+										E19DCCBA03BE900300B934BF,
+										E19DCCBB03BE900300B934BF,
+										E19DCCBC03BE900300B934BF,
+										E19DCCBD03BE900300B934BF,
+										E19DCCBE03BE900300B934BF,
+										E19DCCBF03BE900300B934BF,
+										E19DCCC003BE900300B934BF,
+										E19DCCC103BE900300B934BF,
+										E19DCCC203BE900300B934BF,
+										E19DCCC403BE900300B934BF,
+										E19DCCC503BE900300B934BF,
+										E19DCCC603BE900300B934BF,
+										E19DCCC703BE900300B934BF,
+										E19DCCC803BE900300B934BF,
+										E19DCCC903BE900300B934BF,
+										E19DCCCA03BE900300B934BF,
+										E19DCCCB03BE900300B934BF,
+										E19DCCCF03BE900300B934BF,
+										E19DCCD103BE900300B934BF,
+										E19DCCD203BE900300B934BF,
+										E19DCCD403BE900300B934BF,
+										E19DCCD503BE900300B934BF,
+										E19DCCD603BE900300B934BF,
+										E19DCCD703BE900300B934BF,
+										E19DCCD803BE900300B934BF,
+										E19DCCD903BE900300B934BF,
+										E19DCCDA03BE900300B934BF,
+										E19DCCDB03BE900300B934BF,
+										E1A9DEF703BF480F0089E8B2,
+										E1A9DEFB03BF480F0089E8B2,
+										E1A9DEFC03BF480F0089E8B2,
+										E1A9DEFD03BF480F0089E8B2,
+										E1A9DEFE03BF480F0089E8B2,
+										E1A9DF0203BF480F0089E8B2,
+										E1A9DF0303BF480F0089E8B2,
+										E1A9DF0403BF480F0089E8B2,
+										E1A9DF0503BF480F0089E8B2,
+										E1A9DF0603BF480F0089E8B2,
+										E1A9DF0703BF480F0089E8B2,
+										E1A9DF0803BF480F0089E8B2,
+										E11CD2E303BF9B3300C49BEF,
+										E11CD2E503BF9B3300C49BEF,
+										E11CD2E603BF9B3300C49BEF,
+										E11CD2E703BF9B3300C49BEF,
+										E11CD2E803BF9B3300C49BEF,
+										E11CD2E903BF9B3300C49BEF,
+										E11CD2EA03BF9B3300C49BEF,
+										E11CD2EC03BF9B3300C49BEF,
+										E11CD2ED03BF9B3300C49BEF,
+										E11CD2EF03BF9B3300C49BEF,
+										E17AED8E03C0F5D300B89ACF,
+										E17AED8F03C0F5D300B89ACF,
+										E17AED9003C0F5D300B89ACF,
+										E17AED9103C0F5D300B89ACF,
+										E17AED9203C0F5D300B89ACF,
+										E17AED9303C0F5D300B89ACF,
+										E17AED9403C0F5D300B89ACF,
+										E17AED9503C0F5D300B89ACF,
+										E17AED9603C0F5D300B89ACF,
+										E17AEDA003C0F5D300B89ACF,
+										E17AEDA103C0F5D300B89ACF,
+										E17AEDA403C0F5D300B89ACF,
+										E17AEDA503C0F5D300B89ACF,
+										E17AEDA603C0F5D300B89ACF,
+										E17AEDA703C0F5D300B89ACF,
+										E17AEDA803C0F5D300B89ACF,
+										E17AEDA903C0F5D300B89ACF,
+										E17AEDAA03C0F5D300B89ACF,
+										E17AEDAB03C0F5D300B89ACF,
+										E17AEDAC03C0F5D300B89ACF,
+										E17AEDAD03C0F5D300B89ACF,
+										E17AEDAE03C0F5D300B89ACF,
+										E17AEDAF03C0F5D300B89ACF,
+										E17AEDB003C0F5D300B89ACF,
+										E17AEDB103C0F5D300B89ACF,
+										E17AEDB203C0F5D300B89ACF,
+										E17AEDB503C0F5D300B89ACF,
+										E17AEDB603C0F5D300B89ACF,
+										E17AEDB803C0F5D300B89ACF,
+										E17AEDB903C0F5D300B89ACF,
+										E17AEDBB03C0F5D300B89ACF,
+										E17AEDBD03C0F5D300B89ACF,
+										E17AEDBE03C0F5D300B89ACF,
+										E17AEDC003C0F5D300B89ACF,
+										E17AEDC103C0F5D300B89ACF,
+										E17AEDC203C0F5D300B89ACF,
+										E17AEDC303C0F5D300B89ACF,
+										E17AEDC603C0F5D300B89ACF,
+										E17AEDC803C0F5D300B89ACF,
+										E117A4B203C3E9C600E10BA2,
+										E117A4B303C3E9C600E10BA2,
+										E117A4B403C3E9C600E10BA2,
+										E1096EB803C3EDB0009B92C1,
+										E1BF6EAC03C95F4E00050002,
+										E1BF6EAE03C95F4E00050002,
+										E1BF6EB003C95F4E00050002,
+										E1BF6EB503C95F4E00050002,
+										E1BF6EBB03C95F4E00050002,
+										E1BF6EBC03C95F4E00050002,
+										E1BF6EC103C95F4E00050002,
+										E1BF6EC203C95F4E00050002,
+										E1BF6EC403C95F4E00050002,
+										E1BF6EDA03C95F4E00050002,
+										E1BF6EDF03C95F4E00050002,
+										E1BF6EEF03C95F4E00050002,
+										E198FA9803C963C700050002,
+										E19FD3A603C9985C001509F3,
+										E19FD3A703C9985C001509F3,
+										E19FD3A803C9985C001509F3,
+										E19FD3A903C9985C001509F3,
+										E19FD3AA03C9985C001509F3,
+										E1AFB0E003C9A59C001509F3,
+										E1AFB0E103C9A59C001509F3,
+										E1AFB0E203C9A59C001509F3,
+										E1AFB0E303C9A59C001509F3,
+										E1AFB0E403C9A59C001509F3,
+										E1AFB0E503C9A59C001509F3,
+										E1AFB0E603C9A59C001509F3,
+										E1AFB0E703C9A59C001509F3,
+										E1AFB0E803C9A59C001509F3,
+										E1AFB0E903C9A59C001509F3,
+										E1AFB0EA03C9A59C001509F3,
+										E1AFB0EB03C9A59C001509F3,
+										E1AFB0EC03C9A59C001509F3,
+										E1AFB0ED03C9A59C001509F3,
+										E1AFB0EE03C9A59C001509F3,
+										E1AFB0EF03C9A59C001509F3,
+										E1AFB0F003C9A59C001509F3,
+										E1AFB0F103C9A59C001509F3,
+										E1AFB0F203C9A59C001509F3,
+										E1AFB0F303C9A59C001509F3,
+										E1AFB0F403C9A59C001509F3,
+										E1AFB0F503C9A59C001509F3,
+										E1AFB0F603C9A59C001509F3,
+										E1AFB0F703C9A59C001509F3,
+										E1AFB0F803C9A59C001509F3,
+										E1AFB0F903C9A59C001509F3,
+										E1AFB0FA03C9A59C001509F3,
+										E1AFB0FB03C9A59C001509F3,
+										E1AFB0FC03C9A59C001509F3,
+										E1AFB0FD03C9A59C001509F3,
+										E1AFB0FE03C9A59C001509F3,
+										E1AFB0FF03C9A59C001509F3,
+										E1AFB10003C9A59C001509F3,
+										E1AFB10103C9A59C001509F3,
+										E1AFB10203C9A59C001509F3,
+										E1AFB10303C9A59C001509F3,
+										E1AFB10403C9A59C001509F3,
+										E1AFB10503C9A59C001509F3,
+										E1AFB10603C9A59C001509F3,
+										E1AFB10703C9A59C001509F3,
+										E1AFB10803C9A59C001509F3,
+										E1AFB10903C9A59C001509F3,
+										E1AFB10A03C9A59C001509F3,
+										E1AFB10B03C9A59C001509F3,
+										E1AFB10C03C9A59C001509F3,
+										E1AFB10D03C9A59C001509F3,
+										E1C6414703C9AC4B001509F3,
+										E1C6414803C9AC4B001509F3,
+										E1C6414903C9AC4B001509F3,
+										E1C6414A03C9AC4B001509F3,
+										E1C6414B03C9AC4B001509F3,
+										E1C6414C03C9AC4B001509F3,
+										E1C6414D03C9AC4B001509F3,
+										E1C6414E03C9AC4B001509F3,
+										E1C6414F03C9AC4B001509F3,
+										E1C6415003C9AC4B001509F3,
+										E1C6415103C9AC4B001509F3,
+										E1C6415203C9AC4B001509F3,
+										E1C6415303C9AC4B001509F3,
+										E1C6415403C9AC4B001509F3,
+										E1F4C96403C9B1E6001509F3,
+										E1F4C96503C9B1E6001509F3,
+									);
+								};
+								NavCount = 1;
+								NavGeometry0 = {
+									Frame = "{{0, 0}, {689, 635}}";
+									NavBarVisible = YES;
+								};
+								NavSplitVertical = NO;
+							};
+							SplitCount = 1;
+							Tab1 = {
+								Debugger = {
+									Split0 = {
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									TabCount = 2;
+								};
+								LauncherConfigVersion = 7;
+							};
+							Tab2 = {
+								LauncherConfigVersion = 3;
+								Runner = {
+								};
+							};
+							TabCount = 5;
+						};
+						SplitCount = 1;
+						Tab1 = {
+							OptionsSetName = "Flat, project classes";
+						};
+						TabCount = 5;
+					};
+				},
+				{
+					LeftSlideOut = {
+						Split0 = {
+							Split0 = {
+								NavCount = 1;
+								NavGeometry0 = {
+									Frame = "{{0, 0}, {955, 150}}";
+									NavBarVisible = YES;
+								};
+								NavSplitVertical = NO;
+							};
+							SplitCount = 1;
+							Tab1 = {
+								Debugger = {
+									Split0 = {
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									TabCount = 2;
+								};
+								LauncherConfigVersion = 7;
+							};
+							Tab2 = {
+								LauncherConfigVersion = 3;
+								Runner = {
+								};
+							};
+							TabCount = 5;
+						};
+						SplitCount = 1;
+						Tab1 = {
+							OptionsSetName = "Hierarchy, all classes";
+						};
+						TabCount = 5;
+					};
+				},
+			);
+			PBXWorkspaceGeometries = (
+				{
+					ContentSize = "{968, 658}";
+					LeftSlideOut = {
+						ActiveTab = 0;
+						ActiveTabName = PBXGroupTreeModule;
+						Collapsed = NO;
+						Frame = "{{0, 23}, {968, 635}}";
+						Split0 = {
+							Collapsed = NO;
+							Frame = "{{279, 0}, {689, 635}}";
+							Split0 = {
+								Frame = "{{0, 0}, {689, 635}}";
+							};
+							SplitCount = 1;
+							Tab0 = {
+								Frame = "{{0, 0}, {681, 289}}";
+							};
+							Tab1 = {
+								Debugger = {
+									Collapsed = NO;
+									Frame = "{{0, 0}, {681, 150}}";
+									Split0 = {
+										Frame = "{{0, 24}, {681, 126}}";
+										Split0 = {
+											Frame = "{{0, 0}, {333, 126}}";
+										};
+										Split1 = {
+											DebugVariablesTableConfiguration = (
+												Name,
+												123,
+												Value,
+												85,
+												Summary,
+												105.123,
+											);
+											Frame = "{{342, 0}, {339, 126}}";
+										};
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									Tab0 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									Tab1 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									TabCount = 2;
+									TabsVisible = YES;
+								};
+								Frame = "{{0, 0}, {681, 120}}";
+								LauncherConfigVersion = 7;
+							};
+							Tab2 = {
+								Frame = "{{0, 0}, {681, 234}}";
+								LauncherConfigVersion = 3;
+								Runner = {
+									Frame = "{{0, 0}, {681, 234}}";
+								};
+							};
+							Tab3 = {
+								BuildMessageFrame = "{{0, 0}, {683, 205}}";
+								BuildTranscriptFrame = "{{0, 214}, {683, 2}}";
+								BuildTranscriptFrameExpanded = YES;
+								Frame = "{{0, 0}, {681, 238}}";
+							};
+							Tab4 = {
+								Frame = "{{0, 0}, {612, 295}}";
+							};
+							TabCount = 5;
+							TabsVisible = NO;
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Frame = "{{0, 0}, {255, 635}}";
+							GroupTreeTableConfiguration = (
+								TargetStatusColumn,
+								18,
+								MainColumn,
+								222,
+							);
+						};
+						Tab1 = {
+							ClassesFrame = "{{0, 0}, {235, 381}}";
+							ClassesTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXClassColumnIdentifier,
+								192,
+							);
+							Frame = "{{0, 0}, {233, 635}}";
+							MembersFrame = "{{0, 390}, {235, 245}}";
+							MembersTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXMethodColumnIdentifier,
+								191,
+							);
+						};
+						Tab2 = {
+							Frame = "{{0, 0}, {217, 635}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {239, 554}}";
+							TargetTableConfiguration = (
+								ActiveObject,
+								16,
+								ObjectNames,
+								206.296,
+							);
+						};
+						Tab4 = {
+							BreakpointsTreeTableConfiguration = (
+								breakpointColumn,
+								197,
+								enabledColumn,
+								31,
+							);
+							Frame = "{{0, 0}, {250, 635}}";
+						};
+						TabCount = 5;
+						TabsVisible = YES;
+					};
+					NavBarShownByDefault = YES;
+					StatusViewVisible = YES;
+					Template = 64ABBB4501FA494900185B06;
+					ToolbarVisible = YES;
+					WindowLocation = "{15, 277}";
+				},
+				{
+					ContentSize = "{955, 237}";
+					LeftSlideOut = {
+						Collapsed = NO;
+						Frame = "{{0, 23}, {955, 214}}";
+						Split0 = {
+							ActiveTab = 1;
+							ActiveTabName = PBXRunSessionModule;
+							Collapsed = YES;
+							Frame = "{{0, 0}, {955, 214}}";
+							Split0 = {
+								Frame = "{{1e+06, 1e+06}, {955, 0}}";
+							};
+							SplitCount = 1;
+							Tab0 = {
+								Frame = "{{0, 0}, {804, 321}}";
+							};
+							Tab1 = {
+								Debugger = {
+									Collapsed = NO;
+									Frame = "{{0, 0}, {594, 274}}";
+									Split0 = {
+										Frame = "{{0, 24}, {594, 250}}";
+										Split0 = {
+											Frame = "{{0, 0}, {290, 250}}";
+										};
+										Split1 = {
+											DebugVariablesTableConfiguration = (
+												Name,
+												123,
+												Value,
+												85,
+												Summary,
+												62.123,
+											);
+											Frame = "{{299, 0}, {295, 250}}";
+										};
+										SplitCount = 2;
+									};
+									SplitCount = 1;
+									Tab0 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									Tab1 = {
+										Frame = "{{0, 0}, {100, 50}}";
+									};
+									TabCount = 2;
+									TabsVisible = YES;
+								};
+								Frame = "{{0, 0}, {594, 274}}";
+								LauncherConfigVersion = 7;
+							};
+							Tab2 = {
+								Frame = "{{0, 0}, {955, 208}}";
+								LauncherConfigVersion = 3;
+								Runner = {
+									Frame = "{{0, 0}, {955, 208}}";
+								};
+							};
+							Tab3 = {
+								BuildMessageFrame = "{{0, 0}, {614, 262}}";
+								BuildTranscriptFrame = "{{0, 271}, {614, 2}}";
+								BuildTranscriptFrameExpanded = YES;
+								Frame = "{{0, 0}, {612, 295}}";
+							};
+							Tab4 = {
+								Frame = "{{0, 0}, {612, 295}}";
+							};
+							TabCount = 5;
+							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;
+					};
+					NavBarShownByDefault = YES;
+					StatusViewVisible = YES;
+					Template = F5534CB2020F3F8A0DCA290F;
+					ToolbarVisible = YES;
+					WindowLocation = "{15, 0}";
+				},
+			);
+			PBXWorkspaceStateSaveDate = 63549866;
+		};
+		perUserProjectItems = {
+			E1096EB803C3EDB0009B92C1 = E1096EB803C3EDB0009B92C1;
+			E117A4AC03C3E9C600E10BA2 = E117A4AC03C3E9C600E10BA2;
+			E117A4AD03C3E9C600E10BA2 = E117A4AD03C3E9C600E10BA2;
+			E117A4AE03C3E9C600E10BA2 = E117A4AE03C3E9C600E10BA2;
+			E117A4AF03C3E9C600E10BA2 = E117A4AF03C3E9C600E10BA2;
+			E117A4B003C3E9C600E10BA2 = E117A4B003C3E9C600E10BA2;
+			E117A4B203C3E9C600E10BA2 = E117A4B203C3E9C600E10BA2;
+			E117A4B303C3E9C600E10BA2 = E117A4B303C3E9C600E10BA2;
+			E117A4B403C3E9C600E10BA2 = E117A4B403C3E9C600E10BA2;
+			E11CD2D003BF9B3300C49BEF = E11CD2D003BF9B3300C49BEF;
+			E11CD2D103BF9B3300C49BEF = E11CD2D103BF9B3300C49BEF;
+			E11CD2D203BF9B3300C49BEF = E11CD2D203BF9B3300C49BEF;
+			E11CD2D303BF9B3300C49BEF = E11CD2D303BF9B3300C49BEF;
+			E11CD2D403BF9B3300C49BEF = E11CD2D403BF9B3300C49BEF;
+			E11CD2D503BF9B3300C49BEF = E11CD2D503BF9B3300C49BEF;
+			E11CD2D603BF9B3300C49BEF = E11CD2D603BF9B3300C49BEF;
+			E11CD2D803BF9B3300C49BEF = E11CD2D803BF9B3300C49BEF;
+			E11CD2E003BF9B3300C49BEF = E11CD2E003BF9B3300C49BEF;
+			E11CD2E303BF9B3300C49BEF = E11CD2E303BF9B3300C49BEF;
+			E11CD2E503BF9B3300C49BEF = E11CD2E503BF9B3300C49BEF;
+			E11CD2E603BF9B3300C49BEF = E11CD2E603BF9B3300C49BEF;
+			E11CD2E703BF9B3300C49BEF = E11CD2E703BF9B3300C49BEF;
+			E11CD2E803BF9B3300C49BEF = E11CD2E803BF9B3300C49BEF;
+			E11CD2E903BF9B3300C49BEF = E11CD2E903BF9B3300C49BEF;
+			E11CD2EA03BF9B3300C49BEF = E11CD2EA03BF9B3300C49BEF;
+			E11CD2EC03BF9B3300C49BEF = E11CD2EC03BF9B3300C49BEF;
+			E11CD2ED03BF9B3300C49BEF = E11CD2ED03BF9B3300C49BEF;
+			E11CD2EF03BF9B3300C49BEF = E11CD2EF03BF9B3300C49BEF;
+			E17AED7303C0F5D300B89ACF = E17AED7303C0F5D300B89ACF;
+			E17AED7403C0F5D300B89ACF = E17AED7403C0F5D300B89ACF;
+			E17AED7503C0F5D300B89ACF = E17AED7503C0F5D300B89ACF;
+			E17AED7603C0F5D300B89ACF = E17AED7603C0F5D300B89ACF;
+			E17AED7703C0F5D300B89ACF = E17AED7703C0F5D300B89ACF;
+			E17AED7803C0F5D300B89ACF = E17AED7803C0F5D300B89ACF;
+			E17AED7903C0F5D300B89ACF = E17AED7903C0F5D300B89ACF;
+			E17AED7A03C0F5D300B89ACF = E17AED7A03C0F5D300B89ACF;
+			E17AED7B03C0F5D300B89ACF = E17AED7B03C0F5D300B89ACF;
+			E17AED7D03C0F5D300B89ACF = E17AED7D03C0F5D300B89ACF;
+			E17AED8003C0F5D300B89ACF = E17AED8003C0F5D300B89ACF;
+			E17AED8403C0F5D300B89ACF = E17AED8403C0F5D300B89ACF;
+			E17AED8703C0F5D300B89ACF = E17AED8703C0F5D300B89ACF;
+			E17AED8803C0F5D300B89ACF = E17AED8803C0F5D300B89ACF;
+			E17AED8E03C0F5D300B89ACF = E17AED8E03C0F5D300B89ACF;
+			E17AED8F03C0F5D300B89ACF = E17AED8F03C0F5D300B89ACF;
+			E17AED9003C0F5D300B89ACF = E17AED9003C0F5D300B89ACF;
+			E17AED9103C0F5D300B89ACF = E17AED9103C0F5D300B89ACF;
+			E17AED9203C0F5D300B89ACF = E17AED9203C0F5D300B89ACF;
+			E17AED9303C0F5D300B89ACF = E17AED9303C0F5D300B89ACF;
+			E17AED9403C0F5D300B89ACF = E17AED9403C0F5D300B89ACF;
+			E17AED9503C0F5D300B89ACF = E17AED9503C0F5D300B89ACF;
+			E17AED9603C0F5D300B89ACF = E17AED9603C0F5D300B89ACF;
+			E17AEDA003C0F5D300B89ACF = E17AEDA003C0F5D300B89ACF;
+			E17AEDA103C0F5D300B89ACF = E17AEDA103C0F5D300B89ACF;
+			E17AEDA403C0F5D300B89ACF = E17AEDA403C0F5D300B89ACF;
+			E17AEDA503C0F5D300B89ACF = E17AEDA503C0F5D300B89ACF;
+			E17AEDA603C0F5D300B89ACF = E17AEDA603C0F5D300B89ACF;
+			E17AEDA703C0F5D300B89ACF = E17AEDA703C0F5D300B89ACF;
+			E17AEDA803C0F5D300B89ACF = E17AEDA803C0F5D300B89ACF;
+			E17AEDA903C0F5D300B89ACF = E17AEDA903C0F5D300B89ACF;
+			E17AEDAA03C0F5D300B89ACF = E17AEDAA03C0F5D300B89ACF;
+			E17AEDAB03C0F5D300B89ACF = E17AEDAB03C0F5D300B89ACF;
+			E17AEDAC03C0F5D300B89ACF = E17AEDAC03C0F5D300B89ACF;
+			E17AEDAD03C0F5D300B89ACF = E17AEDAD03C0F5D300B89ACF;
+			E17AEDAE03C0F5D300B89ACF = E17AEDAE03C0F5D300B89ACF;
+			E17AEDAF03C0F5D300B89ACF = E17AEDAF03C0F5D300B89ACF;
+			E17AEDB003C0F5D300B89ACF = E17AEDB003C0F5D300B89ACF;
+			E17AEDB103C0F5D300B89ACF = E17AEDB103C0F5D300B89ACF;
+			E17AEDB203C0F5D300B89ACF = E17AEDB203C0F5D300B89ACF;
+			E17AEDB503C0F5D300B89ACF = E17AEDB503C0F5D300B89ACF;
+			E17AEDB603C0F5D300B89ACF = E17AEDB603C0F5D300B89ACF;
+			E17AEDB803C0F5D300B89ACF = E17AEDB803C0F5D300B89ACF;
+			E17AEDB903C0F5D300B89ACF = E17AEDB903C0F5D300B89ACF;
+			E17AEDBB03C0F5D300B89ACF = E17AEDBB03C0F5D300B89ACF;
+			E17AEDBD03C0F5D300B89ACF = E17AEDBD03C0F5D300B89ACF;
+			E17AEDBE03C0F5D300B89ACF = E17AEDBE03C0F5D300B89ACF;
+			E17AEDC003C0F5D300B89ACF = E17AEDC003C0F5D300B89ACF;
+			E17AEDC103C0F5D300B89ACF = E17AEDC103C0F5D300B89ACF;
+			E17AEDC203C0F5D300B89ACF = E17AEDC203C0F5D300B89ACF;
+			E17AEDC303C0F5D300B89ACF = E17AEDC303C0F5D300B89ACF;
+			E17AEDC603C0F5D300B89ACF = E17AEDC603C0F5D300B89ACF;
+			E17AEDC803C0F5D300B89ACF = E17AEDC803C0F5D300B89ACF;
+			E195A26403BE251F00186F9B = E195A26403BE251F00186F9B;
+			E195A26503BE251F00186F9B = E195A26503BE251F00186F9B;
+			E195A26603BE251F00186F9B = E195A26603BE251F00186F9B;
+			E195A26703BE251F00186F9B = E195A26703BE251F00186F9B;
+			E195A26803BE251F00186F9B = E195A26803BE251F00186F9B;
+			E195A26C03BE251F00186F9B = E195A26C03BE251F00186F9B;
+			E195A26D03BE251F00186F9B = E195A26D03BE251F00186F9B;
+			E195A26E03BE251F00186F9B = E195A26E03BE251F00186F9B;
+			E195A26F03BE251F00186F9B = E195A26F03BE251F00186F9B;
+			E195A27603BE251F00186F9B = E195A27603BE251F00186F9B;
+			E195A27A03BE251F00186F9B = E195A27A03BE251F00186F9B;
+			E195A27B03BE251F00186F9B = E195A27B03BE251F00186F9B;
+			E195A27D03BE251F00186F9B = E195A27D03BE251F00186F9B;
+			E195A27E03BE251F00186F9B = E195A27E03BE251F00186F9B;
+			E195A28003BE251F00186F9B = E195A28003BE251F00186F9B;
+			E195A28F03BE251F00186F9B = E195A28F03BE251F00186F9B;
+			E195A29203BE251F00186F9B = E195A29203BE251F00186F9B;
+			E195A29503BE251F00186F9B = E195A29503BE251F00186F9B;
+			E195A29603BE251F00186F9B = E195A29603BE251F00186F9B;
+			E195A29703BE251F00186F9B = E195A29703BE251F00186F9B;
+			E195A29803BE251F00186F9B = E195A29803BE251F00186F9B;
+			E195A29903BE251F00186F9B = E195A29903BE251F00186F9B;
+			E195A2AC03BE251F00186F9B = E195A2AC03BE251F00186F9B;
+			E195A2AD03BE251F00186F9B = E195A2AD03BE251F00186F9B;
+			E195A2AE03BE251F00186F9B = E195A2AE03BE251F00186F9B;
+			E195A2B003BE251F00186F9B = E195A2B003BE251F00186F9B;
+			E195A2B103BE251F00186F9B = E195A2B103BE251F00186F9B;
+			E195A2B403BE251F00186F9B = E195A2B403BE251F00186F9B;
+			E195A2B503BE251F00186F9B = E195A2B503BE251F00186F9B;
+			E195A2B603BE251F00186F9B = E195A2B603BE251F00186F9B;
+			E195A2B703BE251F00186F9B = E195A2B703BE251F00186F9B;
+			E195A2B803BE251F00186F9B = E195A2B803BE251F00186F9B;
+			E195A2B903BE251F00186F9B = E195A2B903BE251F00186F9B;
+			E195A2BA03BE251F00186F9B = E195A2BA03BE251F00186F9B;
+			E195A2BB03BE251F00186F9B = E195A2BB03BE251F00186F9B;
+			E195A2BC03BE251F00186F9B = E195A2BC03BE251F00186F9B;
+			E195A2BD03BE251F00186F9B = E195A2BD03BE251F00186F9B;
+			E195A2BE03BE251F00186F9B = E195A2BE03BE251F00186F9B;
+			E195A2C103BE251F00186F9B = E195A2C103BE251F00186F9B;
+			E195A2C203BE251F00186F9B = E195A2C203BE251F00186F9B;
+			E195A2C303BE251F00186F9B = E195A2C303BE251F00186F9B;
+			E195A2C403BE251F00186F9B = E195A2C403BE251F00186F9B;
+			E195A2C503BE251F00186F9B = E195A2C503BE251F00186F9B;
+			E195A2C603BE251F00186F9B = E195A2C603BE251F00186F9B;
+			E195A2C703BE251F00186F9B = E195A2C703BE251F00186F9B;
+			E195A2C803BE251F00186F9B = E195A2C803BE251F00186F9B;
+			E195A2C903BE251F00186F9B = E195A2C903BE251F00186F9B;
+			E195A2CA03BE251F00186F9B = E195A2CA03BE251F00186F9B;
+			E195A2CB03BE251F00186F9B = E195A2CB03BE251F00186F9B;
+			E195A2CD03BE251F00186F9B = E195A2CD03BE251F00186F9B;
+			E195A2E003BE251F00186F9B = E195A2E003BE251F00186F9B;
+			E195A2E103BE251F00186F9B = E195A2E103BE251F00186F9B;
+			E195A2E203BE251F00186F9B = E195A2E203BE251F00186F9B;
+			E195A2E803BE251F00186F9B = E195A2E803BE251F00186F9B;
+			E195A2E903BE251F00186F9B = E195A2E903BE251F00186F9B;
+			E195A2EA03BE251F00186F9B = E195A2EA03BE251F00186F9B;
+			E195A2EB03BE251F00186F9B = E195A2EB03BE251F00186F9B;
+			E195A2EC03BE251F00186F9B = E195A2EC03BE251F00186F9B;
+			E195A2ED03BE251F00186F9B = E195A2ED03BE251F00186F9B;
+			E195A2F003BE251F00186F9B = E195A2F003BE251F00186F9B;
+			E195A2F103BE251F00186F9B = E195A2F103BE251F00186F9B;
+			E195A2F303BE251F00186F9B = E195A2F303BE251F00186F9B;
+			E195A2F503BE251F00186F9B = E195A2F503BE251F00186F9B;
+			E195A2F703BE251F00186F9B = E195A2F703BE251F00186F9B;
+			E195A2F903BE251F00186F9B = E195A2F903BE251F00186F9B;
+			E195A2FC03BE251F00186F9B = E195A2FC03BE251F00186F9B;
+			E195A2FE03BE251F00186F9B = E195A2FE03BE251F00186F9B;
+			E198FA9803C963C700050002 = E198FA9803C963C700050002;
+			E19DCB7803BE4A0A00B934BF = E19DCB7803BE4A0A00B934BF;
+			E19DCB8203BE4A0A00B934BF = E19DCB8203BE4A0A00B934BF;
+			E19DCB8303BE4A0A00B934BF = E19DCB8303BE4A0A00B934BF;
+			E19DCB8503BE4A0A00B934BF = E19DCB8503BE4A0A00B934BF;
+			E19DCB8903BE4A0A00B934BF = E19DCB8903BE4A0A00B934BF;
+			E19DCB8B03BE4A0A00B934BF = E19DCB8B03BE4A0A00B934BF;
+			E19DCB8C03BE4A0A00B934BF = E19DCB8C03BE4A0A00B934BF;
+			E19DCB8E03BE4A0A00B934BF = E19DCB8E03BE4A0A00B934BF;
+			E19DCB9003BE4A0A00B934BF = E19DCB9003BE4A0A00B934BF;
+			E19DCB9103BE4A0A00B934BF = E19DCB9103BE4A0A00B934BF;
+			E19DCB9303BE4A0A00B934BF = E19DCB9303BE4A0A00B934BF;
+			E19DCB9403BE4A0A00B934BF = E19DCB9403BE4A0A00B934BF;
+			E19DCB9503BE4A0A00B934BF = E19DCB9503BE4A0A00B934BF;
+			E19DCB9603BE4A0A00B934BF = E19DCB9603BE4A0A00B934BF;
+			E19DCB9703BE4A0A00B934BF = E19DCB9703BE4A0A00B934BF;
+			E19DCB9803BE4A0A00B934BF = E19DCB9803BE4A0A00B934BF;
+			E19DCB9903BE4A0A00B934BF = E19DCB9903BE4A0A00B934BF;
+			E19DCB9A03BE4A0A00B934BF = E19DCB9A03BE4A0A00B934BF;
+			E19DCB9B03BE4A0A00B934BF = E19DCB9B03BE4A0A00B934BF;
+			E19DCB9C03BE4A0A00B934BF = E19DCB9C03BE4A0A00B934BF;
+			E19DCB9D03BE4A0A00B934BF = E19DCB9D03BE4A0A00B934BF;
+			E19DCB9E03BE4A0A00B934BF = E19DCB9E03BE4A0A00B934BF;
+			E19DCB9F03BE4A0A00B934BF = E19DCB9F03BE4A0A00B934BF;
+			E19DCBA103BE4A0A00B934BF = E19DCBA103BE4A0A00B934BF;
+			E19DCBA203BE4A0A00B934BF = E19DCBA203BE4A0A00B934BF;
+			E19DCBA803BE4A0A00B934BF = E19DCBA803BE4A0A00B934BF;
+			E19DCBA903BE4A0A00B934BF = E19DCBA903BE4A0A00B934BF;
+			E19DCBAA03BE4A0A00B934BF = E19DCBAA03BE4A0A00B934BF;
+			E19DCBAB03BE4A0A00B934BF = E19DCBAB03BE4A0A00B934BF;
+			E19DCBAC03BE4A0A00B934BF = E19DCBAC03BE4A0A00B934BF;
+			E19DCBAD03BE4A0A00B934BF = E19DCBAD03BE4A0A00B934BF;
+			E19DCBAE03BE4A0A00B934BF = E19DCBAE03BE4A0A00B934BF;
+			E19DCBB203BE4A0A00B934BF = E19DCBB203BE4A0A00B934BF;
+			E19DCBB603BE4A0A00B934BF = E19DCBB603BE4A0A00B934BF;
+			E19DCBBC03BE4A0A00B934BF = E19DCBBC03BE4A0A00B934BF;
+			E19DCBBD03BE4A0A00B934BF = E19DCBBD03BE4A0A00B934BF;
+			E19DCC8703BE900300B934BF = E19DCC8703BE900300B934BF;
+			E19DCC8903BE900300B934BF = E19DCC8903BE900300B934BF;
+			E19DCC8A03BE900300B934BF = E19DCC8A03BE900300B934BF;
+			E19DCC8E03BE900300B934BF = E19DCC8E03BE900300B934BF;
+			E19DCC8F03BE900300B934BF = E19DCC8F03BE900300B934BF;
+			E19DCC9203BE900300B934BF = E19DCC9203BE900300B934BF;
+			E19DCC9603BE900300B934BF = E19DCC9603BE900300B934BF;
+			E19DCC9C03BE900300B934BF = E19DCC9C03BE900300B934BF;
+			E19DCC9E03BE900300B934BF = E19DCC9E03BE900300B934BF;
+			E19DCCA203BE900300B934BF = E19DCCA203BE900300B934BF;
+			E19DCCA303BE900300B934BF = E19DCCA303BE900300B934BF;
+			E19DCCA403BE900300B934BF = E19DCCA403BE900300B934BF;
+			E19DCCA603BE900300B934BF = E19DCCA603BE900300B934BF;
+			E19DCCA703BE900300B934BF = E19DCCA703BE900300B934BF;
+			E19DCCA903BE900300B934BF = E19DCCA903BE900300B934BF;
+			E19DCCAC03BE900300B934BF = E19DCCAC03BE900300B934BF;
+			E19DCCAE03BE900300B934BF = E19DCCAE03BE900300B934BF;
+			E19DCCB203BE900300B934BF = E19DCCB203BE900300B934BF;
+			E19DCCB303BE900300B934BF = E19DCCB303BE900300B934BF;
+			E19DCCB403BE900300B934BF = E19DCCB403BE900300B934BF;
+			E19DCCB503BE900300B934BF = E19DCCB503BE900300B934BF;
+			E19DCCB603BE900300B934BF = E19DCCB603BE900300B934BF;
+			E19DCCB703BE900300B934BF = E19DCCB703BE900300B934BF;
+			E19DCCB903BE900300B934BF = E19DCCB903BE900300B934BF;
+			E19DCCBA03BE900300B934BF = E19DCCBA03BE900300B934BF;
+			E19DCCBB03BE900300B934BF = E19DCCBB03BE900300B934BF;
+			E19DCCBC03BE900300B934BF = E19DCCBC03BE900300B934BF;
+			E19DCCBD03BE900300B934BF = E19DCCBD03BE900300B934BF;
+			E19DCCBE03BE900300B934BF = E19DCCBE03BE900300B934BF;
+			E19DCCBF03BE900300B934BF = E19DCCBF03BE900300B934BF;
+			E19DCCC003BE900300B934BF = E19DCCC003BE900300B934BF;
+			E19DCCC103BE900300B934BF = E19DCCC103BE900300B934BF;
+			E19DCCC203BE900300B934BF = E19DCCC203BE900300B934BF;
+			E19DCCC403BE900300B934BF = E19DCCC403BE900300B934BF;
+			E19DCCC503BE900300B934BF = E19DCCC503BE900300B934BF;
+			E19DCCC603BE900300B934BF = E19DCCC603BE900300B934BF;
+			E19DCCC703BE900300B934BF = E19DCCC703BE900300B934BF;
+			E19DCCC803BE900300B934BF = E19DCCC803BE900300B934BF;
+			E19DCCC903BE900300B934BF = E19DCCC903BE900300B934BF;
+			E19DCCCA03BE900300B934BF = E19DCCCA03BE900300B934BF;
+			E19DCCCB03BE900300B934BF = E19DCCCB03BE900300B934BF;
+			E19DCCCF03BE900300B934BF = E19DCCCF03BE900300B934BF;
+			E19DCCD103BE900300B934BF = E19DCCD103BE900300B934BF;
+			E19DCCD203BE900300B934BF = E19DCCD203BE900300B934BF;
+			E19DCCD403BE900300B934BF = E19DCCD403BE900300B934BF;
+			E19DCCD503BE900300B934BF = E19DCCD503BE900300B934BF;
+			E19DCCD603BE900300B934BF = E19DCCD603BE900300B934BF;
+			E19DCCD703BE900300B934BF = E19DCCD703BE900300B934BF;
+			E19DCCD803BE900300B934BF = E19DCCD803BE900300B934BF;
+			E19DCCD903BE900300B934BF = E19DCCD903BE900300B934BF;
+			E19DCCDA03BE900300B934BF = E19DCCDA03BE900300B934BF;
+			E19DCCDB03BE900300B934BF = E19DCCDB03BE900300B934BF;
+			E19FD3A203C9985C001509F3 = E19FD3A203C9985C001509F3;
+			E19FD3A603C9985C001509F3 = E19FD3A603C9985C001509F3;
+			E19FD3A703C9985C001509F3 = E19FD3A703C9985C001509F3;
+			E19FD3A803C9985C001509F3 = E19FD3A803C9985C001509F3;
+			E19FD3A903C9985C001509F3 = E19FD3A903C9985C001509F3;
+			E19FD3AA03C9985C001509F3 = E19FD3AA03C9985C001509F3;
+			E1A9DEEB03BF480F0089E8B2 = E1A9DEEB03BF480F0089E8B2;
+			E1A9DEEE03BF480F0089E8B2 = E1A9DEEE03BF480F0089E8B2;
+			E1A9DEF003BF480F0089E8B2 = E1A9DEF003BF480F0089E8B2;
+			E1A9DEF103BF480F0089E8B2 = E1A9DEF103BF480F0089E8B2;
+			E1A9DEF203BF480F0089E8B2 = E1A9DEF203BF480F0089E8B2;
+			E1A9DEF703BF480F0089E8B2 = E1A9DEF703BF480F0089E8B2;
+			E1A9DEFB03BF480F0089E8B2 = E1A9DEFB03BF480F0089E8B2;
+			E1A9DEFC03BF480F0089E8B2 = E1A9DEFC03BF480F0089E8B2;
+			E1A9DEFD03BF480F0089E8B2 = E1A9DEFD03BF480F0089E8B2;
+			E1A9DEFE03BF480F0089E8B2 = E1A9DEFE03BF480F0089E8B2;
+			E1A9DF0203BF480F0089E8B2 = E1A9DF0203BF480F0089E8B2;
+			E1A9DF0303BF480F0089E8B2 = E1A9DF0303BF480F0089E8B2;
+			E1A9DF0403BF480F0089E8B2 = E1A9DF0403BF480F0089E8B2;
+			E1A9DF0503BF480F0089E8B2 = E1A9DF0503BF480F0089E8B2;
+			E1A9DF0603BF480F0089E8B2 = E1A9DF0603BF480F0089E8B2;
+			E1A9DF0703BF480F0089E8B2 = E1A9DF0703BF480F0089E8B2;
+			E1A9DF0803BF480F0089E8B2 = E1A9DF0803BF480F0089E8B2;
+			E1AFB0CE03C9A59C001509F3 = E1AFB0CE03C9A59C001509F3;
+			E1AFB0D103C9A59C001509F3 = E1AFB0D103C9A59C001509F3;
+			E1AFB0D203C9A59C001509F3 = E1AFB0D203C9A59C001509F3;
+			E1AFB0D303C9A59C001509F3 = E1AFB0D303C9A59C001509F3;
+			E1AFB0D403C9A59C001509F3 = E1AFB0D403C9A59C001509F3;
+			E1AFB0D503C9A59C001509F3 = E1AFB0D503C9A59C001509F3;
+			E1AFB0D603C9A59C001509F3 = E1AFB0D603C9A59C001509F3;
+			E1AFB0D703C9A59C001509F3 = E1AFB0D703C9A59C001509F3;
+			E1AFB0D803C9A59C001509F3 = E1AFB0D803C9A59C001509F3;
+			E1AFB0D903C9A59C001509F3 = E1AFB0D903C9A59C001509F3;
+			E1AFB0DA03C9A59C001509F3 = E1AFB0DA03C9A59C001509F3;
+			E1AFB0DB03C9A59C001509F3 = E1AFB0DB03C9A59C001509F3;
+			E1AFB0DE03C9A59C001509F3 = E1AFB0DE03C9A59C001509F3;
+			E1AFB0E003C9A59C001509F3 = E1AFB0E003C9A59C001509F3;
+			E1AFB0E103C9A59C001509F3 = E1AFB0E103C9A59C001509F3;
+			E1AFB0E203C9A59C001509F3 = E1AFB0E203C9A59C001509F3;
+			E1AFB0E303C9A59C001509F3 = E1AFB0E303C9A59C001509F3;
+			E1AFB0E403C9A59C001509F3 = E1AFB0E403C9A59C001509F3;
+			E1AFB0E503C9A59C001509F3 = E1AFB0E503C9A59C001509F3;
+			E1AFB0E603C9A59C001509F3 = E1AFB0E603C9A59C001509F3;
+			E1AFB0E703C9A59C001509F3 = E1AFB0E703C9A59C001509F3;
+			E1AFB0E803C9A59C001509F3 = E1AFB0E803C9A59C001509F3;
+			E1AFB0E903C9A59C001509F3 = E1AFB0E903C9A59C001509F3;
+			E1AFB0EA03C9A59C001509F3 = E1AFB0EA03C9A59C001509F3;
+			E1AFB0EB03C9A59C001509F3 = E1AFB0EB03C9A59C001509F3;
+			E1AFB0EC03C9A59C001509F3 = E1AFB0EC03C9A59C001509F3;
+			E1AFB0ED03C9A59C001509F3 = E1AFB0ED03C9A59C001509F3;
+			E1AFB0EE03C9A59C001509F3 = E1AFB0EE03C9A59C001509F3;
+			E1AFB0EF03C9A59C001509F3 = E1AFB0EF03C9A59C001509F3;
+			E1AFB0F003C9A59C001509F3 = E1AFB0F003C9A59C001509F3;
+			E1AFB0F103C9A59C001509F3 = E1AFB0F103C9A59C001509F3;
+			E1AFB0F203C9A59C001509F3 = E1AFB0F203C9A59C001509F3;
+			E1AFB0F303C9A59C001509F3 = E1AFB0F303C9A59C001509F3;
+			E1AFB0F403C9A59C001509F3 = E1AFB0F403C9A59C001509F3;
+			E1AFB0F503C9A59C001509F3 = E1AFB0F503C9A59C001509F3;
+			E1AFB0F603C9A59C001509F3 = E1AFB0F603C9A59C001509F3;
+			E1AFB0F703C9A59C001509F3 = E1AFB0F703C9A59C001509F3;
+			E1AFB0F803C9A59C001509F3 = E1AFB0F803C9A59C001509F3;
+			E1AFB0F903C9A59C001509F3 = E1AFB0F903C9A59C001509F3;
+			E1AFB0FA03C9A59C001509F3 = E1AFB0FA03C9A59C001509F3;
+			E1AFB0FB03C9A59C001509F3 = E1AFB0FB03C9A59C001509F3;
+			E1AFB0FC03C9A59C001509F3 = E1AFB0FC03C9A59C001509F3;
+			E1AFB0FD03C9A59C001509F3 = E1AFB0FD03C9A59C001509F3;
+			E1AFB0FE03C9A59C001509F3 = E1AFB0FE03C9A59C001509F3;
+			E1AFB0FF03C9A59C001509F3 = E1AFB0FF03C9A59C001509F3;
+			E1AFB10003C9A59C001509F3 = E1AFB10003C9A59C001509F3;
+			E1AFB10103C9A59C001509F3 = E1AFB10103C9A59C001509F3;
+			E1AFB10203C9A59C001509F3 = E1AFB10203C9A59C001509F3;
+			E1AFB10303C9A59C001509F3 = E1AFB10303C9A59C001509F3;
+			E1AFB10403C9A59C001509F3 = E1AFB10403C9A59C001509F3;
+			E1AFB10503C9A59C001509F3 = E1AFB10503C9A59C001509F3;
+			E1AFB10603C9A59C001509F3 = E1AFB10603C9A59C001509F3;
+			E1AFB10703C9A59C001509F3 = E1AFB10703C9A59C001509F3;
+			E1AFB10803C9A59C001509F3 = E1AFB10803C9A59C001509F3;
+			E1AFB10903C9A59C001509F3 = E1AFB10903C9A59C001509F3;
+			E1AFB10A03C9A59C001509F3 = E1AFB10A03C9A59C001509F3;
+			E1AFB10B03C9A59C001509F3 = E1AFB10B03C9A59C001509F3;
+			E1AFB10C03C9A59C001509F3 = E1AFB10C03C9A59C001509F3;
+			E1AFB10D03C9A59C001509F3 = E1AFB10D03C9A59C001509F3;
+			E1BF6E9A03C95F4E00050002 = E1BF6E9A03C95F4E00050002;
+			E1BF6E9D03C95F4E00050002 = E1BF6E9D03C95F4E00050002;
+			E1BF6E9E03C95F4E00050002 = E1BF6E9E03C95F4E00050002;
+			E1BF6E9F03C95F4E00050002 = E1BF6E9F03C95F4E00050002;
+			E1BF6EA003C95F4E00050002 = E1BF6EA003C95F4E00050002;
+			E1BF6EA103C95F4E00050002 = E1BF6EA103C95F4E00050002;
+			E1BF6EA203C95F4E00050002 = E1BF6EA203C95F4E00050002;
+			E1BF6EA903C95F4E00050002 = E1BF6EA903C95F4E00050002;
+			E1BF6EAC03C95F4E00050002 = E1BF6EAC03C95F4E00050002;
+			E1BF6EAE03C95F4E00050002 = E1BF6EAE03C95F4E00050002;
+			E1BF6EB003C95F4E00050002 = E1BF6EB003C95F4E00050002;
+			E1BF6EB503C95F4E00050002 = E1BF6EB503C95F4E00050002;
+			E1BF6EBB03C95F4E00050002 = E1BF6EBB03C95F4E00050002;
+			E1BF6EBC03C95F4E00050002 = E1BF6EBC03C95F4E00050002;
+			E1BF6EC103C95F4E00050002 = E1BF6EC103C95F4E00050002;
+			E1BF6EC203C95F4E00050002 = E1BF6EC203C95F4E00050002;
+			E1BF6EC403C95F4E00050002 = E1BF6EC403C95F4E00050002;
+			E1BF6EDA03C95F4E00050002 = E1BF6EDA03C95F4E00050002;
+			E1BF6EDF03C95F4E00050002 = E1BF6EDF03C95F4E00050002;
+			E1BF6EEF03C95F4E00050002 = E1BF6EEF03C95F4E00050002;
+			E1C6414303C9AC4B001509F3 = E1C6414303C9AC4B001509F3;
+			E1C6414403C9AC4B001509F3 = E1C6414403C9AC4B001509F3;
+			E1C6414503C9AC4B001509F3 = E1C6414503C9AC4B001509F3;
+			E1C6414703C9AC4B001509F3 = E1C6414703C9AC4B001509F3;
+			E1C6414803C9AC4B001509F3 = E1C6414803C9AC4B001509F3;
+			E1C6414903C9AC4B001509F3 = E1C6414903C9AC4B001509F3;
+			E1C6414A03C9AC4B001509F3 = E1C6414A03C9AC4B001509F3;
+			E1C6414B03C9AC4B001509F3 = E1C6414B03C9AC4B001509F3;
+			E1C6414C03C9AC4B001509F3 = E1C6414C03C9AC4B001509F3;
+			E1C6414D03C9AC4B001509F3 = E1C6414D03C9AC4B001509F3;
+			E1C6414E03C9AC4B001509F3 = E1C6414E03C9AC4B001509F3;
+			E1C6414F03C9AC4B001509F3 = E1C6414F03C9AC4B001509F3;
+			E1C6415003C9AC4B001509F3 = E1C6415003C9AC4B001509F3;
+			E1C6415103C9AC4B001509F3 = E1C6415103C9AC4B001509F3;
+			E1C6415203C9AC4B001509F3 = E1C6415203C9AC4B001509F3;
+			E1C6415303C9AC4B001509F3 = E1C6415303C9AC4B001509F3;
+			E1C6415403C9AC4B001509F3 = E1C6415403C9AC4B001509F3;
+			E1D2937503BD418200F9204E = E1D2937503BD418200F9204E;
+			E1D2937B03BD418200F9204E = E1D2937B03BD418200F9204E;
+			E1D2937C03BD418200F9204E = E1D2937C03BD418200F9204E;
+			E1D2937E03BD418200F9204E = E1D2937E03BD418200F9204E;
+			E1D2938303BD418200F9204E = E1D2938303BD418200F9204E;
+			E1D2938403BD418200F9204E = E1D2938403BD418200F9204E;
+			E1D2938503BD418200F9204E = E1D2938503BD418200F9204E;
+			E1D2938603BD418200F9204E = E1D2938603BD418200F9204E;
+			E1D2939103BD418200F9204E = E1D2939103BD418200F9204E;
+			E1D2939203BD418200F9204E = E1D2939203BD418200F9204E;
+			E1D2939503BD418200F9204E = E1D2939503BD418200F9204E;
+			E1D2939703BD418200F9204E = E1D2939703BD418200F9204E;
+			E1D293B003BD418200F9204E = E1D293B003BD418200F9204E;
+			E1D293B403BD418200F9204E = E1D293B403BD418200F9204E;
+			E1D293B503BD418200F9204E = E1D293B503BD418200F9204E;
+			E1D293B703BD418200F9204E = E1D293B703BD418200F9204E;
+			E1D293B903BD418200F9204E = E1D293B903BD418200F9204E;
+			E1D293BA03BD418200F9204E = E1D293BA03BD418200F9204E;
+			E1D293BB03BD418200F9204E = E1D293BB03BD418200F9204E;
+			E1D293BC03BD418200F9204E = E1D293BC03BD418200F9204E;
+			E1D293BD03BD418200F9204E = E1D293BD03BD418200F9204E;
+			E1D293BE03BD418200F9204E = E1D293BE03BD418200F9204E;
+			E1D293BF03BD418200F9204E = E1D293BF03BD418200F9204E;
+			E1D293C003BD418200F9204E = E1D293C003BD418200F9204E;
+			E1D293C103BD418200F9204E = E1D293C103BD418200F9204E;
+			E1D293C203BD418200F9204E = E1D293C203BD418200F9204E;
+			E1D293C403BD418200F9204E = E1D293C403BD418200F9204E;
+			E1D293C503BD418200F9204E = E1D293C503BD418200F9204E;
+			E1D293C603BD418200F9204E = E1D293C603BD418200F9204E;
+			E1D293C703BD418200F9204E = E1D293C703BD418200F9204E;
+			E1D293C803BD418200F9204E = E1D293C803BD418200F9204E;
+			E1D293C903BD418200F9204E = E1D293C903BD418200F9204E;
+			E1D293CA03BD418200F9204E = E1D293CA03BD418200F9204E;
+			E1D293CB03BD418200F9204E = E1D293CB03BD418200F9204E;
+			E1D293CC03BD418200F9204E = E1D293CC03BD418200F9204E;
+			E1D293CD03BD418200F9204E = E1D293CD03BD418200F9204E;
+			E1D293CE03BD418200F9204E = E1D293CE03BD418200F9204E;
+			E1D293CF03BD418200F9204E = E1D293CF03BD418200F9204E;
+			E1D293D003BD418200F9204E = E1D293D003BD418200F9204E;
+			E1D293D103BD418200F9204E = E1D293D103BD418200F9204E;
+			E1D293D203BD418200F9204E = E1D293D203BD418200F9204E;
+			E1D293D303BD418200F9204E = E1D293D303BD418200F9204E;
+			E1D293D403BD418200F9204E = E1D293D403BD418200F9204E;
+			E1D293D503BD418200F9204E = E1D293D503BD418200F9204E;
+			E1D293D603BD418200F9204E = E1D293D603BD418200F9204E;
+			E1D293D703BD418200F9204E = E1D293D703BD418200F9204E;
+			E1D293D803BD418200F9204E = E1D293D803BD418200F9204E;
+			E1D293D903BD418200F9204E = E1D293D903BD418200F9204E;
+			E1D293DA03BD418200F9204E = E1D293DA03BD418200F9204E;
+			E1D293DB03BD418200F9204E = E1D293DB03BD418200F9204E;
+			E1D293DC03BD418200F9204E = E1D293DC03BD418200F9204E;
+			E1D293DD03BD418200F9204E = E1D293DD03BD418200F9204E;
+			E1D293DE03BD418200F9204E = E1D293DE03BD418200F9204E;
+			E1D293DF03BD418200F9204E = E1D293DF03BD418200F9204E;
+			E1D293E003BD418200F9204E = E1D293E003BD418200F9204E;
+			E1D293E103BD418200F9204E = E1D293E103BD418200F9204E;
+			E1D293E203BD418200F9204E = E1D293E203BD418200F9204E;
+			E1D293E303BD418200F9204E = E1D293E303BD418200F9204E;
+			E1D293E403BD418200F9204E = E1D293E403BD418200F9204E;
+			E1D293E503BD418200F9204E = E1D293E503BD418200F9204E;
+			E1D293E603BD418200F9204E = E1D293E603BD418200F9204E;
+			E1D293E703BD418200F9204E = E1D293E703BD418200F9204E;
+			E1D293E803BD418200F9204E = E1D293E803BD418200F9204E;
+			E1D293E903BD418200F9204E = E1D293E903BD418200F9204E;
+			E1D293EA03BD418200F9204E = E1D293EA03BD418200F9204E;
+			E1D293EB03BD418200F9204E = E1D293EB03BD418200F9204E;
+			E1D293EC03BD418200F9204E = E1D293EC03BD418200F9204E;
+			E1D293F103BD418200F9204E = E1D293F103BD418200F9204E;
+			E1D293F203BD418200F9204E = E1D293F203BD418200F9204E;
+			E1D293F303BD418200F9204E = E1D293F303BD418200F9204E;
+			E1D293F403BD418200F9204E = E1D293F403BD418200F9204E;
+			E1D293F503BD418200F9204E = E1D293F503BD418200F9204E;
+			E1D293F703BD418200F9204E = E1D293F703BD418200F9204E;
+			E1D293F803BD418200F9204E = E1D293F803BD418200F9204E;
+			E1D293F903BD418200F9204E = E1D293F903BD418200F9204E;
+			E1D293FC03BD418200F9204E = E1D293FC03BD418200F9204E;
+			E1D293FD03BD418200F9204E = E1D293FD03BD418200F9204E;
+			E1D293FE03BD418200F9204E = E1D293FE03BD418200F9204E;
+			E1D293FF03BD418200F9204E = E1D293FF03BD418200F9204E;
+			E1D2940003BD418200F9204E = E1D2940003BD418200F9204E;
+			E1D2940103BD418200F9204E = E1D2940103BD418200F9204E;
+			E1D2940203BD418200F9204E = E1D2940203BD418200F9204E;
+			E1D2940303BD418200F9204E = E1D2940303BD418200F9204E;
+			E1D2940403BD418200F9204E = E1D2940403BD418200F9204E;
+			E1D2940503BD418200F9204E = E1D2940503BD418200F9204E;
+			E1D2940603BD418200F9204E = E1D2940603BD418200F9204E;
+			E1D2940703BD418200F9204E = E1D2940703BD418200F9204E;
+			E1D2940803BD418200F9204E = E1D2940803BD418200F9204E;
+			E1D2942C03BD418200F9204E = E1D2942C03BD418200F9204E;
+			E1D2942D03BD418200F9204E = E1D2942D03BD418200F9204E;
+			E1D2942E03BD418200F9204E = E1D2942E03BD418200F9204E;
+			E1D2942F03BD418200F9204E = E1D2942F03BD418200F9204E;
+			E1D2943103BD418200F9204E = E1D2943103BD418200F9204E;
+			E1D2943903BD418200F9204E = E1D2943903BD418200F9204E;
+			E1F4C96203C9B1E6001509F3 = E1F4C96203C9B1E6001509F3;
+			E1F4C96303C9B1E6001509F3 = E1F4C96303C9B1E6001509F3;
+			E1F4C96403C9B1E6001509F3 = E1F4C96403C9B1E6001509F3;
+			E1F4C96503C9B1E6001509F3 = E1F4C96503C9B1E6001509F3;
+			E1F4C96603C9B1E6001509F3 = E1F4C96603C9B1E6001509F3;
+			E1FCECFD03C972CF001509F3 = E1FCECFD03C972CF001509F3;
+		};
+		projectwideBuildSettings = {
+		};
+		userBookmarkGroup = E130B91603B69C6300000028;
+		wantsIndex = 1;
+		wantsSCM = -1;
+	};
+	29B97326FDCFA39411CA2CEA = {
+		activeExec = 0;
+		executables = (
+			F59B967103538BE201154278,
+		);
+	};
+	E1096EB803C3EDB0009B92C1 = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 77";
+		rLen = 0;
+		rLoc = 4965;
+		rType = 0;
+		vrLen = 2641;
+		vrLoc = 6972;
+	};
+	E1156BFA03C148E2006717DC = {
+		fileReference = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXFileBreakpoint;
+		lineNumber = 493;
+		state = 1;
+	};
+	E1156C2C03C394D6006717DC = {
+		fileReference = F59DC6D40353C9E601AEEDB1;
+		isa = PBXFileBreakpoint;
+		lineNumber = 487;
+		state = 1;
+	};
+	E1156C2D03C39718006717DC = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: 71";
+		rLen = 115;
+		rLoc = 2331;
+		rType = 0;
+		vrLen = 1900;
+		vrLoc = 1587;
+	};
+	E117A4AB03C3E2FD00E10BA2 = {
+		fileReference = F59DC6D40353C9E601AEEDB1;
+		isa = PBXFileBreakpoint;
+		lineNumber = 512;
+		state = 1;
+	};
+	E117A4AC03C3E9C600E10BA2 = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 94";
+		rLen = 0;
+		rLoc = 2296;
+		rType = 0;
+		vrLen = 877;
+		vrLoc = 0;
+	};
+	E117A4AD03C3E9C600E10BA2 = {
+		fRef = E117A4C003C3E9C600E10BA2;
+		isa = PBXTextBookmark;
+		name = "NSObject.h: 23";
+		rLen = 0;
+		rLoc = 456;
+		rType = 0;
+		vrLen = 928;
+		vrLoc = 0;
+	};
+	E117A4AE03C3E9C600E10BA2 = {
+		fRef = E117A4C103C3E9C600E10BA2;
+		glyphRangeLength = 1836;
+		glyphRangeLocation = 27611;
+		isa = PBXDocBookmark;
+		name = "NSControl.html: controlTextD...";
+	};
+	E117A4AF03C3E9C600E10BA2 = {
+		fRef = E117A4C203C3E9C600E10BA2;
+		isa = PBXTextBookmark;
+		name = "NSControl.h: 121";
+		rLen = 81;
+		rLoc = 3801;
+		rType = 0;
+		vrLen = 1658;
+		vrLoc = 2392;
+	};
+	E117A4B003C3E9C600E10BA2 = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: 137";
+		rLen = 0;
+		rLoc = 6239;
+		rType = 0;
+		vrLen = 2083;
+		vrLoc = 4886;
+	};
+	E117A4B203C3E9C600E10BA2 = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 94";
+		rLen = 0;
+		rLoc = 2296;
+		rType = 0;
+		vrLen = 877;
+		vrLoc = 0;
+	};
+	E117A4B303C3E9C600E10BA2 = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 131";
+		rLen = 0;
+		rLoc = 11177;
+		rType = 0;
+		vrLen = 2754;
+		vrLoc = 7422;
+	};
+	E117A4B403C3E9C600E10BA2 = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: 137";
+		rLen = 0;
+		rLoc = 6239;
+		rType = 0;
+		vrLen = 2083;
+		vrLoc = 4886;
+	};
+	E117A4C003C3E9C600E10BA2 = {
+		isa = PBXFileReference;
+		name = NSObject.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObject.h;
+		refType = 0;
+	};
+	E117A4C103C3E9C600E10BA2 = {
+		isa = PBXFileReference;
+		name = NSControl.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSControl.html;
+		refType = 0;
+	};
+	E117A4C203C3E9C600E10BA2 = {
+		isa = PBXFileReference;
+		name = NSControl.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSControl.h;
+		refType = 0;
+	};
+	E11CD2D003BF9B3300C49BEF = {
+		fRef = E11CD30D03BF9B3300C49BEF;
+		isa = PBXTextBookmark;
+		name = "NSURL.h: 28";
+		rLen = 0;
+		rLoc = 948;
+		rType = 0;
+		vrLen = 1648;
+		vrLoc = 0;
+	};
+	E11CD2D103BF9B3300C49BEF = {
+		fRef = E11CD30E03BF9B3300C49BEF;
+		isa = PBXTextBookmark;
+		name = "NSAppleScript.h: 17";
+		rLen = 392;
+		rLoc = 671;
+		rType = 0;
+		vrLen = 1925;
+		vrLoc = 0;
+	};
+	E11CD2D203BF9B3300C49BEF = {
+		fRef = E11CD30F03BF9B3300C49BEF;
+		glyphRangeLength = 1212;
+		glyphRangeLocation = 96;
+		isa = PBXDocBookmark;
+		name = "NSAppleScript.html: Declared in ...";
+	};
+	E11CD2D303BF9B3300C49BEF = {
+		fRef = F5F240B9036A867901FE7503;
+		isa = PBXTextBookmark;
+		name = "BDAlias.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1240;
+		vrLoc = 1630;
+	};
+	E11CD2D403BF9B3300C49BEF = {
+		fRef = E11CD31003BF9B3300C49BEF;
+		isa = PBXTextBookmark;
+		name = "NSFileManager.h: 32";
+		rLen = 7;
+		rLoc = 1066;
+		rType = 0;
+		vrLen = 1624;
+		vrLoc = 0;
+	};
+	E11CD2D503BF9B3300C49BEF = {
+		fRef = E11CD31103BF9B3300C49BEF;
+		isa = PBXTextBookmark;
+		name = "NSString.h: 158";
+		rLen = 48;
+		rLoc = 6048;
+		rType = 0;
+		vrLen = 2149;
+		vrLoc = 5042;
+	};
+	E11CD2D603BF9B3300C49BEF = {
+		fRef = E1A18CB203B439CF00000028;
+		isa = PBXTextBookmark;
+		name = "PSPropertyListSerialization.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 491;
+		vrLoc = 0;
+	};
+	E11CD2D803BF9B3300C49BEF = {
+		fRef = F5F240CA036A869401FE7503;
+		isa = PBXTextBookmark;
+		name = "BDAlias.m: displayNameWithKindString:";
+		rLen = 0;
+		rLoc = 6212;
+		rType = 0;
+		vrLen = 987;
+		vrLoc = 5329;
+	};
+	E11CD2E003BF9B3300C49BEF = {
+		fRef = E11CD31203BF9B3300C49BEF;
+		isa = PBXTextBookmark;
+		name = "NSException.h: 95";
+		rLen = 60;
+		rLoc = 2920;
+		rType = 0;
+		vrLen = 1659;
+		vrLoc = 2172;
+	};
+	E11CD2E303BF9B3300C49BEF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: ";
+		rLen = 0;
+		rLoc = 509;
+		rType = 0;
+		vrLen = 1021;
+		vrLoc = 1280;
+	};
+	E11CD2E503BF9B3300C49BEF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 72";
+		rLen = 0;
+		rLoc = 1694;
+		rType = 0;
+		vrLen = 1218;
+		vrLoc = 1083;
+	};
+	E11CD2E603BF9B3300C49BEF = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: 19";
+		rLen = 0;
+		rLoc = 455;
+		rType = 0;
+		vrLen = 814;
+		vrLoc = 0;
+	};
+	E11CD2E703BF9B3300C49BEF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: ";
+		rLen = 0;
+		rLoc = 4481;
+		rType = 0;
+		vrLen = 1348;
+		vrLoc = 3368;
+	};
+	E11CD2E803BF9B3300C49BEF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: alert";
+		rLen = 0;
+		rLoc = 1130;
+		rType = 0;
+		vrLen = 1623;
+		vrLoc = 319;
+	};
+	E11CD2E903BF9B3300C49BEF = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: PSAlarmAlertStopNotification";
+		rLen = 54;
+		rLoc = 207;
+		rType = 0;
+		vrLen = 525;
+		vrLoc = 0;
+	};
+	E11CD2EA03BF9B3300C49BEF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 38";
+		rLen = 0;
+		rLoc = 1558;
+		rType = 0;
+		vrLen = 1672;
+		vrLoc = 319;
+	};
+	E11CD2EC03BF9B3300C49BEF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: ";
+		rLen = 0;
+		rLoc = 993;
+		rType = 0;
+		vrLen = 1075;
+		vrLoc = 508;
+	};
+	E11CD2ED03BF9B3300C49BEF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 244";
+		rLen = 0;
+		rLoc = 7719;
+		rType = 0;
+		vrLen = 1412;
+		vrLoc = 6161;
+	};
+	E11CD2EF03BF9B3300C49BEF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 34";
+		rLen = 0;
+		rLoc = 672;
+		rType = 0;
+		vrLen = 1066;
+		vrLoc = 177;
+	};
+	E11CD30D03BF9B3300C49BEF = {
+		isa = PBXFileReference;
+		name = NSURL.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSURL.h;
+		refType = 0;
+	};
+	E11CD30E03BF9B3300C49BEF = {
+		isa = PBXFileReference;
+		name = NSAppleScript.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSAppleScript.h;
+		refType = 0;
+	};
+	E11CD30F03BF9B3300C49BEF = {
+		isa = PBXFileReference;
+		name = NSAppleScript.html;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSAppleScript.html;
+		refType = 0;
+	};
+	E11CD31003BF9B3300C49BEF = {
+		isa = PBXFileReference;
+		name = NSFileManager.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSFileManager.h;
+		refType = 0;
+	};
+	E11CD31103BF9B3300C49BEF = {
+		isa = PBXFileReference;
+		name = NSString.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSString.h;
+		refType = 0;
+	};
+	E11CD31203BF9B3300C49BEF = {
+		isa = PBXFileReference;
+		name = NSException.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSException.h;
+		refType = 0;
+	};
+	E12725EC03B8FE2300000028 = {
+		fRef = F59E47A7036AAA6D016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlert.m: propertyListRepresentation";
+		rLen = 0;
+		rLoc = 1213;
+		rType = 0;
+		vrLen = 1316;
+		vrLoc = 227;
+	};
+	E130B91603B69C6300000028 = {
+		children = (
+			E130B91703B6A98E00000028,
+			E130B91803B6C81D00000028,
+			E12725EC03B8FE2300000028,
+			E1D2936E03BD2A2700F9204E,
+			E1ECA00A03C003C300F54C66,
+			E1ECA00B03C0056B00F54C66,
+			E1156C2D03C39718006717DC,
+			E1BF6E9403C9330000050002,
+		);
+		isa = PBXBookmarkGroup;
+		name = Root;
+	};
+	E130B91703B6A98E00000028 = {
+		fRef = F5F240B9036A867901FE7503;
+		isa = PBXTextBookmark;
+		name = "BDAlias.h: aliasWithData:";
+		rLen = 43;
+		rLoc = 2576;
+		rType = 0;
+		vrLen = 1579;
+		vrLoc = 1291;
+	};
+	E130B91803B6C81D00000028 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXBookmark;
+	};
+	E17AED7003C0F4D600B89ACF = {
+		fileReference = F5F1986C036B813101EB0372;
+		isa = PBXFileBreakpoint;
+		lineNumber = 91;
+		state = 1;
+	};
+	E17AED7303C0F5D300B89ACF = {
+		fRef = E17AEDD203C0F5D300B89ACF;
+		glyphRangeLength = 782;
+		glyphRangeLocation = 22457;
+		isa = PBXDocBookmark;
+		name = "NSApplication.html: isActive  - ...";
+	};
+	E17AED7403C0F5D300B89ACF = {
+		fRef = E17AEDD303C0F5D300B89ACF;
+		glyphRangeLength = 1214;
+		glyphRangeLocation = 6436;
+		isa = PBXDocBookmark;
+		name = "Getting_Proc__Information.html: Sets the fro...";
+	};
+	E17AED7503C0F5D300B89ACF = {
+		fRef = E17AEDD403C0F5D300B89ACF;
+		glyphRangeLength = 468;
+		glyphRangeLocation = 901;
+		isa = PBXDocBookmark;
+		name = "NSWorkspace.html: The constant...";
+	};
+	E17AED7603C0F5D300B89ACF = {
+		fRef = E17AEDD103C0F5D300B89ACF;
+		isa = PBXTextBookmark;
+		name = "Processes.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 932;
+		vrLoc = 0;
+	};
+	E17AED7703C0F5D300B89ACF = {
+		fRef = E17AEDD503C0F5D300B89ACF;
+		isa = PBXTextBookmark;
+		name = "NSWorkspace.h: 80";
+		rLen = 36;
+		rLoc = 2996;
+		rType = 0;
+		vrLen = 2064;
+		vrLoc = 2420;
+	};
+	E17AED7803C0F5D300B89ACF = {
+		fRef = F59E47B0036AACD1016B311C;
+		isa = PBXTextBookmark;
+		name = "PSNotifierAlert.m: actionDescription";
+		rLen = 0;
+		rLoc = 620;
+		rType = 0;
+		vrLen = 894;
+		vrLoc = 0;
+	};
+	E17AED7903C0F5D300B89ACF = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 61";
+		rLen = 0;
+		rLoc = 1829;
+		rType = 0;
+		vrLen = 1158;
+		vrLoc = 511;
+	};
+	E17AED7A03C0F5D300B89ACF = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: delay";
+		rLen = 0;
+		rLoc = 578;
+		rType = 0;
+		vrLen = 1660;
+		vrLoc = 319;
+	};
+	E17AED7B03C0F5D300B89ACF = {
+		fRef = E17AEDD603C0F5D300B89ACF;
+		isa = PBXTextBookmark;
+		name = "NSApplication.h: 96";
+		rLen = 25;
+		rLoc = 3085;
+		rType = 0;
+		vrLen = 1433;
+		vrLoc = 2268;
+	};
+	E17AED7D03C0F5D300B89ACF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E17AED8003C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 47";
+		rLen = 0;
+		rLoc = 1751;
+		rType = 0;
+		vrLen = 1652;
+		vrLoc = 284;
+	};
+	E17AED8403C0F5D300B89ACF = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 17";
+		rLen = 23;
+		rLoc = 380;
+		rType = 0;
+		vrLen = 586;
+		vrLoc = 0;
+	};
+	E17AED8703C0F5D300B89ACF = {
+		fRef = F5F19867036B80AF01EB0372;
+		isa = PBXTextBookmark;
+		name = "SUSpeaker.m: handleMessage:";
+		rLen = 17;
+		rLoc = 5621;
+		rType = 0;
+		vrLen = 1014;
+		vrLoc = 5080;
+	};
+	E17AED8803C0F5D300B89ACF = {
+		fRef = F5F19866036B80AF01EB0372;
+		isa = PBXTextBookmark;
+		name = "SUSpeaker.h: didFinishSpeaking:";
+		rLen = 47;
+		rLoc = 660;
+		rType = 0;
+		vrLen = 787;
+		vrLoc = 0;
+	};
+	E17AED8E03C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 38";
+		rLen = 0;
+		rLoc = 1558;
+		rType = 0;
+		vrLen = 1406;
+		vrLoc = 96;
+	};
+	E17AED8F03C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 50";
+		rLen = 0;
+		rLoc = 1827;
+		rType = 0;
+		vrLen = 1564;
+		vrLoc = 493;
+	};
+	E17AED9003C0F5D300B89ACF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E17AED9103C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 159";
+		rLen = 0;
+		rLoc = 5636;
+		rType = 0;
+		vrLen = 1391;
+		vrLoc = 3831;
+	};
+	E17AED9203C0F5D300B89ACF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E17AED9303C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 52";
+		rLen = 0;
+		rLoc = 1827;
+		rType = 0;
+		vrLen = 1385;
+		vrLoc = 1429;
+	};
+	E17AED9403C0F5D300B89ACF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E17AED9503C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 50";
+		rLen = 0;
+		rLoc = 1827;
+		rType = 0;
+		vrLen = 1485;
+		vrLoc = 1429;
+	};
+	E17AED9603C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 29";
+		rLen = 0;
+		rLoc = 757;
+		rType = 0;
+		vrLen = 1496;
+		vrLoc = 729;
+	};
+	E17AEDA003C0F5D300B89ACF = {
+		fRef = F59E47B0036AACD1016B311C;
+		isa = PBXTextBookmark;
+		name = "PSNotifierAlert.m: actionDescription";
+		rLen = 0;
+		rLoc = 620;
+		rType = 0;
+		vrLen = 894;
+		vrLoc = 0;
+	};
+	E17AEDA103C0F5D300B89ACF = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 61";
+		rLen = 0;
+		rLoc = 1829;
+		rType = 0;
+		vrLen = 1158;
+		vrLoc = 511;
+	};
+	E17AEDA403C0F5D300B89ACF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E17AEDA503C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 29";
+		rLen = 0;
+		rLoc = 757;
+		rType = 0;
+		vrLen = 1491;
+		vrLoc = 729;
+	};
+	E17AEDA603C0F5D300B89ACF = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 16";
+		rLen = 0;
+		rLoc = 402;
+		rType = 0;
+		vrLen = 563;
+		vrLoc = 0;
+	};
+	E17AEDA703C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1568;
+		vrLoc = 0;
+	};
+	E17AEDA803C0F5D300B89ACF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E17AEDA903C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 50";
+		rLen = 0;
+		rLoc = 1827;
+		rType = 0;
+		vrLen = 1333;
+		vrLoc = 1429;
+	};
+	E17AEDAA03C0F5D300B89ACF = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: delay";
+		rLen = 0;
+		rLoc = 578;
+		rType = 0;
+		vrLen = 1660;
+		vrLoc = 319;
+	};
+	E17AEDAB03C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 49";
+		rLen = 0;
+		rLoc = 1821;
+		rType = 0;
+		vrLen = 1331;
+		vrLoc = 1429;
+	};
+	E17AEDAC03C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: ";
+		rLen = 0;
+		rLoc = 2750;
+		rType = 0;
+		vrLen = 1857;
+		vrLoc = 727;
+	};
+	E17AEDAD03C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 149";
+		rLen = 0;
+		rLoc = 5300;
+		rType = 0;
+		vrLen = 1627;
+		vrLoc = 3595;
+	};
+	E17AEDAE03C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 60";
+		rLen = 0;
+		rLoc = 2432;
+		rType = 0;
+		vrLen = 1856;
+		vrLoc = 727;
+	};
+	E17AEDAF03C0F5D300B89ACF = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 17";
+		rLen = 23;
+		rLoc = 380;
+		rType = 0;
+		vrLen = 586;
+		vrLoc = 0;
+	};
+	E17AEDB003C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: _alertCompleted:";
+		rLen = 0;
+		rLoc = 1045;
+		rType = 0;
+		vrLen = 1704;
+		vrLoc = 359;
+	};
+	E17AEDB103C0F5D300B89ACF = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 17";
+		rLen = 23;
+		rLoc = 380;
+		rType = 0;
+		vrLen = 586;
+		vrLoc = 0;
+	};
+	E17AEDB203C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 32";
+		rLen = 0;
+		rLoc = 985;
+		rType = 0;
+		vrLen = 1642;
+		vrLoc = 359;
+	};
+	E17AEDB503C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 29";
+		rLen = 142;
+		rLoc = 785;
+		rType = 0;
+		vrLen = 1425;
+		vrLoc = 0;
+	};
+	E17AEDB603C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 149";
+		rLen = 0;
+		rLoc = 5300;
+		rType = 0;
+		vrLen = 1568;
+		vrLoc = 0;
+	};
+	E17AEDB803C0F5D300B89ACF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E17AEDB903C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 67";
+		rLen = 0;
+		rLoc = 2598;
+		rType = 0;
+		vrLen = 1800;
+		vrLoc = 1111;
+	};
+	E17AEDBB03C0F5D300B89ACF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 205";
+		rLen = 0;
+		rLoc = 6053;
+		rType = 0;
+		vrLen = 1441;
+		vrLoc = 2048;
+	};
+	E17AEDBD03C0F5D300B89ACF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 12";
+		rLen = 0;
+		rLoc = 272;
+		rType = 0;
+		vrLen = 877;
+		vrLoc = 0;
+	};
+	E17AEDBE03C0F5D300B89ACF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 47";
+		rLen = 0;
+		rLoc = 1751;
+		rType = 0;
+		vrLen = 1652;
+		vrLoc = 284;
+	};
+	E17AEDC003C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 78";
+		rLen = 0;
+		rLoc = 3032;
+		rType = 0;
+		vrLen = 1532;
+		vrLoc = 1387;
+	};
+	E17AEDC103C0F5D300B89ACF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 27";
+		rLen = 0;
+		rLoc = 611;
+		rType = 0;
+		vrLen = 1116;
+		vrLoc = 389;
+	};
+	E17AEDC203C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 78";
+		rLen = 32;
+		rLoc = 3004;
+		rType = 0;
+		vrLen = 1636;
+		vrLoc = 1287;
+	};
+	E17AEDC303C0F5D300B89ACF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 19";
+		rLen = 0;
+		rLoc = 398;
+		rType = 0;
+		vrLen = 1067;
+		vrLoc = 296;
+	};
+	E17AEDC603C0F5D300B89ACF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 62";
+		rLen = 14;
+		rLoc = 2155;
+		rType = 0;
+		vrLen = 1536;
+		vrLoc = 1552;
+	};
+	E17AEDC803C0F5D300B89ACF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 93";
+		rLen = 0;
+		rLoc = 2219;
+		rType = 0;
+		vrLen = 1069;
+		vrLoc = 1232;
+	};
+	E17AEDD103C0F5D300B89ACF = {
+		isa = PBXFileReference;
+		name = Processes.h;
+		path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Headers/Processes.h;
+		refType = 0;
+	};
+	E17AEDD203C0F5D300B89ACF = {
+		isa = PBXFileReference;
+		name = NSApplication.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSApplication.html;
+		refType = 0;
+	};
+	E17AEDD303C0F5D300B89ACF = {
+		isa = PBXFileReference;
+		name = Getting_Proc__Information.html;
+		path = /Developer/Documentation/Carbon/oss/ProcessManager/Process_Manager/Functions/Getting_Proc__Information.html;
+		refType = 0;
+	};
+	E17AEDD403C0F5D300B89ACF = {
+		isa = PBXFileReference;
+		name = NSWorkspace.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSWorkspace.html;
+		refType = 0;
+	};
+	E17AEDD503C0F5D300B89ACF = {
+		isa = PBXFileReference;
+		name = NSWorkspace.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWorkspace.h;
+		refType = 0;
+	};
+	E17AEDD603C0F5D300B89ACF = {
+		isa = PBXFileReference;
+		name = NSApplication.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSApplication.h;
+		refType = 0;
+	};
+	E195A26403BE251F00186F9B = {
+		fRef = F5F198D0036BE57401EB0372;
+		isa = PBXTextBookmark;
+		name = "NJRTableDelegate.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1350;
+		vrLoc = 0;
+	};
+	E195A26503BE251F00186F9B = {
+		fRef = F5F198D1036BE57401EB0372;
+		isa = PBXTextBookmark;
+		name = "NJRTableDelegate.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 546;
+		vrLoc = 0;
+	};
+	E195A26603BE251F00186F9B = {
+		fRef = E195A32003BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "fp.h: 2178";
+		rLen = 39;
+		rLoc = 68209;
+		rType = 0;
+		vrLen = 1340;
+		vrLoc = 67559;
+	};
+	E195A26703BE251F00186F9B = {
+		fRef = E195A32103BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "float.h: 241";
+		rLen = 5;
+		rLoc = 8672;
+		rType = 0;
+		vrLen = 1576;
+		vrLoc = 0;
+	};
+	E195A26803BE251F00186F9B = {
+		fRef = E195A31403BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "stdlib.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 2595;
+		vrLoc = 0;
+	};
+	E195A26C03BE251F00186F9B = {
+		fRef = E1F0B14E03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E195A26D03BE251F00186F9B = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: __STDC__";
+		rLen = 35;
+		rLoc = 160;
+		rType = 0;
+		vrLen = 1309;
+		vrLoc = 0;
+	};
+	E195A26E03BE251F00186F9B = {
+		fRef = E195A31603BE251F00186F9B;
+		glyphRangeLength = 1300;
+		glyphRangeLocation = 3099;
+		isa = PBXDocBookmark;
+		name = "NSHelpManager.html: See Also - r...";
+	};
+	E195A26F03BE251F00186F9B = {
+		fRef = E195A30F03BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSHelpManager.h: 65";
+		rLen = 0;
+		rLoc = 1677;
+		rType = 0;
+		vrLen = 1330;
+		vrLoc = 347;
+	};
+	E195A27603BE251F00186F9B = {
+		fRef = E195A31003BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSSet.h: 63";
+		rLen = 19;
+		rLoc = 1498;
+		rType = 0;
+		vrLen = 1023;
+		vrLoc = 1199;
+	};
+	E195A27A03BE251F00186F9B = {
+		fRef = E195A31103BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSNumberFormatter.h: 77";
+		rLen = 0;
+		rLoc = 2579;
+		rType = 0;
+		vrLen = 1547;
+		vrLoc = 1034;
+	};
+	E195A27B03BE251F00186F9B = {
+		fRef = E195A31203BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSDecimalNumber.h: 35";
+		rLen = 8;
+		rLoc = 1139;
+		rType = 0;
+		vrLen = 1562;
+		vrLoc = 0;
+	};
+	E195A27D03BE251F00186F9B = {
+		fRef = E195A31703BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSFormatter.h: 18";
+		rLen = 27;
+		rLoc = 431;
+		rType = 0;
+		vrLen = 1230;
+		vrLoc = 0;
+	};
+	E195A27E03BE251F00186F9B = {
+		fRef = E195A31803BE251F00186F9B;
+		glyphRangeLength = 1826;
+		glyphRangeLocation = 1689;
+		isa = PBXDocBookmark;
+		name = "NSFormatter.html: Textual repr...";
+	};
+	E195A28003BE251F00186F9B = {
+		fRef = E1F0B14A03AD8CEF00AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NJRUnfocusableMovieView.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 249;
+		vrLoc = 0;
+	};
+	E195A28F03BE251F00186F9B = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 12";
+		rLen = 0;
+		rLoc = 212;
+		rType = 0;
+		vrLen = 651;
+		vrLoc = 0;
+	};
+	E195A29203BE251F00186F9B = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 493;
+		vrLoc = 0;
+	};
+	E195A29503BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: stopAlerts:";
+		rLen = 0;
+		rLoc = 1681;
+		rType = 0;
+		vrLen = 945;
+		vrLoc = 0;
+	};
+	E195A29603BE251F00186F9B = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 78";
+		rLen = 0;
+		rLoc = 2730;
+		rType = 0;
+		vrLen = 1220;
+		vrLoc = 2049;
+	};
+	E195A29703BE251F00186F9B = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 608;
+		vrLoc = 0;
+	};
+	E195A29803BE251F00186F9B = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1553;
+		vrLoc = 0;
+	};
+	E195A29903BE251F00186F9B = {
+		fRef = F5F198D1036BE57401EB0372;
+		isa = PBXTextBookmark;
+		name = "NJRTableDelegate.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 546;
+		vrLoc = 0;
+	};
+	E195A2AC03BE251F00186F9B = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 78";
+		rLen = 0;
+		rLoc = 2730;
+		rType = 0;
+		vrLen = 1220;
+		vrLoc = 2049;
+	};
+	E195A2AD03BE251F00186F9B = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1553;
+		vrLoc = 0;
+	};
+	E195A2AE03BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1699;
+		rType = 0;
+		vrLen = 945;
+		vrLoc = 0;
+	};
+	E195A2B003BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1948;
+		rType = 0;
+		vrLen = 945;
+		vrLoc = 0;
+	};
+	E195A2B103BE251F00186F9B = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 15";
+		rLen = 0;
+		rLoc = 341;
+		rType = 0;
+		vrLen = 504;
+		vrLoc = 0;
+	};
+	E195A2B403BE251F00186F9B = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 19";
+		rLen = 0;
+		rLoc = 675;
+		rType = 0;
+		vrLen = 1371;
+		vrLoc = 0;
+	};
+	E195A2B503BE251F00186F9B = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: 19";
+		rLen = 0;
+		rLoc = 465;
+		rType = 0;
+		vrLen = 814;
+		vrLoc = 0;
+	};
+	E195A2B603BE251F00186F9B = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: allAlarms";
+		rLen = 0;
+		rLoc = 4481;
+		rType = 0;
+		vrLen = 1234;
+		vrLoc = 2975;
+	};
+	E195A2B703BE251F00186F9B = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 15";
+		rLen = 0;
+		rLoc = 341;
+		rType = 0;
+		vrLen = 518;
+		vrLoc = 0;
+	};
+	E195A2B803BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 2959;
+		rType = 0;
+		vrLen = 954;
+		vrLoc = 0;
+	};
+	E195A2B903BE251F00186F9B = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 15";
+		rLen = 0;
+		rLoc = 341;
+		rType = 0;
+		vrLen = 518;
+		vrLoc = 0;
+	};
+	E195A2BA03BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 2352;
+		rType = 0;
+		vrLen = 1005;
+		vrLoc = 0;
+	};
+	E195A2BB03BE251F00186F9B = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 15";
+		rLen = 0;
+		rLoc = 322;
+		rType = 0;
+		vrLen = 525;
+		vrLoc = 0;
+	};
+	E195A2BC03BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 2033;
+		rType = 0;
+		vrLen = 1025;
+		vrLoc = 0;
+	};
+	E195A2BD03BE251F00186F9B = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 15";
+		rLen = 0;
+		rLoc = 322;
+		rType = 0;
+		vrLen = 525;
+		vrLoc = 0;
+	};
+	E195A2BE03BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: dealloc";
+		rLen = 0;
+		rLoc = 3033;
+		rType = 0;
+		vrLen = 1202;
+		vrLoc = 0;
+	};
+	E195A2C103BE251F00186F9B = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1752;
+		rType = 0;
+		vrLen = 1633;
+		vrLoc = 201;
+	};
+	E195A2C203BE251F00186F9B = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 12";
+		rLen = 0;
+		rLoc = 215;
+		rType = 0;
+		vrLen = 746;
+		vrLoc = 0;
+	};
+	E195A2C303BE251F00186F9B = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1752;
+		rType = 0;
+		vrLen = 1196;
+		vrLoc = 2247;
+	};
+	E195A2C403BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 2985;
+		rType = 0;
+		vrLen = 1202;
+		vrLoc = 0;
+	};
+	E195A2C503BE251F00186F9B = {
+		fRef = E195A31B03BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSFormatter.h: 14";
+		rLen = 20;
+		rLoc = 277;
+		rType = 0;
+		vrLen = 1230;
+		vrLoc = 0;
+	};
+	E195A2C603BE251F00186F9B = {
+		fRef = E195A31C03BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSDecimalNumber.h: 35";
+		rLen = 8;
+		rLoc = 1139;
+		rType = 0;
+		vrLen = 1562;
+		vrLoc = 0;
+	};
+	E195A2C703BE251F00186F9B = {
+		fRef = E195A31D03BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSValue.h: 59";
+		rLen = 0;
+		rLoc = 1356;
+		rType = 0;
+		vrLen = 1649;
+		vrLoc = 937;
+	};
+	E195A2C803BE251F00186F9B = {
+		fRef = E195A31E03BE251F00186F9B;
+		isa = PBXTextBookmark;
+		name = "NSFormatter.h: 18";
+		rLen = 27;
+		rLoc = 431;
+		rType = 0;
+		vrLen = 1230;
+		vrLoc = 0;
+	};
+	E195A2C903BE251F00186F9B = {
+		fRef = E195A31F03BE251F00186F9B;
+		glyphRangeLength = 1826;
+		glyphRangeLocation = 1689;
+		isa = PBXDocBookmark;
+		name = "NSFormatter.html: Textual repr...";
+	};
+	E195A2CA03BE251F00186F9B = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 107";
+		rLen = 1;
+		rLoc = 8766;
+		rType = 0;
+		vrLen = 2613;
+		vrLoc = 7027;
+	};
+	E195A2CB03BE251F00186F9B = {
+		fRef = E1F0B14A03AD8CEF00AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NJRUnfocusableMovieView.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 249;
+		vrLoc = 0;
+	};
+	E195A2CD03BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: stopAlerts:";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 1202;
+		vrLoc = 0;
+	};
+	E195A2E003BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: stopAlerts:";
+		rLen = 0;
+		rLoc = 684;
+		rType = 0;
+		vrLen = 1159;
+		vrLoc = 0;
+	};
+	E195A2E103BE251F00186F9B = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: PSAlarmAlertStopNotification";
+		rLen = 54;
+		rLoc = 207;
+		rType = 0;
+		vrLen = 525;
+		vrLoc = 0;
+	};
+	E195A2E203BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: stopAlerts:";
+		rLen = 0;
+		rLoc = 1681;
+		rType = 0;
+		vrLen = 1238;
+		vrLoc = 0;
+	};
+	E195A2E803BE251F00186F9B = {
+		fRef = F59E47B0036AACD1016B311C;
+		isa = PBXTextBookmark;
+		name = "PSNotifierAlert.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 805;
+		vrLoc = 0;
+	};
+	E195A2E903BE251F00186F9B = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 434;
+		vrLoc = 0;
+	};
+	E195A2EA03BE251F00186F9B = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: triggerForAlarm:";
+		rLen = 0;
+		rLoc = 1531;
+		rType = 0;
+		vrLen = 1443;
+		vrLoc = 836;
+	};
+	E195A2EB03BE251F00186F9B = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 12";
+		rLen = 0;
+		rLoc = 224;
+		rType = 0;
+		vrLen = 434;
+		vrLoc = 0;
+	};
+	E195A2EC03BE251F00186F9B = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: dealloc";
+		rLen = 107;
+		rLoc = 668;
+		rType = 0;
+		vrLen = 1194;
+		vrLoc = 648;
+	};
+	E195A2ED03BE251F00186F9B = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: _alertCompleted:";
+		rLen = 0;
+		rLoc = 1611;
+		rType = 0;
+		vrLen = 1435;
+		vrLoc = 538;
+	};
+	E195A2F003BE251F00186F9B = {
+		fRef = F59E47B0036AACD1016B311C;
+		isa = PBXTextBookmark;
+		name = "PSNotifierAlert.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 805;
+		vrLoc = 0;
+	};
+	E195A2F103BE251F00186F9B = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: dealloc";
+		rLen = 107;
+		rLoc = 668;
+		rType = 0;
+		vrLen = 1194;
+		vrLoc = 648;
+	};
+	E195A2F303BE251F00186F9B = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: didFinishSpeaking:";
+		rLen = 0;
+		rLoc = 2205;
+		rType = 0;
+		vrLen = 1254;
+		vrLoc = 1027;
+	};
+	E195A2F503BE251F00186F9B = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 13";
+		rLen = 0;
+		rLoc = 273;
+		rType = 0;
+		vrLen = 1051;
+		vrLoc = 0;
+	};
+	E195A2F703BE251F00186F9B = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: triggerForAlarm:";
+		rLen = 0;
+		rLoc = 1033;
+		rType = 0;
+		vrLen = 1252;
+		vrLoc = 1049;
+	};
+	E195A2F903BE251F00186F9B = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: initWithPropertyList:";
+		rLen = 0;
+		rLoc = 2016;
+		rType = 0;
+		vrLen = 1249;
+		vrLoc = 1052;
+	};
+	E195A2FC03BE251F00186F9B = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 12";
+		rLen = 0;
+		rLoc = 212;
+		rType = 0;
+		vrLen = 651;
+		vrLoc = 0;
+	};
+	E195A2FE03BE251F00186F9B = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 12";
+		rLen = 0;
+		rLoc = 212;
+		rType = 0;
+		vrLen = 651;
+		vrLoc = 0;
+	};
+	E195A30F03BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSHelpManager.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSHelpManager.h;
+		refType = 0;
+	};
+	E195A31003BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSSet.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSSet.h;
+		refType = 0;
+	};
+	E195A31103BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSNumberFormatter.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSNumberFormatter.h;
+		refType = 0;
+	};
+	E195A31203BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSDecimalNumber.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDecimalNumber.h;
+		refType = 0;
+	};
+	E195A31403BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = stdlib.h;
+		path = /usr/include/stdlib.h;
+		refType = 0;
+	};
+	E195A31603BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSHelpManager.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSHelpManager.html;
+		refType = 0;
+	};
+	E195A31703BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSFormatter.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSFormatter.h;
+		refType = 0;
+	};
+	E195A31803BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSFormatter.html;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSFormatter.html;
+		refType = 0;
+	};
+	E195A31B03BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSFormatter.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSFormatter.h;
+		refType = 0;
+	};
+	E195A31C03BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSDecimalNumber.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDecimalNumber.h;
+		refType = 0;
+	};
+	E195A31D03BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSValue.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSValue.h;
+		refType = 0;
+	};
+	E195A31E03BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSFormatter.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSFormatter.h;
+		refType = 0;
+	};
+	E195A31F03BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = NSFormatter.html;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSFormatter.html;
+		refType = 0;
+	};
+	E195A32003BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = fp.h;
+		path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/fp.h;
+		refType = 0;
+	};
+	E195A32103BE251F00186F9B = {
+		isa = PBXFileReference;
+		name = float.h;
+		path = /usr/include/gcc/darwin/3.1/float.h;
+		refType = 0;
+	};
+	E198FA9803C963C700050002 = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 93";
+		rLen = 0;
+		rLoc = 2808;
+		rType = 0;
+		vrLen = 1387;
+		vrLoc = 2086;
+	};
+	E19DCB7803BE4A0A00B934BF = {
+		fRef = E19DCBC203BE4A0A00B934BF;
+		isa = PBXTextBookmark;
+		name = "NSNotification.h: 34";
+		rLen = 13;
+		rLoc = 765;
+		rType = 0;
+		vrLen = 1240;
+		vrLoc = 0;
+	};
+	E19DCB8203BE4A0A00B934BF = {
+		fRef = E19DCBC303BE4A0A00B934BF;
+		isa = PBXTextBookmark;
+		name = "Movies.h: 1269";
+		rLen = 10;
+		rLoc = 55658;
+		rType = 0;
+		vrLen = 1395;
+		vrLoc = 55000;
+	};
+	E19DCB8303BE4A0A00B934BF = {
+		fRef = E19DCBC403BE4A0A00B934BF;
+		isa = PBXTextBookmark;
+		name = "NSSound.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1487;
+		vrLoc = 0;
+	};
+	E19DCB8503BE4A0A00B934BF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 71";
+		rLen = 0;
+		rLoc = 1687;
+		rType = 0;
+		vrLen = 1249;
+		vrLoc = 1052;
+	};
+	E19DCB8903BE4A0A00B934BF = {
+		fRef = F59E47B0036AACD1016B311C;
+		isa = PBXTextBookmark;
+		name = "PSNotifierAlert.m: 37";
+		rLen = 65;
+		rLoc = 827;
+		rType = 0;
+		vrLen = 846;
+		vrLoc = 0;
+	};
+	E19DCB8B03BE4A0A00B934BF = {
+		fRef = F59E47B0036AACD1016B311C;
+		isa = PBXTextBookmark;
+		name = "PSNotifierAlert.m: 37";
+		rLen = 65;
+		rLoc = 827;
+		rType = 0;
+		vrLen = 846;
+		vrLoc = 0;
+	};
+	E19DCB8C03BE4A0A00B934BF = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 85";
+		rLen = 0;
+		rLoc = 2192;
+		rType = 0;
+		vrLen = 1429;
+		vrLoc = 850;
+	};
+	E19DCB8E03BE4A0A00B934BF = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: 97";
+		rLen = 0;
+		rLoc = 2296;
+		rType = 0;
+		vrLen = 1249;
+		vrLoc = 1052;
+	};
+	E19DCB9003BE4A0A00B934BF = {
+		fRef = F59E47B0036AACD1016B311C;
+		isa = PBXTextBookmark;
+		name = "PSNotifierAlert.m: 14";
+		rLen = 15;
+		rLoc = 284;
+		rType = 0;
+		vrLen = 846;
+		vrLoc = 0;
+	};
+	E19DCB9103BE4A0A00B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 12";
+		rLen = 0;
+		rLoc = 283;
+		rType = 0;
+		vrLen = 1785;
+		vrLoc = 0;
+	};
+	E19DCB9303BE4A0A00B934BF = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: windowWillClose:";
+		rLen = 0;
+		rLoc = 4730;
+		rType = 0;
+		vrLen = 1986;
+		vrLoc = 2295;
+	};
+	E19DCB9403BE4A0A00B934BF = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 608;
+		vrLoc = 0;
+	};
+	E19DCB9503BE4A0A00B934BF = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: windowWillClose:";
+		rLen = 0;
+		rLoc = 4543;
+		rType = 0;
+		vrLen = 1994;
+		vrLoc = 2295;
+	};
+	E19DCB9603BE4A0A00B934BF = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 25";
+		rLen = 0;
+		rLoc = 649;
+		rType = 0;
+		vrLen = 661;
+		vrLoc = 0;
+	};
+	E19DCB9703BE4A0A00B934BF = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: dealloc";
+		rLen = 0;
+		rLoc = 4240;
+		rType = 0;
+		vrLen = 2014;
+		vrLoc = 2373;
+	};
+	E19DCB9803BE4A0A00B934BF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 2964;
+		rType = 0;
+		vrLen = 1561;
+		vrLoc = 460;
+	};
+	E19DCB9903BE4A0A00B934BF = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: triggerForAlarm:";
+		rLen = 0;
+		rLoc = 1531;
+		rType = 0;
+		vrLen = 1443;
+		vrLoc = 836;
+	};
+	E19DCB9A03BE4A0A00B934BF = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 11";
+		rLen = 0;
+		rLoc = 170;
+		rType = 0;
+		vrLen = 453;
+		vrLoc = 0;
+	};
+	E19DCB9B03BE4A0A00B934BF = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: __OBJC__";
+		rLen = 0;
+		rLoc = 175;
+		rType = 0;
+		vrLen = 975;
+		vrLoc = 0;
+	};
+	E19DCB9C03BE4A0A00B934BF = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 11";
+		rLen = 0;
+		rLoc = 170;
+		rType = 0;
+		vrLen = 453;
+		vrLoc = 0;
+	};
+	E19DCB9D03BE4A0A00B934BF = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: dealloc";
+		rLen = 0;
+		rLoc = 687;
+		rType = 0;
+		vrLen = 1060;
+		vrLoc = 514;
+	};
+	E19DCB9E03BE4A0A00B934BF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 2342;
+		rType = 0;
+		vrLen = 1622;
+		vrLoc = 460;
+	};
+	E19DCB9F03BE4A0A00B934BF = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: __OBJC__";
+		rLen = 0;
+		rLoc = 198;
+		rType = 0;
+		vrLen = 996;
+		vrLoc = 0;
+	};
+	E19DCBA103BE4A0A00B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 12";
+		rLen = 0;
+		rLoc = 215;
+		rType = 0;
+		vrLen = 746;
+		vrLoc = 0;
+	};
+	E19DCBA203BE4A0A00B934BF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: _alertCompleted:";
+		rLen = 0;
+		rLoc = 1558;
+		rType = 0;
+		vrLen = 1440;
+		vrLoc = 0;
+	};
+	E19DCBA803BE4A0A00B934BF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: alarm";
+		rLen = 0;
+		rLoc = 4481;
+		rType = 0;
+		vrLen = 1292;
+		vrLoc = 2939;
+	};
+	E19DCBA903BE4A0A00B934BF = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: 19";
+		rLen = 0;
+		rLoc = 465;
+		rType = 0;
+		vrLen = 814;
+		vrLoc = 0;
+	};
+	E19DCBAA03BE4A0A00B934BF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: init";
+		rLen = 0;
+		rLoc = 4208;
+		rType = 0;
+		vrLen = 1554;
+		vrLoc = 2504;
+	};
+	E19DCBAB03BE4A0A00B934BF = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: 19";
+		rLen = 0;
+		rLoc = 455;
+		rType = 0;
+		vrLen = 814;
+		vrLoc = 0;
+	};
+	E19DCBAC03BE4A0A00B934BF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: init";
+		rLen = 0;
+		rLoc = 4208;
+		rType = 0;
+		vrLen = 1554;
+		vrLoc = 2504;
+	};
+	E19DCBAD03BE4A0A00B934BF = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: 19";
+		rLen = 0;
+		rLoc = 455;
+		rType = 0;
+		vrLen = 814;
+		vrLoc = 0;
+	};
+	E19DCBAE03BE4A0A00B934BF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: dealloc";
+		rLen = 0;
+		rLoc = 4392;
+		rType = 0;
+		vrLen = 1581;
+		vrLoc = 2504;
+	};
+	E19DCBB203BE4A0A00B934BF = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 103";
+		rLen = 0;
+		rLoc = 8906;
+		rType = 0;
+		vrLen = 3512;
+		vrLoc = 4668;
+	};
+	E19DCBB603BE4A0A00B934BF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: _alertCompleted:";
+		rLen = 0;
+		rLoc = 1558;
+		rType = 0;
+		vrLen = 1440;
+		vrLoc = 0;
+	};
+	E19DCBBC03BE4A0A00B934BF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: _alarmDied:";
+		rLen = 0;
+		rLoc = 4481;
+		rType = 0;
+		vrLen = 1278;
+		vrLoc = 3171;
+	};
+	E19DCBBD03BE4A0A00B934BF = {
+		fRef = E19DCBC103BE4A0A00B934BF;
+		isa = PBXTextBookmark;
+		name = "NSSound.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1487;
+		vrLoc = 0;
+	};
+	E19DCBC103BE4A0A00B934BF = {
+		isa = PBXFileReference;
+		name = NSSound.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSSound.h;
+		refType = 0;
+	};
+	E19DCBC203BE4A0A00B934BF = {
+		isa = PBXFileReference;
+		name = NSNotification.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSNotification.h;
+		refType = 0;
+	};
+	E19DCBC303BE4A0A00B934BF = {
+		isa = PBXFileReference;
+		name = Movies.h;
+		path = /System/Library/Frameworks/QuickTime.framework/Versions/A/Headers/Movies.h;
+		refType = 0;
+	};
+	E19DCBC403BE4A0A00B934BF = {
+		isa = PBXFileReference;
+		name = NSSound.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSSound.h;
+		refType = 0;
+	};
+	E19DCC8703BE900300B934BF = {
+		fRef = 29B97316FDCFA39411CA2CEA;
+		isa = PBXTextBookmark;
+		name = "main.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 252;
+		vrLoc = 0;
+	};
+	E19DCC8903BE900300B934BF = {
+		fRef = E19DCCE403BE900300B934BF;
+		isa = PBXTextBookmark;
+		name = "math.h: 225";
+		rLen = 4;
+		rLoc = 9556;
+		rType = 0;
+		vrLen = 1314;
+		vrLoc = 8899;
+	};
+	E19DCC8A03BE900300B934BF = {
+		fRef = E19DCCE203BE900300B934BF;
+		isa = PBXTextBookmark;
+		name = "math.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1095;
+		vrLoc = 0;
+	};
+	E19DCC8E03BE900300B934BF = {
+		fRef = E19DCCE503BE900300B934BF;
+		isa = PBXTextBookmark;
+		name = "NSValue.h: 88";
+		rLen = 46;
+		rLoc = 2491;
+		rType = 0;
+		vrLen = 1443;
+		vrLoc = 1143;
+	};
+	E19DCC8F03BE900300B934BF = {
+		fRef = E19DCCE603BE900300B934BF;
+		isa = PBXTextBookmark;
+		name = "NSUserDefaults.h: 66";
+		rLen = 0;
+		rLoc = 2244;
+		rType = 0;
+		vrLen = 1698;
+		vrLoc = 610;
+	};
+	E19DCC9203BE900300B934BF = {
+		fRef = E19DCCDF03BE900300B934BF;
+		isa = PBXTextBookmark;
+		name = "NSTextField.h: 11";
+		rLen = 9;
+		rLoc = 198;
+		rType = 0;
+		vrLen = 1244;
+		vrLoc = 0;
+	};
+	E19DCC9603BE900300B934BF = {
+		fRef = E19DCCE103BE900300B934BF;
+		glyphRangeLength = 1784;
+		glyphRangeLocation = 24666;
+		isa = PBXDocBookmark;
+		name = "NSWindow.html: display  - (...";
+	};
+	E19DCC9C03BE900300B934BF = {
+		fRef = F560E3160357895001A4E466;
+		isa = PBXTextBookmark;
+		name = "NJRHistoryTrackingComboBox.m: 62";
+		rLen = 0;
+		rLoc = 1883;
+		rType = 0;
+		vrLen = 1252;
+		vrLoc = 1028;
+	};
+	E19DCC9E03BE900300B934BF = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: initWithAlarm:movieAlert:";
+		rLen = 0;
+		rLoc = 649;
+		rType = 0;
+		vrLen = 661;
+		vrLoc = 0;
+	};
+	E19DCCA203BE900300B934BF = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: controllerWithAlarm:movieAlert:";
+		rLen = 0;
+		rLoc = 535;
+		rType = 0;
+		vrLen = 1544;
+		vrLoc = 0;
+	};
+	E19DCCA303BE900300B934BF = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+	};
+	E19DCCA403BE900300B934BF = {
+		fRef = 29B97316FDCFA39411CA2CEA;
+		isa = PBXTextBookmark;
+		name = "main.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 252;
+		vrLoc = 0;
+	};
+	E19DCCA603BE900300B934BF = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+	};
+	E19DCCA703BE900300B934BF = {
+		fRef = 29B97316FDCFA39411CA2CEA;
+		isa = PBXTextBookmark;
+		name = "main.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 252;
+		vrLoc = 0;
+	};
+	E19DCCA903BE900300B934BF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: alarm";
+		rLen = 0;
+		rLoc = 4481;
+		rType = 0;
+		vrLen = 1228;
+		vrLoc = 3171;
+	};
+	E19DCCAC03BE900300B934BF = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 103";
+		rLen = 0;
+		rLoc = 8980;
+		rType = 0;
+		vrLen = 2645;
+		vrLoc = 7550;
+	};
+	E19DCCAE03BE900300B934BF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 169";
+		rLen = 11;
+		rLoc = 4825;
+		rType = 0;
+		vrLen = 1022;
+		vrLoc = 4420;
+	};
+	E19DCCB203BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 24";
+		rLen = 0;
+		rLoc = 619;
+		rType = 0;
+		vrLen = 1465;
+		vrLoc = 0;
+	};
+	E19DCCB303BE900300B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 30";
+		rLen = 46;
+		rLoc = 752;
+		rType = 0;
+		vrLen = 792;
+		vrLoc = 0;
+	};
+	E19DCCB403BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: ";
+		rLen = 0;
+		rLoc = 3587;
+		rType = 0;
+		vrLen = 1145;
+		vrLoc = 2540;
+	};
+	E19DCCB503BE900300B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 20";
+		rLen = 0;
+		rLoc = 535;
+		rType = 0;
+		vrLen = 792;
+		vrLoc = 0;
+	};
+	E19DCCB603BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 45";
+		rLen = 0;
+		rLoc = 1752;
+		rType = 0;
+		vrLen = 1566;
+		vrLoc = 465;
+	};
+	E19DCCB703BE900300B934BF = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: PSAlarmAlertStopNotification";
+		rLen = 54;
+		rLoc = 207;
+		rType = 0;
+		vrLen = 525;
+		vrLoc = 0;
+	};
+	E19DCCB903BE900300B934BF = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: _alertCompleted:";
+		rLen = 0;
+		rLoc = 1558;
+		rType = 0;
+		vrLen = 1267;
+		vrLoc = 0;
+	};
+	E19DCCBA03BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 39";
+		rLen = 0;
+		rLoc = 1250;
+		rType = 0;
+		vrLen = 1641;
+		vrLoc = 314;
+	};
+	E19DCCBB03BE900300B934BF = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 90";
+		rLen = 0;
+		rLoc = 6597;
+		rType = 0;
+		vrLen = 2581;
+		vrLoc = 4602;
+	};
+	E19DCCBC03BE900300B934BF = {
+		fRef = E19DCCE903BE900300B934BF;
+		isa = PBXTextBookmark;
+		name = "NSTextField.h: 11";
+		rLen = 9;
+		rLoc = 198;
+		rType = 0;
+		vrLen = 1244;
+		vrLoc = 0;
+	};
+	E19DCCBD03BE900300B934BF = {
+		fRef = E19DCCE803BE900300B934BF;
+		isa = PBXTextBookmark;
+		name = "NSControl.h: 115";
+		rLen = 111;
+		rLoc = 3488;
+		rType = 0;
+		vrLen = 1658;
+		vrLoc = 2392;
+	};
+	E19DCCBE03BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 120";
+		rLen = 0;
+		rLoc = 4586;
+		rType = 0;
+		vrLen = 1470;
+		vrLoc = 2746;
+	};
+	E19DCCBF03BE900300B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 20";
+		rLen = 0;
+		rLoc = 535;
+		rType = 0;
+		vrLen = 792;
+		vrLoc = 0;
+	};
+	E19DCCC003BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 120";
+		rLen = 0;
+		rLoc = 4586;
+		rType = 0;
+		vrLen = 1469;
+		vrLoc = 2746;
+	};
+	E19DCCC103BE900300B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: close:";
+		rLen = 0;
+		rLoc = 704;
+		rType = 0;
+		vrLen = 784;
+		vrLoc = 0;
+	};
+	E19DCCC203BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 126";
+		rLen = 0;
+		rLoc = 4870;
+		rType = 0;
+		vrLen = 1609;
+		vrLoc = 2804;
+	};
+	E19DCCC403BE900300B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: close:";
+		rLen = 0;
+		rLoc = 704;
+		rType = 0;
+		vrLen = 784;
+		vrLoc = 0;
+	};
+	E19DCCC503BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: canSnooze";
+		rLen = 9;
+		rLoc = 2436;
+		rType = 0;
+		vrLen = 1209;
+		vrLoc = 1910;
+	};
+	E19DCCC603BE900300B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 24";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E19DCCC703BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 78";
+		rLen = 0;
+		rLoc = 2484;
+		rType = 0;
+		vrLen = 1209;
+		vrLoc = 1695;
+	};
+	E19DCCC803BE900300B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E19DCCC903BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 78";
+		rLen = 0;
+		rLoc = 2484;
+		rType = 0;
+		vrLen = 1207;
+		vrLoc = 1695;
+	};
+	E19DCCCA03BE900300B934BF = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 804;
+		vrLoc = 0;
+	};
+	E19DCCCB03BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 79";
+		rLen = 0;
+		rLoc = 2525;
+		rType = 0;
+		vrLen = 1296;
+		vrLoc = 1987;
+	};
+	E19DCCCF03BE900300B934BF = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 90";
+		rLen = 0;
+		rLoc = 6597;
+		rType = 0;
+		vrLen = 2581;
+		vrLoc = 4602;
+	};
+	E19DCCD103BE900300B934BF = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 145";
+		rLen = 0;
+		rLoc = 5133;
+		rType = 0;
+		vrLen = 1524;
+		vrLoc = 3698;
+	};
+	E19DCCD203BE900300B934BF = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 113";
+		rLen = 0;
+		rLoc = 10205;
+		rType = 0;
+		vrLen = 2830;
+		vrLoc = 7613;
+	};
+	E19DCCD403BE900300B934BF = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 181";
+		rLen = 0;
+		rLoc = 6730;
+		rType = 0;
+		vrLen = 952;
+		vrLoc = 6028;
+	};
+	E19DCCD503BE900300B934BF = {
+		fRef = F560E3160357895001A4E466;
+		isa = PBXTextBookmark;
+		name = "NJRHistoryTrackingComboBox.m: 62";
+		rLen = 0;
+		rLoc = 1883;
+		rType = 0;
+		vrLen = 1252;
+		vrLoc = 1028;
+	};
+	E19DCCD603BE900300B934BF = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 169";
+		rLen = 11;
+		rLoc = 4825;
+		rType = 0;
+		vrLen = 1007;
+		vrLoc = 4420;
+	};
+	E19DCCD703BE900300B934BF = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 86";
+		rLen = 0;
+		rLoc = 6155;
+		rType = 0;
+		vrLen = 2751;
+		vrLoc = 4838;
+	};
+	E19DCCD803BE900300B934BF = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 92";
+		rLen = 0;
+		rLoc = 4240;
+		rType = 0;
+		vrLen = 1703;
+		vrLoc = 2680;
+	};
+	E19DCCD903BE900300B934BF = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: initWithAlarm:movieAlert:";
+		rLen = 0;
+		rLoc = 649;
+		rType = 0;
+		vrLen = 661;
+		vrLoc = 0;
+	};
+	E19DCCDA03BE900300B934BF = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 105";
+		rLen = 0;
+		rLoc = 4558;
+		rType = 0;
+		vrLen = 1707;
+		vrLoc = 2680;
+	};
+	E19DCCDB03BE900300B934BF = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: ";
+		rLen = 0;
+		rLoc = 4152;
+		rType = 0;
+		vrLen = 1323;
+		vrLoc = 0;
+	};
+	E19DCCDF03BE900300B934BF = {
+		isa = PBXFileReference;
+		name = NSTextField.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextField.h;
+		refType = 0;
+	};
+	E19DCCE103BE900300B934BF = {
+		isa = PBXFileReference;
+		name = NSWindow.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSWindow.html;
+		refType = 0;
+	};
+	E19DCCE203BE900300B934BF = {
+		isa = PBXFileReference;
+		name = math.h;
+		path = /usr/include/math.h;
+		refType = 0;
+	};
+	E19DCCE403BE900300B934BF = {
+		isa = PBXFileReference;
+		name = math.h;
+		path = /usr/include/architecture/ppc/math.h;
+		refType = 0;
+	};
+	E19DCCE503BE900300B934BF = {
+		isa = PBXFileReference;
+		name = NSValue.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSValue.h;
+		refType = 0;
+	};
+	E19DCCE603BE900300B934BF = {
+		isa = PBXFileReference;
+		name = NSUserDefaults.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSUserDefaults.h;
+		refType = 0;
+	};
+	E19DCCE803BE900300B934BF = {
+		isa = PBXFileReference;
+		name = NSControl.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSControl.h;
+		refType = 0;
+	};
+	E19DCCE903BE900300B934BF = {
+		isa = PBXFileReference;
+		name = NSTextField.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextField.h;
+		refType = 0;
+	};
+	E19FD3A203C9985C001509F3 = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 108";
+		rLen = 0;
+		rLoc = 9315;
+		rType = 0;
+		vrLen = 2313;
+		vrLoc = 8173;
+	};
+	E19FD3A603C9985C001509F3 = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 108";
+		rLen = 0;
+		rLoc = 9148;
+		rType = 0;
+		vrLen = 2452;
+		vrLoc = 7854;
+	};
+	E19FD3A703C9985C001509F3 = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 108";
+		rLen = 0;
+		rLoc = 9315;
+		rType = 0;
+		vrLen = 2313;
+		vrLoc = 8173;
+	};
+	E19FD3A803C9985C001509F3 = {
+		fRef = E19FD39F03C98645001509F3;
+		isa = PBXTextBookmark;
+		name = "PSWakeAlert.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 745;
+		vrLoc = 0;
+	};
+	E19FD3A903C9985C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: 4";
+		rLen = 0;
+		rLoc = 30;
+		rType = 0;
+		vrLen = 1687;
+		vrLoc = 0;
+	};
+	E19FD3AA03C9985C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 64";
+		rLen = 0;
+		rLoc = 2389;
+		rType = 0;
+		vrLen = 1835;
+		vrLoc = 622;
+	};
+	E1A9DEE703BF3C110089E8B2 = {
+		isa = PBXSymbolicBreakpoint;
+		state = 1;
+		symbolName = "-[_NSZombie release]";
+	};
+	E1A9DEEB03BF480F0089E8B2 = {
+		fRef = E1A9DF1103BF480F0089E8B2;
+		isa = PBXTextBookmark;
+		name = "NSPopUpButton.h: 23";
+		rLen = 0;
+		rLoc = 546;
+		rType = 0;
+		vrLen = 1222;
+		vrLoc = 1166;
+	};
+	E1A9DEEE03BF480F0089E8B2 = {
+		fRef = E1A9DF1303BF480F0089E8B2;
+		isa = PBXTextBookmark;
+		name = "NSStepper.h: 10";
+		rLen = 9;
+		rLoc = 187;
+		rType = 0;
+		vrLen = 636;
+		vrLoc = 0;
+	};
+	E1A9DEF003BF480F0089E8B2 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: ";
+		rLen = 0;
+		rLoc = 6866;
+		rType = 0;
+		vrLen = 1590;
+		vrLoc = 6840;
+	};
+	E1A9DEF103BF480F0089E8B2 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 11";
+		rLen = 0;
+		rLoc = 170;
+		rType = 0;
+		vrLen = 453;
+		vrLoc = 0;
+	};
+	E1A9DEF203BF480F0089E8B2 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: __STDC__";
+		rLen = 0;
+		rLoc = 163;
+		rType = 0;
+		vrLen = 852;
+		vrLoc = 0;
+	};
+	E1A9DEF703BF480F0089E8B2 = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 167";
+		rLen = 0;
+		rLoc = 12371;
+		rType = 0;
+		vrLen = 2647;
+		vrLoc = 8836;
+	};
+	E1A9DEFB03BF480F0089E8B2 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 259";
+		rLen = 0;
+		rLoc = 9522;
+		rType = 0;
+		vrLen = 1353;
+		vrLoc = 8714;
+	};
+	E1A9DEFC03BF480F0089E8B2 = {
+		fRef = F5F240CA036A869401FE7503;
+		isa = PBXTextBookmark;
+		name = "BDAlias.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 920;
+		vrLoc = 1697;
+	};
+	E1A9DEFD03BF480F0089E8B2 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: ";
+		rLen = 0;
+		rLoc = 6341;
+		rType = 0;
+		vrLen = 960;
+		vrLoc = 6020;
+	};
+	E1A9DEFE03BF480F0089E8B2 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: _alertCompleted:";
+		rLen = 0;
+		rLoc = 1558;
+		rType = 0;
+		vrLen = 1267;
+		vrLoc = 0;
+	};
+	E1A9DF0203BF480F0089E8B2 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: ";
+		rLen = 0;
+		rLoc = 6866;
+		rType = 0;
+		vrLen = 1590;
+		vrLoc = 6840;
+	};
+	E1A9DF0303BF480F0089E8B2 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 18";
+		rLen = 0;
+		rLoc = 392;
+		rType = 0;
+		vrLen = 852;
+		vrLoc = 0;
+	};
+	E1A9DF0403BF480F0089E8B2 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 11";
+		rLen = 0;
+		rLoc = 170;
+		rType = 0;
+		vrLen = 453;
+		vrLoc = 0;
+	};
+	E1A9DF0503BF480F0089E8B2 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: __STDC__";
+		rLen = 0;
+		rLoc = 163;
+		rType = 0;
+		vrLen = 852;
+		vrLoc = 0;
+	};
+	E1A9DF0603BF480F0089E8B2 = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: voice";
+		rLen = 0;
+		rLoc = 853;
+		rType = 0;
+		vrLen = 908;
+		vrLoc = 0;
+	};
+	E1A9DF0703BF480F0089E8B2 = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 103";
+		rLen = 0;
+		rLoc = 8933;
+		rType = 0;
+		vrLen = 2871;
+		vrLoc = 6954;
+	};
+	E1A9DF0803BF480F0089E8B2 = {
+		fRef = F5F1986C036B813101EB0372;
+		isa = PBXTextBookmark;
+		name = "PSSpeechAlert.m: ";
+		rLen = 0;
+		rLoc = 2109;
+		rType = 0;
+		vrLen = 1218;
+		vrLoc = 1083;
+	};
+	E1A9DF1103BF480F0089E8B2 = {
+		isa = PBXFileReference;
+		name = NSPopUpButton.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSPopUpButton.h;
+		refType = 0;
+	};
+	E1A9DF1303BF480F0089E8B2 = {
+		isa = PBXFileReference;
+		name = NSStepper.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSStepper.h;
+		refType = 0;
+	};
+	E1AFB0CE03C9A59C001509F3 = {
+		fRef = 089C165DFE840E0CC02AAC07;
+		isa = PBXTextBookmark;
+		name = "English: 7";
+		rLen = 0;
+		rLoc = 226;
+		rType = 0;
+		vrLen = 223;
+		vrLoc = 0;
+	};
+	E1AFB0D103C9A59C001509F3 = {
+		fRef = E1A18CAC03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.m: triggerForAlarm:";
+		rLen = 42;
+		rLoc = 1388;
+		rType = 0;
+		vrLen = 1007;
+		vrLoc = 1056;
+	};
+	E1AFB0D203C9A59C001509F3 = {
+		fRef = F59E47A7036AAA6D016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlert.m: ";
+		rLen = 0;
+		rLoc = 618;
+		rType = 0;
+		vrLen = 986;
+		vrLoc = 3;
+	};
+	E1AFB0D303C9A59C001509F3 = {
+		fRef = F59E47A8036AAA6D016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlert.h: prepareForAlarm:";
+		rLen = 42;
+		rLoc = 557;
+		rType = 0;
+		vrLen = 823;
+		vrLoc = 0;
+	};
+	E1AFB0D403C9A59C001509F3 = {
+		fRef = E1A18CAB03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.h: triggerForAlarm:";
+		rLen = 0;
+		rLoc = 634;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 0;
+	};
+	E1AFB0D503C9A59C001509F3 = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 86";
+		rLen = 0;
+		rLoc = 2679;
+		rType = 0;
+		vrLen = 1369;
+		vrLoc = 1388;
+	};
+	E1AFB0D603C9A59C001509F3 = {
+		fRef = F59F6CB40354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.h: 48";
+		rLen = 0;
+		rLoc = 1545;
+		rType = 0;
+		vrLen = 1397;
+		vrLoc = 767;
+	};
+	E1AFB0D703C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: setWakeUp:";
+		rLen = 32;
+		rLoc = 6863;
+		rType = 0;
+		vrLen = 1179;
+		vrLoc = 5752;
+	};
+	E1AFB0D803C9A59C001509F3 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 78";
+		rLen = 0;
+		rLoc = 2399;
+		rType = 0;
+		vrLen = 1827;
+		vrLoc = 1626;
+	};
+	E1AFB0D903C9A59C001509F3 = {
+		fRef = E1AFB11403C9A59C001509F3;
+		isa = PBXTextBookmark;
+		name = "NSInvocation.h: 76";
+		rLen = 25;
+		rLoc = 1700;
+		rType = 0;
+		vrLen = 966;
+		vrLoc = 1098;
+	};
+	E1AFB0DA03C9A59C001509F3 = {
+		fRef = E1AFB11503C9A59C001509F3;
+		isa = PBXTextBookmark;
+		name = "IOMessage.h: 52";
+		rLen = 25;
+		rLoc = 2250;
+		rType = 0;
+		vrLen = 1878;
+		vrLoc = 668;
+	};
+	E1AFB0DB03C9A59C001509F3 = {
+		fRef = E19FD39F03C98645001509F3;
+		isa = PBXTextBookmark;
+		name = "PSWakeAlert.m: 24";
+		rLen = 0;
+		rLoc = 444;
+		rType = 0;
+		vrLen = 815;
+		vrLoc = 0;
+	};
+	E1AFB0DE03C9A59C001509F3 = {
+		fRef = E1AFB11603C9A59C001509F3;
+		isa = PBXTextBookmark;
+		name = "NSDate.h: 25";
+		rLen = 15;
+		rLoc = 496;
+		rType = 0;
+		vrLen = 1049;
+		vrLoc = 0;
+	};
+	E1AFB0E003C9A59C001509F3 = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+	};
+	E1AFB0E103C9A59C001509F3 = {
+		fRef = 089C165DFE840E0CC02AAC07;
+		isa = PBXTextBookmark;
+		name = "English: 7";
+		rLen = 0;
+		rLoc = 226;
+		rType = 0;
+		vrLen = 223;
+		vrLoc = 0;
+	};
+	E1AFB0E203C9A59C001509F3 = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+	};
+	E1AFB0E303C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: 205";
+		rLen = 0;
+		rLoc = 6897;
+		rType = 0;
+		vrLen = 895;
+		vrLoc = 6428;
+	};
+	E1AFB0E403C9A59C001509F3 = {
+		fRef = F59F6CB40354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1400;
+		vrLoc = 0;
+	};
+	E1AFB0E503C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: 205";
+		rLen = 0;
+		rLoc = 6897;
+		rType = 0;
+		vrLen = 907;
+		vrLoc = 6428;
+	};
+	E1AFB0E603C9A59C001509F3 = {
+		fRef = F59F6CB40354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.h: 38";
+		rLen = 0;
+		rLoc = 1176;
+		rType = 0;
+		vrLen = 1419;
+		vrLoc = 0;
+	};
+	E1AFB0E703C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: 205";
+		rLen = 0;
+		rLoc = 6917;
+		rType = 0;
+		vrLen = 944;
+		vrLoc = 6428;
+	};
+	E1AFB0E803C9A59C001509F3 = {
+		fRef = F59F6CB40354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.h: 38";
+		rLen = 0;
+		rLoc = 1176;
+		rType = 0;
+		vrLen = 1368;
+		vrLoc = 840;
+	};
+	E1AFB0E903C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: setWakeUp:";
+		rLen = 32;
+		rLoc = 6863;
+		rType = 0;
+		vrLen = 946;
+		vrLoc = 6428;
+	};
+	E1AFB0EA03C9A59C001509F3 = {
+		fRef = F59F6CB40354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.h: setWakeUp:";
+		rLen = 0;
+		rLoc = 1545;
+		rType = 0;
+		vrLen = 1440;
+		vrLoc = 767;
+	};
+	E1AFB0EB03C9A59C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 181";
+		rLen = 18;
+		rLoc = 5369;
+		rType = 0;
+		vrLen = 708;
+		vrLoc = 4844;
+	};
+	E1AFB0EC03C9A59C001509F3 = {
+		fRef = E1BF6E9003C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.h: setWake:";
+		rLen = 0;
+		rLoc = 1211;
+		rType = 0;
+		vrLen = 1112;
+		vrLoc = 180;
+	};
+	E1AFB0ED03C9A59C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 186";
+		rLen = 32;
+		rLoc = 5413;
+		rType = 0;
+		vrLen = 682;
+		vrLoc = 4844;
+	};
+	E1AFB0EE03C9A59C001509F3 = {
+		fRef = E1BF6E9003C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.h: 46";
+		rLen = 0;
+		rLoc = 1243;
+		rType = 0;
+		vrLen = 1115;
+		vrLoc = 179;
+	};
+	E1AFB0EF03C9A59C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: ";
+		rLen = 0;
+		rLoc = 5445;
+		rType = 0;
+		vrLen = 682;
+		vrLoc = 4844;
+	};
+	E1AFB0F003C9A59C001509F3 = {
+		fRef = E1BF6E9003C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.h: 15";
+		rLen = 19;
+		rLoc = 249;
+		rType = 0;
+		vrLen = 1175;
+		vrLoc = 17;
+	};
+	E1AFB0F103C9A59C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 47";
+		rLen = 0;
+		rLoc = 1313;
+		rType = 0;
+		vrLen = 1411;
+		vrLoc = 165;
+	};
+	E1AFB0F203C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: setWakeUp:";
+		rLen = 32;
+		rLoc = 6863;
+		rType = 0;
+		vrLen = 946;
+		vrLoc = 6428;
+	};
+	E1AFB0F303C9A59C001509F3 = {
+		fRef = E1A18CAC03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.m: 49";
+		rLen = 0;
+		rLoc = 973;
+		rType = 0;
+		vrLen = 834;
+		vrLoc = 350;
+	};
+	E1AFB0F403C9A59C001509F3 = {
+		fRef = E1A18CAB03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 695;
+		vrLoc = 0;
+	};
+	E1AFB0F503C9A59C001509F3 = {
+		fRef = E1A18CAC03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.m: triggerForAlarm:";
+		rLen = 0;
+		rLoc = 1429;
+		rType = 0;
+		vrLen = 1014;
+		vrLoc = 1056;
+	};
+	E1AFB0F603C9A59C001509F3 = {
+		fRef = F59E47A7036AAA6D016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlert.m: prepareForAlarm:";
+		rLen = 42;
+		rLoc = 561;
+		rType = 0;
+		vrLen = 986;
+		vrLoc = 3;
+	};
+	E1AFB0F703C9A59C001509F3 = {
+		fRef = E1A18CAC03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.m: 79";
+		rLen = 0;
+		rLoc = 1497;
+		rType = 0;
+		vrLen = 1007;
+		vrLoc = 1056;
+	};
+	E1AFB0F803C9A59C001509F3 = {
+		fRef = E1A18CAB03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 695;
+		vrLoc = 0;
+	};
+	E1AFB0F903C9A59C001509F3 = {
+		fRef = E1A18CAC03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.m: triggerForAlarm:";
+		rLen = 42;
+		rLoc = 1388;
+		rType = 0;
+		vrLen = 1007;
+		vrLoc = 1056;
+	};
+	E1AFB0FA03C9A59C001509F3 = {
+		fRef = E1A18CAB03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.h: 31";
+		rLen = 0;
+		rLoc = 652;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 0;
+	};
+	E1AFB0FB03C9A59C001509F3 = {
+		fRef = E1A18CAC03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.m: triggerForAlarm:";
+		rLen = 42;
+		rLoc = 1388;
+		rType = 0;
+		vrLen = 1007;
+		vrLoc = 1056;
+	};
+	E1AFB0FC03C9A59C001509F3 = {
+		fRef = F59E47A7036AAA6D016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlert.m: ";
+		rLen = 0;
+		rLoc = 618;
+		rType = 0;
+		vrLen = 986;
+		vrLoc = 3;
+	};
+	E1AFB0FD03C9A59C001509F3 = {
+		fRef = F59E47A8036AAA6D016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlert.h: prepareForAlarm:";
+		rLen = 42;
+		rLoc = 557;
+		rType = 0;
+		vrLen = 823;
+		vrLoc = 0;
+	};
+	E1AFB0FE03C9A59C001509F3 = {
+		fRef = E1A18CAB03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.h: triggerForAlarm:";
+		rLen = 0;
+		rLoc = 634;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 0;
+	};
+	E1AFB0FF03C9A59C001509F3 = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 86";
+		rLen = 0;
+		rLoc = 2679;
+		rType = 0;
+		vrLen = 1369;
+		vrLoc = 1388;
+	};
+	E1AFB10003C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: 391";
+		rLen = 0;
+		rLoc = 12663;
+		rType = 0;
+		vrLen = 1574;
+		vrLoc = 11400;
+	};
+	E1AFB10103C9A59C001509F3 = {
+		fRef = F59F6CB40354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.h: 48";
+		rLen = 0;
+		rLoc = 1545;
+		rType = 0;
+		vrLen = 1397;
+		vrLoc = 767;
+	};
+	E1AFB10203C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: 389";
+		rLen = 0;
+		rLoc = 12604;
+		rType = 0;
+		vrLen = 1653;
+		vrLoc = 15492;
+	};
+	E1AFB10303C9A59C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: setWakeUp:";
+		rLen = 9;
+		rLoc = 5421;
+		rType = 0;
+		vrLen = 690;
+		vrLoc = 5148;
+	};
+	E1AFB10403C9A59C001509F3 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: setWakeUp:";
+		rLen = 32;
+		rLoc = 6863;
+		rType = 0;
+		vrLen = 1179;
+		vrLoc = 5752;
+	};
+	E1AFB10503C9A59C001509F3 = {
+		fRef = E19FD39F03C98645001509F3;
+		isa = PBXTextBookmark;
+		name = "PSWakeAlert.m: 24";
+		rLen = 0;
+		rLoc = 444;
+		rType = 0;
+		vrLen = 815;
+		vrLoc = 0;
+	};
+	E1AFB10603C9A59C001509F3 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 78";
+		rLen = 0;
+		rLoc = 2399;
+		rType = 0;
+		vrLen = 1827;
+		vrLoc = 1626;
+	};
+	E1AFB10703C9A59C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: ";
+		rLen = 0;
+		rLoc = 6624;
+		rType = 0;
+		vrLen = 1086;
+		vrLoc = 5320;
+	};
+	E1AFB10803C9A59C001509F3 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 222";
+		rLen = 0;
+		rLoc = 7377;
+		rType = 0;
+		vrLen = 1665;
+		vrLoc = 6570;
+	};
+	E1AFB10903C9A59C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 147";
+		rLen = 0;
+		rLoc = 4576;
+		rType = 0;
+		vrLen = 1062;
+		vrLoc = 5442;
+	};
+	E1AFB10A03C9A59C001509F3 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 245";
+		rLen = 0;
+		rLoc = 7670;
+		rType = 0;
+		vrLen = 1673;
+		vrLoc = 7118;
+	};
+	E1AFB10B03C9A59C001509F3 = {
+		fRef = E19FD39F03C98645001509F3;
+		isa = PBXTextBookmark;
+		name = "PSWakeAlert.m: 24";
+		rLen = 0;
+		rLoc = 444;
+		rType = 0;
+		vrLen = 815;
+		vrLoc = 0;
+	};
+	E1AFB10C03C9A59C001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: powerManagerShouldSleep:";
+		rLen = 0;
+		rLoc = 5841;
+		rType = 0;
+		vrLen = 1062;
+		vrLoc = 5442;
+	};
+	E1AFB10D03C9A59C001509F3 = {
+		fRef = E130B9AC03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.h: 29";
+		rLen = 68;
+		rLoc = 527;
+		rType = 0;
+		vrLen = 718;
+		vrLoc = 0;
+	};
+	E1AFB11403C9A59C001509F3 = {
+		isa = PBXFileReference;
+		name = NSInvocation.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSInvocation.h;
+		refType = 0;
+	};
+	E1AFB11503C9A59C001509F3 = {
+		isa = PBXFileReference;
+		name = IOMessage.h;
+		path = /System/Library/Frameworks/IOKit.framework/Versions/A/Headers/IOMessage.h;
+		refType = 0;
+	};
+	E1AFB11603C9A59C001509F3 = {
+		isa = PBXFileReference;
+		name = NSDate.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDate.h;
+		refType = 0;
+	};
+	E1BF6E9403C9330000050002 = {
+		fRef = F560E2F20357506401A4E466;
+		isa = PBXBookmark;
+	};
+	E1BF6E9A03C95F4E00050002 = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: setUp";
+		rLen = 15;
+		rLoc = 499;
+		rType = 0;
+		vrLen = 905;
+		vrLoc = 0;
+	};
+	E1BF6E9D03C95F4E00050002 = {
+		fRef = E1BF6F0403C95F4E00050002;
+		glyphRangeLength = 1986;
+		glyphRangeLocation = 34063;
+		isa = PBXDocBookmark;
+		name = "NSObject.html: super init  ...";
+	};
+	E1BF6E9E03C95F4E00050002 = {
+		fRef = E1BF6F0503C95F4E00050002;
+		glyphRangeLength = 1792;
+		glyphRangeLocation = 11;
+		isa = PBXDocBookmark;
+		name = "NSMethodSignature.html: NSMethodSign...";
+	};
+	E1BF6E9F03C95F4E00050002 = {
+		fRef = E1BF6F0603C95F4E00050002;
+		isa = PBXTextBookmark;
+		name = "NSMethodSignature.h: 7";
+		rLen = 42;
+		rLoc = 115;
+		rType = 0;
+		vrLen = 541;
+		vrLoc = 0;
+	};
+	E1BF6EA003C95F4E00050002 = {
+		fRef = E1BF6EFD03C95F4E00050002;
+		isa = PBXTextBookmark;
+		name = "NSArray.h: 99";
+		rLen = 0;
+		rLoc = 3750;
+		rType = 0;
+		vrLen = 1512;
+		vrLoc = 2552;
+	};
+	E1BF6EA103C95F4E00050002 = {
+		fRef = E1BF6EFF03C95F4E00050002;
+		isa = PBXTextBookmark;
+		name = "NSRunLoop.h: 13";
+		rLen = 34;
+		rLoc = 266;
+		rType = 0;
+		vrLen = 1443;
+		vrLoc = 526;
+	};
+	E1BF6EA203C95F4E00050002 = {
+		fRef = E1BF6F0003C95F4E00050002;
+		isa = PBXTextBookmark;
+		name = "NSTimer.h: 17";
+		rLen = 130;
+		rLoc = 758;
+		rType = 0;
+		vrLen = 1129;
+		vrLoc = 0;
+	};
+	E1BF6EA903C95F4E00050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: ";
+		rLen = 0;
+		rLoc = 2948;
+		rType = 0;
+		vrLen = 1948;
+		vrLoc = 1054;
+	};
+	E1BF6EAC03C95F4E00050002 = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+	};
+	E1BF6EAE03C95F4E00050002 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 35";
+		rLen = 0;
+		rLoc = 1215;
+		rType = 0;
+		vrLen = 1549;
+		vrLoc = 0;
+	};
+	E1BF6EB003C95F4E00050002 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 34";
+		rLen = 0;
+		rLoc = 1185;
+		rType = 0;
+		vrLen = 1548;
+		vrLoc = 24;
+	};
+	E1BF6EB503C95F4E00050002 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 270";
+		rLen = 0;
+		rLoc = 9065;
+		rType = 0;
+		vrLen = 1300;
+		vrLoc = 7725;
+	};
+	E1BF6EBB03C95F4E00050002 = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 206";
+		rLen = 0;
+		rLoc = 6053;
+		rType = 0;
+		vrLen = 1340;
+		vrLoc = 2041;
+	};
+	E1BF6EBC03C95F4E00050002 = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: setUp";
+		rLen = 15;
+		rLoc = 499;
+		rType = 0;
+		vrLen = 905;
+		vrLoc = 0;
+	};
+	E1BF6EC103C95F4E00050002 = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: setUp";
+		rLen = 15;
+		rLoc = 499;
+		rType = 0;
+		vrLen = 905;
+		vrLoc = 0;
+	};
+	E1BF6EC203C95F4E00050002 = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: 48";
+		rLen = 0;
+		rLoc = 1413;
+		rType = 0;
+		vrLen = 1406;
+		vrLoc = 146;
+	};
+	E1BF6EC403C95F4E00050002 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: notificationPort";
+		rLen = 0;
+		rLoc = 7670;
+		rType = 0;
+		vrLen = 1717;
+		vrLoc = 7174;
+	};
+	E1BF6EDA03C95F4E00050002 = {
+		fRef = E1BF6EFE03C95F4E00050002;
+		isa = PBXTextBookmark;
+		name = "NSArray.h: 99";
+		rLen = 0;
+		rLoc = 3750;
+		rType = 0;
+		vrLen = 1512;
+		vrLoc = 2552;
+	};
+	E1BF6EDF03C95F4E00050002 = {
+		fRef = E1BF6EFC03C95F4E00050002;
+		isa = PBXTextBookmark;
+		name = "NSDate.h: 29";
+		rLen = 47;
+		rLoc = 630;
+		rType = 0;
+		vrLen = 1147;
+		vrLoc = 200;
+	};
+	E1BF6EEF03C95F4E00050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: ";
+		rLen = 0;
+		rLoc = 2948;
+		rType = 0;
+		vrLen = 1948;
+		vrLoc = 1054;
+	};
+	E1BF6EFC03C95F4E00050002 = {
+		isa = PBXFileReference;
+		name = NSDate.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDate.h;
+		refType = 0;
+	};
+	E1BF6EFD03C95F4E00050002 = {
+		isa = PBXFileReference;
+		name = NSArray.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSArray.h;
+		refType = 0;
+	};
+	E1BF6EFE03C95F4E00050002 = {
+		isa = PBXFileReference;
+		name = NSArray.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSArray.h;
+		refType = 0;
+	};
+	E1BF6EFF03C95F4E00050002 = {
+		isa = PBXFileReference;
+		name = NSRunLoop.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSRunLoop.h;
+		refType = 0;
+	};
+	E1BF6F0003C95F4E00050002 = {
+		isa = PBXFileReference;
+		name = NSTimer.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSTimer.h;
+		refType = 0;
+	};
+	E1BF6F0403C95F4E00050002 = {
+		isa = PBXFileReference;
+		name = NSObject.html;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSObject.html;
+		refType = 0;
+	};
+	E1BF6F0503C95F4E00050002 = {
+		isa = PBXFileReference;
+		name = NSMethodSignature.html;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSMethodSignature.html;
+		refType = 0;
+	};
+	E1BF6F0603C95F4E00050002 = {
+		isa = PBXFileReference;
+		name = NSMethodSignature.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSMethodSignature.h;
+		refType = 0;
+	};
+	E1C6414303C9AC4B001509F3 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 225";
+		rLen = 0;
+		rLoc = 7599;
+		rType = 0;
+		vrLen = 1591;
+		vrLoc = 6863;
+	};
+	E1C6414403C9AC4B001509F3 = {
+		fRef = E1BF6E9003C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.h: 30";
+		rLen = 0;
+		rLoc = 987;
+		rType = 0;
+		vrLen = 1175;
+		vrLoc = 17;
+	};
+	E1C6414503C9AC4B001509F3 = {
+		fRef = E130B9AC03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.h: 33";
+		rLen = 0;
+		rLoc = 728;
+		rType = 0;
+		vrLen = 728;
+		vrLoc = 0;
+	};
+	E1C6414703C9AC4B001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 30";
+		rLen = 0;
+		rLoc = 619;
+		rType = 0;
+		vrLen = 1294;
+		vrLoc = 144;
+	};
+	E1C6414803C9AC4B001509F3 = {
+		fRef = E130B9AC03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.h: 29";
+		rLen = 136;
+		rLoc = 527;
+		rType = 0;
+		vrLen = 730;
+		vrLoc = 0;
+	};
+	E1C6414903C9AC4B001509F3 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 195";
+		rLen = 36;
+		rLoc = 6570;
+		rType = 0;
+		vrLen = 1382;
+		vrLoc = 5793;
+	};
+	E1C6414A03C9AC4B001509F3 = {
+		fRef = E130B9AC03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.h: 29";
+		rLen = 136;
+		rLoc = 527;
+		rType = 0;
+		vrLen = 730;
+		vrLoc = 0;
+	};
+	E1C6414B03C9AC4B001509F3 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 229";
+		rLen = 0;
+		rLoc = 7631;
+		rType = 0;
+		vrLen = 1629;
+		vrLoc = 6863;
+	};
+	E1C6414C03C9AC4B001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 217";
+		rLen = 0;
+		rLoc = 5931;
+		rType = 0;
+		vrLen = 1138;
+		vrLoc = 5369;
+	};
+	E1C6414D03C9AC4B001509F3 = {
+		fRef = E1BF6E9003C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.h: 15";
+		rLen = 19;
+		rLoc = 249;
+		rType = 0;
+		vrLen = 1175;
+		vrLoc = 17;
+	};
+	E1C6414E03C9AC4B001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 217";
+		rLen = 0;
+		rLoc = 5931;
+		rType = 0;
+		vrLen = 1138;
+		vrLoc = 5369;
+	};
+	E1C6414F03C9AC4B001509F3 = {
+		fRef = E1BF6E9003C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.h: 16";
+		rLen = 0;
+		rLoc = 268;
+		rType = 0;
+		vrLen = 1175;
+		vrLoc = 17;
+	};
+	E1C6415003C9AC4B001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 224";
+		rLen = 0;
+		rLoc = 6333;
+		rType = 0;
+		vrLen = 1092;
+		vrLoc = 5369;
+	};
+	E1C6415103C9AC4B001509F3 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 223";
+		rLen = 27;
+		rLoc = 7493;
+		rType = 0;
+		vrLen = 1529;
+		vrLoc = 6863;
+	};
+	E1C6415203C9AC4B001509F3 = {
+		fRef = E130B9AC03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.h: 29";
+		rLen = 0;
+		rLoc = 562;
+		rType = 0;
+		vrLen = 728;
+		vrLoc = 0;
+	};
+	E1C6415303C9AC4B001509F3 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 225";
+		rLen = 0;
+		rLoc = 7599;
+		rType = 0;
+		vrLen = 1591;
+		vrLoc = 6863;
+	};
+	E1C6415403C9AC4B001509F3 = {
+		fRef = E1BF6E9003C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.h: 30";
+		rLen = 0;
+		rLoc = 987;
+		rType = 0;
+		vrLen = 1175;
+		vrLoc = 17;
+	};
+	E1D2936E03BD2A2700F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 40;
+		rLoc = 637;
+		rType = 0;
+		vrLen = 1672;
+		vrLoc = 380;
+	};
+	E1D2937503BD418200F9204E = {
+		fRef = E1D2945A03BD418200F9204E;
+		isa = PBXTextBookmark;
+		name = "NSButton.h: 13";
+		rLen = 9;
+		rLoc = 206;
+		rType = 0;
+		vrLen = 1162;
+		vrLoc = 0;
+	};
+	E1D2937B03BD418200F9204E = {
+		fRef = E1D2945C03BD418200F9204E;
+		glyphRangeLength = 0;
+		glyphRangeLocation = 0;
+		isa = PBXDocBookmark;
+	};
+	E1D2937C03BD418200F9204E = {
+		fRef = E1D2945D03BD418200F9204E;
+		glyphRangeLength = 770;
+		glyphRangeLocation = 7269;
+		isa = PBXDocBookmark;
+		name = "NSTimer.html: isValid  - (...";
+	};
+	E1D2937E03BD418200F9204E = {
+		fRef = E13919E203B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.h: 17";
+		rLen = 0;
+		rLoc = 378;
+		rType = 0;
+		vrLen = 385;
+		vrLoc = 0;
+	};
+	E1D2938303BD418200F9204E = {
+		fRef = E1D2945F03BD418200F9204E;
+		isa = PBXTextBookmark;
+		name = "NSWindowController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1770;
+		vrLoc = 0;
+	};
+	E1D2938403BD418200F9204E = {
+		fRef = E1D2946003BD418200F9204E;
+		isa = PBXTextBookmark;
+		name = "NSWindow.h: 442";
+		rLen = 56;
+		rLoc = 15678;
+		rType = 0;
+		vrLen = 2148;
+		vrLoc = 14728;
+	};
+	E1D2938503BD418200F9204E = {
+		fRef = E1D2946103BD418200F9204E;
+		glyphRangeLength = 0;
+		glyphRangeLocation = 0;
+		isa = PBXDocBookmark;
+	};
+	E1D2938603BD418200F9204E = {
+		fRef = E1D2946203BD418200F9204E;
+		glyphRangeLength = 1683;
+		glyphRangeLocation = 0;
+		isa = PBXDocBookmark;
+		name = "HowWindowIsDisplayed.html: Show Topic  ...";
+	};
+	E1D2939103BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1827;
+		rType = 0;
+		vrLen = 645;
+		vrLoc = 299;
+	};
+	E1D2939203BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 7";
+		rLen = 0;
+		rLoc = 161;
+		rType = 0;
+		vrLen = 506;
+		vrLoc = 0;
+	};
+	E1D2939503BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: close:";
+		rLen = 0;
+		rLoc = 1752;
+		rType = 0;
+		vrLen = 1339;
+		vrLoc = 0;
+	};
+	E1D2939703BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 14;
+		rLoc = 1393;
+		rType = 0;
+		vrLen = 1462;
+		vrLoc = 0;
+	};
+	E1D293B003BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1476;
+		rType = 0;
+		vrLen = 1397;
+		vrLoc = 0;
+	};
+	E1D293B403BD418200F9204E = {
+		fRef = E1D2946703BD418200F9204E;
+		isa = PBXTextBookmark;
+		name = "NSButton.h: 13";
+		rLen = 9;
+		rLoc = 206;
+		rType = 0;
+		vrLen = 1162;
+		vrLoc = 0;
+	};
+	E1D293B503BD418200F9204E = {
+		fRef = E1D2946803BD418200F9204E;
+		isa = PBXTextBookmark;
+		name = "NSControl.h: 14";
+		rLen = 2;
+		rLoc = 274;
+		rType = 0;
+		vrLen = 1658;
+		vrLoc = 2392;
+	};
+	E1D293B703BD418200F9204E = {
+		fRef = E1D2946903BD418200F9204E;
+		isa = PBXTextBookmark;
+		name = "NSControl.h: 30";
+		rLen = 0;
+		rLoc = 721;
+		rType = 0;
+		vrLen = 1246;
+		vrLoc = 477;
+	};
+	E1D293B903BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 50";
+		rLen = 0;
+		rLoc = 2727;
+		rType = 0;
+		vrLen = 1312;
+		vrLoc = 382;
+	};
+	E1D293BA03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 7";
+		rLen = 0;
+		rLoc = 161;
+		rType = 0;
+		vrLen = 671;
+		vrLoc = 0;
+	};
+	E1D293BB03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 50";
+		rLen = 0;
+		rLoc = 2727;
+		rType = 0;
+		vrLen = 1060;
+		vrLoc = 1295;
+	};
+	E1D293BC03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 7";
+		rLen = 0;
+		rLoc = 161;
+		rType = 0;
+		vrLen = 671;
+		vrLoc = 0;
+	};
+	E1D293BD03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: update:";
+		rLen = 0;
+		rLoc = 2661;
+		rType = 0;
+		vrLen = 958;
+		vrLoc = 1295;
+	};
+	E1D293BE03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 7";
+		rLen = 0;
+		rLoc = 161;
+		rType = 0;
+		vrLen = 671;
+		vrLoc = 0;
+	};
+	E1D293BF03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: update:";
+		rLen = 0;
+		rLoc = 2627;
+		rType = 0;
+		vrLen = 1009;
+		vrLoc = 1295;
+	};
+	E1D293C003BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 7";
+		rLen = 0;
+		rLoc = 161;
+		rType = 0;
+		vrLen = 671;
+		vrLoc = 0;
+	};
+	E1D293C103BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1932;
+		rType = 0;
+		vrLen = 1562;
+		vrLoc = 474;
+	};
+	E1D293C203BD418200F9204E = {
+		fRef = F5F240CA036A869401FE7503;
+		isa = PBXTextBookmark;
+		name = "BDAlias.m: ret";
+		rLen = 0;
+		rLoc = 3776;
+		rType = 0;
+		vrLen = 779;
+		vrLoc = 3292;
+	};
+	E1D293C403BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 22";
+		rLen = 0;
+		rLoc = 636;
+		rType = 0;
+		vrLen = 1506;
+		vrLoc = 0;
+	};
+	E1D293C503BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 21";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 697;
+		vrLoc = 0;
+	};
+	E1D293C603BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: update:";
+		rLen = 0;
+		rLoc = 2401;
+		rType = 0;
+		vrLen = 1514;
+		vrLoc = 527;
+	};
+	E1D293C703BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 21";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 697;
+		vrLoc = 0;
+	};
+	E1D293C803BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: close:";
+		rLen = 0;
+		rLoc = 2400;
+		rType = 0;
+		vrLen = 1891;
+		vrLoc = 474;
+	};
+	E1D293C903BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 21";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 697;
+		vrLoc = 0;
+	};
+	E1D293CA03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: control:didFailToValidatePartialString:errorDescription:";
+		rLen = 1;
+		rLoc = 2759;
+		rType = 0;
+		vrLen = 1498;
+		vrLoc = 831;
+	};
+	E1D293CB03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 27";
+		rLen = 85;
+		rLoc = 713;
+		rType = 0;
+		vrLen = 694;
+		vrLoc = 0;
+	};
+	E1D293CC03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: updateNextDateDisplay:";
+		rLen = 0;
+		rLoc = 2381;
+		rType = 0;
+		vrLen = 1625;
+		vrLoc = 0;
+	};
+	E1D293CD03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 22";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 714;
+		vrLoc = 0;
+	};
+	E1D293CE03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: updateNextDateDisplay:";
+		rLen = 0;
+		rLoc = 2381;
+		rType = 0;
+		vrLen = 1625;
+		vrLoc = 0;
+	};
+	E1D293CF03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 22";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 714;
+		vrLoc = 0;
+	};
+	E1D293D003BD418200F9204E = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 877;
+		vrLoc = 0;
+	};
+	E1D293D103BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: updateNextDateDisplay:";
+		rLen = 0;
+		rLoc = 2381;
+		rType = 0;
+		vrLen = 1625;
+		vrLoc = 0;
+	};
+	E1D293D203BD418200F9204E = {
+		fRef = F59E47B5036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 493;
+		vrLoc = 0;
+	};
+	E1D293D303BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 22";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 714;
+		vrLoc = 0;
+	};
+	E1D293D403BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 647;
+		rType = 0;
+		vrLen = 1625;
+		vrLoc = 0;
+	};
+	E1D293D503BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 22";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 714;
+		vrLoc = 0;
+	};
+	E1D293D603BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 647;
+		rType = 0;
+		vrLen = 1625;
+		vrLoc = 0;
+	};
+	E1D293D703BD418200F9204E = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 877;
+		vrLoc = 0;
+	};
+	E1D293D803BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 23";
+		rLen = 0;
+		rLoc = 636;
+		rType = 0;
+		vrLen = 1625;
+		vrLoc = 0;
+	};
+	E1D293D903BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 22";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 714;
+		vrLoc = 0;
+	};
+	E1D293DA03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 23";
+		rLen = 0;
+		rLoc = 636;
+		rType = 0;
+		vrLen = 1670;
+		vrLoc = 380;
+	};
+	E1D293DB03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 22";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 694;
+		vrLoc = 0;
+	};
+	E1D293DC03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 7;
+		rLoc = 668;
+		rType = 0;
+		vrLen = 1672;
+		vrLoc = 380;
+	};
+	E1D293DD03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: initWithAlarm:";
+		rLen = 40;
+		rLoc = 642;
+		rType = 0;
+		vrLen = 694;
+		vrLoc = 0;
+	};
+	E1D293DE03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 40;
+		rLoc = 637;
+		rType = 0;
+		vrLen = 1672;
+		vrLoc = 380;
+	};
+	E1D293DF03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 25";
+		rLen = 0;
+		rLoc = 682;
+		rType = 0;
+		vrLen = 696;
+		vrLoc = 0;
+	};
+	E1D293E003BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 40;
+		rLoc = 637;
+		rType = 0;
+		vrLen = 1672;
+		vrLoc = 380;
+	};
+	E1D293E103BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 22";
+		rLen = 0;
+		rLoc = 639;
+		rType = 0;
+		vrLen = 716;
+		vrLoc = 0;
+	};
+	E1D293E203BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1639;
+		rType = 0;
+		vrLen = 1613;
+		vrLoc = 380;
+	};
+	E1D293E303BD418200F9204E = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "PSIntervalField.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 912;
+		vrLoc = 0;
+	};
+	E1D293E403BD418200F9204E = {
+		fRef = E13919E203B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 275;
+		vrLoc = 0;
+	};
+	E1D293E503BD418200F9204E = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: 12";
+		rLen = 0;
+		rLoc = 348;
+		rType = 0;
+		vrLen = 915;
+		vrLoc = 0;
+	};
+	E1D293E603BD418200F9204E = {
+		fRef = E13919E203B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.h: 12";
+		rLen = 0;
+		rLoc = 196;
+		rType = 0;
+		vrLen = 277;
+		vrLoc = 0;
+	};
+	E1D293E703BD418200F9204E = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: c";
+		rLen = 0;
+		rLoc = 765;
+		rType = 0;
+		vrLen = 1456;
+		vrLoc = 0;
+	};
+	E1D293E803BD418200F9204E = {
+		fRef = E13919E203B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.h: 12";
+		rLen = 0;
+		rLoc = 196;
+		rType = 0;
+		vrLen = 277;
+		vrLoc = 0;
+	};
+	E1D293E903BD418200F9204E = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: textView:shouldChangeTextInRange:replacementString:";
+		rLen = 0;
+		rLoc = 763;
+		rType = 0;
+		vrLen = 1481;
+		vrLoc = 0;
+	};
+	E1D293EA03BD418200F9204E = {
+		fRef = E13919E203B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.h: 13";
+		rLen = 13;
+		rLoc = 254;
+		rType = 0;
+		vrLen = 277;
+		vrLoc = 0;
+	};
+	E1D293EB03BD418200F9204E = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: 32";
+		rLen = 0;
+		rLoc = 1597;
+		rType = 0;
+		vrLen = 1417;
+		vrLoc = 0;
+	};
+	E1D293EC03BD418200F9204E = {
+		fRef = F589C9C6035AA12B0155F4B2;
+		isa = PBXTextBookmark;
+		name = "Read Me.rtfd: 114";
+		rLen = 0;
+		rLoc = 9144;
+		rType = 0;
+		vrLen = 2457;
+		vrLoc = 7261;
+	};
+	E1D293F103BD418200F9204E = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: 53";
+		rLen = 0;
+		rLoc = 2231;
+		rType = 0;
+		vrLen = 1396;
+		vrLoc = 281;
+	};
+	E1D293F203BD418200F9204E = {
+		fRef = E13919E203B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.h: 17";
+		rLen = 0;
+		rLoc = 378;
+		rType = 0;
+		vrLen = 385;
+		vrLoc = 0;
+	};
+	E1D293F303BD418200F9204E = {
+		fRef = E13919E303B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.m: 35";
+		rLen = 0;
+		rLoc = 1640;
+		rType = 0;
+		vrLen = 1494;
+		vrLoc = 183;
+	};
+	E1D293F403BD418200F9204E = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 877;
+		vrLoc = 0;
+	};
+	E1D293F503BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1639;
+		rType = 0;
+		vrLen = 1613;
+		vrLoc = 380;
+	};
+	E1D293F703BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 13";
+		rLen = 0;
+		rLoc = 417;
+		rType = 0;
+		vrLen = 1662;
+		vrLoc = 0;
+	};
+	E1D293F803BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 12";
+		rLen = 0;
+		rLoc = 215;
+		rType = 0;
+		vrLen = 746;
+		vrLoc = 0;
+	};
+	E1D293F903BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 13";
+		rLen = 0;
+		rLoc = 417;
+		rType = 0;
+		vrLen = 1135;
+		vrLoc = 1824;
+	};
+	E1D293FC03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1284;
+		rType = 0;
+		vrLen = 1671;
+		vrLoc = 410;
+	};
+	E1D293FD03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 12";
+		rLen = 0;
+		rLoc = 215;
+		rType = 0;
+		vrLen = 746;
+		vrLoc = 0;
+	};
+	E1D293FE03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 1284;
+		rType = 0;
+		vrLen = 1648;
+		vrLoc = 403;
+	};
+	E1D293FF03BD418200F9204E = {
+		fRef = E1D2945803BD418200F9204E;
+		isa = PBXTextBookmark;
+		name = "NSWindow.h: 2";
+		rLen = 8;
+		rLoc = 4;
+		rType = 0;
+		vrLen = 1408;
+		vrLoc = 0;
+	};
+	E1D2940003BD418200F9204E = {
+		fRef = E1D2946503BD418200F9204E;
+		glyphRangeLength = 1683;
+		glyphRangeLocation = 0;
+		isa = PBXDocBookmark;
+		name = "HowWindowIsDisplayed.html: Show Topic  ...";
+	};
+	E1D2940103BD418200F9204E = {
+		fRef = E1D2946603BD418200F9204E;
+		glyphRangeLength = 0;
+		glyphRangeLocation = 0;
+		isa = PBXDocBookmark;
+	};
+	E1D2940203BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: initWithAlarm:";
+		rLen = 0;
+		rLoc = 869;
+		rType = 0;
+		vrLen = 1661;
+		vrLoc = 163;
+	};
+	E1D2940303BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 12";
+		rLen = 0;
+		rLoc = 215;
+		rType = 0;
+		vrLen = 746;
+		vrLoc = 0;
+	};
+	E1D2940403BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: snooze:";
+		rLen = 0;
+		rLoc = 3174;
+		rType = 0;
+		vrLen = 1134;
+		vrLoc = 1773;
+	};
+	E1D2940503BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 12";
+		rLen = 0;
+		rLoc = 215;
+		rType = 0;
+		vrLen = 746;
+		vrLoc = 0;
+	};
+	E1D2940603BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: snooze:";
+		rLen = 0;
+		rLoc = 3174;
+		rType = 0;
+		vrLen = 1135;
+		vrLoc = 1773;
+	};
+	E1D2940703BD418200F9204E = {
+		fRef = F517D6420356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.m: setUp";
+		rLen = 0;
+		rLoc = 1190;
+		rType = 0;
+		vrLen = 1371;
+		vrLoc = 0;
+	};
+	E1D2940803BD418200F9204E = {
+		fRef = F517D6430356B8CC016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarms.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 781;
+		vrLoc = 0;
+	};
+	E1D2942C03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: snooze:";
+		rLen = 0;
+		rLoc = 3041;
+		rType = 0;
+		vrLen = 1191;
+		vrLoc = 2049;
+	};
+	E1D2942D03BD418200F9204E = {
+		fRef = F59DC6DB0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.h: 12";
+		rLen = 0;
+		rLoc = 215;
+		rType = 0;
+		vrLen = 746;
+		vrLoc = 0;
+	};
+	E1D2942E03BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: snooze:";
+		rLen = 0;
+		rLoc = 3199;
+		rType = 0;
+		vrLen = 1220;
+		vrLoc = 2049;
+	};
+	E1D2942F03BD418200F9204E = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: __VERSION__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 877;
+		vrLoc = 0;
+	};
+	E1D2943103BD418200F9204E = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: stopAlerts:";
+		rLen = 0;
+		rLoc = 1681;
+		rType = 0;
+		vrLen = 945;
+		vrLoc = 0;
+	};
+	E1D2943903BD418200F9204E = {
+		fRef = F59DC6DC0353DE5101AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmNotifierController.m: 78";
+		rLen = 0;
+		rLoc = 2730;
+		rType = 0;
+		vrLen = 1220;
+		vrLoc = 2049;
+	};
+	E1D2945803BD418200F9204E = {
+		isa = PBXFileReference;
+		name = NSWindow.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindow.h;
+		refType = 0;
+	};
+	E1D2945A03BD418200F9204E = {
+		isa = PBXFileReference;
+		name = NSButton.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSButton.h;
+		refType = 0;
+	};
+	E1D2945C03BD418200F9204E = {
+		isa = PBXFileReference;
+		name = index.html;
+		path = /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/Timers/index.html;
+		refType = 0;
+	};
+	E1D2945D03BD418200F9204E = {
+		isa = PBXFileReference;
+		name = NSTimer.html;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSTimer.html;
+		refType = 0;
+	};
+	E1D2945F03BD418200F9204E = {
+		isa = PBXFileReference;
+		name = NSWindowController.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindowController.h;
+		refType = 0;
+	};
+	E1D2946003BD418200F9204E = {
+		isa = PBXFileReference;
+		name = NSWindow.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindow.h;
+		refType = 0;
+	};
+	E1D2946103BD418200F9204E = {
+		isa = PBXFileReference;
+		name = iHowWindowIsDisplayed.html;
+		path = /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/WinPanel/iHowWindowIsDisplayed.html;
+		refType = 0;
+	};
+	E1D2946203BD418200F9204E = {
+		isa = PBXFileReference;
+		name = HowWindowIsDisplayed.html;
+		path = /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/WinPanel/Concepts/HowWindowIsDisplayed.html;
+		refType = 0;
+	};
+	E1D2946503BD418200F9204E = {
+		isa = PBXFileReference;
+		name = HowWindowIsDisplayed.html;
+		path = /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/WinPanel/Concepts/HowWindowIsDisplayed.html;
+		refType = 0;
+	};
+	E1D2946603BD418200F9204E = {
+		isa = PBXFileReference;
+		name = iHowWindowIsDisplayed.html;
+		path = /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/WinPanel/iHowWindowIsDisplayed.html;
+		refType = 0;
+	};
+	E1D2946703BD418200F9204E = {
+		isa = PBXFileReference;
+		name = NSButton.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSButton.h;
+		refType = 0;
+	};
+	E1D2946803BD418200F9204E = {
+		isa = PBXFileReference;
+		name = NSControl.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSControl.h;
+		refType = 0;
+	};
+	E1D2946903BD418200F9204E = {
+		isa = PBXFileReference;
+		name = NSControl.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSControl.h;
+		refType = 0;
+	};
+	E1ECA00A03C003C300F54C66 = {
+		fRef = E1ECA00603C002B300F54C66;
+		isa = PBXTextBookmark;
+		name = "PSException.h: 15";
+		rLen = 0;
+		rLoc = 379;
+		rType = 0;
+		vrLen = 254;
+		vrLoc = 0;
+	};
+	E1ECA00B03C0056B00F54C66 = {
+		fRef = E1A18CAB03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 585;
+		vrLoc = 0;
+	};
+	E1F4C96203C9B1E6001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 176";
+		rLen = 0;
+		rLoc = 5239;
+		rType = 0;
+		vrLen = 641;
+		vrLoc = 5143;
+	};
+	E1F4C96303C9B1E6001509F3 = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+		uiCtxt = {
+			TOCViewDetailVisibleRect = "{{0, 0}, {467, 581}}";
+			TOCViewExpandedItems = (
+				"com.apple.target-editor-pane.settings",
+				"com.apple.target-editor-pane.settings.simple",
+				"com.apple.target-editor-pane.info-plist",
+				"com.apple.target-editor-pane.info-plist.simple",
+				"com.apple.target-editor-pane.buildphases",
+			);
+			TOCViewMasterVisibleRect = "{{0, 0}, {183, 581}}";
+			TOCViewSelectedItems = (
+				"com.apple.target-editor-pane.info-plist",
+			);
+		};
+	};
+	E1F4C96403C9B1E6001509F3 = {
+		fRef = E1BF6E9103C928D200050002;
+		isa = PBXTextBookmark;
+		name = "PSTimer.m: 176";
+		rLen = 0;
+		rLoc = 5239;
+		rType = 0;
+		vrLen = 641;
+		vrLoc = 5143;
+	};
+	E1F4C96503C9B1E6001509F3 = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+		uiCtxt = {
+			TOCViewDetailVisibleRect = "{{0, 0}, {467, 581}}";
+			TOCViewExpandedItems = (
+				"com.apple.target-editor-pane.settings",
+				"com.apple.target-editor-pane.settings.simple",
+				"com.apple.target-editor-pane.info-plist",
+				"com.apple.target-editor-pane.info-plist.simple",
+				"com.apple.target-editor-pane.buildphases",
+			);
+			TOCViewMasterVisibleRect = "{{0, 0}, {183, 581}}";
+			TOCViewSelectedItems = (
+				"com.apple.target-editor-pane.info-plist",
+			);
+		};
+	};
+	E1F4C96603C9B1E6001509F3 = {
+		fRef = 089C165DFE840E0CC02AAC07;
+		isa = PBXTextBookmark;
+		name = "English: 5";
+		rLen = 0;
+		rLoc = 156;
+		rType = 0;
+		vrLen = 226;
+		vrLoc = 0;
+	};
+	E1FCECFD03C972CF001509F3 = {
+		fRef = E1FCED0803C972D0001509F3;
+		isa = PBXTextBookmark;
+		name = "NSObjCRuntime.h: 66";
+		rLen = 32;
+		rLoc = 1860;
+		rType = 0;
+		vrLen = 1243;
+		vrLoc = 1024;
+	};
+	E1FCED0803C972D0001509F3 = {
+		isa = PBXFileReference;
+		name = NSObjCRuntime.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObjCRuntime.h;
+		refType = 0;
+	};
+	F500E5370359719B01AEEDB1 = {
+		isa = PBXSymbolicBreakpoint;
+		state = 1;
+		symbolName = szone_error;
+	};
+	F596730D0355CFA301407038 = {
+		isa = PBXSymbolicBreakpoint;
+		state = 1;
+		symbolName = "-[_NSZombie methodSignatureForSelector:]";
+	};
+	F59B967103538BE201154278 = {
+		activeArgIndex = 2147483647;
+		activeArgIndices = (
+		);
+		argumentStrings = (
+		);
+		configStateDict = {
+		};
+		debuggerPlugin = GDBDebugging;
+		dylibVariantSuffix = "";
+		enableDebugStr = 1;
+		environmentEntries = (
+			{
+				active = YES;
+				name = NSZombieEnabled;
+				value = YES;
+			},
+		);
+		isa = PBXExecutable;
+		name = Pester;
+		shlibInfoDictList = (
+		);
+		sourceDirectories = (
+		);
+	};
+	F5B15F74037E42EB01AEEDB1 = {
+		isa = PBXSymbolicBreakpoint;
+		state = 1;
+		symbolName = "-[NSException raise]";
+	};
+	F5F19866036B80AF01EB0372 = {
+		fileEncoding = 30;
+		isa = PBXFileReference;
+		name = SUSpeaker.h;
+		path = /Users/nicholas/Documents/Development/Cocoa/Pester/Source/SUSpeaker.h;
+		refType = 0;
+	};
+	F5F19867036B80AF01EB0372 = {
+		fileEncoding = 30;
+		isa = PBXFileReference;
+		name = SUSpeaker.m;
+		path = /Users/nicholas/Documents/Development/Cocoa/Pester/Source/SUSpeaker.m;
+		refType = 0;
+	};
+}
Index: releases/Pester/1.1b1/Source/Pester.pbproj/project.pbxproj
===================================================================
--- releases/Pester/1.1b1/Source/Pester.pbproj/project.pbxproj	(revision 62)
+++ releases/Pester/1.1b1/Source/Pester.pbproj/project.pbxproj	(revision 62)
@@ -0,0 +1,1896 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 38;
+	objects = {
+		080E96DDFE201D6D7F000001 = {
+			children = (
+				F560E2F20357506401A4E466,
+				F560E2F10357506401A4E466,
+				F560E311035787D501A4E466,
+				F560E314035787F901A4E466,
+				F59E47AF036AAC31016B311C,
+				F560E312035787E001A4E466,
+				F560E313035787ED01A4E466,
+				E162698703B6189D00000028,
+			);
+			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;
+		};
+//080
+//081
+//082
+//083
+//084
+//100
+//101
+//102
+//103
+//104
+		1058C7A0FEA54F0111CA2CBB = {
+			children = (
+				1058C7A1FEA54F0111CA2CBB,
+				F5F240D0036A87E301FE7503,
+				F5F24187036A90D901FE7503,
+				F59E4BEA036B33EC016B311C,
+				E14DB31203B8038300000028,
+			);
+			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,
+				F562F809037E5D0101AEEDB1,
+			);
+			isa = PBXGroup;
+			name = Products;
+			refType = 4;
+		};
+//190
+//191
+//192
+//193
+//194
+//290
+//291
+//292
+//293
+//294
+		29B97313FDCFA39411CA2CEA = {
+			buildStyles = (
+				4A9504CCFFE6A4B311CA0CBA,
+				4A9504CDFFE6A4B311CA0CBA,
+			);
+			hasScannedForEncodings = 1;
+			isa = PBXProject;
+			mainGroup = 29B97314FDCFA39411CA2CEA;
+			projectDirPath = "";
+			targets = (
+				29B97326FDCFA39411CA2CEA,
+			);
+		};
+		29B97314FDCFA39411CA2CEA = {
+			children = (
+				080E96DDFE201D6D7F000001,
+				29B97315FDCFA39411CA2CEA,
+				E19DCBE503BE516000B934BF,
+				29B97317FDCFA39411CA2CEA,
+				29B97323FDCFA39411CA2CEA,
+				19C28FACFE9D520D11CA2CBB,
+			);
+			isa = PBXGroup;
+			name = Pester;
+			path = "";
+			refType = 4;
+		};
+		29B97315FDCFA39411CA2CEA = {
+			children = (
+				E19DCBD203BE4AA200B934BF,
+				29B97316FDCFA39411CA2CEA,
+			);
+			isa = PBXGroup;
+			name = "Other Sources";
+			path = "";
+			refType = 4;
+		};
+		29B97316FDCFA39411CA2CEA = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = main.m;
+			refType = 4;
+		};
+		29B97317FDCFA39411CA2CEA = {
+			children = (
+				F5243DA40378681101AEEDB1,
+				29B97318FDCFA39411CA2CEA,
+				F560E2EE03574F8A01A4E466,
+				F59DC6DF0353DF5E01AEEDB1,
+				F59E4BDE036B1D94016B311C,
+				089C165CFE840E0CC02AAC07,
+				F59DD44F0358ABF4017318D0,
+				F59DC6E30353ED1201AEEDB1,
+			);
+			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,
+				E162698803B618BD00000028,
+			);
+			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,
+				E130B9A903B7AEED00000028,
+			);
+			buildSettings = {
+				CURRENT_PROJECT_VERSION = 9;
+				FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"";
+				HEADER_SEARCH_PATHS = "";
+				INSTALL_PATH = /;
+				JAVA_COMPILER_DEBUGGING_SYMBOLS = NO;
+				LIBRARY_SEARCH_PATHS = "";
+				OTHER_CFLAGS = "";
+				PRECOMPILE_PREFIX_HEADER = YES;
+				PREFIX_HEADER = Pester_Prefix.h;
+				PRODUCT_NAME = Pester;
+				PRODUCT_VERSION = 1.1a4;
+				SECTORDER_FLAGS = "";
+				USE_GCC3_PFE_SUPPORT = YES;
+				VERSIONING_SYSTEM = "apple-generic";
+				WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+				WRAPPER_EXTENSION = app;
+			};
+			dependencies = (
+			);
+			isa = PBXApplicationTarget;
+			name = Pester;
+			productInstallPath = /;
+			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.1b1, © 2002–03 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.1b1</string>
+	<key>CFBundleSignature</key>
+	<string>Pstr</string>
+	<key>CFBundleVersion</key>
+	<string>9</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>PSApplication</string>
+</dict>
+</plist>
+";
+		};
+		29B97327FDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				E19DCBD303BE4AA200B934BF,
+				F5F240BA036A867901FE7503,
+				F59DC6FE0354188F01AEEDB1,
+				F5F240B7036A862301FE7503,
+				F560E3170357895001A4E466,
+				F59DC6EB0353F58B01AEEDB1,
+				F515C768037DFB56018DB5B3,
+				F552A8AD0358E8B201AEEDB1,
+				F5F198D3036BE57401EB0372,
+				F5B79839035F64F80136A8DD,
+				E1F0B14C03AD8CEF00AEFBE0,
+				F5F19873036B822E01EB0372,
+				E1F0B26A03AEDE8600AEFBE0,
+				E162698B03B6190B00000028,
+				F5B79868038865B30136A8DD,
+				F5EE8DBC038A76AC0134BEAC,
+				E191700C03AD24A700AEFBE0,
+				F5F19910036D3B3101EB0372,
+				F59E4C10036B43D2016B311C,
+				E1F0B15003ADBE3800AEFBE0,
+				E162698603B6189000000028,
+				F59F6CB60354E7DA01AEEDB1,
+				F59E47B7036AAD55016B311C,
+				F59DC6DD0353DE5101AEEDB1,
+				F59DC6D50353C9E601AEEDB1,
+				F517D6450356B8CC016D68B9,
+				F517D6410356B80C016D68B9,
+				F59E47AA036AAA6D016B311C,
+				E1A18CAD03B4344C00000028,
+				F560E2F40357506501A4E466,
+				F59E47AE036AAC1E016B311C,
+				F59E47BB036AB217016B311C,
+				F59E47BF036AB228016B311C,
+				F59E47C3036B1ADD016B311C,
+				F59E47B3036AACD1016B311C,
+				E1A18CB403B439CF00000028,
+				F59E4BE9036B2E5E016B311C,
+				F5F1986F036B813101EB0372,
+				F5F2418B036A910B01FE7503,
+				E130B9AE03B7C59700000028,
+				E13919E403B9E4E100000028,
+				E1ECA00803C002B300F54C66,
+				E1D358BB03C60CE900C8A18E,
+				E1E9A33C03C8EF6700050002,
+				E1BF6E9203C928D200050002,
+				E19FD3A003C98645001509F3,
+			);
+			isa = PBXHeadersBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B97328FDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				F59DC6E10353DF5E01AEEDB1,
+				F59DC6E40353ED1201AEEDB1,
+				F560E2F003574F8A01A4E466,
+				F560E2F6035766F101A4E466,
+				F560E2F7035766F201A4E466,
+				F59DD4510358ABF7017318D0,
+				F589C9C7035AA12E0155F4B2,
+				F59E4BE0036B1D94016B311C,
+				F5243DA50378681101AEEDB1,
+			);
+			isa = PBXResourcesBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B9732BFDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				F5F240CB036A869401FE7503,
+				F59DC6FF0354188F01AEEDB1,
+				F5F240B8036A862301FE7503,
+				F560E3180357895001A4E466,
+				F59DC6EA0353F58B01AEEDB1,
+				F5F240CE036A877301FE7503,
+				F552A8AE0358E8B201AEEDB1,
+				F5F198D2036BE57401EB0372,
+				F5B79838035F64F80136A8DD,
+				E1F0B14D03AD8CEF00AEFBE0,
+				F5F19872036B822E01EB0372,
+				E1F0B26B03AEDE8600AEFBE0,
+				E14AFB7703B620FE00000028,
+				F5B79867038865B30136A8DD,
+				F5EE8DBB038A76AC0134BEAC,
+				F5F1990F036D3B3101EB0372,
+				F59E4C0F036B43D2016B311C,
+				E1F0B15103ADBE3800AEFBE0,
+				E162698503B6189000000028,
+				F59F6CB70354E7DA01AEEDB1,
+				F59E47B6036AAD55016B311C,
+				F59DC6DE0353DE5101AEEDB1,
+				F59DC6D60353C9E601AEEDB1,
+				F517D6440356B8CC016D68B9,
+				F517D6400356B80C016D68B9,
+				F59E47A9036AAA6D016B311C,
+				E1A18CAE03B4344C00000028,
+				F560E2F30357506401A4E466,
+				F59E47AD036AAC1E016B311C,
+				F59E47BA036AB217016B311C,
+				F59E47BE036AB228016B311C,
+				F59E47C2036B1ADD016B311C,
+				F59E47B2036AACD1016B311C,
+				E1271F040000012300000028,
+				F59E4BE8036B2E5E016B311C,
+				E1A18CB103B439AD00000028,
+				29B9732CFDCFA39411CA2CEA,
+				E13919E503B9E4E100000028,
+				E1ECA00903C002B300F54C66,
+				E1D358BC03C60CE900C8A18E,
+				E1E9A33B03C8EF6700050002,
+				E1BF6E9303C928D200050002,
+				E19FD3A103C98645001509F3,
+			);
+			isa = PBXSourcesBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B9732CFDCFA39411CA2CEA = {
+			fileRef = 29B97316FDCFA39411CA2CEA;
+			isa = PBXBuildFile;
+			settings = {
+				ATTRIBUTES = (
+				);
+			};
+		};
+		29B9732DFDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				1058C7A3FEA54F0111CA2CBB,
+				F5F24166036A87E401FE7503,
+				F5F24189036A90D901FE7503,
+				F59E4C0C036B33EC016B311C,
+				E14DB31303B8038300000028,
+			);
+			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
+//E10
+//E11
+//E12
+//E13
+//E14
+		E1271F040000012300000028 = {
+			fileRef = E130B9AD03B7C59700000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E130B9A903B7AEED00000028 = {
+			buildActionMask = 2147483647;
+			files = (
+			);
+			generatedFileNames = (
+			);
+			isa = PBXShellScriptBuildPhase;
+			neededFileNames = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "/Developer/Tools/agvtool mvers -terse >| ${SRCROOT}/VERSION";
+		};
+		E130B9AC03B7C59700000028 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSPowerManager.h;
+			refType = 4;
+		};
+		E130B9AD03B7C59700000028 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSPowerManager.m;
+			refType = 4;
+		};
+		E130B9AE03B7C59700000028 = {
+			fileRef = E130B9AC03B7C59700000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E13919E203B9E4E100000028 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRIntervalField.h;
+			refType = 4;
+		};
+		E13919E303B9E4E100000028 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRIntervalField.m;
+			refType = 4;
+		};
+		E13919E403B9E4E100000028 = {
+			fileRef = E13919E203B9E4E100000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E13919E503B9E4E100000028 = {
+			fileRef = E13919E303B9E4E100000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E14AFB7703B620FE00000028 = {
+			fileRef = E162698A03B6190B00000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E14DB31203B8038300000028 = {
+			isa = PBXFrameworkReference;
+			name = IOKit.framework;
+			path = /System/Library/Frameworks/IOKit.framework;
+			refType = 0;
+		};
+		E14DB31303B8038300000028 = {
+			fileRef = E14DB31203B8038300000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E162698303B6189000000028 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSTableView-NJRExtensions.m";
+			refType = 4;
+		};
+		E162698403B6189000000028 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSTableView-NJRExtensions.h";
+			refType = 4;
+		};
+		E162698503B6189000000028 = {
+			fileRef = E162698303B6189000000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E162698603B6189000000028 = {
+			fileRef = E162698403B6189000000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E162698703B6189D00000028 = {
+			children = (
+				E1F0B26803AEDE8600AEFBE0,
+				E1F0B26903AEDE8600AEFBE0,
+				E162698903B6190B00000028,
+				E162698A03B6190B00000028,
+				F5B79866038865B30136A8DD,
+				F5B79865038865B30136A8DD,
+				F5EE8DBA038A76AC0134BEAC,
+				F5EE8DB9038A76AC0134BEAC,
+				F5F1990E036D3B3101EB0372,
+				F5F1990D036D3B3101EB0372,
+				F59E4C0E036B43D2016B311C,
+				F59E4C0D036B43D2016B311C,
+				E1F0B14E03ADBE3800AEFBE0,
+				E1F0B14F03ADBE3800AEFBE0,
+				E162698303B6189000000028,
+				E162698403B6189000000028,
+			);
+			isa = PBXGroup;
+			name = Categories;
+			path = "";
+			refType = 4;
+		};
+		E162698803B618BD00000028 = {
+			children = (
+				F5F2418A036A910B01FE7503,
+				E191700B03AD24A600AEFBE0,
+			);
+			isa = PBXGroup;
+			name = "Private Headers";
+			path = "";
+			refType = 4;
+		};
+		E162698903B6190B00000028 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = "NSCalendarDate-NJRExtensions.h";
+			refType = 4;
+		};
+		E162698A03B6190B00000028 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = "NSCalendarDate-NJRExtensions.m";
+			refType = 4;
+		};
+		E162698B03B6190B00000028 = {
+			fileRef = E162698903B6190B00000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E191700B03AD24A600AEFBE0 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NSDisclosureButtonCell.h;
+			refType = 4;
+		};
+		E191700C03AD24A700AEFBE0 = {
+			fileRef = E191700B03AD24A600AEFBE0;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E19DCBD203BE4AA200B934BF = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = Pester_Prefix.h;
+			refType = 4;
+		};
+		E19DCBD303BE4AA200B934BF = {
+			fileRef = E19DCBD203BE4AA200B934BF;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E19DCBE503BE516000B934BF = {
+			children = (
+				F589C9C6035AA12B0155F4B2,
+			);
+			isa = PBXGroup;
+			name = Documentation;
+			path = "";
+			refType = 4;
+		};
+		E19FD39E03C98645001509F3 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSWakeAlert.h;
+			refType = 4;
+		};
+		E19FD39F03C98645001509F3 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSWakeAlert.m;
+			refType = 4;
+		};
+		E19FD3A003C98645001509F3 = {
+			fileRef = E19FD39E03C98645001509F3;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E19FD3A103C98645001509F3 = {
+			fileRef = E19FD39F03C98645001509F3;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1A18CAB03B4344C00000028 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSAlerts.h;
+			refType = 4;
+		};
+		E1A18CAC03B4344C00000028 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlerts.m;
+			refType = 4;
+		};
+		E1A18CAD03B4344C00000028 = {
+			fileRef = E1A18CAB03B4344C00000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1A18CAE03B4344C00000028 = {
+			fileRef = E1A18CAC03B4344C00000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1A18CB103B439AD00000028 = {
+			fileRef = F5F1986C036B813101EB0372;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1A18CB203B439CF00000028 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSPropertyListSerialization.h;
+			refType = 2;
+		};
+		E1A18CB403B439CF00000028 = {
+			fileRef = E1A18CB203B439CF00000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1BF6E9003C928D200050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSTimer.h;
+			refType = 4;
+		};
+		E1BF6E9103C928D200050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSTimer.m;
+			refType = 4;
+		};
+		E1BF6E9203C928D200050002 = {
+			fileRef = E1BF6E9003C928D200050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1BF6E9303C928D200050002 = {
+			fileRef = E1BF6E9103C928D200050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1D358B903C60CE900C8A18E = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRCenteringMovieView.h;
+			refType = 4;
+		};
+		E1D358BA03C60CE900C8A18E = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRCenteringMovieView.m;
+			refType = 4;
+		};
+		E1D358BB03C60CE900C8A18E = {
+			fileRef = E1D358B903C60CE900C8A18E;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1D358BC03C60CE900C8A18E = {
+			fileRef = E1D358BA03C60CE900C8A18E;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1E9A33903C8EF6700050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = SUSpeaker.m;
+			refType = 4;
+		};
+		E1E9A33A03C8EF6700050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = SUSpeaker.h;
+			refType = 4;
+		};
+		E1E9A33B03C8EF6700050002 = {
+			fileRef = E1E9A33903C8EF6700050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1E9A33C03C8EF6700050002 = {
+			fileRef = E1E9A33A03C8EF6700050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1E9A33D03C8EF6800050002 = {
+			children = (
+				E1E9A33903C8EF6700050002,
+				E1E9A33A03C8EF6700050002,
+			);
+			isa = PBXGroup;
+			name = SpeechUtilities;
+			refType = 4;
+		};
+		E1ECA00603C002B300F54C66 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSError.h;
+			refType = 2;
+		};
+		E1ECA00703C002B300F54C66 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSError.m;
+			refType = 2;
+		};
+		E1ECA00803C002B300F54C66 = {
+			fileRef = E1ECA00603C002B300F54C66;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1ECA00903C002B300F54C66 = {
+			fileRef = E1ECA00703C002B300F54C66;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F0B14A03AD8CEF00AEFBE0 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRUnfocusableMovieView.h;
+			refType = 4;
+		};
+		E1F0B14B03AD8CEF00AEFBE0 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRUnfocusableMovieView.m;
+			refType = 4;
+		};
+		E1F0B14C03AD8CEF00AEFBE0 = {
+			fileRef = E1F0B14A03AD8CEF00AEFBE0;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F0B14D03AD8CEF00AEFBE0 = {
+			fileRef = E1F0B14B03AD8CEF00AEFBE0;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F0B14E03ADBE3800AEFBE0 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = "NSString-NJRExtensions.h";
+			refType = 4;
+		};
+		E1F0B14F03ADBE3800AEFBE0 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = "NSString-NJRExtensions.m";
+			refType = 4;
+		};
+		E1F0B15003ADBE3800AEFBE0 = {
+			fileRef = E1F0B14E03ADBE3800AEFBE0;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F0B15103ADBE3800AEFBE0 = {
+			fileRef = E1F0B14F03ADBE3800AEFBE0;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F0B26803AEDE8600AEFBE0 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = "NSAttributedString-NJRExtensions.h";
+			refType = 4;
+		};
+		E1F0B26903AEDE8600AEFBE0 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = "NSAttributedString-NJRExtensions.m";
+			refType = 4;
+		};
+		E1F0B26A03AEDE8600AEFBE0 = {
+			fileRef = E1F0B26803AEDE8600AEFBE0;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F0B26B03AEDE8600AEFBE0 = {
+			fileRef = E1F0B26903AEDE8600AEFBE0;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+//E10
+//E11
+//E12
+//E13
+//E14
+//F50
+//F51
+//F52
+//F53
+//F54
+		F515C768037DFB56018DB5B3 = {
+			fileRef = F5F240CD036A877301FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F517D63E0356B80C016D68B9 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarmsController.m;
+			refType = 4;
+		};
+		F517D63F0356B80C016D68B9 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarmsController.h;
+			refType = 4;
+		};
+		F517D6400356B80C016D68B9 = {
+			fileRef = F517D63E0356B80C016D68B9;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F517D6410356B80C016D68B9 = {
+			fileRef = F517D63F0356B80C016D68B9;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F517D6420356B8CC016D68B9 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarms.m;
+			refType = 4;
+		};
+		F517D6430356B8CC016D68B9 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarms.h;
+			refType = 4;
+		};
+		F517D6440356B8CC016D68B9 = {
+			fileRef = F517D6420356B8CC016D68B9;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F517D6450356B8CC016D68B9 = {
+			fileRef = F517D6430356B8CC016D68B9;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5243DA40378681101AEEDB1 = {
+			isa = PBXFileReference;
+			path = "Popup triangle.tiff";
+			refType = 4;
+		};
+		F5243DA50378681101AEEDB1 = {
+			fileRef = F5243DA40378681101AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F552A8AB0358E8B201AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRScrollView.h;
+			refType = 4;
+		};
+		F552A8AC0358E8B201AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRScrollView.m;
+			refType = 4;
+		};
+		F552A8AD0358E8B201AEEDB1 = {
+			fileRef = F552A8AB0358E8B201AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F552A8AE0358E8B201AEEDB1 = {
+			fileRef = F552A8AC0358E8B201AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F560E2EE03574F8A01A4E466 = {
+			children = (
+				F560E2EF03574F8A01A4E466,
+			);
+			isa = PBXVariantGroup;
+			name = Alarms.nib;
+			path = "";
+			refType = 4;
+		};
+		F560E2EF03574F8A01A4E466 = {
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/Alarms.nib;
+			refType = 4;
+		};
+		F560E2F003574F8A01A4E466 = {
+			fileRef = F560E2EE03574F8A01A4E466;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F560E2F10357506401A4E466 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSApplication.m;
+			refType = 4;
+		};
+		F560E2F20357506401A4E466 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSApplication.h;
+			refType = 4;
+		};
+		F560E2F30357506401A4E466 = {
+			fileRef = F560E2F10357506401A4E466;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F560E2F40357506501A4E466 = {
+			fileRef = F560E2F20357506401A4E466;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F560E2F6035766F101A4E466 = {
+			fileRef = 29B97318FDCFA39411CA2CEA;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F560E2F7035766F201A4E466 = {
+			fileRef = 089C165CFE840E0CC02AAC07;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F560E311035787D501A4E466 = {
+			children = (
+				F517D63F0356B80C016D68B9,
+				F517D63E0356B80C016D68B9,
+				F59DC6D30353C9E601AEEDB1,
+				F59DC6D40353C9E601AEEDB1,
+				F59E47B5036AAD55016B311C,
+				F59E47B4036AAD55016B311C,
+				F59DC6DB0353DE5101AEEDB1,
+				F59DC6DC0353DE5101AEEDB1,
+				F59E47C1036B1ADD016B311C,
+				F59E47C0036B1ADD016B311C,
+				F5F198D1036BE57401EB0372,
+				F5F198D0036BE57401EB0372,
+			);
+			isa = PBXGroup;
+			name = Controllers;
+			refType = 4;
+		};
+		F560E312035787E001A4E466 = {
+			children = (
+				F517D6430356B8CC016D68B9,
+				F517D6420356B8CC016D68B9,
+				F59F6CB40354E7DA01AEEDB1,
+				F59F6CB50354E7DA01AEEDB1,
+				E1BF6E9003C928D200050002,
+				E1BF6E9103C928D200050002,
+			);
+			isa = PBXGroup;
+			name = Alarms;
+			refType = 4;
+		};
+		F560E313035787ED01A4E466 = {
+			children = (
+				E1E9A33D03C8EF6800050002,
+				F59E47A6036AA5FC016B311C,
+				E1ECA00603C002B300F54C66,
+				E1ECA00703C002B300F54C66,
+				E1A18CB203B439CF00000028,
+				E130B9AC03B7C59700000028,
+				E130B9AD03B7C59700000028,
+				F59DC6E90353F58B01AEEDB1,
+				F59DC6E80353F58B01AEEDB1,
+				F59DC6FC0354188F01AEEDB1,
+				F59DC6FD0354188F01AEEDB1,
+			);
+			isa = PBXGroup;
+			name = Utilities;
+			refType = 4;
+		};
+		F560E314035787F901A4E466 = {
+			children = (
+				E1D358B903C60CE900C8A18E,
+				E1D358BA03C60CE900C8A18E,
+				E1F0B14A03AD8CEF00AEFBE0,
+				E1F0B14B03AD8CEF00AEFBE0,
+				F5B79837035F64F80136A8DD,
+				F5B79836035F64F80136A8DD,
+				F552A8AB0358E8B201AEEDB1,
+				F552A8AC0358E8B201AEEDB1,
+				F560E3150357895001A4E466,
+				F560E3160357895001A4E466,
+				E13919E203B9E4E100000028,
+				E13919E303B9E4E100000028,
+				F5F240B6036A862101FE7503,
+				F5F240B5036A862101FE7503,
+				F5F240CD036A877301FE7503,
+				F5F240CC036A877301FE7503,
+				F5F19871036B822E01EB0372,
+				F5F19870036B822E01EB0372,
+			);
+			isa = PBXGroup;
+			name = Views;
+			path = "";
+			refType = 4;
+		};
+		F560E3150357895001A4E466 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRHistoryTrackingComboBox.h;
+			refType = 4;
+		};
+		F560E3160357895001A4E466 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRHistoryTrackingComboBox.m;
+			refType = 4;
+		};
+		F560E3170357895001A4E466 = {
+			fileRef = F560E3150357895001A4E466;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F560E3180357895001A4E466 = {
+			fileRef = F560E3160357895001A4E466;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F562F809037E5D0101AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = VERSION;
+			refType = 4;
+		};
+		F589C9C6035AA12B0155F4B2 = {
+			isa = PBXFileReference;
+			path = "Read Me.rtfd";
+			refType = 4;
+		};
+		F589C9C7035AA12E0155F4B2 = {
+			fileRef = F589C9C6035AA12B0155F4B2;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6D30353C9E601AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarmSetController.h;
+			refType = 4;
+		};
+		F59DC6D40353C9E601AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarmSetController.m;
+			refType = 4;
+		};
+		F59DC6D50353C9E601AEEDB1 = {
+			fileRef = F59DC6D30353C9E601AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6D60353C9E601AEEDB1 = {
+			fileRef = F59DC6D40353C9E601AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6DB0353DE5101AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarmNotifierController.h;
+			refType = 4;
+		};
+		F59DC6DC0353DE5101AEEDB1 = {
+			fileEncoding = 30;
+			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 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRIntegerFilter.m;
+			refType = 4;
+		};
+		F59DC6E90353F58B01AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRIntegerFilter.h;
+			refType = 4;
+		};
+		F59DC6EA0353F58B01AEEDB1 = {
+			fileRef = F59DC6E80353F58B01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6EB0353F58B01AEEDB1 = {
+			fileRef = F59DC6E90353F58B01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6FC0354188F01AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRDateFormatter.h;
+			refType = 4;
+		};
+		F59DC6FD0354188F01AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRDateFormatter.m;
+			refType = 4;
+		};
+		F59DC6FE0354188F01AEEDB1 = {
+			fileRef = F59DC6FC0354188F01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DC6FF0354188F01AEEDB1 = {
+			fileRef = F59DC6FD0354188F01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59DD44F0358ABF4017318D0 = {
+			children = (
+				F59DD4500358ABF4017318D0,
+			);
+			isa = PBXVariantGroup;
+			name = Credits.html;
+			path = "";
+			refType = 4;
+		};
+		F59DD4500358ABF4017318D0 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/Credits.html;
+			refType = 4;
+		};
+		F59DD4510358ABF7017318D0 = {
+			fileRef = F59DD44F0358ABF4017318D0;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47A6036AA5FC016B311C = {
+			children = (
+				F5F240B9036A867901FE7503,
+				F5F240CA036A869401FE7503,
+			);
+			isa = PBXGroup;
+			name = BDAlias;
+			path = "";
+			refType = 4;
+		};
+		F59E47A7036AAA6D016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlert.m;
+			refType = 4;
+		};
+		F59E47A8036AAA6D016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlert.h;
+			refType = 4;
+		};
+		F59E47A9036AAA6D016B311C = {
+			fileRef = F59E47A7036AAA6D016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47AA036AAA6D016B311C = {
+			fileRef = F59E47A8036AAA6D016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47AB036AAC1E016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSBeepAlert.m;
+			refType = 4;
+		};
+		F59E47AC036AAC1E016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSBeepAlert.h;
+			refType = 4;
+		};
+		F59E47AD036AAC1E016B311C = {
+			fileRef = F59E47AB036AAC1E016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47AE036AAC1E016B311C = {
+			fileRef = F59E47AC036AAC1E016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47AF036AAC31016B311C = {
+			children = (
+				E1A18CAB03B4344C00000028,
+				E1A18CAC03B4344C00000028,
+				F59E47A8036AAA6D016B311C,
+				F59E47A7036AAA6D016B311C,
+				F59E47B9036AB217016B311C,
+				F59E47B8036AB217016B311C,
+				F59E4BE7036B2E5E016B311C,
+				F59E4BE6036B2E5E016B311C,
+				F59E47B1036AACD1016B311C,
+				F59E47B0036AACD1016B311C,
+				F59E47AC036AAC1E016B311C,
+				F59E47AB036AAC1E016B311C,
+				F59E47BD036AB228016B311C,
+				F59E47BC036AB228016B311C,
+				F5F1986D036B813101EB0372,
+				F5F1986C036B813101EB0372,
+				E19FD39E03C98645001509F3,
+				E19FD39F03C98645001509F3,
+			);
+			isa = PBXGroup;
+			name = Alerts;
+			path = "";
+			refType = 4;
+		};
+		F59E47B0036AACD1016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSNotifierAlert.m;
+			refType = 4;
+		};
+		F59E47B1036AACD1016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSNotifierAlert.h;
+			refType = 4;
+		};
+		F59E47B2036AACD1016B311C = {
+			fileRef = F59E47B0036AACD1016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47B3036AACD1016B311C = {
+			fileRef = F59E47B1036AACD1016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47B4036AAD55016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarmAlertController.m;
+			refType = 4;
+		};
+		F59E47B5036AAD55016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarmAlertController.h;
+			refType = 4;
+		};
+		F59E47B6036AAD55016B311C = {
+			fileRef = F59E47B4036AAD55016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47B7036AAD55016B311C = {
+			fileRef = F59E47B5036AAD55016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47B8036AB217016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSDockBounceAlert.m;
+			refType = 4;
+		};
+		F59E47B9036AB217016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSDockBounceAlert.h;
+			refType = 4;
+		};
+		F59E47BA036AB217016B311C = {
+			fileRef = F59E47B8036AB217016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47BB036AB217016B311C = {
+			fileRef = F59E47B9036AB217016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47BC036AB228016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSMovieAlert.m;
+			refType = 4;
+		};
+		F59E47BD036AB228016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSMovieAlert.h;
+			refType = 4;
+		};
+		F59E47BE036AB228016B311C = {
+			fileRef = F59E47BC036AB228016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47BF036AB228016B311C = {
+			fileRef = F59E47BD036AB228016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47C0036B1ADD016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSMovieAlertController.m;
+			refType = 4;
+		};
+		F59E47C1036B1ADD016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSMovieAlertController.h;
+			refType = 4;
+		};
+		F59E47C2036B1ADD016B311C = {
+			fileRef = F59E47C0036B1ADD016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E47C3036B1ADD016B311C = {
+			fileRef = F59E47C1036B1ADD016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E4BDE036B1D94016B311C = {
+			children = (
+				F59E4BDF036B1D94016B311C,
+			);
+			isa = PBXVariantGroup;
+			name = "Movie alert.nib";
+			path = "";
+			refType = 4;
+		};
+		F59E4BDF036B1D94016B311C = {
+			isa = PBXFileReference;
+			name = English;
+			path = "English.lproj/Movie alert.nib";
+			refType = 4;
+		};
+		F59E4BE0036B1D94016B311C = {
+			fileRef = F59E4BDE036B1D94016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E4BE6036B2E5E016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSScriptAlert.m;
+			refType = 4;
+		};
+		F59E4BE7036B2E5E016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSScriptAlert.h;
+			refType = 4;
+		};
+		F59E4BE8036B2E5E016B311C = {
+			fileRef = F59E4BE6036B2E5E016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E4BE9036B2E5E016B311C = {
+			fileRef = F59E4BE7036B2E5E016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E4BEA036B33EC016B311C = {
+			isa = PBXFrameworkReference;
+			name = QuickTime.framework;
+			path = /System/Library/Frameworks/QuickTime.framework;
+			refType = 0;
+		};
+		F59E4C0C036B33EC016B311C = {
+			fileRef = F59E4BEA036B33EC016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E4C0D036B43D2016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSMovie-NJRExtensions.m";
+			refType = 4;
+		};
+		F59E4C0E036B43D2016B311C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSMovie-NJRExtensions.h";
+			refType = 4;
+		};
+		F59E4C0F036B43D2016B311C = {
+			fileRef = F59E4C0D036B43D2016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59E4C10036B43D2016B311C = {
+			fileRef = F59E4C0E036B43D2016B311C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59F6CB40354E7DA01AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarm.h;
+			refType = 4;
+		};
+		F59F6CB50354E7DA01AEEDB1 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSAlarm.m;
+			refType = 4;
+		};
+		F59F6CB60354E7DA01AEEDB1 = {
+			fileRef = F59F6CB40354E7DA01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F59F6CB70354E7DA01AEEDB1 = {
+			fileRef = F59F6CB50354E7DA01AEEDB1;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5B79836035F64F80136A8DD = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRTableView.m;
+			refType = 4;
+		};
+		F5B79837035F64F80136A8DD = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRTableView.h;
+			refType = 4;
+		};
+		F5B79838035F64F80136A8DD = {
+			fileRef = F5B79836035F64F80136A8DD;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5B79839035F64F80136A8DD = {
+			fileRef = F5B79837035F64F80136A8DD;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5B79865038865B30136A8DD = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSCharacterSet-NJRExtensions.m";
+			refType = 4;
+		};
+		F5B79866038865B30136A8DD = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSCharacterSet-NJRExtensions.h";
+			refType = 4;
+		};
+		F5B79867038865B30136A8DD = {
+			fileRef = F5B79865038865B30136A8DD;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5B79868038865B30136A8DD = {
+			fileRef = F5B79866038865B30136A8DD;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5EE8DB9038A76AC0134BEAC = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSDictionary-NJRExtensions.m";
+			refType = 4;
+		};
+		F5EE8DBA038A76AC0134BEAC = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSDictionary-NJRExtensions.h";
+			refType = 4;
+		};
+		F5EE8DBB038A76AC0134BEAC = {
+			fileRef = F5EE8DB9038A76AC0134BEAC;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5EE8DBC038A76AC0134BEAC = {
+			fileRef = F5EE8DBA038A76AC0134BEAC;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F1986C036B813101EB0372 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSSpeechAlert.m;
+			refType = 4;
+		};
+		F5F1986D036B813101EB0372 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSSpeechAlert.h;
+			refType = 4;
+		};
+		F5F1986F036B813101EB0372 = {
+			fileRef = F5F1986D036B813101EB0372;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F19870036B822E01EB0372 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRVoicePopUpButton.m;
+			refType = 4;
+		};
+		F5F19871036B822E01EB0372 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRVoicePopUpButton.h;
+			refType = 4;
+		};
+		F5F19872036B822E01EB0372 = {
+			fileRef = F5F19870036B822E01EB0372;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F19873036B822E01EB0372 = {
+			fileRef = F5F19871036B822E01EB0372;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F198D0036BE57401EB0372 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRTableDelegate.m;
+			refType = 4;
+		};
+		F5F198D1036BE57401EB0372 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRTableDelegate.h;
+			refType = 4;
+		};
+		F5F198D2036BE57401EB0372 = {
+			fileRef = F5F198D0036BE57401EB0372;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F198D3036BE57401EB0372 = {
+			fileRef = F5F198D1036BE57401EB0372;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F1990D036D3B3101EB0372 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSImage-NJRExtensions.m";
+			refType = 4;
+		};
+		F5F1990E036D3B3101EB0372 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSImage-NJRExtensions.h";
+			refType = 4;
+		};
+		F5F1990F036D3B3101EB0372 = {
+			fileRef = F5F1990D036D3B3101EB0372;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F19910036D3B3101EB0372 = {
+			fileRef = F5F1990E036D3B3101EB0372;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F240B5036A862101FE7503 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRFSObjectSelector.m;
+			refType = 4;
+		};
+		F5F240B6036A862101FE7503 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRFSObjectSelector.h;
+			refType = 4;
+		};
+		F5F240B7036A862301FE7503 = {
+			fileRef = F5F240B6036A862101FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F240B8036A862301FE7503 = {
+			fileRef = F5F240B5036A862101FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F240B9036A867901FE7503 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = BDAlias.h;
+			refType = 4;
+		};
+		F5F240BA036A867901FE7503 = {
+			fileRef = F5F240B9036A867901FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F240CA036A869401FE7503 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = BDAlias.m;
+			refType = 4;
+		};
+		F5F240CB036A869401FE7503 = {
+			fileRef = F5F240CA036A869401FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F240CC036A877301FE7503 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRQTMediaPopUpButton.m;
+			refType = 4;
+		};
+		F5F240CD036A877301FE7503 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRQTMediaPopUpButton.h;
+			refType = 4;
+		};
+		F5F240CE036A877301FE7503 = {
+			fileRef = F5F240CC036A877301FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F240D0036A87E301FE7503 = {
+			isa = PBXFrameworkReference;
+			name = Carbon.framework;
+			path = /System/Library/Frameworks/Carbon.framework;
+			refType = 0;
+		};
+		F5F24166036A87E401FE7503 = {
+			fileRef = F5F240D0036A87E301FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F24187036A90D901FE7503 = {
+			isa = PBXFrameworkReference;
+			name = MachineSettings.framework;
+			path = /System/Library/PrivateFrameworks/MachineSettings.framework;
+			refType = 0;
+		};
+		F5F24189036A90D901FE7503 = {
+			fileRef = F5F24187036A90D901FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5F2418A036A910B01FE7503 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = SoundFileManager.h;
+			refType = 4;
+		};
+		F5F2418B036A910B01FE7503 = {
+			fileRef = F5F2418A036A910B01FE7503;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+	};
+	rootObject = 29B97313FDCFA39411CA2CEA;
+}
Index: releases/Pester/1.1b1/Source/Pester_Prefix.h
===================================================================
--- releases/Pester/1.1b1/Source/Pester_Prefix.h	(revision 62)
+++ releases/Pester/1.1b1/Source/Pester_Prefix.h	(revision 62)
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'Pester' target in the 'Pester' project
+//
+
+#ifdef __OBJC__
+    #import <Cocoa/Cocoa.h>
+#endif
Index: releases/Pester/1.1b1/Source/SUSpeaker.h
===================================================================
--- releases/Pester/1.1b1/Source/SUSpeaker.h	(revision 62)
+++ releases/Pester/1.1b1/Source/SUSpeaker.h	(revision 62)
@@ -0,0 +1,40 @@
+//
+//  SUSpeaker.h
+//  SpeechTest
+//
+//  Created by raf on Sun Jan 28 2001.
+//  Copyright (c) 2000 Raphael Sebbe. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Carbon/Carbon.h>
+
+@interface SUSpeaker : NSObject 
+{
+    SpeechChannel _speechChannel;
+    id _delegate;
+    NSPort *_port;
+    
+    BOOL _usePort;
+    unsigned int _reserved1;
+    unsigned int _reserved2;
+}
+
++(NSArray*) voiceNames;
++ (NSString *)defaultVoice;
+
+-(void) setPitch:(float)pitch;
+-(void) setVoice:(int)index;
+-(void) speakText:(NSString*)text;
+-(void) stopSpeaking;
+
+-(void) setDelegate:(id)delegate;
+-(id) delegate;
+
+@end
+
+
+@interface NSObject (SUSpeakerDelegate)
+-(void) didFinishSpeaking:(SUSpeaker*)speaker;
+-(void) willSpeakWord:(SUSpeaker*)speaker at:(int)where length:(int)length;
+@end
Index: releases/Pester/1.1b1/Source/SUSpeaker.m
===================================================================
--- releases/Pester/1.1b1/Source/SUSpeaker.m	(revision 62)
+++ releases/Pester/1.1b1/Source/SUSpeaker.m	(revision 62)
@@ -0,0 +1,296 @@
+//
+//  SUSpeaker.m
+//  SpeechTest
+//
+//  Created by raf on Sun Jan 28 2001.
+//  Copyright (c) 2000 Raphael Sebbe. All rights reserved.
+//
+
+#import "SUSpeaker.h"
+#include <unistd.h>
+#include <pthread.h>
+
+void MySpeechDoneCallback(SpeechChannel chan,SInt32 refCon);
+void MySpeechWordCallback (SpeechChannel chan, SInt32 refCon, UInt32 wordPos, 
+    UInt16 wordLen);
+
+@interface SUSpeaker (Private)
+-(void) setCallbacks;
+-(NSPort*) port;
+-(void) setReserved1:(unsigned int)r;
+-(void) setReserved2:(unsigned int)r;
+-(BOOL) usesPort;
+-(void) handleMessage:(unsigned)msgid;
+@end
+
+
+@implementation SUSpeaker
+
+/*"Returns the voice names in the same order as expected by setVoice:."*/
++(NSArray*) voiceNames
+{
+    NSMutableArray *voices = [NSMutableArray arrayWithCapacity:0];
+    short voiceCount;
+    OSErr error = noErr;
+    int voiceIndex;
+    
+    
+    
+    error = CountVoices(&voiceCount);
+    
+    if(error != noErr) return voices;
+    //NSLog(@"hello : %d", voiceCount);
+    for(voiceIndex=0; voiceIndex<voiceCount; voiceIndex++)
+    {
+        VoiceSpec	voiceSpec;
+        VoiceDescription voiceDescription;
+        
+        error = GetIndVoice(voiceIndex+1, &voiceSpec);
+        if(error != noErr) return voices;
+        error = GetVoiceDescription( &voiceSpec, &voiceDescription, sizeof(voiceDescription));
+        if(error == noErr)
+        {
+            NSString *voiceName = [[[NSString alloc] initWithCString:
+                &(voiceDescription.name[1]) length:voiceDescription.name[0]] autorelease];
+            //NSLog(voiceName);
+            
+            [voices addObject:voiceName];
+        }
+        else return voices;
+    }
+    return voices;
+}
+
++ (NSString *)defaultVoice;
+{
+    OSStatus err = noErr;
+    VoiceDescription voiceDescription;
+
+    err = GetVoiceDescription(NULL, &voiceDescription, sizeof(voiceDescription));
+
+    return [[[NSString alloc] initWithCString: &(voiceDescription.name[1]) length:voiceDescription.name[0]] autorelease];
+}
+
+-init
+{
+    NSRunLoop *loop = [NSRunLoop currentRunLoop];
+    [super init];
+
+    // we have 2 options here : we use a port or we don't.
+    // using a port means delegate message are invoked from the main 
+    // thread (runloop in which this object is created), otherwise, those message 
+    // are asynchronous.
+    if(loop != nil) 
+    {
+        _port = [[NSPort port] retain];
+        // we use a port so that the speech manager callbacks can talk to the main thread.
+        // That way, we can safely access interface elements from the delegate methods
+        
+        [_port setDelegate:self];
+        [loop addPort:_port forMode:NSDefaultRunLoopMode];
+        _usePort = YES;
+    }
+    else _usePort = NO;
+    
+    NewSpeechChannel(NULL, &_speechChannel); // NULL voice is default voice
+    [self setCallbacks];
+    return self;
+}
+
+-(void) dealloc
+{
+
+    [_port release];
+    if(_speechChannel != NULL)
+    {
+        DisposeSpeechChannel(_speechChannel);
+    }
+    
+    [super dealloc];
+}
+
+
+/*"Sets the pitch. Pitch is given in Hertz and should be comprised between 80 and 500, depending on the voice. Note that extreme value can make you app crash..."*/ 
+-(void) setPitch:(float)pitch
+{
+    int fixedPitch;
+    
+    
+    pitch = (pitch-90.0)/(300.0-90.0)*(65.0 - 30.0) + 30.0;
+    /* I don't know what Apple means with pitch between 30 and 65, so I convert that range to [90, 300]. I did not test frequencies correspond, though.*/
+    
+    fixedPitch = (int)pitch;
+    
+    fixedPitch = fixedPitch << 16; // fixed point
+    
+    if(_speechChannel != NULL)
+    {
+        SetSpeechPitch (_speechChannel, fixedPitch);
+    }
+}
+-(void) setVoice:(int)index
+{
+    VoiceSpec voice;
+    OSErr error = noErr;
+    
+    if(_speechChannel != NULL)
+    {
+        DisposeSpeechChannel(_speechChannel);
+        _speechChannel = NULL;
+    }
+    
+    error = GetIndVoice(index, &voice);
+    if(error == noErr)
+    {
+        NewSpeechChannel(&voice, &_speechChannel);
+        [self setCallbacks];
+    }
+}
+-(void) speakText:(NSString*)text
+{
+    //pid_t pid = getpid();
+    //pthread_t t = pthread_self();
+    //NSLog(@"pid : %d", t);
+
+    if(_speechChannel != NULL && text != nil)
+    {
+        //finished = NO;
+        SpeakText(_speechChannel, [text cString], [text length]);
+        //while(!finished) ;
+        //sleep(2);
+    }
+}
+-(void) stopSpeaking
+{
+    if(_speechChannel != NULL)
+    {
+        StopSpeech(_speechChannel);
+        if([_delegate respondsToSelector:@selector(didFinishSpeaking:)])
+        {
+            [_delegate didFinishSpeaking:self];
+        }
+    }
+}
+
+-(void) setDelegate:(id)delegate
+{
+    _delegate = delegate;
+}
+-(id) delegate
+{
+    return _delegate;
+}
+
+//--- Private ---
+
+-(void) setCallbacks
+{
+    if(_speechChannel != NULL)
+    {
+        SetSpeechInfo(_speechChannel, soSpeechDoneCallBack, &MySpeechDoneCallback);
+        SetSpeechInfo(_speechChannel, soWordCallBack, &MySpeechWordCallback);
+        SetSpeechInfo(_speechChannel, soRefCon, (const void*)self);
+    }
+}
+-(void) setReserved1:(unsigned int)r
+{
+    _reserved1 = r;
+}
+-(void) setReserved2:(unsigned int)r
+{
+    _reserved2 = r;
+}
+-(NSPort*) port
+{
+    return _port;
+}
+-(BOOL) usesPort
+{
+    return _usePort;
+}
+-(void) handleMessage:(unsigned)msgid
+{
+    if(msgid == 5)
+    {
+        if([_delegate respondsToSelector:@selector(willSpeakWord:at:length:)])
+        {
+            if(_reserved1 >= 0 && _reserved2 >= 0)
+                [_delegate willSpeakWord:self at:_reserved1 length:_reserved2];
+            else
+                [_delegate willSpeakWord:self at:0 length:0];
+        }
+    }
+    else if(msgid == 8)
+    {
+        if([_delegate respondsToSelector:@selector(didFinishSpeaking:)])
+        {
+            [_delegate didFinishSpeaking:self];
+        }
+    }
+}
+//--- NSPort delegate ---
+- (void)handlePortMessage:(NSPortMessage *)portMessage
+{
+    int msg = [portMessage msgid];
+    
+    [self handleMessage:msg];
+}
+
+@end
+
+void MySpeechDoneCallback(SpeechChannel chan,SInt32 refCon)
+{
+    SUSpeaker *speaker = (SUSpeaker*)refCon;
+    unsigned msg = 8;
+    //NSLog(@"Speech Done");
+    
+    if([speaker isKindOfClass:[SUSpeaker class]])
+    {
+        if([speaker usesPort])
+        {
+            NSPortMessage *message = [[NSPortMessage alloc] initWithSendPort:[speaker port]
+                receivePort:[speaker port] components:nil];
+        
+            [message setMsgid:msg];
+            [message sendBeforeDate:nil];
+            [message release];
+        }
+        else
+        {
+            // short-circuit port
+            [speaker handleMessage:msg];
+        }
+    } 
+}
+void MySpeechWordCallback(SpeechChannel chan, SInt32 refCon, UInt32 wordPos,UInt16 wordLen)
+{
+    SUSpeaker *speaker = (SUSpeaker*)refCon;
+    unsigned msg = 5;
+    //pid_t pid = getpid();
+    //pthread_t t = pthread_self();
+    //NSLog(@"pid : %d", t);
+    
+    
+    //NSLog(@"Word Done");
+    //while(1);
+    if([speaker isKindOfClass:[SUSpeaker class]])
+    {
+        [speaker setReserved1:wordPos];
+        [speaker setReserved2:wordLen];
+        
+        if([speaker usesPort])
+        {
+            NSPortMessage *message = [[NSPortMessage alloc] initWithSendPort:[speaker port]
+                receivePort:[speaker port] components:nil];
+        
+            [message setMsgid:msg];
+            [message sendBeforeDate:nil];
+            [message release];
+        }
+        else 
+        {
+            // short-circuit port
+            [speaker handleMessage:msg];
+        }
+    } 
+}
Index: releases/Pester/1.1b1/Source/SoundFileManager.h
===================================================================
--- releases/Pester/1.1b1/Source/SoundFileManager.h	(revision 62)
+++ releases/Pester/1.1b1/Source/SoundFileManager.h	(revision 62)
@@ -0,0 +1,56 @@
+/*
+ *     Generated by class-dump (version 2.1.5).
+ *
+ *     class-dump is Copyright (C) 1997, 1999, 2000, 2001 by Steve Nygard.
+ */
+
+/*
+ * File: /Volumes/Mac OS X/System/Library/PrivateFrameworks/MachineSettings.framework/Versions/A/MachineSettings
+ */
+
+// Note: dumped from Mac OS X 10.1.5; Mac OS X 10.2.1's SoundFileManager is identical.
+
+@class SoundFile;
+
+@interface SoundFileManager
+{
+    NSMutableArray *_soundFiles;
+    NSFileManager *_fileManager;
+}
+
++ (void)initialize;
++ (SoundFileManager *)sharedSoundFileManager;
+- (id)init;
+- (void)dealloc;
+- (void)findSoundFiles;
+- (void)addSoundFilesFromDirectory:(NSString *)directory asType:(int)type;
+- (void)sortByType;
+- (void)sortByName;
+- (SoundFile *)soundFileAtIndex:(int)index;
+- (int)count;
+- (int)indexOfSoundFile:index;
+- (SoundFile *)soundFileFromPath:(NSString *)path;
+- (SoundFile *)soundFileWithName:(NSString *)name type:(int)type;
+
+@end
+
+@interface SoundFile
+{
+    int _type;
+    NSString *_name;
+}
+
+- (id)initWithName:(NSString *)name type:(int)type;
+- (void)dealloc;
+- (int)type;
+- (NSString *)name;
+- (NSString *)path;
+- (NSString *)pathWithoutExtension;
+- (void)setType:(int)type;
+- (void)setName:(NSString *)name;
+- (int)compareName:(SoundFile *)other;
+- (int)compareType:(SoundFile *)other;
+- (int)compareNameThenType:(SoundFile *)other;
+- (int)compareTypeThenName:(SoundFile *)other;
+
+@end
Index: releases/Pester/1.1b1/Source/VERSION
===================================================================
--- releases/Pester/1.1b1/Source/VERSION	(revision 62)
+++ releases/Pester/1.1b1/Source/VERSION	(revision 62)
@@ -0,0 +1,1 @@
+1.1b1
Index: releases/Pester/1.1b1/Source/main.m
===================================================================
--- releases/Pester/1.1b1/Source/main.m	(revision 62)
+++ releases/Pester/1.1b1/Source/main.m	(revision 62)
@@ -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: releases/Pester/1.1b1/package-Pester.sh
===================================================================
--- releases/Pester/1.1b1/package-Pester.sh	(revision 62)
+++ releases/Pester/1.1b1/package-Pester.sh	(revision 62)
@@ -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/ && \
+:
